Compare commits

..
Author SHA1 Message Date
apion 263bccca4b idk whats up here but I wanna swap off this branch so 2025-02-07 17:49:10 -05:00
apion 1d94adface Fabric now boots 2025-01-26 03:02:57 -05:00
apion c741ddbc2e Comments 2025-01-25 04:23:40 -05:00
apion 8cad44ffb1 NEOFORGE IS BOOTING INTO A WORLD!!! 2025-01-25 04:05:34 -05:00
apion dec0376d11 More MDG testing 2025-01-18 15:46:50 -05:00
apion 007b2a49f4 More ModDevGradle porting 2025-01-18 01:19:26 -05:00
apion 082683723d Initial moddevgradle port 2025-01-17 21:31:25 -05:00
3004 changed files with 124468 additions and 232913 deletions

No files matched your search

-16
View File
@@ -1,16 +0,0 @@
### Additions
- Added ability to rename PC Boxes by clicking on the name of a box
- Added ability to set wallpapers per PC Box by clicking the button right to the box name
- Added sorting by Name, Level and type by clicking the button left of the box name (shift reverses order)
- Added filtering/search functionality in PC UI, which also supports pokemon properties (e.g. shiny=yes shows all shinies)
- Added /changewallpaper <player> <boxNumber> <wallpaper> command to change a wallpaper through commands
- Added /renamebox <player> <boxNumber> <name> command to rename a PC box through commands
### Developer
- Added RenamePCBoxEvent.Pre/Post events to prevent players from renaming a box or change their input
- Added ChangePCBoxWallpaperEvent.Pre/Post to prevent players from changing to a wallpaper or change their selection
- Added WallpaperCollectionEvent which gets called when clients connect to a server, allowing the server which of the clients found wallpapers it's allowed to move (collected wallpapers can be removed for example to make it "vanish" client-side)
- Wallpapers are loaded from `assets/<namespace>/textures/gui/pc/wallpaper/` and all wallpapers in this folder are available to the client to choose by default
- Renamed `SetPCBoxPokemonPacket` and the respective handler to `SetPCBoxPacket`
-3
View File
@@ -1,3 +0,0 @@
### Additions
- Added the ability to ride Pokémon by shift-right clicking and selecting the ride option.
-10
View File
@@ -1,10 +0,0 @@
### Additions
- Added support for NPCs to use Pokémon models and vice versa. This will require changes in addons that add fossil types due to naming conflicts between fossils and the Pokémon species.
- Added `/changejointscale` command to change the scale of a joint in a model. Unbelievably funny.
### Developer
- Removed all VaryingModelRepository subclasses into the parent class.
### Addons
- Added `transformedParts` to the root of poser JSONs so it now exists in both poses and the model overall.
+40 -228
View File
@@ -1,208 +1,52 @@
# Changelog # Changelog
## [1.7.0 (Month xth, 2025)](#1-7-0) ## [1.6.1 (Release TBD)](#1-6-1)
### Additions ### 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.
- Added `blacklisted_items_to_hold` and `whitelisted_items_to_hold` tags to allow for controlling which items players can give to their Pokémon. If the whitelist is empty, it will consider all item as allowed (unless they are in the blacklist).
- Pokémon now follow the mouse cursor on the Summary screen, with an option to disable this in the settings.
- Pokémon's held items can now be rendered, with a visibility toggle in the Summary screen.
- Added cosmetic item functionality for Pokémon. Certain cosmetic items can be given to applicable Pokémon via the interact menu.
- Added the various log blocks as cosmetic items for Timburr and Komala.
- Added `visibility/hidden`, `visibility/hat` and `visibility/face` tags to control where and how certain items are rendered.
### 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.
- Fixed not being able to do complex item requirements aside from just NBT with evolution conditions, requirements and fossil items.
- Fixed the usage `hiddenability` in `pokegive` or other spawn commands resulting in a forced hidden ability
- Fixed the consumption of friendship berries (or EV berries) not making any noise
- Fixed Instantly breaking and replacing a fossil analyzer with any block entity crashing the game in a complete multi-structure
- Fixed players getting disconnected when sidemods update a Pokémon's teratype
- Fixed fling not using Item Names for minecraft held items that substitute Pokémon items
- Fixed evolutions sometimes preventing players from logging in to servers
- Fixed rendering of shoulder-mounted Pokémon desyncing between clients
- Fixed apricorn chest boats forgetting their inventories when being unloaded
- Fixed moves not updating correctly between form changes resulting in illegal movesets
- Fixed crash sometimes occurring with the "Oritech" mod
- Fixed crashes due to an incorrect Java version handing out an obscure crash.
- Fixed some berries being able to rarely get too many berries and cause a crash.
- Fixed status curing berries not playing the berry eating sound, same for healing berries used mid-battle.
- Fixed owned Pokémon sometimes being un-interactable after the player relogs fast
- Fixed field name in evolution requirements for Spewpa Pokeball.
- Fixed LevelUpCriterion logic to correctly check that the Pokémon is a preEvo.
### 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.
- Removed the NbtItemPredicate class, all the mod usages now use the vanilla item predicate solution, this causes breaking changes on Fossil, HeldItemRequirement & ItemInteractionEvolution
- Renamed Cobblemon's creative tabs to start with "Cobblemon: " to distinguish Cobblemon's tabs from tabs for other mods.
- Various items now have a rarity value.
### Changes
- When using the `cobblemon` or `generation_9` capture calculators a critical capture with a single shake will always play for successful captures when you've already registered the Pokémon as caught in your Pokédex.
### MoLang & Datapacks
- The following usages for item predicates can now use item conditions like advancements do, you can learn about them in the [Minecraft wiki](https://minecraft.wiki/w/Advancement_definition#minecraft:filled_bucket)
- The `requiredContext` for an item interaction evolution
- The `itemCondition` for a held item evolution requirement
- The `fossils` for a fossil entry
- Added MoLang flows for `poke_ball_capture_calculated`, `evolution_tested`, `evolution_accepted`, `evolution_completed`
## [1.6.1 (January 26th, 2025)](#1-6-1)
### Additions
- Added crossover paintings from Close Combat: Premonition, Altar, Slumber, and Nomad.
- Added Galarica Nuts, used for crafting Galarica Cuffs and Wreaths. Dropped from certain Pokémon. Take a wild guess which.
- Added compatibility with Repurposed Structures. (Thank you, TelepathicGrunt!)
- Added an evolution method for Karrablast to evolve into Escavalier in singleplayer.
- Pokédexes can now be placed in Chiseled Bookshelves.
- Added optional box argument to the /pc command.
- Pokédex and Dialogue screens now close when the inventory keybind is pressed.
- Added config setting `maxPokedexScanningDetectionRange` to control from what distance the player can scan Pokémon using the Pokédex. - Added config setting `maxPokedexScanningDetectionRange` to control from what distance the player can scan Pokémon using the Pokédex.
- Added the `is_standing_on_blocks(depth, blocks...)` MoLang function, which returns whether the specified entity is standing on a specific block or set of blocks. Example usage: `q.is_standing_on_blocks(2, minecraft:sand)`
- Added config setting `hideUnimplementedPokemonInThePokedex` which hides unimplemented Pokémon from the Pokédex when set to true. - 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 molang particle queries for getting distance to targeted entities.
- Added crossover paintings from Close Combat, Premonition, Altar, Slumber, and Nomad. - Added debug renderer for poseable entity locators.
- Added optional box argument to the /pc command - Added `baseScale` property to NPCs.
- Added the player to `PokerodReelEvent`.
- Pokédex and Dialogue API screens now close when the inventory keybind is pressed.
- Added Galarica Nuts, used for crafting Galarica Cuffs and Wreaths. Dropped from certain Pokémon.
- Added specific compatibility with Repurposed Structures. (Thank you, TelepathicGrunt!)
### Changes ### 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. - 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. - 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. - 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
#### Gen 5
- Ducklett
- Swanna
- Shelmet
- Accelgor
- Karrablast
- Escavalier
- Rufflet
- Braviary
- Foongus
- Amoonguss
#### Gen 6
- Binacle
- Barbaracle
#### Gen 7
- Dewpider
- Araquanid
- Alolan Geodude
- Alolan Graveler
- Alolan Golem
#### Gen 8
- Galarian Slowpoke
- Galarian Slowbro
- Galarian Slowking
#### Gen 9
- Paldean Tauros
### Added cries to the following Pokémon
- All Nidorans
- Shellder, Cloyster
- Pinsir
- Tyrogue, Hitmontop
- Spinda
### Animation updates for the following Pokémon
- Primeape
- Munchlax
- Snorlax
- Poliwrath
- Goldeen
- Seaking
- Dondozo
- Wobbuffet
- Charcadet
- Armarouge
- Ceruledge
- Geodude
- Graveler
- Golem
- Sandile
- Krokorok
- Krookodile
### Model updates for the following Pokémon
- Slowpoke
- Slowbro
- Slowking
- Eiscue
- Tauros
- Goldeen
- Seaking
- Charcadet
- Armarouge
- Ceruledge
- Pinsir
- Geodude
- Graveler
- Golem
### Cry updates for the following Pokémon
- Sceptile
### Changes
- Completely re-synced Pokémon move and stat data based on later games. Learnsets have changed considerably to maximise available moves.
- Pokémon will now be dynamically revealed to the Pokédex as they're seen in battle instead of revealing entire parties at the end of battle.
- Unseen wild Pokémon will update their name from '???' to their real name as soon as a battle starts to match how the battle UI shows 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.
- Berries will now drop from berry trees if broken at age 0 so you aren't punished for mistaken planting.
- Increased Fortune drops on Mint Seeds.
- Updated Slowpoke's shiny texture.
- Updated drops for many Pokémon.
- Adjusted the evolution sound to match the timing of the particle effect.
- Made berry trees shear-able by dispenser blocks. I'm sure nobody will make unholy contraptions with this.
- Edited some recipes to utilize tags instead of direct item IDs, for better mod compatibility.
- Added more support for a variety of Fabric/NeoForge conventional tags.
- Reformatted some tags to be more consistent.
### Fixes ### Fixes
- Fixed Pokédex sometimes crashing when switching forms. - Fixed Pokédex sometimes crashing when switching forms.
- Fixed Pokédex interface not transitioning out when closed. - Fixed Pokédex interface not transitioning out when closed.
- Fixed texture dimensions for the player and Pokémon interact interface. - Fixed texture dimensions for the interact interface.
- Fixed crash related to Tom's Simple Storage mod and the Fossil Machine. - Fixed crash related to Tom's Simple Storage mod and Fossil Machine.
- Fixed not being able to retrieve a fossil from the Fossil Machine with an empty hand. - Fixed not being able to retrieve a fossil from the Fossil Machine with an empty hand.
- Fixed Pokémon being collidable (collidible? collissionable? kaleidoscopable?) while being captured by a Poké Ball. - Fixed Pokémon being collidable while being captured by a Poké Ball.
- Fixed `full_party`, `own_zangoose_seviper`, `use_revive` and `use_candy` Advancement triggers. - Fixed `full_party`, `own_zangoose_seviper`, `use_revive` and `use_candy` Advancement triggers.
- Fixed `healing_machine` Advancement by using the correct 1.21 trigger. - Fixed `healing_machine` Advancement by using the correct 1.21 trigger.
- Fix Display Cases not dropping items if destroyed through explosions. - Fix Display Cases not dropping items if destroyed through explosions.
- Fixed an issue where the first Pokémon in the pastured Pokémon list clipped into the interface. - Fixed an issue where the first Pokémon in the pastured Pokémon list clipped into the interface.
- Fixed all Pokémon facing South on spawn. - Fixed all Pokémon facing South on spawn.
- Fixed bait being consumed even when not reeling in any Pokémon. - Parametric particle motion now works.
- Event spawned particles now work.
- Particles can now have independent coordinate spaces.
- Fixed bait being consumed when not reeling in any Pokémon.
- Fixed Miltank milk magically disappearing out of your bucket. - Fixed Miltank milk magically disappearing out of your bucket.
- Fixed Pokémon nicknames migrating from 1.5.2 not being displayed properly. - Fixed Pokémon nicknames migrating from 1.5.2 not being displayed properly.
- Fixed capitalization in one of our config options. It was a very important fix. Very important. Old configs are fine. - Fixed capitalization in one of our config fields, but allowing typo'd version to still be valid.
- Fixed Poké Rods not working if Lure or Luck of the Sea enchantments get removed by other mods. - Fixed Poké Rods not working if lure or luck of the sea enchantments get removed by other mods.
- Fixed crashes related to Pokémon when they are ready to evolve while holding an enchanted item. Very specific. - Fixed crashes related to Pokémon when they are ready to evolve while holding an enchanted item.
- Fixed a crash that sometimes occurred when evolving Nincada. - Fixed crashes that sometimes occur when evolving Nincada.
- Fixed Cobblemon plants not being compostable on NeoForge. - Fixed plants not being compostible on NeoForge.
- Fixed hide UI (F1 key) not hiding the party overlay. - Fixed hide UI (F1 key) not hiding the party overlay.
- Fixed NPC MoLang command `player_lose_command` not working. - Fixed NPC MoLang command `player_lose_command` not working.
- Fixed misaligned tooltips with edit boxes in the NPC editor screen. - Corrected misaligned tooltips with editboxes in the NPC editor screen.
- Fixed Pokémon riding two boats when attempting to deploy a platform on water. - Fixed Pokémon riding two boats when attempting to deploy a platform on water.
- Fixed the summary screen showing there's experience to reach the next level when they are at the level cap. - Made berry trees be shearable by dispenser blocks.
- Fixed the summary screen showing there's experience to reach the next level when at level cap.
- Fixed Pokémon forgetting moves when evolving on specific cases. - Fixed Pokémon forgetting moves when evolving on specific cases.
- Fixed Adorn compatibility, including improvements when using JEI/REI (Apricorn items now show up under the collapsed entries rather than standalone). - Fixed Adorn compatibility, including improvements when using JEI/REI (Apricorn items now show up under the collapsed entries rather than standalone).
- Fixed error message appearing on battle log when using Solar Beam with Sunny Day. - Fixed error message appearing on battle log when using Solar Beam with Sunny Day.
@@ -210,68 +54,35 @@
- Fixed `/pokedex grant all` command not giving male/female/shininess completion for some Pokémon. - Fixed `/pokedex grant all` command not giving male/female/shininess completion for some Pokémon.
- Fixed `/pokedex grant only` and `/pokedex remove only` not respecting the form parameter passed. - Fixed `/pokedex grant only` and `/pokedex remove only` not respecting the form parameter passed.
- Fixed variant forms appearing incorrectly in the Pokédex when the normal form had not been unlocked. - Fixed variant forms appearing incorrectly in the Pokédex when the normal form had not been unlocked.
- Fixed Pokémon occasionally being shot into the sky during battle. No Pokémon were harmed by this bug, probably. - Fixed Pokémon occasionally being shot into the sky during battle.
- Fixed NPC editing GUI not updating aspects until a game restart. - Fixed NPC editing GUI not updating aspects until a game restart.
- Fixed some users being unable to open their PC if a Pokémon in it had a lot of PP raises beyond normal bounds. How did you get those, anyway? Tell me or the Bellossom gets it. - Fix some users being unable to open their PC if a Pokémon in said PC had a lot of pp raises beyond normal bounds
- Fixed some color variants (Dubwool, Conkeldurr and Undyed wooloo) being missing in the Pokédex. - Fix some color variants (dubwool, conkeldurr and undyed wooloo) missing in the Pokédex
- Fixed invalid species or held items causing Players to not be able to load into their world anymore (commonly happening after removing addons/mods). - Fix invalid species or held_items causing Players to not be able to load into their world anymore (commonly happening after removing addons/mods)
- Fixed Wooloo variants not being automatically registered in the owner's Pokédex when dyed. - Fixed Wooloo variants not being automatically registered in the owner's Pokédex when dyed.
- Fixed Vivichoke Dip and Leek & Potato Stew not returning a bowl upon consumption. - Fixed Vivichoke Dip and Leek and Potato Stew not returning a bowl upon consumption.
- Fixed Fossil Restoration Tank not accepting Hay Bales as organic material. - Fixed Fossil Restoration Machine not accepting Hay Bales.
- Fixed Potion items applying double their intended healing value. - Fixed Potion items so that they no longer apply over double their intended healing value.
- Fixed Fast Ball capture bonuses applying to all Pokémon, making it the Best Ball instead of the Mediocre Edge-Case Ball.
- Fixed "learned new move" messages appearing for already-known moves on Pokémon evolutions.
- Fixed Pokémon Item Models breaking shadows nearby when being placed in Display Cases or Item Frames.
- Fixed berries not giving bonus yields when planted in their preferred biomes. I'm sure we've fixed that 5 times now.
- Fixed the NeoForge version not supporting "SodiumDynamicLights".
- Fixed players disconnecting from servers if they made changes to certain config options.
- Fixed players with shouldered Pokémon not being able to rejoin their 1.5.2 worlds using 1.6.
- Fixed `PokemonProperties` utilizing `ability=<some ability>` being treated as a forced ability even when it is a legal ability for the Pokémon.
- Fixed type formatting in Pokédex scanner mode when dual types require two lines.
- Fixed trading sometimes crashing the game or server.
- Fixed Wild shiny sounds not respecting the `shinyNoticeParticlesDistance` config setting.
- Fixed Pokémon being able to evolve mid-battle.
- Fixed NPC held items being able to be stolen by players. Don't be a thief!
- Fixed evolutions that require a held item consuming it as soon as meeting requirements when it should only be consumed upon evolution.
- Fixed Pokémon showing only the default form when selecting them as a target in battle.
- Fixed a possible error coming out of reeling fishing rods in specific situations.
- Fixed incorrect weights being used when Poké Fishing with Luck of the Sea.
- Parametric particle motion now works.
- Event-spawned particles now work.
- Particles can now have independent coordinate spaces.
### Developer ### Molang & Datapacks
- Updated the Pokédex data updated events to always include a `Pokemon` instance, and optionally a `DisguiseData` instance.
- Updated fields in `SpawnNPCPacket` and `SpawnPokemonPacket` to be visible and mutable.
- Updated `UnvalidatedPlaySoundS2CPacket` to be public instead of internal and made its fields mutable.
- 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
- Added flows for: - Added flows for:
- `forme_change`: Triggered when a Pokémon changes form in battle. - `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) - `mega_evolution`: Triggered when a Pokémon mega evolves in battle. (Note: Third party mods are required for this feature currently)
- `zpower_used`: Triggered when a Pokémon uses a Z-Power move in battle. (Note: Third-party mods are required for this feature currently) - `zpower_used`: Triggered when a Pokémon uses a Z-Power move in battle. (Note: Third party mods are required for this feature currently)
- `terastallization`: Triggered when a Pokémon terastallizes in battle. (Note: Third-party mods are required for this feature currently) - `terastallization`: Triggered when a Pokémon terastallizes in battle. (Note: Third party mods are required for this feature currently)
- `battle_fainted`: Triggered when a Pokémon faints in battle. - `battle_fainted`: Triggered when a Pokémon faints in battle.
- `battle_fled`: Triggered when a player flees from battle. - `battle_fled`: Triggered when a Player flees from battle.
- `battle_started_pre`: Triggered when a battle starts. Cancelable! - `battle_started_pre`: Triggered when a battle starts. Cancelable!
- `battle_started_post`: Triggered when a battle starts. - `battle_started_post`: Triggered when a battle starts.
- `apricorn_harvested`: Triggered when an Apricorn is harvested. - `apricorn_harvested`: Triggered when an apricorn is harvested.
- `thrown_pokeball_hit`: Triggered when a thrown Pokéball hits a Pokémon. - `thrown_pokeball_hit`: Triggered when a thrown Pokéball hits a Pokémon.
- `level_up`: Triggered when a Pokémon levels up. - `level_up`: Triggered when a Pokémon levels up.
- `pokemon_fainted`: Triggered when a Pokémon faints. - `pokemon_fainted`: Triggered when a Pokémon faints.
- `pokemon_gained`: Triggered when a player gains a Pokémon. - `pokemon_gained`: Triggered when a Player gains a Pokémon.
- Added MoLang functions: - Added molang functions:
- For Pokémon: - For Pokémon:
- `pokemon.apply(PokemonProperties)`: Applies the given properties to the Pokémon. - `pokemon.apply(PokemonProperties)`: Applies the given properties to the Pokémon.
- `pokemon.owner`: Returns the owner of the Pokémon or 0.0 if there is no owner or they are not online. - `pokemon.owner`: Returns the owner of the Pokémon or 0.0 if there is no owner or they are not online.
- For all entities:
- `entity.is_standing_on_blocks(depth, blocks...)`: Returns whether the specified entity is standing on a specific block or set of blocks. Example usage: `q.is_standing_on_blocks(2, minecraft:sand)`
- Added NPC field:
- `hideNameTag`: Hides the name tag of the NPC.
- Added `baseScale` property to NPCs.
- Added MoLang particle queries for getting distance to targeted entities.
## [1.6.0 - The Record Catch Update (December 25th, 2024)](#1-6-0) ## [1.6.0 - The Record Catch Update (December 25th, 2024)](#1-6-0)
#### "Now that there's a fishing mechanic, the mod is actually good!" #### "Now that there's a fishing mechanic, the mod is actually good!"
@@ -2175,3 +1986,4 @@ Thank you so much to all of our community translators that bring the mod to the
## [1.0.0 (November 12th, 2022)](#1-0-0) ## [1.0.0 (November 12th, 2022)](#1-0-0)
- Initial release. - Initial release.
+1 -1
View File
@@ -1,6 +1,6 @@
# Cobblemon # Cobblemon
An open-source Pokémon mod for Minecraft Java Edition, written in Kotlin for Fabric and NeoForge. An open-source Pokémon mod for Minecraft Java Edition, written in Kotlin for Fabric and Forge.
## Getting started ## Getting started
+27
View File
@@ -0,0 +1,27 @@
plugins {
id("java-gradle-plugin")
kotlin("jvm") version "2.1.0"
}
repositories {
mavenCentral()
gradlePluginPortal()
maven("https://maven.architectury.dev/")
maven("https://maven.fabricmc.net/")
}
dependencies {
implementation("net.neoforged:moddev-gradle:2.0.75")
implementation("dev.architectury:at:1.0.1")
implementation("net.fabricmc:access-widener:2.1.0")
}
gradlePlugin {
plugins {
create("cobblemongradle") {
id = "com.cobblemon.gradle"
implementationClass = "com.cobblemon.gradle.CobblemonGradle"
version = "1.0.0"
}
}
}
+7
View File
@@ -0,0 +1,7 @@
dependencyResolutionManagement {
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
}
@@ -0,0 +1,85 @@
package com.cobblemon.gradle
import com.cobblemon.gradle.extension.CobblemonGradleExtension
import com.cobblemon.gradle.extension.tasks.ConvertAccessWidenersTask
import com.cobblemon.gradle.extension.tasks.UnzipAccessWidenersTask
import net.neoforged.nfrtgradle.CreateMinecraftArtifacts
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.attributes.LibraryElements
import org.gradle.language.jvm.tasks.ProcessResources
class CobblemonGradle : Plugin<Project> {
override fun apply(project: Project) {
val cobblemonExtension = project.extensions.create(
CobblemonGradleExtension.EXTENSION_NAME,
CobblemonGradleExtension::class.java
)
//This exists because all of
// - com.cobblemon:mod
// - com.cobblemon:mod-resources
// - com.cobblemon:accesswidener
//technically point to the same dependency (the :common project). To pick the proper artifact from that project
//we set attributes in that project and check for them here.
val accessWideners = project.configurations.register("accessWidener") { configuration ->
configuration.isCanBeConsumed = false
configuration.isCanBeResolved = true
configuration.isCanBeDeclared = true
configuration.attributes {
it.attribute(
LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE,
project.objects.named(LibraryElements::class.java, LibraryElements.OBJECTS)
)
}
}
val includeRootResources = project.configurations.register("includeRootResources") { configuration ->
configuration.isCanBeConsumed = false
configuration.isCanBeResolved = true
configuration.isCanBeDeclared = true
configuration.attributes {
it.attribute(
LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE,
project.objects.named(LibraryElements::class.java, LibraryElements.RESOURCES)
)
}
}
val unzipAwTask = project.tasks.register("unzipAccessWideners", UnzipAccessWidenersTask::class.java) {
it.accessWidenerZips = accessWideners.get()
}
val convertAwTask = project.tasks.register(ConvertAccessWidenersTask.NAME, ConvertAccessWidenersTask::class.java) {
it.enabled = cobblemonExtension.convertAccessWideners
it.dependsOn(unzipAwTask)
it.accessWideners = project.files(unzipAwTask).plus(project.files(cobblemonExtension.additionalAccessWideners))
}
//Add root resources and access wideners to output jar
project.tasks.named("processResources", ProcessResources::class.java) { task ->
task.dependsOn(includeRootResources)
if (cobblemonExtension.convertAccessWideners) {
task.dependsOn(convertAwTask)
task.from(convertAwTask)
}
else {
task.dependsOn(unzipAwTask)
task.from(unzipAwTask)
}
task.doLast {
project.copy {
it.from(project.provider {
includeRootResources.get().resolve().map { project.zipTree(it) }
})
it.into(task.destinationDir)
}
}
}
project.tasks.withType(CreateMinecraftArtifacts::class.java) {
it.dependsOn(convertAwTask)
it.accessTransformers.from(convertAwTask)
}
}
}
@@ -0,0 +1,12 @@
package com.cobblemon.gradle.extension
import org.gradle.api.file.FileCollection
abstract class CobblemonGradleExtension {
var additionalAccessWideners: FileCollection? = null
var convertAccessWideners = true
companion object {
const val EXTENSION_NAME = "cobblemon"
}
}
@@ -0,0 +1,82 @@
package com.cobblemon.gradle.extension.tasks
import dev.architectury.at.AccessChange
import dev.architectury.at.AccessTransform
import dev.architectury.at.AccessTransformSet
import dev.architectury.at.ModifierChange
import dev.architectury.at.io.AccessTransformFormats
import net.fabricmc.accesswidener.AccessWidenerReader
import net.fabricmc.accesswidener.AccessWidenerVisitor
import org.cadixdev.bombe.type.signature.MethodSignature
import org.gradle.api.DefaultTask
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.OutputFiles
import org.gradle.api.tasks.TaskAction
import java.io.Writer
import java.nio.file.Files
abstract class ConvertAccessWidenersTask : DefaultTask() {
abstract var accessWideners: FileCollection
@InputFiles get
@Internal
val accessTransformerDir = project.layout.buildDirectory.dir("access-transformers")
@OutputFiles
val accessTransformers = project.files ({
accessWideners.files.map {
accessTransformerDir.get().file(it.name.replace("accesswidener", "accesstransformer.cfg"))
}
})
@TaskAction
fun convertAccessWideners() {
accessWideners.files.forEach { file ->
val awFile = Files.newBufferedReader(file.toPath())
val result = AccessTransformSet.create();
AccessWidenerReader(object : AccessWidenerVisitor {
override fun visitClass(name: String, access: AccessWidenerReader.AccessType, transitive: Boolean) {
result.getOrCreateClass(name).merge(toAt(access));
}
override fun visitMethod(owner: String, name: String, descriptor: String, access: AccessWidenerReader.AccessType, transitive: Boolean) {
result.getOrCreateClass(owner).mergeMethod(MethodSignature.of(name, descriptor), toAt(access));
}
override fun visitField(owner: String, name: String, descriptor: String, access: AccessWidenerReader.AccessType, transitive: Boolean) {
result.getOrCreateClass(owner).mergeField(name, toAt(access));
}
}).read(awFile)
val outputFile = accessTransformerDir.get().file(
file.name.replace("accesswidener", "accesstransformer.cfg")
)
var outputWriter: Writer? = null
try {
outputWriter = outputFile.asFile.writer()
AccessTransformFormats.FML.write(outputWriter, result)
}
finally {
outputWriter?.flush()
outputWriter?.close()
}
}
}
private fun toAt(access: AccessWidenerReader.AccessType): AccessTransform {
return when (access) {
AccessWidenerReader.AccessType.ACCESSIBLE -> AccessTransform.of(AccessChange.PUBLIC)
AccessWidenerReader.AccessType.EXTENDABLE, AccessWidenerReader.AccessType.MUTABLE -> AccessTransform.of(
AccessChange.PUBLIC,
ModifierChange.REMOVE
)
}
}
companion object {
const val NAME = "convertAccessWideners"
}
}
@@ -0,0 +1,33 @@
package com.cobblemon.gradle.extension.tasks
import org.gradle.api.DefaultTask
import org.gradle.api.Task
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.OutputFiles
import org.gradle.api.tasks.TaskAction
abstract class UnzipAccessWidenersTask : DefaultTask() {
abstract var accessWidenerZips: FileCollection
@InputFiles get
@OutputFiles
val outputFiles = project.provider {
project.files(accessWidenerZips.flatMap { zip ->
project.zipTree(zip).files.map { OUTPUT_DIR.get().file(it.name) }
})
}
@Internal
val OUTPUT_DIR = project.layout.buildDirectory.dir("cobblemon-working/access-wideners")
@TaskAction
fun run() {
project.copy {
it.from(accessWidenerZips.map(project::zipTree))
it.into(OUTPUT_DIR)
}
}
}
+3 -1
View File
@@ -1,12 +1,14 @@
plugins { plugins {
id("cobblemon.root-conventions") //id("cobblemon.root-conventions")
id ("net.nemerosa.versioning") version "3.1.0" id ("net.nemerosa.versioning") version "3.1.0"
} }
version = "${project.property("mod_version")}+${project.property("mc_version")}" version = "${project.property("mod_version")}+${project.property("mc_version")}"
val isSnapshot = project.property("snapshot")?.equals("true") ?: false val isSnapshot = project.property("snapshot")?.equals("true") ?: false
/*
if (isSnapshot) { if (isSnapshot) {
val fixedBranchName = versioning.info.branch.substringAfter("/") val fixedBranchName = versioning.info.branch.substringAfter("/")
version = "$version-${fixedBranchName}-${versioning.info.build}" version = "$version-${fixedBranchName}-${versioning.info.build}"
} }
*/
+90 -54
View File
@@ -1,68 +1,102 @@
import java.time.OffsetDateTime
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import utilities.isSnapshot
import utilities.version
/*
*
* * 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/.
*
*/
plugins { plugins {
id("cobblemon.base-conventions") kotlin("jvm") version "2.1.0"
id("cobblemon.publish-conventions") id ("net.neoforged.moddev") version "2.0.75"
id("net.kyori.blossom") version "2.1.0"
id("net.kyori.blossom") id("com.github.johnrengelman.shadow") version "8.1.1"
id("org.jetbrains.gradle.plugin.idea-ext") id("com.cobblemon.gradle")
id("net.nemerosa.versioning") version "3.1.0"
} }
architectury { cobblemon {
common("neoforge", "fabric") additionalAccessWideners = files(sourceSets.main.get().resources).filter { it.extension == "accesswidener" }
}
val rootResources = configurations.create("rootResources") {
isCanBeConsumed = true
isCanBeResolved = false
attributes {
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.RESOURCES))
}
}
val accessWidenerExport = configurations.create("accessWidenerExport") {
isCanBeConsumed = true
isCanBeResolved = false
attributes {
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.OBJECTS))
}
}
tasks.processResources {
exclude("*.accesswidener")
}
tasks.create<Zip>("zipResources") {
dependsOn("processResources")
from(tasks.processResources.get().destinationDir)
this.archiveBaseName = "mod-resources"
}
tasks.create<Zip>("zipAccessWideners") {
from(sourceSets.main.get().resources)
include("*.accesswidener")
this.archiveBaseName = "mod-accesswideners"
}
tasks.jar {
archiveBaseName = "mod"
manifest {
attributes(mapOf("FMLModType" to "GAMELIBRARY"))
}
exclude {
it.file in tasks.processResources.get().outputs.files
}
}
tasks.assemble {
dependsOn(tasks.named("zipResources"))
dependsOn(tasks.named("zipAccessWideners"))
}
artifacts {
add("rootResources", tasks.getByName<Zip>("zipResources"))
add("accessWidenerExport", tasks.getByName("zipAccessWideners"))
}
buildscript {
repositories {
mavenCentral()
gradlePluginPortal()
maven("https://maven.architectury.dev/")
maven("https://maven.fabricmc.net/")
}
} }
repositories { repositories {
maven(url = "${rootProject.projectDir}/deps") mavenCentral()
maven(url = "https://api.modrinth.com/maven") maven("https://maven.fabricmc.net/")
maven(url = "https://maven.neoforged.net/releases") maven("https://maven.blamejared.com/")
mavenLocal() maven("https://api.modrinth.com/maven")
maven(url = "../deps")
} }
dependencies { dependencies {
implementation(libs.bundles.kotlin) compileOnly(libs.bundles.mongo)
modImplementation(libs.fabric.loader) compileOnly(libs.bundles.kotlin)
modApi(libs.molang) compileOnly(libs.molang)
compileOnly(libs.graal)
// Integrations compileOnly(libs.jei.api)
compileOnlyApi(libs.jei.api) compileOnly(libs.bundles.fabric.integrations.compileOnly) {
modCompileOnly(libs.bundles.common.integrations.compileOnly) {
isTransitive = false isTransitive = false
} }
// Flywheel has no common dep so just pick one and don't use any platform specific code in common compileOnly("net.fabricmc:sponge-mixin:0.15.5+mixin.0.8.7")
// modCompileOnly(libs.flywheelFabric) compileOnly("io.github.llamalad7:mixinextras-fabric:0.4.1")
// Showdown
modCompileOnly(libs.graal)
// Data Storage
modCompileOnly(libs.bundles.mongo)
// Unit Testing
testImplementation(libs.bundles.unitTesting) testImplementation(libs.bundles.unitTesting)
} }
tasks.withType<Test> { neoForge {
useJUnitPlatform() neoFormVersion = "1.21.1-20240808.144430"
testLogging { interfaceInjectionData.from("src/main/resources/interfaces.json")
setEvents(listOf("failed")) validateAccessTransformers = true
setExceptionFormat("full")
}
} }
sourceSets { sourceSets {
@@ -72,7 +106,7 @@ sourceSets {
fun generateLicenseHeader() : String { fun generateLicenseHeader() : String {
val builder = StringBuilder() val builder = StringBuilder()
builder.append("/*\n") builder.append("/*\n")
rootProject.file("HEADER").forEachLine { project.projectDir.parentFile.resolve("HEADER").forEachLine {
if(it.isEmpty()) { if(it.isEmpty()) {
builder.append(" *").append("\n") builder.append(" *").append("\n")
} else { } else {
@@ -85,12 +119,14 @@ sourceSets {
property("license", generateLicenseHeader()) property("license", generateLicenseHeader())
property("modid", "cobblemon") property("modid", "cobblemon")
property("version", project.version()) property("version", project.version as String)
property("isSnapshot", if(rootProject.isSnapshot()) "true" else "false") property("isSnapshot", "true")
/*
property("gitCommit", versioning.info.commit) property("gitCommit", versioning.info.commit)
property("branch", versioning.info.branch) property("branch", versioning.info.branch)
System.getProperty("buildNumber")?.let { property("buildNumber", it) } System.getProperty("buildNumber")?.let { property("buildNumber", it) }
property("timestamp", OffsetDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss")) + " UTC") property("timestamp", OffsetDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss")) + " UTC")
*/
} }
} }
} }
+97
View File
@@ -0,0 +1,97 @@
import java.time.OffsetDateTime
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import utilities.isSnapshot
import utilities.version
/*
*
* * 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/.
*
*/
plugins {
id("cobblemon.base-conventions")
id("cobblemon.publish-conventions")
id("net.kyori.blossom")
id("org.jetbrains.gradle.plugin.idea-ext")
id("net.nemerosa.versioning") version "3.1.0"
}
architectury {
common("neoforge", "fabric")
}
repositories {
maven(url = "${rootProject.projectDir}/deps")
maven(url = "https://api.modrinth.com/maven")
maven(url = "https://maven.neoforged.net/releases")
mavenLocal()
}
dependencies {
implementation(libs.bundles.kotlin)
modImplementation(libs.fabric.loader)
modApi(libs.molang)
// Integrations
compileOnlyApi(libs.jei.api)
modCompileOnly(libs.bundles.fabric.integrations.compileOnly) {
isTransitive = false
}
// Flywheel has no common dep so just pick one and don't use any platform specific code in common
// modCompileOnly(libs.flywheelFabric)
// Showdown
modCompileOnly(libs.graal)
// Data Storage
modCompileOnly(libs.bundles.mongo)
// Unit Testing
testImplementation(libs.bundles.unitTesting)
}
tasks.withType<Test> {
useJUnitPlatform()
testLogging {
setEvents(listOf("failed"))
setExceptionFormat("full")
}
}
sourceSets {
main {
blossom {
kotlinSources {
fun generateLicenseHeader() : String {
val builder = StringBuilder()
builder.append("/*\n")
rootProject.file("HEADER").forEachLine {
if(it.isEmpty()) {
builder.append(" *").append("\n")
} else {
builder.append(" * ").append(it).append("\n")
}
}
return builder.append(" */").append("\n").toString()
}
property("license", generateLicenseHeader())
property("modid", "cobblemon")
property("version", project.version())
property("isSnapshot", if(rootProject.isSnapshot()) "true" else "false")
property("gitCommit", versioning.info.commit)
property("branch", versioning.info.branch)
System.getProperty("buildNumber")?.let { property("buildNumber", it) }
property("timestamp", OffsetDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss")) + " UTC")
}
}
}
}
+95
View File
@@ -0,0 +1,95 @@
[versions]
# Kotlin
kotlin = "2.0.0"
# Plugins
licenser = "0.6.1"
shadow = "8.1.1"
blossom = "2.1.0"
idea-ext = "1.1.7"
# Loom
loom = "1.7-SNAPSHOT"
architectury-plugin = "3.4-SNAPSHOT"
# Common
molang = "1.1.18"
graal = "22.3.0"
icu4j = "71.1"
jei-api = "19.8.2.99"
# Fabric
fabric-loader = "0.16.5"
fabric-api = "0.104.0+1.21.1"
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"
# NeoForge
neoforge = "21.1.66"
neo-kotlin-for-forge = "5.5.0"
debugutils-forge = "1.21-1.0.6-neoforge"
# Data Storage
mongo = "4.10.2"
# Testing
junit = "5.9.0"
mockito = "5.2.0"
mockk = "1.12.1"
classgraph = "4.8.153"
[libraries]
# General Buildscript Plugins
kotlin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" }
loom = { group = "dev.architectury", name = "architectury-loom", version.ref = "loom" }
architectury = { group = "architectury-plugin", name = "architectury-plugin.gradle.plugin", version.ref = "architectury-plugin" }
shadow = { group = "com.github.johnrengelman", name = "shadow", version.ref = "shadow" }
blossom = { group = "net.kyori", name = "blossom", version.ref = "blossom" }
ideaExt = { group = "org.jetbrains.gradle.plugin.idea-ext", name = "org.jetbrains.gradle.plugin.idea-ext.gradle.plugin", version.ref = "idea-ext"}
licenser = { group = "gradle.plugin.org.cadixdev.gradle", name = "licenser", version.ref = "licenser" }
# Kotlin
kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk8", version.ref = "kotlin" }
kotlin-reflect = { group = "org.jetbrains.kotlin", name = "kotlin-reflect", version.ref = "kotlin" }
# Common
jei-api = { group = "mezz.jei", name = "jei-1.21-common-api", version.ref = "jei-api"}
molang = { group = "local.com.bedrockk", name = "molang", version.ref = "molang" }
graal = { group = "org.graalvm.js", name = "js", version.ref = "graal" }
icu4j = { group = "com.ibm.icu", name = "icu4j", version.ref = "icu4j" }
# Fabric
fabric-loader = { group = "net.fabricmc", name = "fabric-loader", version.ref = "fabric-loader" }
fabric-api = { group = "net.fabricmc.fabric-api", name = "fabric-api", version.ref = "fabric-api" }
fabric-kotlin = { group = "net.fabricmc", name = "fabric-language-kotlin", version.ref = "fabric-kotlin" }
fabric-permissions = { group = "me.lucko", name = "fabric-permissions-api", version.ref = "fabric-permissions-api" }
adorn-fabric = { group = "maven.modrinth", name = "adorn", version = "6.0.0-neoforge"}
lambDynamicLights = { group = "maven.modrinth", name = "lambdynamiclights", version.ref = "lambDynamicLights"}
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"}
# NeoForge
neoforge = { group = "net.neoforged", name = "neoforge", version.ref = "neoforge" }
neo-kotlin-forge = { group = "thedarkcolour", name = "kotlinforforge-neoforge", version.ref = "neo-kotlin-for-forge" }
neoforge-debugutils = { group = "maven.modrinth", name = "debugutils", version.ref = "debugutils-forge"}
# Data Storage
mongo-driver-core = { group = "org.mongodb", name = "mongodb-driver-core", version.ref = "mongo" }
mongo-driver-sync = { group = "org.mongodb", name = "mongodb-driver-sync", version.ref = "mongo" }
# Testing
junit = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junit" }
mockito-core = { group = "org.mockito", name = "mockito-core", version.ref = "mockito" }
mock-kotlin = { group = "io.mockk", name = "mockk", version.ref = "mockk" }
classgraph = { group = "io.github.classgraph", name = "classgraph", version.ref = "classgraph" }
[bundles]
kotlin = [ "kotlin-stdlib", "kotlin-reflect" ]
fabric = [ "fabric-kotlin", "fabric-permissions" ]
fabric-integrations-compileOnly = [ "adorn-fabric", "lambDynamicLights", "jei-api-fabric" ]
fabric-integrations-runtimeOnly = [ "jei-fabric" ]
mongo = [ "mongo-driver-core", "mongo-driver-sync" ]
unitTesting = [ "junit", "mockito-core", "mock-kotlin", "classgraph" ]
@@ -1,124 +0,0 @@
/*
* 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;
import net.minecraft.util.Mth;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix3f;
import org.joml.Vector3f;
import java.util.function.Function;
public interface Rollable {
// From Minecraft's Camera
Vector3f FORWARDS = new Vector3f(0.0F, 0.0F, -1.0F);
Vector3f UP = new Vector3f(0.0F, 1.0F, 0.0F);
Vector3f LEFT = new Vector3f(-1.0F, 0.0F, 0.0F);
@Nullable Matrix3f getOrientation();
Rollable updateOrientation(Function<Matrix3f, Matrix3f> update);
/**
* @return The forward vector (0, 0, -1) after the rotation matrix is applied.
*/
default Vector3f getForwardVector() {
if (getOrientation() == null) return new Vector3f(FORWARDS);
return getOrientation().transform(FORWARDS, new Vector3f());
}
/**
* @return The left vector (-1, 0, 0) after the rotation matrix is applied.
*/
default Vector3f getLeftVector() {
if (getOrientation() == null) return new Vector3f(LEFT);
return getOrientation().transform(LEFT, new Vector3f());
}
/**
* @return The up vector (0, 1, 0) after the rotation matrix is applied.
*/
default Vector3f getUpVector() {
if (getOrientation() == null) return new Vector3f(UP);
return getOrientation().transform(UP, new Vector3f());
}
/**
*
* @param yaw change in degrees
* @return The Rollable object this method was called on
*/
default Rollable rotateYaw(float yaw) {
return updateOrientation(prev -> prev.rotateY((float) Math.toRadians(-yaw)));
}
/**
*
* @param pitch change in degrees
* @return The Rollable object this method was called on
*/
default Rollable rotatePitch(float pitch) {
return updateOrientation(prev -> prev.rotateX((float) Math.toRadians(-pitch)));
}
/**
*
* @param roll change in degrees
* @return The Rollable object this method was called on
*/
default Rollable rotateRoll(float roll) {
return updateOrientation(prev -> prev.rotateZ((float) Math.toRadians(-roll)));
}
/**
* Order matters when rotating an object. If you need a different order, individually call rotateYaw, rotatePitch, and rotateRoll
*
* @param yaw change in degrees
* @param pitch change in degrees
* @param roll change in degrees
* @return The Rollable object this method was called on
*/
default Rollable rotate(float yaw, float pitch, float roll) {
return rotateYaw(yaw).rotatePitch(pitch).rotateRoll(roll);
}
/**
* @return The pitch angle in degrees as a float.
* Value is between [-180, 180] with 0 being South, 90 being West, 180/-180 being North, and -90 being East
*/
default float getYaw() {
return (float) Mth.wrapDegrees(-Math.toDegrees(FORWARDS.angleSigned(getForwardVector(), UP)) + 180);
}
/**
* @return The yaw angle in degrees as a float.
* Value is between [-90, 90] with 0 being straight forward, 90 being straight down, and -90 being straight up
*/
default float getPitch() {
return (float) Mth.wrapDegrees(-Math.toDegrees(Math.asin(getForwardVector().y)));
}
/**
* @return The roll angle in degrees as a float.
* Value is between [-180, 180] with 0 being no roll (normal), 90 being 90 degrees CW, 180/-180 being 180 degrees CW/CCW, and -90 being 90 degrees CCW
*/
default float getRoll() {
//Cobblemon.LOGGER.info("{}", (float) Math.toDegrees(getUpVector().angleSigned(UP, getForwardVector())));
return (float) Mth.wrapDegrees(-Math.toDegrees(getUpVector().angleSigned(UP, getForwardVector())));
}
boolean shouldRoll();
void clearRotation();
}
@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package com.cobblemon.mod.common.mixin.client; package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.api.scheduling.ClientTaskTracker; import com.cobblemon.mod.common.api.scheduling.ClientTaskTracker;
import net.minecraft.client.DeltaTracker; import net.minecraft.client.DeltaTracker;
@@ -6,22 +6,18 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package com.cobblemon.mod.common.mixin.client; package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.Rollable;
import com.cobblemon.mod.common.item.PokedexItem; import com.cobblemon.mod.common.item.PokedexItem;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.AbstractClientPlayer; import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.renderer.ItemInHandRenderer; import net.minecraft.client.renderer.ItemInHandRenderer;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import org.joml.Quaternionf;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ItemInHandRenderer.class) @Mixin(ItemInHandRenderer.class)
@@ -31,15 +27,5 @@ public class ItemInHandRendererMixin {
if (abstractClientPlayer.isUsingItem() && abstractClientPlayer.getUseItem().getItem() instanceof PokedexItem) { if (abstractClientPlayer.isUsingItem() && abstractClientPlayer.getUseItem().getItem() instanceof PokedexItem) {
ci.cancel(); ci.cancel();
} }
else if (abstractClientPlayer instanceof Rollable rollable && rollable.shouldRoll()) {
}
}
@Redirect(method = "renderHandsWithItems", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;mulPose(Lorg/joml/Quaternionf;)V", ordinal = 1))
private void cobblemon$renderHandswithItems(PoseStack instance, Quaternionf quaternion) {
if (!(Minecraft.getInstance().player instanceof Rollable rollable && rollable.shouldRoll())) {
instance.mulPose(quaternion);
}
} }
} }
@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package com.cobblemon.mod.common.mixin.client; package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.Cobblemon; import com.cobblemon.mod.common.Cobblemon;
import com.cobblemon.mod.common.ModAPI; import com.cobblemon.mod.common.ModAPI;
@@ -40,8 +40,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
*/ */
@Mixin(ItemRenderer.class) @Mixin(ItemRenderer.class)
public abstract class ItemRendererMixin { public abstract class ItemRendererMixin {
// ignore the hint saying implmentation is never null, if something crashes then it is null and causes red herrings @Unique private final String MODEL_PATH = Cobblemon.implementation.getModAPI() == ModAPI.FABRIC ? "fabric_resource" : "standalone";
@Unique private final String MODEL_PATH = (Cobblemon.implementation != null && Cobblemon.implementation.getModAPI() == ModAPI.FABRIC) ? "fabric_resource" : "standalone";
@Shadow @Final private ItemModelShaper itemModelShaper; @Shadow @Final private ItemModelShaper itemModelShaper;
@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package com.cobblemon.mod.common.mixin.client; package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.client.CobblemonBakingOverrides; import com.cobblemon.mod.common.client.CobblemonBakingOverrides;
import java.util.List; import java.util.List;
@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package com.cobblemon.mod.common.mixin.client; package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Bone; import com.cobblemon.mod.common.client.render.models.blockbench.pose.Bone;
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext; import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext;
@@ -6,9 +6,8 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package com.cobblemon.mod.common.mixin.client; package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.Rollable;
import com.cobblemon.mod.common.client.CobblemonClient; import com.cobblemon.mod.common.client.CobblemonClient;
import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding; import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding;
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext; import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext;
@@ -23,18 +22,16 @@ import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(MouseHandler.class) @Mixin(MouseHandler.class)
public class MouseHandlerMixin { public class MouseHandlerMixin {
@Shadow private double accumulatedScrollY; @Shadow
@Shadow @Final private Minecraft minecraft; private double accumulatedScrollY;
@Unique SmoothDouble pitchSmoother = new SmoothDouble(); @Shadow @Final private Minecraft minecraft;
@Unique SmoothDouble rollSmoother = new SmoothDouble();
@Shadow @Final private SmoothDouble smoothTurnY; @Shadow @Final private SmoothDouble smoothTurnY;
@@ -96,6 +93,7 @@ public class MouseHandlerMixin {
) )
) )
public boolean cobblemon$modifyRotation(LocalPlayer player, double cursorDeltaX, double cursorDeltaY, @Local(argsOnly = true) double d) { public boolean cobblemon$modifyRotation(LocalPlayer player, double cursorDeltaX, double cursorDeltaY, @Local(argsOnly = true) double d) {
// I know this technically doesn't need to be a WrapWithCondition, but it'll make things easier later for riding.
PokedexUsageContext usageContext = CobblemonClient.INSTANCE.getPokedexUsageContext(); PokedexUsageContext usageContext = CobblemonClient.INSTANCE.getPokedexUsageContext();
if (usageContext.getScanningGuiOpen()) { if (usageContext.getScanningGuiOpen()) {
this.smoothTurnY.reset(); this.smoothTurnY.reset();
@@ -107,30 +105,7 @@ public class MouseHandlerMixin {
player.turn(this.accumulatedDX * sensitivity, (this.accumulatedDY * sensitivity)); player.turn(this.accumulatedDX * sensitivity, (this.accumulatedDY * sensitivity));
return false; return false;
} }
return true;
if (!(player instanceof Rollable rollable)) return true;
if (!rollable.shouldRoll()) {
pitchSmoother.reset();
rollSmoother.reset();
return true;
}
var pitch = pitchSmoother.getNewDeltaValue(cursorDeltaY * 0.15f, d);
var roll = rollSmoother.getNewDeltaValue(cursorDeltaX * 0.15f, d);
rollable.rotate(0.0F, (float)pitch, (float)roll);
return false;
}
@Inject(method = "handleAccumulatedMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MouseHandler;isMouseGrabbed()Z", ordinal = 0))
private void cobblemon$maintainMovementWhenInScreens(CallbackInfo ci, @Local(ordinal = 1) double e) {
if (minecraft.player == null) return;
if (!(minecraft.player instanceof Rollable rollable)) return;
if (!rollable.shouldRoll()) return;
if (minecraft.isPaused()) return;
var pitch = pitchSmoother.getNewDeltaValue(0, e);
var roll = rollSmoother.getNewDeltaValue(0, e);
rollable.rotate(0.0F, (float)pitch, (float)roll);
} }
} }
@@ -10,15 +10,11 @@ package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.Cobblemon; import com.cobblemon.mod.common.Cobblemon;
import com.cobblemon.mod.common.CobblemonItems; import com.cobblemon.mod.common.CobblemonItems;
import com.cobblemon.mod.common.Rollable;
import com.cobblemon.mod.common.api.events.CobblemonEvents; import com.cobblemon.mod.common.api.events.CobblemonEvents;
import com.cobblemon.mod.common.api.events.item.LeftoversCreatedEvent; import com.cobblemon.mod.common.api.events.item.LeftoversCreatedEvent;
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies; import com.cobblemon.mod.common.api.pokemon.PokemonSpecies;
import com.cobblemon.mod.common.api.riding.Rideable;
import com.cobblemon.mod.common.api.storage.party.PartyStore; import com.cobblemon.mod.common.api.storage.party.PartyStore;
import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore;
import com.cobblemon.mod.common.api.tags.CobblemonItemTags; import com.cobblemon.mod.common.api.tags.CobblemonItemTags;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData; import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData;
import com.cobblemon.mod.common.pokedex.scanner.ScannableEntity; import com.cobblemon.mod.common.pokedex.scanner.ScannableEntity;
import com.cobblemon.mod.common.pokemon.FormData; import com.cobblemon.mod.common.pokemon.FormData;
@@ -29,10 +25,6 @@ import com.cobblemon.mod.common.util.CompoundTagExtensionsKt;
import com.cobblemon.mod.common.util.CompoundTagUtilities; import com.cobblemon.mod.common.util.CompoundTagUtilities;
import com.cobblemon.mod.common.util.DataKeys; import com.cobblemon.mod.common.util.DataKeys;
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules; import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag; import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
@@ -45,10 +37,8 @@ import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.food.FoodProperties; import net.minecraft.world.food.FoodProperties;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.joml.Matrix3f;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@@ -62,11 +52,10 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Mixin(Player.class) @Mixin(Player.class)
public abstract class PlayerMixin extends LivingEntity implements Rollable, ScannableEntity { public abstract class PlayerMixin extends LivingEntity implements ScannableEntity {
@Shadow public abstract CompoundTag getShoulderEntityLeft(); @Shadow public abstract CompoundTag getShoulderEntityLeft();
@@ -84,7 +73,6 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
@Shadow public abstract void displayClientMessage(Component message, boolean overlay); @Shadow public abstract void displayClientMessage(Component message, boolean overlay);
@Unique private Matrix3f orientation = null;
protected PlayerMixin(EntityType<? extends LivingEntity> p_20966_, Level p_20967_) { protected PlayerMixin(EntityType<? extends LivingEntity> p_20966_, Level p_20967_) {
super(p_20966_, p_20967_); super(p_20966_, p_20967_);
@@ -178,7 +166,8 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
@Inject(method = "isInvulnerableTo", at = @At("HEAD"), cancellable = true) @Inject(method = "isInvulnerableTo", at = @At("HEAD"), cancellable = true)
public void isInvulnerableTo(DamageSource source, CallbackInfoReturnable<Boolean> ci) { public void isInvulnerableTo(DamageSource source, CallbackInfoReturnable<Boolean> ci) {
if (!level().isClientSide && (Object) this instanceof ServerPlayer player) { if (!level().isClientSide) {
ServerPlayer player = (ServerPlayer)(Object)this;
boolean invulnerableInBattle = this.level().getGameRules().getBoolean(CobblemonGameRules.BATTLE_INVULNERABILITY); boolean invulnerableInBattle = this.level().getGameRules().getBoolean(CobblemonGameRules.BATTLE_INVULNERABILITY);
boolean inBattle = Cobblemon.INSTANCE.getBattleRegistry().getBattleByParticipatingPlayer(player) != null; boolean inBattle = Cobblemon.INSTANCE.getBattleRegistry().getBattleByParticipatingPlayer(player) != null;
if (invulnerableInBattle && inBattle) { if (invulnerableInBattle && inBattle) {
@@ -189,10 +178,10 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
@Override @Nullable @Override @Nullable
public PokedexEntityData resolvePokemonScan() { public PokedexEntityData resolvePokemonScan() {
if (CompoundTagUtilities.isShoulderPokemon(this.getShoulderEntityRight())){ if(CompoundTagUtilities.isShoulderPokemon(this.getShoulderEntityRight())){
return getDataFromShoulderPokemon(this.getShoulderEntityRight()); return getDataFromShoulderPokemon(this.getShoulderEntityRight());
} }
if (CompoundTagUtilities.isShoulderPokemon(this.getShoulderEntityLeft())){ if(CompoundTagUtilities.isShoulderPokemon(this.getShoulderEntityLeft())){
return getDataFromShoulderPokemon(this.getShoulderEntityLeft()); return getDataFromShoulderPokemon(this.getShoulderEntityLeft());
} }
return null; return null;
@@ -201,115 +190,34 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
@Nullable @Unique @Nullable @Unique
private PokedexEntityData getDataFromShoulderPokemon(CompoundTag shoulderTag) { private PokedexEntityData getDataFromShoulderPokemon(CompoundTag shoulderTag) {
CompoundTag pokemonTag = shoulderTag.getCompound(DataKeys.POKEMON); CompoundTag pokemonTag = shoulderTag.getCompound(DataKeys.POKEMON);
if (pokemonTag.isEmpty()) return null; if(pokemonTag.isEmpty()) return null;
Species species = PokemonSpecies.INSTANCE.getByIdentifier(ResourceLocation.parse(pokemonTag.getString(DataKeys.POKEMON_SPECIES_IDENTIFIER))); Species species = PokemonSpecies.INSTANCE.getByIdentifier(ResourceLocation.parse(pokemonTag.getString(DataKeys.POKEMON_SPECIES_IDENTIFIER)));
if (species == null) return null; if(species == null) return null;
String formId = pokemonTag.getString(DataKeys.POKEMON_FORM_ID); String formId = pokemonTag.getString(DataKeys.POKEMON_FORM_ID);
FormData form = species.getStandardForm(); FormData form = species.getStandardForm();
List<FormData> formList = species.getForms().stream().filter(it -> it.formOnlyShowdownId().equals(formId)).toList(); List<FormData> formList = species.getForms().stream().filter(it -> it.formOnlyShowdownId().equals(formId)).toList();
if (!formList.isEmpty()) form = formList.getFirst(); if(!formList.isEmpty()) form = formList.getFirst();
if (form == null) return null; if(form == null) return null;
String genderString = pokemonTag.getString(DataKeys.POKEMON_GENDER); String genderString = pokemonTag.getString(DataKeys.POKEMON_GENDER);
if (genderString.isEmpty()) return null; if(genderString.isEmpty()) return null;
Gender gender = Gender.valueOf(genderString); Gender gender = Gender.valueOf(genderString);
boolean shiny = pokemonTag.getBoolean(DataKeys.POKEMON_SHINY); boolean shiny = pokemonTag.getBoolean(DataKeys.POKEMON_SHINY);
int level = pokemonTag.getInt(DataKeys.POKEMON_LEVEL); int level = pokemonTag.getInt(DataKeys.POKEMON_LEVEL);
Set<String> aspects = shoulderTag.getList(DataKeys.SHOULDER_ASPECTS, Tag.TAG_STRING).stream().map(Tag::getAsString).collect(Collectors.toSet()); Set<String> aspects = shoulderTag.getList(DataKeys.SHOULDER_ASPECTS, Tag.TAG_STRING).stream().map(Tag::getAsString).collect(Collectors.toSet());
Pokemon pokemon = new Pokemon(); return new PokedexEntityData(
if (level().isClientSide) { species,
pokemon.setSpecies(species); form,
pokemon.setForm(form); gender,
pokemon.setGender(gender); aspects,
pokemon.setShiny(shiny); shiny,
pokemon.setLevel(level); level,
pokemon.setForcedAspects(aspects); this.getUUID()
} else { );
PlayerPartyStore party = Cobblemon.INSTANCE.getStorage().getParty(this.getUUID(), this.registryAccess());
pokemon = party.get(shoulderTag.getUUID(DataKeys.SHOULDER_UUID));
}
return new PokedexEntityData(pokemon, null);
} }
@Override @Override
public LivingEntity resolveEntityScan() { public LivingEntity resolveEntityScan() {
return this; return this;
} }
}
@Override
public void absMoveTo(double x, double y, double z, float yaw, float pitch) {
if (shouldRoll()) {
this.absMoveTo(x, y, z);
this.setYRot(yaw % 360.0f);
this.setXRot(pitch % 360.0f);
this.yRotO = this.getYRot();
this.xRotO = this.getXRot();
}
else {
this.absMoveTo(x, y, z);
this.absRotateTo(yaw, pitch);
}
}
@Inject(method = "tick", at = @At("HEAD"))
public void tick(CallbackInfo ci) {
if (this.shouldRoll()) {
// Proof of concept for yaw movement
if (this.getMainHandItem().is(Items.STICK)) {
this.rotateYaw(2);
}
else if (this.getMainHandItem().is(Items.BLAZE_ROD)) {
this.rotateYaw(-2);
}
}
}
@Override
public Matrix3f getOrientation() {
return orientation;
}
@Override
public Rollable updateOrientation(Function<Matrix3f, Matrix3f> update) {
if (!shouldRoll()) return this;
if (this.orientation == null) {
this.orientation = new Matrix3f();
this.rotate(getYRot() - 180, getXRot(), 0);
}
this.orientation = update.apply(this.orientation);
setYRot(this.getYaw());
setXRot(this.getPitch());
return this;
}
@Override
public boolean shouldRoll() {
LocalPlayer player = Minecraft.getInstance().player;
if (!this.equals(player)) return false;
if (player.isHolding(Items.DIAMOND)) return true;
var playerVehicle = player.getVehicle();
if (playerVehicle == null) return false;
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return false;
return pokemonEntity.getRiding().shouldRoll(pokemonEntity);
}
@Override
public void clearRotation() {
this.orientation = null;
}
@WrapOperation(
method = "rideTick()V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;wantsToStopRiding()Z")
)
public boolean delegateDismountToController(Player instance, Operation<Boolean> original) {
if (this.getVehicle() instanceof Rideable vehicle) {
return vehicle.getRiding().dismountOnShift() && original.call(instance);
}
return original.call(instance);
}
}
@@ -0,0 +1,28 @@
/*
* 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.mixin;
import com.cobblemon.mod.common.client.render.ClientPlayerIcon;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(PlayerRenderer.class)
public class PlayerRendererMixin {
@Inject(method = "render", at = @At(value = "TAIL"))
public void renderPlayer(AbstractClientPlayer player, float f, float g, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, CallbackInfo ci) {
ClientPlayerIcon.Companion.onRenderPlayer(player);
}
}
@@ -1,151 +0,0 @@
/*
* 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.mixin.client;
import com.cobblemon.mod.common.Rollable;
import com.cobblemon.mod.common.api.riding.Rideable;
import com.cobblemon.mod.common.api.riding.Seat;
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate;
import com.cobblemon.mod.common.client.render.MatrixWrapper;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.Vec3;
import org.joml.Matrix3f;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(Camera.class)
public abstract class CameraMixin {
@Shadow @Final private static float DEFAULT_CAMERA_DISTANCE;
@Shadow private Entity entity;
@Shadow @Final private Quaternionf rotation;
@Shadow @Final private Vector3f forwards;
@Shadow @Final private Vector3f up;
@Shadow @Final private Vector3f left;
@Shadow private float xRot;
@Shadow private float yRot;
@Shadow public abstract float getXRot();
@Shadow public abstract float getYRot();
@Shadow private Vec3 position;
@Shadow private float eyeHeight;
@Shadow private float eyeHeightOld;
@Unique private float returnTimer = 0;
@Unique private float rollAngleStart = 0;
@Unique Minecraft minecraft = Minecraft.getInstance();
@Unique boolean disableRollableCameraDebug = false;
@Inject(method = "setRotation", at = @At("HEAD"), cancellable = true)
public void open_camera$setRotation(float f, float g, CallbackInfo ci) {
if (!(this.entity instanceof Rollable rollable) || disableRollableCameraDebug) return;
if (!rollable.shouldRoll() && rollable.getOrientation() != null) {
if(this.returnTimer < 1) {
//Rotation is taken from entity since we no longer handle mouse ourselves
//Stops a period of time when you can't input anything.
rollable.getOrientation().set(
new Matrix3f()
.rotateY((float) Math.toRadians(180 - this.entity.getYRot()))
.rotateX((float) Math.toRadians(-this.entity.getXRot()))
);
if(rollAngleStart == 0){
this.returnTimer = 1;
rollable.clearRotation();
return;
}
rollable.getOrientation().rotateZ((float) Math.toRadians(-rollAngleStart*(1-returnTimer)));
applyRotation();
this.returnTimer += .05F;
ci.cancel();
} else {
this.returnTimer = 1;
rollable.clearRotation();
}
return;
}
if (rollable.getOrientation() == null) return;
applyRotation();
this.returnTimer = 0;
this.rollAngleStart = rollable.getRoll();
ci.cancel();
}
//If you want to move this to a delagate you need an AW for position
@WrapOperation(method = "setup", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Camera;setPosition(DDD)V"))
public void positionCamera(Camera instance, double x, double y, double z, Operation<Void> original){
Entity entity = instance.getEntity();
Entity vehicle = entity.getVehicle();
if(vehicle instanceof Rideable){
//RidingCameraDelagate.INSTANCE.positionCamera(instance, x, y, z, original);
if(!(vehicle instanceof PokemonEntity)){
original.call(instance, x, y, z);
return;
}
PokemonEntity pokemon = (PokemonEntity) vehicle;
int seatIndex = pokemon.getPassengers().indexOf(entity);
Seat seat = pokemon.getSeats().get(seatIndex);
PokemonClientDelegate delegate = (PokemonClientDelegate) pokemon.getDelegate();
MatrixWrapper locator = delegate.getLocatorStates().get(seat.getLocator());
if(locator == null){
original.call(instance, x, y, z);
return;
}
Vec3 locatorOffset = new Vec3(locator.getMatrix().getTranslation(new Vector3f()));
Vec3 entityPos = new Vec3(
Mth.lerp(instance.getPartialTickTime(), pokemon.xOld, pokemon.getX()),
Mth.lerp(instance.getPartialTickTime(), pokemon.yOld, pokemon.getY()),
Mth.lerp(instance.getPartialTickTime(), pokemon.zOld, pokemon.getZ())
);
Rollable rollable = (Rollable) entity;
float currEyeHeight = Mth.lerp(instance.getPartialTickTime(), eyeHeightOld, eyeHeight);
Matrix3f orientation = rollable.shouldRoll() && rollable.getOrientation() != null ? rollable.getOrientation() : new Matrix3f();
Vec3 rotatedEyeHeight = new Vec3(orientation.transform(new Vector3f(0f, currEyeHeight, 0f)));
position = locatorOffset.add(entityPos).add(rotatedEyeHeight);
} else {
original.call(instance, x, y, z);
}
}
@Unique
private void applyRotation(){
if (!(this.entity instanceof Rollable rollable) || rollable.getOrientation() == null) return;
var newRotation = rollable.getOrientation().normal(new Matrix3f()).getNormalizedRotation(new Quaternionf());
if (this.minecraft.options.getCameraType().isMirrored()) {
newRotation.rotateY((float)Math.toRadians(180));
}
this.rotation.set(newRotation);
this.xRot = rollable.getPitch();
this.yRot = rollable.getYaw();
this.forwards.set(rollable.getForwardVector());
this.up.set(rollable.getUpVector());
this.left.set(rollable.getLeftVector());
}
}
@@ -1,66 +0,0 @@
/*
* 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.mixin.client;
import com.cobblemon.mod.common.client.render.player.MountedPlayerRenderer;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.model.geom.ModelPart;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.HashMap;
@Mixin(HumanoidModel.class)
public class HumanoidModelMixin {
@Unique HashMap<String, ModelPart> relevantPartsByName = new HashMap<>();
@Shadow @Final
public ModelPart head;
@Shadow @Final
public ModelPart rightArm;
@Shadow @Final
public ModelPart leftArm;
@Shadow @Final
public ModelPart rightLeg;
@Shadow @Final
public ModelPart leftLeg;
@Inject(method = "setupAnim*", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/model/geom/ModelPart;copyFrom(Lnet/minecraft/client/model/geom/ModelPart;)V", shift = At.Shift.BEFORE))
public void cobblemon$animateRiders(
LivingEntity entity,
float limbSwing,
float limbSwingAmount,
float ageInTicks,
float netHeadYaw,
float headPitch,
CallbackInfo ci
) {
if (relevantPartsByName.isEmpty()) {
relevantPartsByName.put("arm_left", leftArm);
relevantPartsByName.put("arm_right", rightArm);
relevantPartsByName.put("leg_left", leftLeg);
relevantPartsByName.put("leg_right", rightLeg);
relevantPartsByName.put("head", head);
}
Entity vehicle = entity.getVehicle();
if (vehicle instanceof PokemonEntity && entity instanceof AbstractClientPlayer) {
MountedPlayerRenderer.INSTANCE.animate((PokemonEntity) vehicle, (AbstractClientPlayer) entity, relevantPartsByName, netHeadYaw, headPitch, ageInTicks, limbSwing, limbSwingAmount);
}
}
}
@@ -1,43 +0,0 @@
/*
* 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.mixin.client;
import com.cobblemon.mod.common.CobblemonNetwork;
import com.cobblemon.mod.common.Rollable;
import com.cobblemon.mod.common.net.messages.server.orientation.C2SUpdateOrientationPacket;
import net.minecraft.client.player.LocalPlayer;
import org.joml.Matrix3f;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(LocalPlayer.class)
public class LocalPlayerMixin {
@Unique Matrix3f cobblemon$lastOrientation;
@Inject(method = "sendPosition", at = @At("TAIL"))
private void cobblemon_updateRotationMatrix(CallbackInfo ci) {
if (!(this instanceof Rollable rollable)) return;
if (rollable.getOrientation() == cobblemon$lastOrientation) return;
cobblemon$lastOrientation = rollable.getOrientation() != null ? new Matrix3f(rollable.getOrientation()) : null;
CobblemonNetwork.INSTANCE.sendToServer(new C2SUpdateOrientationPacket(rollable.getOrientation()));
}
@Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientPacketListener;send(Lnet/minecraft/network/protocol/Packet;)V"))
private void cobblemon_updateRotationMatrixPassenger(CallbackInfo ci) {
if (!(this instanceof Rollable rollable)) return;
if (rollable.getOrientation() == cobblemon$lastOrientation) return;
cobblemon$lastOrientation = rollable.getOrientation() != null ? new Matrix3f(rollable.getOrientation()) : null;
CobblemonNetwork.INSTANCE.sendToServer(new C2SUpdateOrientationPacket(rollable.getOrientation()));
}
}
@@ -1,36 +0,0 @@
/*
* 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.mixin.client;
import com.cobblemon.mod.common.api.riding.Rideable;
import com.cobblemon.mod.common.api.riding.RidingManager;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import net.minecraft.client.model.PlayerModel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(PlayerModel.class)
public class PlayerModelMixin {
@Inject(method = "setupAnim(Lnet/minecraft/world/entity/LivingEntity;FFFFF)V", at = @At(value = "HEAD"))
private void cobblemon$setHeadRotation(LivingEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, CallbackInfo ci){
if (!(entity instanceof Player)) return;
Entity vehicle = entity.getVehicle();
if (!(vehicle instanceof PokemonEntity)) return;
RidingManager ridingManager = ((Rideable) vehicle).getRiding();
if (ridingManager.shouldRotatePlayerHead((PokemonEntity) vehicle)) return;
netHeadYaw = 0f;
headPitch = 0f;
}
}
@@ -1,44 +0,0 @@
/*
* 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.mixin.client;
import com.cobblemon.mod.common.client.render.ClientPlayerIcon;
import com.cobblemon.mod.common.client.render.player.MountedPlayerRenderer;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(PlayerRenderer.class)
public class PlayerRendererMixin {
@Inject(method = "render(Lnet/minecraft/world/entity/LivingEntity;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At(value = "TAIL"))
public void cobblemon$clientPlayerIcon(LivingEntity entity, float entityYaw, float partialTicks, PoseStack poseStack, MultiBufferSource buffer, int packedLight, CallbackInfo ci) {
ClientPlayerIcon.Companion.onRenderPlayer((Player) entity);
}
@Inject(
method = "setupRotations(Lnet/minecraft/client/player/AbstractClientPlayer;Lcom/mojang/blaze3d/vertex/PoseStack;FFFF)V",
at = @At("HEAD")
)
private void cobblemon$modifyRoll(AbstractClientPlayer player, PoseStack poseStack, float a, float b, float partialTicks, float i, CallbackInfo ci) {
if (player.isPassenger()) {
var vehicle = player.getVehicle();
if (vehicle instanceof PokemonEntity entity) {
MountedPlayerRenderer.INSTANCE.render(player, entity, poseStack, a, b, partialTicks, i);
}
}
}
}
@@ -1,32 +0,0 @@
/*
* 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.mixin.entity;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import net.minecraft.world.entity.Entity;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(Entity.class)
public abstract class EntityMixin {
@Shadow @Nullable public abstract Entity getVehicle();
@Inject(method = "updateInWaterStateAndDoWaterCurrentPushing", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/Entity;wasTouchingWater:Z", ordinal = 1), cancellable = true)
public void cobblemon$verifyActuallyTouchingWater(CallbackInfo ci) {
if(this.getVehicle() instanceof PokemonEntity) {
ci.cancel();
}
}
}
@@ -1,62 +0,0 @@
/*
* 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.mixin.riding;
import net.minecraft.client.player.LocalPlayer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(LocalPlayer.class)
public class JetMixin {
@Shadow private int jumpRidingTicks;
@Shadow private float jumpRidingScale;
private float jetStrength;
// @Redirect(method = "tickMovement", at = @At(target = "Lnet/minecraft/entity/JumpingMount;getJumpCooldown()I", value = "INVOKE"))
// public int cobblemon$tryHandlingJet(JumpingMount mount) {
// if(mount instanceof PokemonEntity pokemon) {
//// if(pokemon.getDataTracker().get(PokemonEntity.MOVING)) {
//// ++this.field_3938;
//// if (this.field_3938 < 11) {
//// this.jetStrength = (float) this.field_3938 * 0.1F;
//// } else {
// this.mountJumpStrength = 0.8F + 2.0F / (float) (this.field_3938 - 9) * 0.1F;
//// }
//// } else {
//// this.field_3938 = 0;
//// this.jetStrength = 0;
//// }
//
//// return -1;
// }
//
// return 0;
// }
@Inject(
method = "aiStep",
at = @At(
target = "Lnet/minecraft/client/player/LocalPlayer;jumpRidingScale:F",
value = "FIELD",
ordinal = 4,
shift = At.Shift.AFTER
),
locals = LocalCapture.CAPTURE_FAILSOFT
)
public void cobblemon$applyCachedJumpStrength(CallbackInfo ci) {
this.jumpRidingScale = this.jetStrength;
}
}
@@ -14,7 +14,6 @@ import com.cobblemon.mod.common.api.SeasonResolver
import com.cobblemon.mod.common.api.data.DataProvider import com.cobblemon.mod.common.api.data.DataProvider
import com.cobblemon.mod.common.api.drop.CommandDropEntry import com.cobblemon.mod.common.api.drop.CommandDropEntry
import com.cobblemon.mod.common.api.drop.DropEntry import com.cobblemon.mod.common.api.drop.DropEntry
import com.cobblemon.mod.common.api.drop.EvolutionItemDropEntry
import com.cobblemon.mod.common.api.drop.ItemDropEntry import com.cobblemon.mod.common.api.drop.ItemDropEntry
import com.cobblemon.mod.common.api.events.CobblemonEvents import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.CobblemonEvents.DATA_SYNCHRONIZED import com.cobblemon.mod.common.api.events.CobblemonEvents.DATA_SYNCHRONIZED
@@ -62,7 +61,11 @@ 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.storage.player.factory.CachedPlayerDataStoreFactory
import com.cobblemon.mod.common.api.tags.CobblemonEntityTypeTags import com.cobblemon.mod.common.api.tags.CobblemonEntityTypeTags
import com.cobblemon.mod.common.api.tags.CobblemonItemTags import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.battles.* 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.actor.PokemonBattleActor import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.client.CobblemonPack import com.cobblemon.mod.common.client.CobblemonPack
@@ -80,17 +83,27 @@ import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacke
import com.cobblemon.mod.common.permission.LaxPermissionValidator import com.cobblemon.mod.common.permission.LaxPermissionValidator
import com.cobblemon.mod.common.platform.events.PlatformEvents import com.cobblemon.mod.common.platform.events.PlatformEvents
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.aspects.COSMETIC_SLOT_ASPECT
import com.cobblemon.mod.common.pokemon.aspects.GENDER_ASPECT import com.cobblemon.mod.common.pokemon.aspects.GENDER_ASPECT
import com.cobblemon.mod.common.pokemon.aspects.SHINY_ASPECT import com.cobblemon.mod.common.pokemon.aspects.SHINY_ASPECT
import com.cobblemon.mod.common.pokemon.evolution.variants.BlockClickEvolution import com.cobblemon.mod.common.pokemon.evolution.variants.BlockClickEvolution
import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
import com.cobblemon.mod.common.pokemon.properties.* 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.tags.PokemonFlagProperty import com.cobblemon.mod.common.pokemon.properties.tags.PokemonFlagProperty
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
import com.cobblemon.mod.common.starter.CobblemonStarterHandler import com.cobblemon.mod.common.starter.CobblemonStarterHandler
import com.cobblemon.mod.common.util.* 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.world.feature.CobblemonPlacedFeatures import com.cobblemon.mod.common.world.feature.CobblemonPlacedFeatures
import com.cobblemon.mod.common.world.feature.ore.CobblemonOrePlacedFeatures import com.cobblemon.mod.common.world.feature.ore.CobblemonOrePlacedFeatures
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
@@ -98,27 +111,25 @@ import com.mongodb.ConnectionString
import com.mongodb.MongoClientSettings import com.mongodb.MongoClientSettings
import com.mongodb.client.MongoClient import com.mongodb.client.MongoClient
import com.mongodb.client.MongoClients 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.client.Minecraft
import net.minecraft.commands.synchronization.SingletonArgumentInfo import net.minecraft.commands.synchronization.SingletonArgumentInfo
import net.minecraft.resources.ResourceKey import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType import net.minecraft.server.packs.PackType
import net.minecraft.world.item.NameTagItem import net.minecraft.world.item.NameTagItem
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import net.minecraft.world.level.storage.LevelResource import net.minecraft.world.level.storage.LevelResource
import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger 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 { object Cobblemon {
const val MODID = CobblemonBuildDetails.MOD_ID const val MODID = CobblemonBuildDetails.MOD_ID
@@ -152,7 +163,6 @@ object Cobblemon {
var permissionValidator: PermissionValidator by Delegates.observable(LaxPermissionValidator().also { it.initialize() }) { _, _, newValue -> newValue.initialize() } var permissionValidator: PermissionValidator by Delegates.observable(LaxPermissionValidator().also { it.initialize() }) { _, _, newValue -> newValue.initialize() }
var statProvider: StatProvider = CobblemonStatProvider var statProvider: StatProvider = CobblemonStatProvider
var seasonResolver: SeasonResolver = TagSeasonResolver var seasonResolver: SeasonResolver = TagSeasonResolver
var wallpapers = mapOf<UUID, List<ResourceLocation>>()
@JvmStatic @JvmStatic
val builtinPacks = listOf<CobblemonPack>( val builtinPacks = listOf<CobblemonPack>(
@@ -190,7 +200,6 @@ object Cobblemon {
DropEntry.register("command", CommandDropEntry::class.java) DropEntry.register("command", CommandDropEntry::class.java)
DropEntry.register("item", ItemDropEntry::class.java, isDefault = true) DropEntry.register("item", ItemDropEntry::class.java, isDefault = true)
DropEntry.register("evolution", EvolutionItemDropEntry::class.java)
ExperienceGroups.registerDefaults() ExperienceGroups.registerDefaults()
CaptureCalculators.registerDefaults() CaptureCalculators.registerDefaults()
@@ -209,8 +218,7 @@ object Cobblemon {
storage.onPlayerDataSync(it) storage.onPlayerDataSync(it)
playerDataManager.syncAllToPlayer(it) playerDataManager.syncAllToPlayer(it)
starterHandler.handleJoin(it) starterHandler.handleJoin(it)
it.requestWallpapers() ServerSettingsPacket(this.config.preventCompletePartyDeposit, this.config.displayEntityLevelLabel, this.config.displayEntityNameLabel, this.config.maxPokemonLevel).sendToPlayer(it)
sendServerSettingsPacketToPlayer(it)
} }
PlatformEvents.SERVER_PLAYER_LOGOUT.subscribe { PlatformEvents.SERVER_PLAYER_LOGOUT.subscribe {
PCLinkManager.removeLink(it.player.uuid) PCLinkManager.removeLink(it.player.uuid)
@@ -248,8 +256,6 @@ object Cobblemon {
// Lowest priority because this applies after luxury ball bonus as of gen 4 // Lowest priority because this applies after luxury ball bonus as of gen 4
CobblemonEvents.FRIENDSHIP_UPDATED.subscribe(Priority.LOWEST) { event -> CobblemonEvents.FRIENDSHIP_UPDATED.subscribe(Priority.LOWEST) { event ->
var increment = (event.newFriendship - event.pokemon.friendship).toFloat() var increment = (event.newFriendship - event.pokemon.friendship).toFloat()
if (increment <= 0) //these affects are only meant to affect positive gains
return@subscribe
// Our Luxury ball spec is diff from official, but we will still assume these stack // Our Luxury ball spec is diff from official, but we will still assume these stack
if (event.pokemon.heldItemNoCopy().`is`(CobblemonItemTags.IS_FRIENDSHIP_BOOSTER)) { if (event.pokemon.heldItemNoCopy().`is`(CobblemonItemTags.IS_FRIENDSHIP_BOOSTER)) {
increment += increment * 0.5F increment += increment * 0.5F
@@ -258,17 +264,8 @@ object Cobblemon {
} }
HeldItemProvider.register(CobblemonHeldItemManager, Priority.LOWEST) 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() { fun initialize() {
@@ -279,7 +276,6 @@ object Cobblemon {
SHINY_ASPECT.register() SHINY_ASPECT.register()
GENDER_ASPECT.register() GENDER_ASPECT.register()
COSMETIC_SLOT_ASPECT.register()
SpeciesFeatures.types["choice"] = ChoiceSpeciesFeatureProvider::class.java SpeciesFeatures.types["choice"] = ChoiceSpeciesFeatureProvider::class.java
SpeciesFeatures.types["flag"] = FlagSpeciesFeatureProvider::class.java SpeciesFeatures.types["flag"] = FlagSpeciesFeatureProvider::class.java
@@ -429,23 +425,7 @@ object Cobblemon {
} }
} }
private fun initializeConfig() {
loadCobblemonConfig()
saveConfig(this.config)
PokemonSpecies.observable.subscribe { starterConfig = this.loadStarterConfig() }
}
fun loadConfig() { fun loadConfig() {
initializeConfig()
bestSpawner.init()
}
fun reloadConfig() {
initializeConfig()
bestSpawner.reloadConfig()
}
private fun loadCobblemonConfig() {
val configFile = File(CONFIG_PATH) val configFile = File(CONFIG_PATH)
configFile.parentFile.mkdirs() configFile.parentFile.mkdirs()
@@ -488,6 +468,12 @@ object Cobblemon {
} else { } else {
this.config = CobblemonConfig() this.config = CobblemonConfig()
} }
config.lastSavedVersion = VERSION
this.saveConfig()
bestSpawner.loadConfig()
PokemonSpecies.observable.subscribe { starterConfig = this.loadStarterConfig() }
} }
fun loadStarterConfig(): StarterConfig { fun loadStarterConfig(): StarterConfig {
@@ -510,14 +496,12 @@ object Cobblemon {
} }
} }
fun saveConfig(config: CobblemonConfig) { fun saveConfig() {
config.lastSavedVersion = VERSION
try { try {
val configFile = File(CONFIG_PATH) val configFile = File(CONFIG_PATH)
val fileWriter = FileWriter(configFile) val fileWriter = FileWriter(configFile)
// Put the config to json then flush the writer to commence writing. // Put the config to json then flush the writer to commence writing.
CobblemonConfig.GSON.toJson(config, fileWriter) CobblemonConfig.GSON.toJson(this.config, fileWriter)
fileWriter.flush() fileWriter.flush()
fileWriter.close() fileWriter.close()
} catch (exception: Exception) { } catch (exception: Exception) {
@@ -539,4 +523,4 @@ object Cobblemon {
this.implementation.registerCommandArgument(cobblemonResource("npc_class"), NPCClassArgumentType::class, SingletonArgumentInfo.contextFree(NPCClassArgumentType::npcClass)) this.implementation.registerCommandArgument(cobblemonResource("npc_class"), NPCClassArgumentType::class, SingletonArgumentInfo.contextFree(NPCClassArgumentType::npcClass))
} }
} }
@@ -23,7 +23,6 @@ object CobblemonCommands {
ChangeEyeHeight.register(dispatcher) ChangeEyeHeight.register(dispatcher)
ChangeScaleAndSize.register(dispatcher) ChangeScaleAndSize.register(dispatcher)
ChangeWalkSpeed.register(dispatcher) ChangeWalkSpeed.register(dispatcher)
ChangeJointScaleCommand.register(dispatcher)
TestCommand.register(dispatcher) TestCommand.register(dispatcher)
ReloadShowdownCommand.register(dispatcher) ReloadShowdownCommand.register(dispatcher)
ClickTextCommand.register(dispatcher) ClickTextCommand.register(dispatcher)
@@ -57,10 +56,7 @@ object CobblemonCommands {
AbandonMultiTeam.register(dispatcher) AbandonMultiTeam.register(dispatcher)
FreezePokemonCommand.register(dispatcher) FreezePokemonCommand.register(dispatcher)
ApplyPlayerTextureCommand.register(dispatcher) ApplyPlayerTextureCommand.register(dispatcher)
RenameBoxCommand.register(dispatcher)
ChangeBoxWallpaperCommand.register(dispatcher)
RunMolangScriptCommand.register(dispatcher) RunMolangScriptCommand.register(dispatcher)
CobblemonConfigCommand.register(dispatcher)
// Possibly lock down registration if and only if under dev environment or running in an environment // Possibly lock down registration if and only if under dev environment or running in an environment
// with a certain system environment variable set // with a certain system environment variable set
@@ -1,63 +0,0 @@
/*
* 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
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.net.messages.client.data.CosmeticItemAssignmentSyncPacket
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.cosmetic.CosmeticItemAssignment
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.adapters.ItemLikeConditionAdapter
import com.cobblemon.mod.common.util.adapters.PokemonPropertiesAdapter
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import net.minecraft.core.RegistryAccess
import net.minecraft.core.registries.Registries
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
object CobblemonCosmeticItems : JsonDataRegistry<CosmeticItemAssignment> {
override val id = cobblemonResource("cosmetic_items")
override val type = PackType.SERVER_DATA
override val observable = SimpleObservable<CobblemonCosmeticItems>()
override val typeToken = TypeToken.get(CosmeticItemAssignment::class.java)
override val resourcePath = "cosmetic_items"
override val gson = GsonBuilder()
.setPrettyPrinting()
.registerTypeAdapter(PokemonProperties::class.java, PokemonPropertiesAdapter(saveLong = false))
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
.create()
val cosmeticItems = mutableListOf<CosmeticItemAssignment>()
override fun reload(data: Map<ResourceLocation, CosmeticItemAssignment>) {
cosmeticItems.clear()
data.entries.forEach { (id, value) -> value.id = id }
cosmeticItems.addAll(data.values)
}
override fun sync(player: ServerPlayer) {
CosmeticItemAssignmentSyncPacket(cosmeticItems).sendToPlayer(player)
}
fun findValidForPokemon(pokemon: Pokemon) = cosmeticItems.filter { it.pokemon.any { it.matches(pokemon) } }
fun findValidCosmeticForPokemonAndItem(registryAccess: RegistryAccess, pokemon: Pokemon, itemStack: ItemStack) = cosmeticItems
.filter { it.pokemon.any { it.matches(pokemon) } }
.flatMap { it.cosmeticItems }
.firstOrNull { it.consumedItem.fits(itemStack.item, registryAccess.registryOrThrow(Registries.ITEM)) }
}
@@ -9,7 +9,6 @@
package com.cobblemon.mod.common package com.cobblemon.mod.common
import com.bedrockk.molang.runtime.MoLangRuntime import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.MoParams
import com.bedrockk.molang.runtime.value.MoValue import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
import com.cobblemon.mod.common.api.data.DataRegistry import com.cobblemon.mod.common.api.data.DataRegistry
@@ -87,20 +86,13 @@ object CobblemonFlows : DataRegistry {
observable.emit(this) observable.emit(this)
} }
fun run( fun run(eventResourceLocation: ResourceLocation, context: Map<String, MoValue>, cancelable: Cancelable? = null) {
eventResourceLocation: ResourceLocation,
context: Map<String, MoValue>,
functions: Map<String, (MoParams) -> Any> = emptyMap(),
cancelable: Cancelable? = null
) {
if (cancelable == null) { if (cancelable == null) {
runtime.environment.query.functions.remove("cancel") runtime.environment.query.functions.remove("cancel")
} else { } else {
runtime.environment.query.addFunction("cancel") { cancelable } runtime.environment.query.addFunction("cancel") { cancelable }
} }
functions.forEach { (name, function) -> runtime.environment.query.addFunction(name, function) }
flows[eventResourceLocation]?.forEach { flows[eventResourceLocation]?.forEach {
if (cancelable != null && cancelable.isCanceled) { if (cancelable != null && cancelable.isCanceled) {
return return
@@ -35,6 +35,7 @@ import com.cobblemon.mod.common.pokeball.PokeBall
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
import com.cobblemon.mod.common.util.cobblemonResource import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.core.Registry import net.minecraft.core.Registry
import net.minecraft.core.component.DataComponents
import net.minecraft.core.registries.BuiltInRegistries import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.core.registries.Registries import net.minecraft.core.registries.Registries
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
@@ -268,7 +269,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField @JvmField
val MONITOR = blockItem("monitor", CobblemonBlocks.MONITOR) val MONITOR = blockItem("monitor", CobblemonBlocks.MONITOR)
@JvmField @JvmField
val HEALING_MACHINE = blockItem("healing_machine", CobblemonBlocks.HEALING_MACHINE, Rarity.UNCOMMON) val HEALING_MACHINE = blockItem("healing_machine", CobblemonBlocks.HEALING_MACHINE)
@JvmField @JvmField
val PC = blockItem("pc", CobblemonBlocks.PC) val PC = blockItem("pc", CobblemonBlocks.PC)
@JvmField @JvmField
@@ -316,7 +317,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField val RAZOR_FANG = noSettingsItem("razor_fang") @JvmField val RAZOR_FANG = noSettingsItem("razor_fang")
@JvmField val AUSPICIOUS_ARMOR = heldItem("auspicious_armor") @JvmField val AUSPICIOUS_ARMOR = heldItem("auspicious_armor")
@JvmField val MALICIOUS_ARMOR = heldItem("malicious_armor") @JvmField val MALICIOUS_ARMOR = heldItem("malicious_armor")
@JvmField val SHELL_HELMET = heldItem("shell_helmet")
private val berries = mutableMapOf<ResourceLocation, BerryItem>() private val berries = mutableMapOf<ResourceLocation, BerryItem>()
// Plants // Plants
@@ -397,7 +397,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
// Medicine // Medicine
@JvmField @JvmField
val RARE_CANDY = candyItem("rare_candy", Rarity.RARE) { _, pokemon -> pokemon.getExperienceToNextLevel() } val RARE_CANDY = candyItem("rare_candy") { _, pokemon -> pokemon.getExperienceToNextLevel() }
@JvmField @JvmField
val EXPERIENCE_CANDY_XS = candyItem("exp_candy_xs") { _, _ -> CandyItem.DEFAULT_XS_CANDY_YIELD } val EXPERIENCE_CANDY_XS = candyItem("exp_candy_xs") { _, _ -> CandyItem.DEFAULT_XS_CANDY_YIELD }
@JvmField @JvmField
@@ -882,48 +882,48 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
// Archaeology // Archaeology
@JvmField @JvmField
val ARMOR_FOSSIL = itemWithRarity("armor_fossil", Rarity.UNCOMMON) val ARMOR_FOSSIL = noSettingsItem("armor_fossil")
@JvmField @JvmField
val FOSSILIZED_BIRD = itemWithRarity("fossilized_bird", Rarity.UNCOMMON) val FOSSILIZED_BIRD = noSettingsItem("fossilized_bird")
@JvmField @JvmField
val CLAW_FOSSIL = itemWithRarity("claw_fossil", Rarity.UNCOMMON) val CLAW_FOSSIL = noSettingsItem("claw_fossil")
@JvmField @JvmField
val COVER_FOSSIL = itemWithRarity("cover_fossil", Rarity.UNCOMMON) val COVER_FOSSIL = noSettingsItem("cover_fossil")
@JvmField @JvmField
val FOSSILIZED_DINO = itemWithRarity("fossilized_dino", Rarity.UNCOMMON) val FOSSILIZED_DINO = noSettingsItem("fossilized_dino")
@JvmField @JvmField
val DOME_FOSSIL = itemWithRarity("dome_fossil", Rarity.UNCOMMON) val DOME_FOSSIL = noSettingsItem("dome_fossil")
@JvmField @JvmField
val FOSSILIZED_DRAKE = itemWithRarity("fossilized_drake", Rarity.UNCOMMON) val FOSSILIZED_DRAKE = noSettingsItem("fossilized_drake")
@JvmField @JvmField
val FOSSILIZED_FISH = itemWithRarity("fossilized_fish", Rarity.UNCOMMON) val FOSSILIZED_FISH = noSettingsItem("fossilized_fish")
@JvmField @JvmField
val HELIX_FOSSIL = itemWithRarity("helix_fossil", Rarity.UNCOMMON) val HELIX_FOSSIL = noSettingsItem("helix_fossil")
@JvmField @JvmField
val JAW_FOSSIL = itemWithRarity("jaw_fossil", Rarity.UNCOMMON) val JAW_FOSSIL = noSettingsItem("jaw_fossil")
@JvmField @JvmField
val OLD_AMBER_FOSSIL = itemWithRarity("old_amber_fossil", Rarity.UNCOMMON) val OLD_AMBER_FOSSIL = noSettingsItem("old_amber_fossil")
@JvmField @JvmField
val PLUME_FOSSIL = itemWithRarity("plume_fossil", Rarity.UNCOMMON) val PLUME_FOSSIL = noSettingsItem("plume_fossil")
@JvmField @JvmField
val ROOT_FOSSIL = itemWithRarity("root_fossil", Rarity.UNCOMMON) val ROOT_FOSSIL = noSettingsItem("root_fossil")
@JvmField @JvmField
val SAIL_FOSSIL = itemWithRarity("sail_fossil", Rarity.UNCOMMON) val SAIL_FOSSIL = noSettingsItem("sail_fossil")
@JvmField @JvmField
val SKULL_FOSSIL = itemWithRarity("skull_fossil", Rarity.UNCOMMON) val SKULL_FOSSIL = noSettingsItem("skull_fossil")
@JvmField @JvmField
val BYGONE_SHERD = itemWithRarity("bygone_sherd", Rarity.UNCOMMON) val BYGONE_SHERD = noSettingsItem("bygone_sherd")
@JvmField @JvmField
val CAPTURE_SHERD = itemWithRarity("capture_sherd",Rarity.UNCOMMON) val CAPTURE_SHERD = noSettingsItem("capture_sherd")
@JvmField @JvmField
val DOME_SHERD = itemWithRarity("dome_sherd", Rarity.UNCOMMON) val DOME_SHERD = noSettingsItem("dome_sherd")
@JvmField @JvmField
val HELIX_SHERD = itemWithRarity("helix_sherd", Rarity.UNCOMMON) val HELIX_SHERD = noSettingsItem("helix_sherd")
@JvmField @JvmField
val NOSTALGIC_SHERD = itemWithRarity("nostalgic_sherd",Rarity.UNCOMMON) val NOSTALGIC_SHERD = noSettingsItem("nostalgic_sherd")
@JvmField @JvmField
val SUSPICIOUS_SHERD = itemWithRarity("suspicious_sherd", Rarity.UNCOMMON) val SUSPICIOUS_SHERD = noSettingsItem("suspicious_sherd")
@JvmField @JvmField
val TUMBLESTONE = this.create("tumblestone", TumblestoneItem(Item.Properties(), CobblemonBlocks.SMALL_BUDDING_TUMBLESTONE)) val TUMBLESTONE = this.create("tumblestone", TumblestoneItem(Item.Properties(), CobblemonBlocks.SMALL_BUDDING_TUMBLESTONE))
@@ -1143,11 +1143,11 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField @JvmField
val DREAM_ROD = pokerodItem(cobblemonResource("dream_rod")) val DREAM_ROD = pokerodItem(cobblemonResource("dream_rod"))
@JvmField @JvmField
val BEAST_ROD = pokerodItem(cobblemonResource("beast_rod"), Rarity.RARE) val BEAST_ROD = pokerodItem(cobblemonResource("beast_rod"))
@JvmField @JvmField
val MASTER_ROD = pokerodItem(cobblemonResource("master_rod"), Rarity.EPIC) val MASTER_ROD = pokerodItem(cobblemonResource("master_rod"))
@JvmField @JvmField
val CHERISH_ROD = pokerodItem(cobblemonResource("cherish_rod"), Rarity.EPIC) val CHERISH_ROD = pokerodItem(cobblemonResource("cherish_rod"))
@JvmField @JvmField
val ANCIENT_POKE_ROD = pokerodItem(cobblemonResource("ancient_poke_rod")) val ANCIENT_POKE_ROD = pokerodItem(cobblemonResource("ancient_poke_rod"))
@JvmField @JvmField
@@ -1179,7 +1179,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField @JvmField
val ANCIENT_GIGATON_ROD = pokerodItem(cobblemonResource("ancient_gigaton_rod")) val ANCIENT_GIGATON_ROD = pokerodItem(cobblemonResource("ancient_gigaton_rod"))
@JvmField @JvmField
val ANCIENT_ORIGIN_ROD = pokerodItem(cobblemonResource("ancient_origin_rod"), Rarity.EPIC) val ANCIENT_ORIGIN_ROD = pokerodItem(cobblemonResource("ancient_origin_rod"))
// Misc // Misc
@JvmField @JvmField
@@ -1231,12 +1231,10 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
//@JvmField //@JvmField
//val BINDING_SOIL = blockItem("binding_soil", CobblemonBlocks.BINDING_SOIL) //val BINDING_SOIL = blockItem("binding_soil", CobblemonBlocks.BINDING_SOIL)
private fun blockItem(name: String, block: Block, rarity: Rarity = Rarity.COMMON): BlockItem = this.create(name, BlockItem(block, Item.Properties().rarity(rarity))) private fun blockItem(name: String, block: Block): BlockItem = this.create(name, BlockItem(block, Item.Properties()))
private fun noSettingsItem(name: String): CobblemonItem = this.create(name, CobblemonItem(Item.Properties())) private fun noSettingsItem(name: String): CobblemonItem = this.create(name, CobblemonItem(Item.Properties()))
private fun itemWithRarity(name: String, rarity: Rarity): CobblemonItem = this.create(name, CobblemonItem(Item.Properties().rarity(rarity)))
fun berries() = this.berries.toMap() fun berries() = this.berries.toMap()
private fun mulchItem(name: String, mulchVariant: MulchVariant): MulchItem = this.create(name, MulchItem(mulchVariant)) private fun mulchItem(name: String, mulchVariant: MulchVariant): MulchItem = this.create(name, MulchItem(mulchVariant))
@@ -1248,10 +1246,10 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
return item return item
} }
private fun candyItem(name: String, rarity: Rarity = Rarity.COMMON, calculator: CandyItem.Calculator): CandyItem = this.create(name, CandyItem(rarity, calculator)) private fun candyItem(name: String, calculator: CandyItem.Calculator): CandyItem = this.create(name, CandyItem(calculator))
private fun pokerodItem(pokeRodId: ResourceLocation, rarity: Rarity = Rarity.COMMON): PokerodItem { private fun pokerodItem(pokeRodId: ResourceLocation): PokerodItem {
val settings = Item.Properties().stacksTo(1).durability(256).rarity(rarity) val settings = Item.Properties().stacksTo(1).durability(256)
val item = create(pokeRodId.path, PokerodItem(pokeRodId, settings)) val item = create(pokeRodId.path, PokerodItem(pokeRodId, settings))
pokeRods.add(item) pokeRods.add(item)
return item return item
@@ -34,7 +34,6 @@ 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.pasture.PokemonUnpasturedHandler
import com.cobblemon.mod.common.client.net.pokedex.ServerConfirmedRegisterHandler 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.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.settings.ServerSettingsPacketHandler
import com.cobblemon.mod.common.client.net.sound.UnvalidatedPlaySoundS2CPacketHandler import com.cobblemon.mod.common.client.net.sound.UnvalidatedPlaySoundS2CPacketHandler
import com.cobblemon.mod.common.client.net.spawn.SpawnExtraDataEntityHandler import com.cobblemon.mod.common.client.net.spawn.SpawnExtraDataEntityHandler
@@ -45,16 +44,14 @@ import com.cobblemon.mod.common.client.net.storage.party.InitializePartyHandler
import com.cobblemon.mod.common.client.net.storage.party.MoveClientPartyPokemonHandler import com.cobblemon.mod.common.client.net.storage.party.MoveClientPartyPokemonHandler
import com.cobblemon.mod.common.client.net.storage.party.SetPartyPokemonHandler import com.cobblemon.mod.common.client.net.storage.party.SetPartyPokemonHandler
import com.cobblemon.mod.common.client.net.storage.party.SetPartyReferenceHandler import com.cobblemon.mod.common.client.net.storage.party.SetPartyReferenceHandler
import com.cobblemon.mod.common.client.net.storage.pc.* import com.cobblemon.mod.common.client.net.storage.pc.ClosePCHandler
import com.cobblemon.mod.common.client.net.storage.pc.InitializePCHandler
import com.cobblemon.mod.common.client.net.storage.pc.MoveClientPCPokemonHandler
import com.cobblemon.mod.common.client.net.storage.pc.OpenPCHandler
import com.cobblemon.mod.common.client.net.storage.pc.SetPCBoxPokemonHandler
import com.cobblemon.mod.common.client.net.storage.pc.SetPCPokemonHandler
import com.cobblemon.mod.common.client.net.toast.ToastPacketHandler import com.cobblemon.mod.common.client.net.toast.ToastPacketHandler
import com.cobblemon.mod.common.client.net.trade.TradeAcceptanceChangedHandler import com.cobblemon.mod.common.client.net.trade.*
import com.cobblemon.mod.common.client.net.trade.TradeCancelledHandler
import com.cobblemon.mod.common.client.net.trade.TradeCompletedHandler
import com.cobblemon.mod.common.client.net.trade.TradeOfferExpiredHandler
import com.cobblemon.mod.common.client.net.trade.TradeOfferNotificationHandler
import com.cobblemon.mod.common.client.net.trade.TradeProcessStartedHandler
import com.cobblemon.mod.common.client.net.trade.TradeStartedHandler
import com.cobblemon.mod.common.client.net.trade.TradeUpdatedHandler
import com.cobblemon.mod.common.net.PacketRegisterInfo import com.cobblemon.mod.common.net.PacketRegisterInfo
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
import com.cobblemon.mod.common.net.messages.client.SetClientPlayerDataPacket import com.cobblemon.mod.common.net.messages.client.SetClientPlayerDataPacket
@@ -69,6 +66,9 @@ import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueOpenedPacke
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
import com.cobblemon.mod.common.net.messages.client.fishing.FishingBaitRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.fossil.FossilRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.fossil.NaturalMaterialRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.npc.CloseNPCEditorPacket import com.cobblemon.mod.common.net.messages.client.npc.CloseNPCEditorPacket
import com.cobblemon.mod.common.net.messages.client.npc.OpenNPCEditorPacket import com.cobblemon.mod.common.net.messages.client.npc.OpenNPCEditorPacket
import com.cobblemon.mod.common.net.messages.client.pasture.ClosePasturePacket import com.cobblemon.mod.common.net.messages.client.pasture.ClosePasturePacket
@@ -80,7 +80,6 @@ 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.AddEvolutionPacket
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.ClearEvolutionsPacket 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.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.settings.ServerSettingsPacket
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnGenericBedrockPacket import com.cobblemon.mod.common.net.messages.client.spawn.SpawnGenericBedrockPacket
@@ -94,41 +93,14 @@ import com.cobblemon.mod.common.net.messages.client.storage.party.InitializePart
import com.cobblemon.mod.common.net.messages.client.storage.party.MoveClientPartyPokemonPacket import com.cobblemon.mod.common.net.messages.client.storage.party.MoveClientPartyPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyPokemonPacket import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyReferencePacket import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyReferencePacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.ClosePCPacket import com.cobblemon.mod.common.net.messages.client.storage.pc.*
import com.cobblemon.mod.common.net.messages.client.storage.pc.InitializePCPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.MoveClientPCPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.OpenPCPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.RenamePCBoxPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.ChangePCBoxWallpaperPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.RequestPCBoxWallpapersPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.SetPCBoxWallpapersPacket
import com.cobblemon.mod.common.net.messages.client.toast.ToastPacket import com.cobblemon.mod.common.net.messages.client.toast.ToastPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeAcceptanceChangedPacket import com.cobblemon.mod.common.net.messages.client.trade.*
import com.cobblemon.mod.common.net.messages.client.trade.TradeCancelledPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeCompletedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferExpiredPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferNotificationPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeProcessStartedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
import com.cobblemon.mod.common.net.messages.client.ui.PokedexUIPacket import com.cobblemon.mod.common.net.messages.client.ui.PokedexUIPacket
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket import com.cobblemon.mod.common.net.messages.server.*
import com.cobblemon.mod.common.net.messages.server.BattleChallengeResponsePacket import com.cobblemon.mod.common.net.messages.server.battle.*
import com.cobblemon.mod.common.net.messages.server.BenchMovePacket
import com.cobblemon.mod.common.net.messages.server.RequestMoveSwapPacket
import com.cobblemon.mod.common.net.messages.server.RequestPlayerInteractionsPacket
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamLeavePacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamRequestPacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamResponsePacket
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
import com.cobblemon.mod.common.net.messages.server.block.AdjustBlockEntityViewerCountPacket import com.cobblemon.mod.common.net.messages.server.block.AdjustBlockEntityViewerCountPacket
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectCancelledPacket import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectCancelledPacket
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectedPacket import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectedPacket
@@ -139,14 +111,12 @@ import com.cobblemon.mod.common.net.messages.server.callback.partymove.PartyPoke
import com.cobblemon.mod.common.net.messages.server.dialogue.EscapeDialoguePacket import com.cobblemon.mod.common.net.messages.server.dialogue.EscapeDialoguePacket
import com.cobblemon.mod.common.net.messages.server.dialogue.InputToDialoguePacket import com.cobblemon.mod.common.net.messages.server.dialogue.InputToDialoguePacket
import com.cobblemon.mod.common.net.messages.server.npc.SaveNPCPacket import com.cobblemon.mod.common.net.messages.server.npc.SaveNPCPacket
import com.cobblemon.mod.common.net.messages.server.orientation.C2SUpdateOrientationPacket
import com.cobblemon.mod.common.net.messages.server.pasture.PasturePokemonPacket import com.cobblemon.mod.common.net.messages.server.pasture.PasturePokemonPacket
import com.cobblemon.mod.common.net.messages.server.pasture.UnpastureAllPokemonPacket import com.cobblemon.mod.common.net.messages.server.pasture.UnpastureAllPokemonPacket
import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPacket import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPacket
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.FinishScanningPacket import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.FinishScanningPacket
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.StartScanningPacket import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.StartScanningPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.interact.InteractPokemonPacket import com.cobblemon.mod.common.net.messages.server.pokemon.interact.InteractPokemonPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetItemHiddenPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetNicknamePacket import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetNicknamePacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.evolution.AcceptEvolutionPacket import com.cobblemon.mod.common.net.messages.server.pokemon.update.evolution.AcceptEvolutionPacket
import com.cobblemon.mod.common.net.messages.server.starter.RequestStarterScreenPacket import com.cobblemon.mod.common.net.messages.server.starter.RequestStarterScreenPacket
@@ -154,22 +124,15 @@ import com.cobblemon.mod.common.net.messages.server.storage.SwapPCPartyPokemonPa
import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokemonPacket import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.party.ReleasePartyPokemonPacket import com.cobblemon.mod.common.net.messages.server.storage.party.ReleasePartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokemonPacket import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.* import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePCPokemonPacket
import com.cobblemon.mod.common.net.messages.server.trade.AcceptTradeRequestPacket import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePCPokemonToPartyPacket
import com.cobblemon.mod.common.net.messages.server.trade.CancelTradePacket import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePartyPokemonToPCPacket
import com.cobblemon.mod.common.net.messages.server.trade.ChangeTradeAcceptancePacket import com.cobblemon.mod.common.net.messages.server.storage.pc.ReleasePCPokemonPacket
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket import com.cobblemon.mod.common.net.messages.server.storage.pc.SwapPCPokemonPacket
import com.cobblemon.mod.common.net.messages.server.trade.PerformTradePacket import com.cobblemon.mod.common.net.messages.server.storage.pc.UnlinkPlayerFromPCPacket
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket import com.cobblemon.mod.common.net.messages.server.trade.*
import com.cobblemon.mod.common.net.serverhandling.ChallengeHandler import com.cobblemon.mod.common.net.serverhandling.*
import com.cobblemon.mod.common.net.serverhandling.ChallengeResponseHandler import com.cobblemon.mod.common.net.serverhandling.battle.*
import com.cobblemon.mod.common.net.serverhandling.RequestInteractionsHandler
import com.cobblemon.mod.common.net.serverhandling.battle.BattleSelectActionsHandler
import com.cobblemon.mod.common.net.serverhandling.battle.RemoveSpectatorHandler
import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
import com.cobblemon.mod.common.net.serverhandling.battle.TeamLeaveHandler
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestHandler
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestResponseHandler
import com.cobblemon.mod.common.net.serverhandling.block.AdjustBlockEntityViewerCountHandler import com.cobblemon.mod.common.net.serverhandling.block.AdjustBlockEntityViewerCountHandler
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectCancelledHandler import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectCancelledHandler
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectedHandler import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectedHandler
@@ -181,14 +144,12 @@ import com.cobblemon.mod.common.net.serverhandling.dialogue.EscapeDialogueHandle
import com.cobblemon.mod.common.net.serverhandling.dialogue.InputToDialogueHandler import com.cobblemon.mod.common.net.serverhandling.dialogue.InputToDialogueHandler
import com.cobblemon.mod.common.net.serverhandling.evolution.AcceptEvolutionHandler import com.cobblemon.mod.common.net.serverhandling.evolution.AcceptEvolutionHandler
import com.cobblemon.mod.common.net.serverhandling.npc.SaveNPCHandler import com.cobblemon.mod.common.net.serverhandling.npc.SaveNPCHandler
import com.cobblemon.mod.common.net.serverhandling.orientation.OrientationPacketHandler
import com.cobblemon.mod.common.net.serverhandling.pasture.PasturePokemonHandler import com.cobblemon.mod.common.net.serverhandling.pasture.PasturePokemonHandler
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpastureAllPokemonHandler import com.cobblemon.mod.common.net.serverhandling.pasture.UnpastureAllPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpasturePokemonHandler import com.cobblemon.mod.common.net.serverhandling.pasture.UnpasturePokemonHandler
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.FinishScanningHandler import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.FinishScanningHandler
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.StartScanningHandler import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.StartScanningHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.interact.InteractPokemonHandler import com.cobblemon.mod.common.net.serverhandling.pokemon.interact.InteractPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetItemHiddenHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetNicknameHandler import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetNicknameHandler
import com.cobblemon.mod.common.net.serverhandling.starter.RequestStarterScreenHandler import com.cobblemon.mod.common.net.serverhandling.starter.RequestStarterScreenHandler
import com.cobblemon.mod.common.net.serverhandling.starter.SelectStarterPacketHandler import com.cobblemon.mod.common.net.serverhandling.starter.SelectStarterPacketHandler
@@ -199,13 +160,13 @@ import com.cobblemon.mod.common.net.serverhandling.storage.SwapPCPartyPokemonHan
import com.cobblemon.mod.common.net.serverhandling.storage.party.MovePartyPokemonHandler import com.cobblemon.mod.common.net.serverhandling.storage.party.MovePartyPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.party.ReleasePCPokemonHandler import com.cobblemon.mod.common.net.serverhandling.storage.party.ReleasePCPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.party.SwapPartyPokemonHandler import com.cobblemon.mod.common.net.serverhandling.storage.party.SwapPartyPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.pc.* import com.cobblemon.mod.common.net.serverhandling.storage.pc.MovePCPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.trade.AcceptTradeRequestHandler import com.cobblemon.mod.common.net.serverhandling.storage.pc.MovePCPokemonToPartyHandler
import com.cobblemon.mod.common.net.serverhandling.trade.CancelTradeHandler import com.cobblemon.mod.common.net.serverhandling.storage.pc.MovePartyPokemonToPCHandler
import com.cobblemon.mod.common.net.serverhandling.trade.ChangeTradeAcceptanceHandler import com.cobblemon.mod.common.net.serverhandling.storage.pc.ReleasePartyPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.trade.OfferTradeHandler import com.cobblemon.mod.common.net.serverhandling.storage.pc.SwapPCPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.trade.PerformTradeHandler import com.cobblemon.mod.common.net.serverhandling.storage.pc.UnlinkPlayerFromPCHandler
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler import com.cobblemon.mod.common.net.serverhandling.trade.*
import com.cobblemon.mod.common.util.server import com.cobblemon.mod.common.util.server
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
@@ -218,11 +179,13 @@ import net.minecraft.server.level.ServerPlayer
* @since November 27th, 2021 * @since November 27th, 2021
*/ */
object CobblemonNetwork { object CobblemonNetwork {
//private val logger = LogUtils.getLogger()
fun ServerPlayer.sendPacket(packet: NetworkPacket<*>) { fun ServerPlayer.sendPacket(packet: NetworkPacket<*>) {
sendPacketToPlayer(this, packet) sendPacketToPlayer(this, packet)
} }
fun sendToServer(packet: NetworkPacket<*>) { fun sendToServer(packet: NetworkPacket<*>) {
//logger.info("[C->S] ${packet.type()}")
Cobblemon.implementation.networkManager.sendToServer(packet) Cobblemon.implementation.networkManager.sendToServer(packet)
} }
fun sendToAllPlayers(packet: NetworkPacket<*>) = sendPacketToPlayers(server()!!.playerList.players, packet) fun sendToAllPlayers(packet: NetworkPacket<*>) = sendPacketToPlayers(server()!!.playerList.players, packet)
@@ -258,10 +221,6 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(SpeciesFeatureUpdatePacket.ID, SpeciesFeatureUpdatePacket::decode, PokemonUpdatePacketHandler())) list.add(PacketRegisterInfo(SpeciesFeatureUpdatePacket.ID, SpeciesFeatureUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(OriginalTrainerUpdatePacket.ID, OriginalTrainerUpdatePacket::decode, PokemonUpdatePacketHandler())) list.add(PacketRegisterInfo(OriginalTrainerUpdatePacket.ID, OriginalTrainerUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(FormUpdatePacket.ID, FormUpdatePacket::decode, PokemonUpdatePacketHandler())) list.add(PacketRegisterInfo(FormUpdatePacket.ID, FormUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(TeraTypeUpdatePacket.ID, TeraTypeUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(DmaxLevelUpdatePacket.ID, DmaxLevelUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(GmaxFactorUpdatePacket.ID, GmaxFactorUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(CosmeticItemUpdatePacket.ID, CosmeticItemUpdatePacket::decode, PokemonUpdatePacketHandler()))
// Evolution start // Evolution start
list.add(PacketRegisterInfo(AddEvolutionPacket.ID, AddEvolutionPacket::decode, PokemonUpdatePacketHandler())) list.add(PacketRegisterInfo(AddEvolutionPacket.ID, AddEvolutionPacket::decode, PokemonUpdatePacketHandler()))
@@ -276,18 +235,13 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(SetPartyReferencePacket.ID, SetPartyReferencePacket::decode, SetPartyReferenceHandler)) list.add(PacketRegisterInfo(SetPartyReferencePacket.ID, SetPartyReferencePacket::decode, SetPartyReferenceHandler))
list.add(PacketRegisterInfo(InitializePCPacket.ID, InitializePCPacket::decode, InitializePCHandler)) list.add(PacketRegisterInfo(InitializePCPacket.ID, InitializePCPacket::decode, InitializePCHandler))
list.add(PacketRegisterInfo(MoveClientPCPokemonPacket.ID, MoveClientPCPokemonPacket::decode, MoveClientPCPokemonHandler)) list.add(PacketRegisterInfo(MoveClientPCPokemonPacket.ID, MoveClientPCPokemonPacket::decode, MoveClientPCPokemonHandler))
list.add(PacketRegisterInfo(SetPCBoxPacket.ID, SetPCBoxPacket::decode, SetPCBoxHandler)) list.add(PacketRegisterInfo(SetPCBoxPokemonPacket.ID, SetPCBoxPokemonPacket::decode, SetPCBoxPokemonHandler))
list.add(PacketRegisterInfo(SetPCPokemonPacket.ID, SetPCPokemonPacket::decode, SetPCPokemonHandler)) list.add(PacketRegisterInfo(SetPCPokemonPacket.ID, SetPCPokemonPacket::decode, SetPCPokemonHandler))
list.add(PacketRegisterInfo(OpenPCPacket.ID, OpenPCPacket::decode, OpenPCHandler)) list.add(PacketRegisterInfo(OpenPCPacket.ID, OpenPCPacket::decode, OpenPCHandler))
list.add(PacketRegisterInfo(ClosePCPacket.ID, ClosePCPacket::decode, ClosePCHandler)) list.add(PacketRegisterInfo(ClosePCPacket.ID, ClosePCPacket::decode, ClosePCHandler))
list.add(PacketRegisterInfo(SwapClientPokemonPacket.ID, SwapClientPokemonPacket::decode, SwapClientPokemonHandler)) list.add(PacketRegisterInfo(SwapClientPokemonPacket.ID, SwapClientPokemonPacket::decode, SwapClientPokemonHandler))
list.add(PacketRegisterInfo(RemoveClientPokemonPacket.ID, RemoveClientPokemonPacket::decode, RemoveClientPokemonHandler)) list.add(PacketRegisterInfo(RemoveClientPokemonPacket.ID, RemoveClientPokemonPacket::decode, RemoveClientPokemonHandler))
list.add(PacketRegisterInfo(RenamePCBoxPacket.ID, RenamePCBoxPacket::decode, RenamePCBoxHandler))
list.add(PacketRegisterInfo(RequestPCBoxWallpapersPacket.ID, RequestPCBoxWallpapersPacket::decode, RequestPCBoxWallpapersHandler))
list.add(PacketRegisterInfo(SetPCBoxWallpapersPacket.ID, SetPCBoxWallpapersPacket::decode, SetPCBoxWallpapersHandler))
list.add(PacketRegisterInfo(ChangePCBoxWallpaperPacket.ID, ChangePCBoxWallpaperPacket::decode, ChangePCBoxWallpaperHandler))
// UI Packets // UI Packets
list.add(PacketRegisterInfo(SummaryUIPacket.ID, SummaryUIPacket::decode, SummaryUIPacketHandler)) list.add(PacketRegisterInfo(SummaryUIPacket.ID, SummaryUIPacket::decode, SummaryUIPacketHandler))
list.add(PacketRegisterInfo(InteractPokemonUIPacket.ID, InteractPokemonUIPacket::decode, InteractPokemonUIPacketHandler)) list.add(PacketRegisterInfo(InteractPokemonUIPacket.ID, InteractPokemonUIPacket::decode, InteractPokemonUIPacketHandler))
@@ -325,13 +279,11 @@ object CobblemonNetwork {
// MultiBattleTeam Packets // MultiBattleTeam Packets
list.add(PacketRegisterInfo(TeamRequestNotificationPacket.ID, TeamRequestNotificationPacket::decode, TeamRequestNotificationHandler)) list.add(PacketRegisterInfo(TeamRequestNotificationPacket.ID, TeamRequestNotificationPacket::decode, TeamRequestNotificationHandler))
list.add(PacketRegisterInfo(TeamRequestExpiredPacket.ID, TeamRequestExpiredPacket::decode, TeamRequestExpiredHandler)) list.add(PacketRegisterInfo(TeamRequestExpiredPacket.ID, TeamRequestExpiredPacket::decode, TeamRequestExpiredHandler))
list.add(PacketRegisterInfo(TeamMemberAddNotificationPacket.ID, TeamMemberAddNotificationPacket::decode, TeamMemberAddNotificationHandler))
list.add(PacketRegisterInfo(TeamMemberRemoveNotificationPacket.ID, TeamMemberRemoveNotificationPacket::decode, TeamMemberRemoveNotificationHandler)) list.add(PacketRegisterInfo(TeamMemberRemoveNotificationPacket.ID, TeamMemberRemoveNotificationPacket::decode, TeamMemberRemoveNotificationHandler))
list.add(PacketRegisterInfo(TeamJoinNotificationPacket.ID, TeamJoinNotificationPacket::decode, TeamJoinNotificationHandler)) list.add(PacketRegisterInfo(TeamJoinNotificationPacket.ID, TeamJoinNotificationPacket::decode, TeamJoinNotificationHandler))
// Settings packets // Settings packets
list.add(PacketRegisterInfo(ServerSettingsPacket.ID, ServerSettingsPacket::decode, ServerSettingsPacketHandler)) list.add(PacketRegisterInfo(ServerSettingsPacket.ID, ServerSettingsPacket::decode, ServerSettingsPacketHandler))
list.add(PacketRegisterInfo(OpenCobblemonConfigScreenPacket.ID, OpenCobblemonConfigScreenPacket::decode, OpenCobblemonConfigEditorHandler))
// Data registries // Data registries
list.add(PacketRegisterInfo(AbilityRegistrySyncPacket.ID, AbilityRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())) list.add(PacketRegisterInfo(AbilityRegistrySyncPacket.ID, AbilityRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
@@ -352,7 +304,6 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(DexEntrySyncPacket.ID, DexEntrySyncPacket::decode, DataRegistrySyncPacketHandler())) list.add(PacketRegisterInfo(DexEntrySyncPacket.ID, DexEntrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(FishingBaitRegistrySyncPacket.ID, FishingBaitRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())) list.add(PacketRegisterInfo(FishingBaitRegistrySyncPacket.ID, FishingBaitRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(FlowRegistrySyncPacket.ID, FlowRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())) list.add(PacketRegisterInfo(FlowRegistrySyncPacket.ID, FlowRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(CosmeticItemAssignmentSyncPacket.ID, CosmeticItemAssignmentSyncPacket::decode, DataRegistrySyncPacketHandler()))
// Effects // Effects
list.add(PacketRegisterInfo(SpawnSnowstormParticlePacket.ID, SpawnSnowstormParticlePacket::decode, SpawnSnowstormParticleHandler)) list.add(PacketRegisterInfo(SpawnSnowstormParticlePacket.ID, SpawnSnowstormParticlePacket::decode, SpawnSnowstormParticleHandler))
@@ -412,7 +363,6 @@ object CobblemonNetwork {
val list = mutableListOf<PacketRegisterInfo<*>>() val list = mutableListOf<PacketRegisterInfo<*>>()
// Pokemon Update Packets // Pokemon Update Packets
list.add(PacketRegisterInfo(SetNicknamePacket.ID, SetNicknamePacket::decode, SetNicknameHandler)) list.add(PacketRegisterInfo(SetNicknamePacket.ID, SetNicknamePacket::decode, SetNicknameHandler))
list.add(PacketRegisterInfo(SetItemHiddenPacket.ID, SetItemHiddenPacket::decode, SetItemHiddenHandler))
// Evolution Packets // Evolution Packets
list.add(PacketRegisterInfo(AcceptEvolutionPacket.ID, AcceptEvolutionPacket::decode, AcceptEvolutionHandler)) list.add(PacketRegisterInfo(AcceptEvolutionPacket.ID, AcceptEvolutionPacket::decode, AcceptEvolutionHandler))
@@ -437,10 +387,6 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(ReleasePCPokemonPacket.ID, ReleasePCPokemonPacket::decode, ReleasePCPokemonHandler)) list.add(PacketRegisterInfo(ReleasePCPokemonPacket.ID, ReleasePCPokemonPacket::decode, ReleasePCPokemonHandler))
list.add(PacketRegisterInfo(UnlinkPlayerFromPCPacket.ID, UnlinkPlayerFromPCPacket::decode, UnlinkPlayerFromPCHandler)) list.add(PacketRegisterInfo(UnlinkPlayerFromPCPacket.ID, UnlinkPlayerFromPCPacket::decode, UnlinkPlayerFromPCHandler))
list.add(PacketRegisterInfo(RequestRenamePCBoxPacket.Companion.ID, RequestRenamePCBoxPacket.Companion::decode, RequestRenamePCBoxHandler))
list.add(PacketRegisterInfo(PCBoxWallpapersPacket.ID, PCBoxWallpapersPacket::decode, PCBoxWallpapersHandler))
list.add(PacketRegisterInfo(RequestChangePCBoxWallpaperPacket.ID, RequestChangePCBoxWallpaperPacket::decode, RequestChangePCBoxWallpaperHandler))
// Starter packets // Starter packets
list.add(PacketRegisterInfo(SelectStarterPacket.ID, SelectStarterPacket::decode, SelectStarterPacketHandler)) list.add(PacketRegisterInfo(SelectStarterPacket.ID, SelectStarterPacket::decode, SelectStarterPacketHandler))
list.add(PacketRegisterInfo(RequestStarterScreenPacket.ID, RequestStarterScreenPacket::decode, RequestStarterScreenHandler)) list.add(PacketRegisterInfo(RequestStarterScreenPacket.ID, RequestStarterScreenPacket::decode, RequestStarterScreenHandler))
@@ -453,8 +399,6 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(SwapPCPartyPokemonPacket.ID, SwapPCPartyPokemonPacket::decode, SwapPCPartyPokemonHandler)) list.add(PacketRegisterInfo(SwapPCPartyPokemonPacket.ID, SwapPCPartyPokemonPacket::decode, SwapPCPartyPokemonHandler))
list.add(PacketRegisterInfo(SortPCBoxPacket.ID, SortPCBoxPacket::decode, SortPCBoxHandler))
// Battle packets // Battle packets
list.add(PacketRegisterInfo(BattleSelectActionsPacket.ID, BattleSelectActionsPacket::decode, BattleSelectActionsHandler)) list.add(PacketRegisterInfo(BattleSelectActionsPacket.ID, BattleSelectActionsPacket::decode, BattleSelectActionsHandler))
list.add(PacketRegisterInfo(SpectateBattlePacket.ID, SpectateBattlePacket::decode, SpectateBattleHandler)) list.add(PacketRegisterInfo(SpectateBattlePacket.ID, SpectateBattlePacket::decode, SpectateBattleHandler))
@@ -499,13 +443,11 @@ object CobblemonNetwork {
// NPC packets // NPC packets
list.add(PacketRegisterInfo(SaveNPCPacket.ID, SaveNPCPacket::decode, SaveNPCHandler)) list.add(PacketRegisterInfo(SaveNPCPacket.ID, SaveNPCPacket::decode, SaveNPCHandler))
// Orientation packet(s)
list.add(PacketRegisterInfo(C2SUpdateOrientationPacket.ID, C2SUpdateOrientationPacket::decode, OrientationPacketHandler))
return list return list
} }
fun sendPacketToPlayer(player: ServerPlayer, packet: NetworkPacket<*>) { fun sendPacketToPlayer(player: ServerPlayer, packet: NetworkPacket<*>) {
//logger.info("[S->C] ${packet.type()}")
Cobblemon.implementation.networkManager.sendPacketToPlayer(player, packet) Cobblemon.implementation.networkManager.sendPacketToPlayer(player, packet)
} }
} }
@@ -33,7 +33,7 @@ class LevelUpCriterion(
} }
override fun matches(player: ServerPlayer, context: LevelUpContext): Boolean { override fun matches(player: ServerPlayer, context: LevelUpContext): Boolean {
val preEvo = context.pokemon.preEvolution != null val preEvo = context.pokemon.preEvolution == null
val hasEvolution = !context.pokemon.evolutions.none() val hasEvolution = !context.pokemon.evolutions.none()
var evolutionCheck = true var evolutionCheck = true
if (preEvo || hasEvolution) { if (preEvo || hasEvolution) {
@@ -43,3 +43,27 @@ class LevelUpCriterion(
} }
} }
/*class LevelUpCriterionCondition(id: Identifier, entity: LootContextPredicate) : SimpleCriterionCondition<LevelUpContext>(id, entity) {
var level = 0
var evolved = true
override fun toJson(json: JsonObject) {
json.addProperty("level", level)
json.addProperty("has_evolved", evolved)
}
override fun fromJson(json: JsonObject) {
level = json.get("level")?.asInt ?: 0
evolved = json.get("has_evolved")?.asBoolean ?: true
}
override fun matches(player: ServerPlayer, context: LevelUpContext): Boolean {
val preEvo = context.pokemon.preEvolution == null
val hasEvolution = !context.pokemon.evolutions.none()
var evolutionCheck = true
if (preEvo || hasEvolution) {
evolutionCheck = !(preEvo == hasEvolution)
}
return level == context.level && evolutionCheck == evolved
}
}*/
@@ -43,8 +43,7 @@ interface SleepDepth {
"comatose" to comatose, "comatose" to comatose,
"normal" to normal "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 fun canSleep(pokemonEntity: PokemonEntity): Boolean
@@ -8,9 +8,6 @@
package com.cobblemon.mod.common.api.battles.interpreter package com.cobblemon.mod.common.api.battles.interpreter
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.queryStructOf
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
/** /**
@@ -33,13 +30,6 @@ interface BattleContext {
/** The [BattlePokemon] that directly or indirectly caused this [BattleContext]. */ /** The [BattlePokemon] that directly or indirectly caused this [BattleContext]. */
val origin: BattlePokemon? val origin: BattlePokemon?
fun getStruct() = queryStructOf(
"type" to { StringValue(type.name) },
"origin" to { origin?.struct ?: DoubleValue(0.0) },
"id" to { StringValue(id) },
"turn_created" to { DoubleValue(turn.toDouble()) }
)
/** /**
* The type of [BattleContext]. * The type of [BattleContext].
* *
@@ -23,7 +23,6 @@ import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.battles.BattleFledEvent import com.cobblemon.mod.common.api.events.battles.BattleFledEvent
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.net.NetworkPacket 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.storage.party.PlayerPartyStore
import com.cobblemon.mod.common.api.tags.CobblemonItemTags import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.api.text.red import com.cobblemon.mod.common.api.text.red
@@ -273,7 +272,7 @@ open class PokemonBattle(
opponent.awardExperience(opponentPokemon, experience) opponent.awardExperience(opponentPokemon, experience)
} }
Cobblemon.evYieldCalculator.calculate(opponentPokemon, faintedPokemon).forEach { (stat, amount) -> Cobblemon.evYieldCalculator.calculate(opponentPokemon, faintedPokemon).forEach { (stat, amount) ->
pokemon.evs.add(stat, amount, BattleEvSource(this, opponentPokemon.facedOpponents.toList(), pokemon)) pokemon.evs.add(stat, amount)
} }
} }
@@ -99,6 +99,7 @@ class Berry(
val weight: Float, val weight: Float,
val boneMealChance: Float val boneMealChance: Float
) { ) {
@Transient @Transient
var identifier: ResourceLocation = identifier var identifier: ResourceLocation = identifier
internal set internal set
@@ -158,7 +159,7 @@ class Berry(
* Calculates the yield for a berry tree being planted or replanted after a life cycle. * Calculates the yield for a berry tree being planted or replanted after a life cycle.
* Triggers [BerryYieldCalculationEvent]. * Triggers [BerryYieldCalculationEvent].
* *
* @param world The [Level] the tree is present in. * @param world The [World] the tree is present in.
* @param state The [BlockState] of the tree. * @param state The [BlockState] of the tree.
* @param pos The [BlockPos] of the tree. * @param pos The [BlockPos] of the tree.
* @param placer The [LivingEntity] tending to the tree, if any. * @param placer The [LivingEntity] tending to the tree, if any.
@@ -172,10 +173,9 @@ class Berry(
if (BerryBlock.getMulch(treeEntity) == MulchVariant.RICH) { if (BerryBlock.getMulch(treeEntity) == MulchVariant.RICH) {
//I hope the upper bound isnt exclusive, especially when there's a method called nextBetweenExclusive //I hope the upper bound isnt exclusive, especially when there's a method called nextBetweenExclusive
// update: it was meant to be exclusive, which caused #1124. I've lowered the upper bound from 3 to 2. // update: it was meant to be exclusive, which caused #1124. I've lowered the upper bound from 3 to 2.
yield += world.random.nextIntBetweenInclusive(RICH_MULCH_MIN, RICH_MULCH_MAX) yield += world.random.nextIntBetweenInclusive(1, 2)
treeEntity.decrementMulchDuration(world, pos, state) treeEntity.decrementMulchDuration(world, pos, state)
} }
yield = yield.coerceAtMost(growthPoints.size)
val event = BerryYieldCalculationEvent(this, world, state, pos, placer, yield, bonus.second) val event = BerryYieldCalculationEvent(this, world, state, pos, placer, yield, bonus.second)
CobblemonEvents.BERRY_YIELD.post(event) { yield = it.yield } CobblemonEvents.BERRY_YIELD.post(event) { yield = it.yield }
return yield return yield
@@ -193,7 +193,7 @@ class Berry(
* *
* @return The maximum possible yield. * @return The maximum possible yield.
*/ */
fun maxYield() = this.baseYield.last + this.growthFactors.sumOf { it.maxYield() } + RICH_MULCH_MAX fun maxYield() = this.baseYield.last + this.growthFactors.sumOf { it.maxYield() }
/** /**
* Checks if this berry can mutate with the given [partner]. * Checks if this berry can mutate with the given [partner].
@@ -231,7 +231,6 @@ class Berry(
} }
// A cheat since gson doesn't invoke init block // A cheat since gson doesn't invoke init block
// well I actually suspect it does but
internal fun validate() { internal fun validate() {
if (this.baseYield.first < 0 || this.baseYield.last < 0) { if (this.baseYield.first < 0 || this.baseYield.last < 0) {
throw IllegalArgumentException("A berry base yield must be a positive range") throw IllegalArgumentException("A berry base yield must be a positive range")
@@ -248,6 +247,10 @@ class Berry(
} }
*/ */
this.growthFactors.forEach { it.validateArguments() } this.growthFactors.forEach { it.validateArguments() }
val maxYield = this.maxYield()
if (this.growthPoints.size < maxYield) {
throw IllegalArgumentException("Anchor points must have enough elements for the max possible yield of $maxYield you've provided ${this.growthPoints.size} points")
}
this.shapedFlower = hashMapOf() this.shapedFlower = hashMapOf()
this.shapedFruit = hashMapOf() this.shapedFruit = hashMapOf()
this.sproutShape = this.createAndUniteShapes(this.sproutShapeBoxes) this.sproutShape = this.createAndUniteShapes(this.sproutShapeBoxes)
@@ -336,8 +339,6 @@ class Berry(
} }
companion object { companion object {
const val RICH_MULCH_MIN = 1
const val RICH_MULCH_MAX = 2
internal fun decode(buffer: RegistryFriendlyByteBuf): Berry { internal fun decode(buffer: RegistryFriendlyByteBuf): Berry {
val identifier = buffer.readIdentifier() val identifier = buffer.readIdentifier()
@@ -15,10 +15,12 @@ package com.cobblemon.mod.common.api.berry
* @author Licious * @author Licious
* @since November 28th, 2022 * @since November 28th, 2022
*/ */
enum class Flavor(val colour: Int) { enum class Flavor {
SPICY(0x00FF00),
DRY(0xFF0000), SPICY,
SWEET(0x0000FF), DRY,
BITTER(0xFFFF00), SWEET,
SOUR(0xFF00FF); BITTER,
SOUR
} }
@@ -1,39 +0,0 @@
/*
* 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.api.conditional
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import com.cobblemon.mod.common.util.codec.CodecUtils
import com.mojang.serialization.Codec
import net.minecraft.core.Registry
import net.minecraft.core.registries.Registries
import net.minecraft.resources.ResourceKey
import net.minecraft.tags.TagKey
val ITEM_REGISTRY_LIKE_CODEC = makeCodecForRegistryLikeCondition("item", Registries.ITEM)
fun <T : Any> makeCodecForRegistryLikeCondition(name: String, registryKey: ResourceKey<Registry<T>>): Codec<RegistryLikeCondition<T>> {
return CodecUtils.createByStringCodec(
from = { str ->
if (str.startsWith("#")) {
return@createByStringCodec RegistryLikeTagCondition<T>(TagKey.create(registryKey, str.substring(1).asIdentifierDefaultingNamespace()))
} else {
return@createByStringCodec RegistryLikeIdentifierCondition<T>(str.asIdentifierDefaultingNamespace())
}
},
to = { condition ->
if (condition is RegistryLikeTagCondition) {
"#${condition.tag.location}"
} else {
(condition as RegistryLikeIdentifierCondition).identifier.toString()
}
},
errorSupplier = { "Unknown $name condition: $it. Should be # followed by a tag, or $name resource location e.g. #minecraft:ladders or minecraft:grass_block." }
)
}
@@ -26,13 +26,13 @@ open class RegistryLikeTagCondition<T : Any>(val tag: TagKey<T>) : RegistryLikeC
companion object { companion object {
const val PREFIX = "#" const val PREFIX = "#"
fun <T : Any> resolver( fun <T : Any> resolver(
resourceKey: ResourceKey<Registry<T>>, ResourceKey: ResourceKey<Registry<T>>,
constructor: (TagKey<T>) -> RegistryLikeTagCondition<T> constructor: (TagKey<T>) -> RegistryLikeTagCondition<T>
): (JsonElement) -> RegistryLikeTagCondition<T>? = { ): (JsonElement) -> RegistryLikeTagCondition<T>? = {
val firstSymbol = it.asString.substring(0, 1) val firstSymbol = it.asString.substring(0, 1)
if (firstSymbol == PREFIX) { if (firstSymbol == PREFIX) {
val identifier = ResourceLocation.parse(it.asString.substring(1)) val identifier = ResourceLocation.parse(it.asString.substring(1))
constructor(TagKey.create(resourceKey, identifier)) constructor(TagKey.create(ResourceKey, identifier))
} else { } else {
null null
} }
@@ -55,7 +55,6 @@ class ActiveDialogue(var playerEntity: ServerPlayer, var dialogueReference: Dial
) )
dialogueReference.initializationAction.invoke(this) dialogueReference.initializationAction.invoke(this)
setPage(currentPage)
if (!completion.isDone) { if (!completion.isDone) {
val packet = DialogueOpenedPacket(this, true) val packet = DialogueOpenedPacket(this, true)
@@ -52,6 +52,6 @@ object DialogueManager {
fun stopDialogue(playerEntity: ServerPlayer) { fun stopDialogue(playerEntity: ServerPlayer) {
val activeDialogue = playerEntity.activeDialogue ?: return val activeDialogue = playerEntity.activeDialogue ?: return
DialogueClosedPacket(activeDialogue.dialogueId).sendToPlayer(playerEntity) DialogueClosedPacket(activeDialogue.dialogueId).sendToPlayer(playerEntity)
activeDialogues.remove(playerEntity.uuid) activeDialogues.remove(activeDialogue.dialogueId)
} }
} }
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common.api.drop package com.cobblemon.mod.common.api.drop
import com.cobblemon.mod.common.pokemon.Pokemon
import net.minecraft.server.level.ServerLevel import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.LivingEntity
@@ -41,23 +40,17 @@ interface DropEntry {
* to be dropped. * to be dropped.
*/ */
val percentage: Float val percentage: Float
/** /**
* The drop's quantity when doing selection from the [DropTable]. See the drop table documentation for more on how * The drop's quantity when doing selection from the [DropTable]. See the drop table documentation for more on how
* this works. * this works.
*/ */
val quantity: Int val quantity: Int
/** /**
* The maximum number of times the item can be selected drop the [DropTable]. In most cases this will just be 1, * The maximum number of times the item can be selected drop the [DropTable]. In most cases this will just be 1,
* meaning that the item, once picked, cannot be picked again. A larger value will allow the same [DropEntry] from * meaning that the item, once picked, cannot be picked again. A larger value will allow the same [DropEntry] from
* appearing multiple times in a drop action. * appearing multiple times in a drop action.
*/ */
val maxSelectableTimes: Int val maxSelectableTimes: Int
/** Whether this is considered a possible drop at the moment or not */
fun canDrop(pokemon: Pokemon?): Boolean = true
/** The logic to use to actually drop the thing. */ /** The logic to use to actually drop the thing. */
fun drop(entity: LivingEntity?, world: ServerLevel, pos: Vec3, player: ServerPlayer?) fun drop(entity: LivingEntity?, world: ServerLevel, pos: Vec3, player: ServerPlayer?)
} }
@@ -11,13 +11,11 @@ package com.cobblemon.mod.common.api.drop
import com.cobblemon.mod.common.api.events.CobblemonEvents.LOOT_DROPPED import com.cobblemon.mod.common.api.events.CobblemonEvents.LOOT_DROPPED
import com.cobblemon.mod.common.api.events.drops.LootDroppedEvent import com.cobblemon.mod.common.api.events.drops.LootDroppedEvent
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.pokemon.Pokemon
import kotlin.random.Random import kotlin.random.Random
import net.minecraft.network.RegistryFriendlyByteBuf import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.server.level.ServerLevel import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.item.ItemStack
import net.minecraft.world.phys.Vec3 import net.minecraft.world.phys.Vec3
/** /**
@@ -47,11 +45,9 @@ class DropTable {
* Gets a drop list from this table as a list of [DropEntry]. You can specify the range of drop quantity totals * Gets a drop list from this table as a list of [DropEntry]. You can specify the range of drop quantity totals
* that will be possible, or if you leave it blank it will use [DropTable.amount]. * that will be possible, or if you leave it blank it will use [DropTable.amount].
*/ */
fun getDrops(amount: IntRange = this.amount, pokemon: Pokemon? = null): List<DropEntry> { fun getDrops(amount: IntRange = this.amount): List<DropEntry> {
val chosenAmount = amount.random() val chosenAmount = amount.random()
val possibleDrops = entries.filter { val possibleDrops = entries.filter { it.quantity <= chosenAmount }.toMutableList()
it.quantity <= chosenAmount && it.canDrop(pokemon)
}.toMutableList()
if (possibleDrops.isEmpty()) { if (possibleDrops.isEmpty()) {
return emptyList() return emptyList()
@@ -91,10 +87,11 @@ class DropTable {
world: ServerLevel, world: ServerLevel,
pos: Vec3, pos: Vec3,
player: ServerPlayer?, player: ServerPlayer?,
amount: IntRange = this.amount, amount: IntRange = this.amount
pokemon: Pokemon? = null,
) { ) {
val drops = getDrops(amount, pokemon).toMutableList() val drops = getDrops(amount).toMutableList()
val heldItem = (entity as PokemonEntity).pokemon.heldItemNoCopy()
if (!heldItem.isEmpty) entity.spawnAtLocation(heldItem.item)
LOOT_DROPPED.postThen( LOOT_DROPPED.postThen(
event = LootDroppedEvent(this, player, entity, drops), event = LootDroppedEvent(this, player, entity, drops),
ifSucceeded = { it.drops.forEach { it.drop(entity, world, pos, player) } } ifSucceeded = { it.drops.forEach { it.drop(entity, world, pos, player) } }
@@ -1,18 +0,0 @@
/*
* 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.api.drop
import com.cobblemon.mod.common.api.pokemon.evolution.requirement.EvolutionRequirement
import com.cobblemon.mod.common.pokemon.Pokemon
class EvolutionItemDropEntry : ItemDropEntry() {
val requirements: MutableSet<EvolutionRequirement> = mutableSetOf()
override fun canDrop(pokemon: Pokemon?): Boolean = pokemon != null && requirements.all { it.check(pokemon) }
}
@@ -9,7 +9,6 @@
package com.cobblemon.mod.common.api.drop package com.cobblemon.mod.common.api.drop
import com.cobblemon.mod.common.api.serialization.StringIdentifiedObjectAdapter import com.cobblemon.mod.common.api.serialization.StringIdentifiedObjectAdapter
import com.google.gson.annotations.SerializedName
/** /**
* The way an item will be dropped. * The way an item will be dropped.
@@ -29,9 +28,6 @@ enum class ItemDropMethod(val methodName: String) {
TO_INVENTORY("to-inventory"); TO_INVENTORY("to-inventory");
companion object { companion object {
val adapter = StringIdentifiedObjectAdapter( val adapter = StringIdentifiedObjectAdapter { str -> values().firstOrNull { it.methodName == str } }
{ str -> ItemDropMethod.entries.firstOrNull { it.methodName == str } },
{ value -> (value ?: ON_ENTITY).methodName },
)
} }
} }
@@ -11,8 +11,6 @@ package com.cobblemon.mod.common.api.entity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
import net.minecraft.world.damagesource.DamageSource import net.minecraft.world.damagesource.DamageSource
import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.Entity.MoveFunction
import net.minecraft.world.entity.player.Player import net.minecraft.world.entity.player.Player
interface PokemonSideDelegate : EntitySideDelegate<PokemonEntity> { interface PokemonSideDelegate : EntitySideDelegate<PokemonEntity> {
@@ -8,10 +8,6 @@
package com.cobblemon.mod.common.api.events package com.cobblemon.mod.common.api.events
import com.bedrockk.molang.runtime.MoParams
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.MoValue
/** /**
* Something that can be canceled. This is a highly complex class and should only be read by professional engineers. * Something that can be canceled. This is a highly complex class and should only be read by professional engineers.
* *
@@ -25,9 +21,4 @@ abstract class Cancelable {
fun cancel() { fun cancel() {
isCanceled = true isCanceled = true
} }
val cancelFunc: Pair<String, (MoParams) -> MoValue> = "cancel" to {
cancel()
DoubleValue.ONE
}
} }
@@ -42,17 +42,13 @@ import com.cobblemon.mod.common.api.events.pokemon.healing.PokemonHealedEvent
import com.cobblemon.mod.common.api.events.pokemon.interaction.ExperienceCandyUseEvent import com.cobblemon.mod.common.api.events.pokemon.interaction.ExperienceCandyUseEvent
import com.cobblemon.mod.common.api.events.pokemon.interaction.PokemonInteractionGUICreationEvent import com.cobblemon.mod.common.api.events.pokemon.interaction.PokemonInteractionGUICreationEvent
import com.cobblemon.mod.common.api.events.starter.StarterChosenEvent import com.cobblemon.mod.common.api.events.starter.StarterChosenEvent
import com.cobblemon.mod.common.api.events.storage.ChangePCBoxWallpaperEvent
import com.cobblemon.mod.common.api.events.storage.ReleasePokemonEvent import com.cobblemon.mod.common.api.events.storage.ReleasePokemonEvent
import com.cobblemon.mod.common.api.events.storage.RenamePCBoxEvent
import com.cobblemon.mod.common.api.events.storage.WallpaperCollectionEvent
import com.cobblemon.mod.common.api.events.world.BigRootPropagatedEvent import com.cobblemon.mod.common.api.events.world.BigRootPropagatedEvent
import com.cobblemon.mod.common.api.reactive.CancelableObservable import com.cobblemon.mod.common.api.reactive.CancelableObservable
import com.cobblemon.mod.common.api.reactive.EventObservable import com.cobblemon.mod.common.api.reactive.EventObservable
import com.cobblemon.mod.common.api.reactive.Observable.Companion.filter import com.cobblemon.mod.common.api.reactive.Observable.Companion.filter
import com.cobblemon.mod.common.api.reactive.Observable.Companion.map import com.cobblemon.mod.common.api.reactive.Observable.Companion.map
import com.cobblemon.mod.common.api.reactive.SimpleObservable import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.api.riding.events.SelectDriverEvent
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
@@ -162,29 +158,11 @@ object CobblemonEvents {
@JvmField @JvmField
val EXPERIENCE_CANDY_USE_POST = EventObservable<ExperienceCandyUseEvent.Post>() 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 @JvmField
val POKEMON_RELEASED_EVENT_PRE = CancelableObservable<ReleasePokemonEvent.Pre>() val POKEMON_RELEASED_EVENT_PRE = CancelableObservable<ReleasePokemonEvent.Pre>()
@JvmField @JvmField
val POKEMON_RELEASED_EVENT_POST = EventObservable<ReleasePokemonEvent.Post>() val POKEMON_RELEASED_EVENT_POST = EventObservable<ReleasePokemonEvent.Post>()
@JvmField
val RENAME_PC_BOX_EVENT_PRE = CancelableObservable<RenamePCBoxEvent.Pre>()
@JvmField
val RENAME_PC_BOX_EVENT_POST = EventObservable<RenamePCBoxEvent.Post>()
@JvmField
val WALLPAPER_COLLECTION_EVENT = EventObservable<WallpaperCollectionEvent>()
@JvmField
val CHANGE_PC_BOX_WALLPAPER_EVENT_PRE = CancelableObservable<ChangePCBoxWallpaperEvent.Pre>()
@JvmField
val CHANGE_PC_BOX_WALLPAPER_EVENT_POST = EventObservable<ChangePCBoxWallpaperEvent.Post>()
@JvmField @JvmField
val LOOT_DROPPED = CancelableObservable<LootDroppedEvent>() val LOOT_DROPPED = CancelableObservable<LootDroppedEvent>()
@JvmField @JvmField
@@ -212,10 +190,6 @@ object CobblemonEvents {
val HELD_ITEM_PRE = CancelableObservable<HeldItemEvent.Pre>() val HELD_ITEM_PRE = CancelableObservable<HeldItemEvent.Pre>()
@JvmField @JvmField
val HELD_ITEM_POST = EventObservable<HeldItemEvent.Post>() val HELD_ITEM_POST = EventObservable<HeldItemEvent.Post>()
@JvmField
val COSMETIC_ITEM_PRE = CancelableObservable<HeldItemEvent.Pre>()
@JvmField
val COSMETIC_ITEM_POST = EventObservable<HeldItemEvent.Post>()
@JvmField @JvmField
val POKEMON_GAINED = EventObservable<PokemonGainedEvent>() val POKEMON_GAINED = EventObservable<PokemonGainedEvent>()
@@ -258,12 +232,4 @@ object CobblemonEvents {
val HATCH_EGG_PRE = CancelableObservable<HatchEggEvent.Pre>() val HATCH_EGG_PRE = CancelableObservable<HatchEggEvent.Pre>()
@JvmField @JvmField
val HATCH_EGG_POST = EventObservable<HatchEggEvent.Post>() val HATCH_EGG_POST = EventObservable<HatchEggEvent.Post>()
// -------------------------------------------------------------------------------------
//
// Riding
//
// -------------------------------------------------------------------------------------
@JvmField
val SELECT_DRIVER = EventObservable<SelectDriverEvent>()
} }
@@ -8,12 +8,16 @@
package com.cobblemon.mod.common.api.events.battles package com.cobblemon.mod.common.api.events.battles
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.MoValue import com.bedrockk.molang.runtime.value.MoValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.battles.interpreter.BattleContext import com.cobblemon.mod.common.api.battles.interpreter.BattleContext
import com.cobblemon.mod.common.api.battles.model.PokemonBattle import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.ActorType import com.cobblemon.mod.common.api.battles.model.actor.ActorType
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.util.asArrayValue import com.cobblemon.mod.common.util.asArrayValue
import java.util.function.Function
/** /**
* Event fired when a [BattlePokemon] faints. Exposes the [BattlePokemon] that fainted and the [BattleContext] * Event fired when a [BattlePokemon] faints. Exposes the [BattlePokemon] that fainted and the [BattleContext]
@@ -33,6 +37,13 @@ data class BattleFaintedEvent(
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct }, "npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct }, "wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct },
"pokemon" to killed.struct, "pokemon" to killed.struct,
"context" to context.getStruct() "context" to QueryStruct(
hashMapOf(
"type" to Function { StringValue(context.type.name) },
"origin" to Function { context.origin?.struct ?: DoubleValue(0.0) },
"id" to Function { StringValue(context.id) },
"turn_created" to Function { DoubleValue(context.turn.toDouble()) },
)
)
) )
} }
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.api.events.battles
import com.cobblemon.mod.common.api.battles.model.PokemonBattle import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.ActorType import com.cobblemon.mod.common.api.battles.model.actor.ActorType
import com.cobblemon.mod.common.api.events.Cancelable import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
import com.cobblemon.mod.common.util.asArrayValue import com.cobblemon.mod.common.util.asArrayValue
import net.minecraft.network.chat.MutableComponent import net.minecraft.network.chat.MutableComponent
@@ -31,8 +30,6 @@ data class BattleStartedPreEvent (override val battle: PokemonBattle, var reason
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct }, "npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct } "wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct }
) )
val functions = moLangFunctionMap(cancelFunc)
} }
/** /**
@@ -26,7 +26,7 @@ data class TerastallizationEvent(
val battle: PokemonBattle, val battle: PokemonBattle,
val pokemon: BattlePokemon, val pokemon: BattlePokemon,
val teraType: TeraType val teraType: TeraType
) { ) {
val context = mutableMapOf<String, MoValue>( val context = mutableMapOf<String, MoValue>(
"battle" to battle.struct, "battle" to battle.struct,
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct }, "players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
@@ -8,15 +8,9 @@
package com.cobblemon.mod.common.api.events.pokeball package com.cobblemon.mod.common.api.events.pokeball
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
import com.cobblemon.mod.common.api.pokeball.catching.CaptureContext import com.cobblemon.mod.common.api.pokeball.catching.CaptureContext
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.getBooleanOrNull
import com.cobblemon.mod.common.util.getIntOrNull
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.LivingEntity
@@ -38,34 +32,4 @@ class PokeBallCaptureCalculatedEvent(
action(this, thrower) action(this, thrower)
} }
} }
val context = mutableMapOf<String, MoValue>(
"thrower" to thrower.asMostSpecificMoLangValue(),
"pokemon" to pokemonEntity.struct,
"poke_ball" to pokeBallEntity.struct,
"is_successful_capture" to DoubleValue(captureResult.isSuccessfulCapture),
"is_critical_capture" to DoubleValue(captureResult.isCriticalCapture),
)
val functions = moLangFunctionMap(
"set_shakes" to { params ->
val numShakes = params.getInt(0)
val successful = params.getBooleanOrNull(1) ?: (numShakes == 4)
captureResult = CaptureContext(
numberOfShakes = numShakes,
isSuccessfulCapture = successful,
isCriticalCapture = false
)
DoubleValue.ONE
},
"set_critical_capture" to { params ->
val numShakes = params.getIntOrNull(0) ?: 1
captureResult = CaptureContext(
numberOfShakes = numShakes,
isSuccessfulCapture = true,
isCriticalCapture = true
)
DoubleValue.ONE
}
)
} }
@@ -18,17 +18,19 @@ import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.LivingEntity
data class PokemonScannedEvent(val player: ServerPlayer, val scannedPokemonEntityData: PokedexEntityData, val scannedEntity: ScannableEntity) { data class PokemonScannedEvent(val player: ServerPlayer, val scannedPokemonEntityData: PokedexEntityData, val scannedEntity: ScannableEntity) {
val pokedexEntityData: PokedexEntityData
get() = scannedPokemonEntityData
val isOwned: Boolean val isOwned: Boolean
get() = scannedPokemonEntityData.pokemon.getOwnerUUID() == player.uuid get() = scannedPokemonEntityData.ownerUUID == player.uuid
val context = mutableMapOf( val context = mutableMapOf(
"player" to player.asMoLangValue(), "player" to player.asMoLangValue(),
"pokemon" to scannedPokemonEntityData.pokemon.struct, "pokemon" to scannedPokemonEntityData.struct,
"disguise" to (scannedPokemonEntityData.disguise?.struct ?: DoubleValue.ZERO),
"entity" to { "entity" to {
when (scannedEntity) { when (scannedEntity) {
is LivingEntity -> scannedEntity.asMostSpecificMoLangValue() is LivingEntity -> scannedEntity.asMostSpecificMoLangValue()
else -> DoubleValue.ZERO else -> DoubleValue(0.0)
} }
}, },
) )
@@ -1,57 +0,0 @@
/*
* 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.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
import com.cobblemon.mod.common.pokemon.Pokemon
/**
* Fired during EV mutation.
*
* @see [Pre]
* @see [Post]
*/
interface EvGainedEvent {
/**
* The [Stat] having EVs added to itself.
*/
val stat: Stat
/**
* @see EvSource.pokemon
*/
val pokemon: Pokemon get() = this.source.pokemon
/**
* 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
}
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common.api.events.pokemon package com.cobblemon.mod.common.api.events.pokemon
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
/** /**
@@ -19,10 +18,5 @@ import com.cobblemon.mod.common.pokemon.Pokemon
*/ */
data class FriendshipUpdatedEvent( data class FriendshipUpdatedEvent(
val pokemon: Pokemon, val pokemon: Pokemon,
val newFriendshipInitial: Int var newFriendship: Int
) { )
var newFriendship: Int = newFriendshipInitial
set(value) {
field = value.coerceIn(0, Cobblemon.config.maxPokemonFriendship)
}
}
@@ -9,11 +9,13 @@
package com.cobblemon.mod.common.api.events.pokemon package com.cobblemon.mod.common.api.events.pokemon
import com.cobblemon.mod.common.api.events.Cancelable import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.events.pokemon.HeldItemEvent.Post
import com.cobblemon.mod.common.api.events.pokemon.HeldItemEvent.Pre
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
/** /**
* The base for all the events related to held items and cosmetic items. * The base for all the events related to held items.
* *
* @see [Pre] * @see [Pre]
* @see [Post] * @see [Post]
@@ -26,7 +28,7 @@ interface HeldItemEvent {
val pokemon: Pokemon val pokemon: Pokemon
/** /**
* Fired at the start of [Pokemon.swapHeldItem] and [Pokemon.swapCosmeticItem]. * Fired at the start of [Pokemon.swapHeldItem].
* *
* This event should be used to mutate the results of this transaction. * This event should be used to mutate the results of this transaction.
* *
@@ -42,7 +44,7 @@ interface HeldItemEvent {
data class Pre(override val pokemon: Pokemon, var receiving: ItemStack, var returning: ItemStack, var decrement: Boolean) : HeldItemEvent, Cancelable() data class Pre(override val pokemon: Pokemon, var receiving: ItemStack, var returning: ItemStack, var decrement: Boolean) : HeldItemEvent, Cancelable()
/** /**
* Fired at the end of [Pokemon.swapHeldItem] and [Pokemon.swapCosmeticItem]. * Fired at the end of [Pokemon.swapHeldItem].
* *
* @property pokemon The [Pokemon] triggering this event. * @property pokemon The [Pokemon] triggering this event.
* @property received The [ItemStack] considered as received and set to the [pokemon]. This is a copy and mutation will not be taken into account. * @property received The [ItemStack] considered as received and set to the [pokemon]. This is a copy and mutation will not be taken into account.
@@ -9,7 +9,6 @@
package com.cobblemon.mod.common.api.events.pokemon package com.cobblemon.mod.common.api.events.pokemon
import com.bedrockk.molang.runtime.value.DoubleValue import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
/** /**
@@ -24,11 +23,4 @@ class LevelUpEvent(val pokemon: Pokemon, val oldLevel: Int, var newLevel: Int) {
"old_level" to DoubleValue(oldLevel.toDouble()), "old_level" to DoubleValue(oldLevel.toDouble()),
"new_level" to DoubleValue(newLevel.toDouble()) "new_level" to DoubleValue(newLevel.toDouble())
) )
val functions = moLangFunctionMap(
"set_new_level" to {
newLevel = it.getInt(0)
DoubleValue.ONE
}
)
} }
@@ -13,19 +13,20 @@ import com.bedrockk.molang.runtime.value.MoValue
import com.bedrockk.molang.runtime.value.StringValue import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.events.Cancelable import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
import com.cobblemon.mod.common.api.pokedex.AbstractPokedexManager import com.cobblemon.mod.common.api.pokedex.AbstractPokedexManager
import com.cobblemon.mod.common.api.pokedex.FormDexRecord import com.cobblemon.mod.common.api.pokedex.FormDexRecord
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.getPlayer import com.cobblemon.mod.common.util.getPlayer
import com.mojang.datafixers.util.Either
import java.util.UUID import java.util.UUID
/** /**
* Event that fires when a Pokémon's information is gained or updated in the Pokédex. * Event that fires when a Pokémon's information is gained or updated in the Pokédex.
*/ */
sealed interface PokedexDataChangedEvent { sealed interface PokedexDataChangedEvent {
val dataSource: PokedexEntityData val dataSource: Either<PokedexEntityData, Pokemon>
val knowledge: PokedexEntryProgress val knowledge: PokedexEntryProgress
val playerUUID: UUID val playerUUID: UUID
val record: FormDexRecord val record: FormDexRecord
@@ -36,24 +37,22 @@ sealed interface PokedexDataChangedEvent {
fun getContext(): MutableMap<String, MoValue> { fun getContext(): MutableMap<String, MoValue> {
return mutableMapOf( return mutableMapOf(
"player" to (playerUUID.getPlayer()?.asMoLangValue() ?: DoubleValue.ZERO), "player" to (playerUUID.getPlayer()?.asMoLangValue() ?: DoubleValue.ZERO),
"pokemon" to dataSource.pokemon.struct, "pokemon" to dataSource.map({ DoubleValue.ZERO }, { it.struct }),
"disguise" to (dataSource.disguise?.struct ?: DoubleValue.ZERO), "data" to dataSource.map({ it.struct }, { DoubleValue.ZERO }),
"knowledge" to StringValue(knowledge.name.lowercase()), "knowledge" to StringValue(knowledge.name.lowercase()),
"pokedex" to pokedexManager.struct "pokedex" to pokedexManager.struct
) )
} }
class Pre( class Pre(
override val dataSource: PokedexEntityData, override val dataSource: Either<PokedexEntityData, Pokemon>,
override val knowledge: PokedexEntryProgress, override val knowledge: PokedexEntryProgress,
override val playerUUID: UUID, override val playerUUID: UUID,
override val record: FormDexRecord override val record: FormDexRecord
) : PokedexDataChangedEvent, Cancelable() { ) : PokedexDataChangedEvent, Cancelable()
val functions = moLangFunctionMap(cancelFunc)
}
class Post( class Post(
override val dataSource: PokedexEntityData, override val dataSource: Either<PokedexEntityData, Pokemon>,
override val knowledge: PokedexEntryProgress, override val knowledge: PokedexEntryProgress,
override val playerUUID: UUID, override val playerUUID: UUID,
override val record: FormDexRecord override val record: FormDexRecord
@@ -8,12 +8,8 @@
package com.cobblemon.mod.common.api.events.pokemon package com.cobblemon.mod.common.api.events.pokemon
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.StringValue import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.server
import java.util.UUID import java.util.UUID
data class PokemonGainedEvent( data class PokemonGainedEvent(
@@ -24,8 +20,4 @@ data class PokemonGainedEvent(
"player_id" to StringValue(playerId.toString()), "player_id" to StringValue(playerId.toString()),
"pokemon" to pokemon.struct "pokemon" to pokemon.struct
) )
val functions = moLangFunctionMap(
"player" to { server()?.playerList?.getPlayer(playerId)?.asMoLangValue() ?: DoubleValue.ZERO },
)
} }
@@ -8,10 +8,7 @@
package com.cobblemon.mod.common.api.events.pokemon.evolution package com.cobblemon.mod.common.api.events.pokemon.evolution
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.events.Cancelable import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
@@ -28,11 +25,4 @@ import com.cobblemon.mod.common.pokemon.Pokemon
data class EvolutionAcceptedEvent( data class EvolutionAcceptedEvent(
override val pokemon: Pokemon, override val pokemon: Pokemon,
override val evolution: Evolution override val evolution: Evolution
) : Cancelable(), EvolutionEvent { ) : Cancelable(), EvolutionEvent
val context = mutableMapOf<String, MoValue>(
"pokemon" to pokemon.struct,
"evolution" to evolution.asMoLangValue()
)
val functions = moLangFunctionMap(cancelFunc)
}
@@ -8,8 +8,6 @@
package com.cobblemon.mod.common.api.events.pokemon.evolution package com.cobblemon.mod.common.api.events.pokemon.evolution
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
@@ -25,9 +23,4 @@ import com.cobblemon.mod.common.pokemon.Pokemon
data class EvolutionCompleteEvent( data class EvolutionCompleteEvent(
override val pokemon: Pokemon, override val pokemon: Pokemon,
override val evolution: Evolution override val evolution: Evolution
) : EvolutionEvent { ) : EvolutionEvent
val context = mutableMapOf<String, MoValue>(
"pokemon" to pokemon.struct,
"evolution" to evolution.asMoLangValue()
)
}
@@ -8,13 +8,8 @@
package com.cobblemon.mod.common.api.events.pokemon.evolution package com.cobblemon.mod.common.api.events.pokemon.evolution
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.getBoolean
/** /**
* An event fired when [Evolution.test] has been performed. * An event fired when [Evolution.test] has been performed.
@@ -30,18 +25,4 @@ data class EvolutionTestedEvent(
override val evolution: Evolution, override val evolution: Evolution,
val originalResult: Boolean, val originalResult: Boolean,
var result: Boolean var result: Boolean
) : EvolutionEvent { ) : EvolutionEvent
val context = mutableMapOf<String, MoValue>(
"pokemon" to pokemon.struct,
"evolution" to evolution.asMoLangValue(),
"original_result" to DoubleValue(originalResult),
)
val functions = moLangFunctionMap(
"result" to { DoubleValue(result) },
"set_result" to {
result = it.getBoolean(0)
DoubleValue.ONE
}
)
}
@@ -16,9 +16,6 @@ import java.util.UUID
data class PokemonInteractionGUICreationEvent( data class PokemonInteractionGUICreationEvent(
val pokemonID: UUID, val pokemonID: UUID,
val mountShoulder: Boolean, val mountShoulder: Boolean,
val giveHeld: Boolean,
val giveCosmetic: Boolean,
val canRide: Boolean,
val options: Multimap<Orientation, InteractWheelOption> val options: Multimap<Orientation, InteractWheelOption>
) { ) {
fun addFillingOption(option: InteractWheelOption) { fun addFillingOption(option: InteractWheelOption) {
@@ -1,52 +0,0 @@
/*
* 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.api.events.storage
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.storage.pc.PCBox
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
/**
* Events fired whenever a player changes their PC Wallpaper.
* Has a cancelable [Pre] event and a [Post] which gets fired after the change.
*
* @author JustAHuman-xD
* @since February 14th, 2025
*/
interface ChangePCBoxWallpaperEvent {
/**
* The [ServerPlayer] who is changing their wallpaper
*/
val player: ServerPlayer
/**
* The [PCBox] whose wallpaper is being changed
*/
val box: PCBox
/**
* The location of the wallpaper that is being changed to. Can be modified in the [Pre] event.
* NOTE: Changing this to a wallpaper that does not exist on the client, will result in a purple/black fallback texture being displayed.
*/
val wallpaper: ResourceLocation
class Pre(
override val player: ServerPlayer,
override val box: PCBox,
override var wallpaper: ResourceLocation
) : ChangePCBoxWallpaperEvent, Cancelable()
class Post(
override val player: ServerPlayer,
override val box: PCBox,
override val wallpaper: ResourceLocation
) : ChangePCBoxWallpaperEvent
}
@@ -1,50 +0,0 @@
/*
* 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.api.events.storage
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.storage.pc.PCBox
import net.minecraft.server.level.ServerPlayer
/**
* Events fired whenever a player renames one of their PC boxes.
* Has a cancelable [Pre] event and a [Post] which gets fired after the change.
*
* @author JustAHuman-xD
* @since February 14th, 2025
*/
interface RenamePCBoxEvent {
/**
* The [ServerPlayer] who is changing their wallpaper
*/
val player: ServerPlayer
/**
* The [PCBox] whose wallpaper is being changed
*/
val box: PCBox
/**
* The new box name being used. This can be modified in the [Pre] event.
*/
val name: String
class Pre(
override val player: ServerPlayer,
override val box: PCBox,
override var name: String
) : RenamePCBoxEvent, Cancelable()
class Post(
override val player: ServerPlayer,
override val box: PCBox,
override val name: String
) : RenamePCBoxEvent
}
@@ -1,26 +0,0 @@
/*
* 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.api.events.storage
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
/**
* Event being fired whenever the client connects to a server and "requests" what wallpapers are available for it to choose from.
* Mods can listen to this event and remove available options from the client when they connect, essentially causing them to not exist client-side
*
* NOTE: Adding wallpapers here that do not exist on the client, will result in the purple/black fallback texture being displayed client-side.
*
* @author JustAHuman-xD
* @since February 14th, 2025
*/
data class WallpaperCollectionEvent(
val player: ServerPlayer,
val wallpapers: MutableList<ResourceLocation>
)
@@ -11,7 +11,7 @@ package com.cobblemon.mod.common.api.fishing
import com.cobblemon.mod.common.CobblemonItemComponents import com.cobblemon.mod.common.CobblemonItemComponents
import com.cobblemon.mod.common.api.data.JsonDataRegistry import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.reactive.SimpleObservable import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.net.messages.client.data.FishingBaitRegistrySyncPacket import com.cobblemon.mod.common.net.messages.client.fishing.FishingBaitRegistrySyncPacket
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.cobblemonResource import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.Gson import com.google.gson.Gson
@@ -9,7 +9,7 @@
package com.cobblemon.mod.common.api.fossil package com.cobblemon.mod.common.api.fossil
import com.cobblemon.mod.common.api.pokemon.PokemonProperties import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import net.minecraft.advancements.critereon.ItemPredicate import com.cobblemon.mod.common.pokemon.evolution.predicate.NbtItemPredicate
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.network.chat.MutableComponent import net.minecraft.network.chat.MutableComponent
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
@@ -19,7 +19,7 @@ import net.minecraft.world.item.ItemStack
class Fossil( class Fossil(
identifier: ResourceLocation, identifier: ResourceLocation,
val result: PokemonProperties, val result: PokemonProperties,
val fossils: List<ItemPredicate> val fossils: List<NbtItemPredicate>
): StringRepresentable { ): StringRepresentable {
@Transient @Transient
@@ -13,15 +13,15 @@ import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
import com.cobblemon.mod.common.api.data.JsonDataRegistry import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.pokemon.PokemonProperties import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.reactive.SimpleObservable import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.net.messages.client.data.FossilRegistrySyncPacket import com.cobblemon.mod.common.net.messages.client.fossil.FossilRegistrySyncPacket
import com.cobblemon.mod.common.pokemon.evolution.adapters.LegacyItemConditionWrapperAdapter import com.cobblemon.mod.common.pokemon.evolution.adapters.NbtItemPredicateAdapter
import com.cobblemon.mod.common.pokemon.evolution.predicate.NbtItemPredicate
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.adapters.ItemLikeConditionAdapter import com.cobblemon.mod.common.util.adapters.ItemLikeConditionAdapter
import com.cobblemon.mod.common.util.adapters.pokemonPropertiesShortAdapter import com.cobblemon.mod.common.util.adapters.pokemonPropertiesShortAdapter
import com.cobblemon.mod.common.util.cobblemonResource import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType import net.minecraft.server.packs.PackType
@@ -40,7 +40,7 @@ object Fossils: JsonDataRegistry<Fossil> {
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter) .registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
.registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter) .registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter) .registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter) .registerTypeAdapter(NbtItemPredicate::class.java, NbtItemPredicateAdapter)
.create() .create()
override val typeToken: TypeToken<Fossil> = TypeToken.get(Fossil::class.java) override val typeToken: TypeToken<Fossil> = TypeToken.get(Fossil::class.java)
@@ -10,7 +10,7 @@ package com.cobblemon.mod.common.api.fossil
import com.cobblemon.mod.common.api.data.JsonDataRegistry import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.reactive.SimpleObservable import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.net.messages.client.data.NaturalMaterialRegistrySyncPacket import com.cobblemon.mod.common.net.messages.client.fossil.NaturalMaterialRegistrySyncPacket
import com.cobblemon.mod.common.registry.ItemTagCondition import com.cobblemon.mod.common.registry.ItemTagCondition
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.adapters.ItemLikeConditionAdapter import com.cobblemon.mod.common.util.adapters.ItemLikeConditionAdapter
@@ -12,10 +12,12 @@ import com.cobblemon.mod.common.api.text.font
import com.cobblemon.mod.common.client.gui.battle.BattleOverlay.Companion.PORTRAIT_DIAMETER import com.cobblemon.mod.common.client.gui.battle.BattleOverlay.Companion.PORTRAIT_DIAMETER
import com.cobblemon.mod.common.client.render.SpriteType import com.cobblemon.mod.common.client.render.SpriteType
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
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.RenderContext
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.entity.PoseType import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.util.toHex import com.cobblemon.mod.common.util.toHex
import com.mojang.authlib.minecraft.client.MinecraftClient
import com.mojang.blaze3d.platform.GlStateManager import com.mojang.blaze3d.platform.GlStateManager
import com.mojang.blaze3d.platform.Lighting import com.mojang.blaze3d.platform.Lighting
import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.systems.RenderSystem
@@ -207,6 +209,7 @@ fun drawPosablePortrait(
contextScale: Float = 1F, contextScale: Float = 1F,
reversed: Boolean = false, reversed: Boolean = false,
state: PosableState, state: PosableState,
repository: VaryingModelRepository<*>,
partialTicks: Float, partialTicks: Float,
limbSwing: Float = 0F, limbSwing: Float = 0F,
limbSwingAmount: Float = 0F, limbSwingAmount: Float = 0F,
@@ -224,16 +227,16 @@ fun drawPosablePortrait(
matrixStack.scale(scale, scale, -scale) matrixStack.scale(scale, scale, -scale)
matrixStack.translate(0.0, -PORTRAIT_DIAMETER / 18.0, 0.0) matrixStack.translate(0.0, -PORTRAIT_DIAMETER / 18.0, 0.0)
val sprite = VaryingModelRepository.getSprite(identifier, state, SpriteType.PORTRAIT); val sprite = repository.getSprite(identifier, state, SpriteType.PORTRAIT);
if (sprite == null) { if (sprite == null) {
val model = VaryingModelRepository.getPoser(identifier, state) val model = repository.getPoser(identifier, state)
state.currentModel = model state.currentModel = model
val texture = VaryingModelRepository.getTexture(identifier, state) val texture = repository.getTexture(identifier, state)
val context = RenderContext() val context = RenderContext()
model.context = context model.context = context
VaryingModelRepository.getTextureNoSubstitute(identifier, state).let { context.put(RenderContext.TEXTURE, it) } repository.getTextureNoSubstitute(identifier, state).let { context.put(RenderContext.TEXTURE, it) }
context.put(RenderContext.SCALE, contextScale) context.put(RenderContext.SCALE, contextScale)
context.put(RenderContext.SPECIES, identifier) context.put(RenderContext.SPECIES, identifier)
context.put(RenderContext.ASPECTS, state.currentAspects) context.put(RenderContext.ASPECTS, state.currentAspects)
@@ -252,7 +255,7 @@ fun drawPosablePortrait(
matrixStack.translate( matrixStack.translate(
model.portraitTranslation.x * if (reversed) -1F else 1F, model.portraitTranslation.x * if (reversed) -1F else 1F,
model.portraitTranslation.y + 1.5 * model.portraitScale, model.portraitTranslation.y,
model.portraitTranslation.z - 4 model.portraitTranslation.z - 4
) )
matrixStack.scale(model.portraitScale, model.portraitScale, 1 / model.portraitScale) matrixStack.scale(model.portraitScale, model.portraitScale, 1 / model.portraitScale)
@@ -269,7 +272,7 @@ fun drawPosablePortrait(
val packedLight = LightTexture.pack(11, 7) val packedLight = LightTexture.pack(11, 7)
val colour = toHex(r, g, b, a) val colour = toHex(r, g, b, a)
model.withLayerContext(immediate, state, VaryingModelRepository.getLayers(identifier, state)) { model.withLayerContext(immediate, state, repository.getLayers(identifier, state)) {
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, colour) model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, colour)
immediate.endBatch() immediate.endBatch()
} }
@@ -285,6 +288,7 @@ fun drawPosablePortrait(
} }
fun drawProfile( fun drawProfile(
repository: VaryingModelRepository<*>,
resourceIdentifier: ResourceLocation, resourceIdentifier: ResourceLocation,
matrixStack: PoseStack, matrixStack: PoseStack,
state: PosableState, state: PosableState,
@@ -294,16 +298,16 @@ fun drawProfile(
RenderSystem.applyModelViewMatrix() RenderSystem.applyModelViewMatrix()
matrixStack.scale(scale, scale, -scale) matrixStack.scale(scale, scale, -scale)
val sprite = VaryingModelRepository.getSprite(resourceIdentifier, state, SpriteType.PROFILE) val sprite = repository.getSprite(resourceIdentifier, state, SpriteType.PROFILE)
if (sprite == null) { if (sprite == null) {
val model = VaryingModelRepository.getPoser(resourceIdentifier, state) val model = repository.getPoser(resourceIdentifier, state)
val texture = VaryingModelRepository.getTexture(resourceIdentifier, state) val texture = repository.getTexture(resourceIdentifier, state)
val context = RenderContext() val context = RenderContext()
model.context = context model.context = context
VaryingModelRepository.getTextureNoSubstitute(resourceIdentifier, state).let { context.put(RenderContext.TEXTURE, it) } repository.getTextureNoSubstitute(resourceIdentifier, state).let { context.put(RenderContext.TEXTURE, it) }
context.put(RenderContext.SCALE, 1F) context.put(RenderContext.SCALE, 1F)
context.put(RenderContext.SPECIES, resourceIdentifier) context.put(RenderContext.SPECIES, resourceIdentifier)
context.put(RenderContext.ASPECTS, state.currentAspects) context.put(RenderContext.ASPECTS, state.currentAspects)
@@ -315,11 +319,7 @@ fun drawProfile(
state.setPoseToFirstSuitable(PoseType.PORTRAIT) state.setPoseToFirstSuitable(PoseType.PORTRAIT)
state.updatePartialTicks(partialTicks) state.updatePartialTicks(partialTicks)
model.applyAnimations(null, state, 0F, 0F, 0F, 0F, 0F) model.applyAnimations(null, state, 0F, 0F, 0F, 0F, 0F)
matrixStack.translate( matrixStack.translate(model.profileTranslation.x, model.profileTranslation.y, model.profileTranslation.z - 4.0)
model.profileTranslation.x,
model.profileTranslation.y + 1.5 * model.profileScale,
model.profileTranslation.z - 4.0
)
matrixStack.scale(model.profileScale, model.profileScale, 1 / model.profileScale) matrixStack.scale(model.profileScale, model.profileScale, 1 / model.profileScale)
// matrixStack.multiply(rotation) // matrixStack.multiply(rotation)
val quaternion1 = Axis.YP.rotationDegrees(-32F * if (false) -1F else 1F) val quaternion1 = Axis.YP.rotationDegrees(-32F * if (false) -1F else 1F)
@@ -337,7 +337,7 @@ fun drawProfile(
RenderSystem.setShaderLights(light1, light2) RenderSystem.setShaderLights(light1, light2)
val packedLight = LightTexture.pack(11, 7) val packedLight = LightTexture.pack(11, 7)
model.withLayerContext(bufferSource, state, VaryingModelRepository.getLayers(resourceIdentifier, state)) { model.withLayerContext(bufferSource, state, repository.getLayers(resourceIdentifier, state)) {
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, -0x1) model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
bufferSource.endBatch() bufferSource.endBatch()
} }
@@ -36,8 +36,6 @@ import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
import com.cobblemon.mod.common.api.pokedex.PokedexManager import com.cobblemon.mod.common.api.pokedex.PokedexManager
import com.cobblemon.mod.common.api.pokedex.SeenCount import com.cobblemon.mod.common.api.pokedex.SeenCount
import com.cobblemon.mod.common.api.pokedex.SeenPercent import com.cobblemon.mod.common.api.pokedex.SeenPercent
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.api.pokemon.stats.Stats import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.api.scripting.CobblemonScripts import com.cobblemon.mod.common.api.scripting.CobblemonScripts
import com.cobblemon.mod.common.api.spawning.context.SpawningContext import com.cobblemon.mod.common.api.spawning.context.SpawningContext
@@ -62,12 +60,8 @@ import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimati
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
import com.cobblemon.mod.common.pokemon.Gender
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.Species import com.cobblemon.mod.common.pokemon.Species
import com.cobblemon.mod.common.pokemon.evolution.variants.ItemInteractionEvolution
import com.cobblemon.mod.common.pokemon.evolution.variants.LevelUpEvolution
import com.cobblemon.mod.common.pokemon.evolution.variants.TradeEvolution
import com.cobblemon.mod.common.util.* import com.cobblemon.mod.common.util.*
import com.mojang.datafixers.util.Either import com.mojang.datafixers.util.Either
import java.util.UUID import java.util.UUID
@@ -1008,82 +1002,6 @@ object MoLangFunctions {
} }
) )
val pokemonPropertiesFunctions: MutableList<(PokemonProperties) -> HashMap<String, java.util.function.Function<MoParams, Any>>> = mutableListOf(
{ props ->
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
map.put("level") { DoubleValue(props.level?.toDouble() ?: 0) }
map.put("set_level") { params ->
props.level = params.getIntOrNull(0)
return@put DoubleValue.ONE
}
map.put("shiny") { DoubleValue(props.shiny) }
map.put("set_shiny") { params ->
props.shiny = params.getBooleanOrNull(0)
return@put DoubleValue.ONE
}
map.put("species") { props.species?.let { StringValue(it) } ?: DoubleValue.ZERO }
map.put("set_species") { params ->
props.species = params.getStringOrNull(0)
return@put DoubleValue.ONE
}
map.put("gender") { props.gender?.let { StringValue(it.name) } ?: DoubleValue.ZERO }
map.put("set_gender") { params ->
props.gender = params.getStringOrNull(0)?.let { Gender.valueOf(it) }
return@put DoubleValue.ONE
}
map.put("form") { props.form?.let { StringValue(it) } ?: DoubleValue.ZERO }
map.put("ivs") {
val ivs = props.ivs
if (ivs == null) {
return@put DoubleValue.ZERO
} else {
return@put ivs.struct
}
}
map.put("evs") {
val evs = props.evs
if (evs == null) {
return@put DoubleValue.ZERO
} else {
return@put evs.struct
}
}
map.put("friendship") { DoubleValue(props.friendship?.toDouble() ?: DoubleValue.ZERO) }
map.put("set_friendship") { params ->
props.friendship = params.getIntOrNull(0)
return@put DoubleValue.ONE
}
map.put("create") { params ->
val pokemon = props.create()
return@put pokemon.struct
}
map
}
)
val evolutionFunctions: MutableList<(Evolution) -> HashMap<String, java.util.function.Function<MoParams, Any>>> = mutableListOf(
{ evolution ->
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
map.put("result") { evolution.result.asMoLangValue() }
if (evolution is LevelUpEvolution) {
map.put("is_level_up") { DoubleValue.ONE }
} else if (evolution is TradeEvolution) {
map.put("is_trade") { DoubleValue.ONE }
} else if (evolution is ItemInteractionEvolution) {
map.put("is_item") { DoubleValue.ONE }
}
map.put("is_optional") { DoubleValue(evolution.optional) }
map.put("consumes_held_item") { DoubleValue(evolution.consumeHeldItem) }
map
}
)
fun Holder<Biome>.asBiomeMoLangValue() = asMoLangValue(Registries.BIOME).addFunctions(biomeFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap()) fun Holder<Biome>.asBiomeMoLangValue() = asMoLangValue(Registries.BIOME).addFunctions(biomeFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
fun Holder<Level>.asWorldMoLangValue() = asMoLangValue(Registries.DIMENSION).addFunctions(worldFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap()) fun Holder<Level>.asWorldMoLangValue() = asMoLangValue(Registries.DIMENSION).addFunctions(worldFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
fun Holder<Block>.asBlockMoLangValue() = asMoLangValue(Registries.BLOCK).addFunctions(blockFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap()) fun Holder<Block>.asBlockMoLangValue() = asMoLangValue(Registries.BLOCK).addFunctions(blockFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
@@ -1116,24 +1034,6 @@ object MoLangFunctions {
return value return value
} }
fun PokemonProperties.asMoLangValue(): ObjectValue<PokemonProperties> {
val value = ObjectValue(
obj = this,
stringify = { it.asString() }
)
value.addFunctions(pokemonPropertiesFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
return value
}
fun Evolution.asMoLangValue(): ObjectValue<Evolution> {
val value = ObjectValue(
obj = this,
stringify = { it.toString() }
)
value.addFunctions(evolutionFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
return value
}
fun PCStore.asMoLangValue(): ObjectValue<PCStore> { fun PCStore.asMoLangValue(): ObjectValue<PCStore> {
val value = ObjectValue( val value = ObjectValue(
obj = this, obj = this,
@@ -1270,24 +1170,6 @@ object MoLangFunctions {
return this return this
} }
fun moLangFunctionMap(
vararg functions: Pair<String, (MoParams) -> MoValue>
): Map<String, (MoParams) -> MoValue> {
return functions.toMap()
}
fun queryStructOf(
vararg functions: Pair<String, (MoParams) -> MoValue>
): QueryStruct {
return QueryStruct(
hashMapOf<String, java.util.function.Function<MoParams, Any>>(
*functions.map { (name, func) ->
name to java.util.function.Function<MoParams, Any> { params -> func(params) }
}.toTypedArray()
)
)
}
fun MoLangRuntime.setup(): MoLangRuntime { fun MoLangRuntime.setup(): MoLangRuntime {
environment.query.addStandardFunctions() environment.query.addStandardFunctions()
return this return this
@@ -54,15 +54,7 @@ class BenchedMoves : Iterable<BenchedMove> {
} }
} }
fun add(benchedMove: BenchedMove): Boolean { fun add(benchedMove: BenchedMove) = doThenEmit { benchedMoves.add(benchedMove) }
if (any { it.moveTemplate == benchedMove.moveTemplate }) {
return false
}
doThenEmit { benchedMoves.add(benchedMove) }
return true
}
fun addAll(benchedMoves: Iterable<BenchedMove>) = doThenEmit { this.benchedMoves.addAll(benchedMoves) } fun addAll(benchedMoves: Iterable<BenchedMove>) = doThenEmit { this.benchedMoves.addAll(benchedMoves) }
fun clear() = doThenEmit { benchedMoves.clear() } fun clear() = doThenEmit { benchedMoves.clear() }
fun remove(benchedMove: BenchedMove) = doThenEmit { benchedMoves.remove(benchedMove) } fun remove(benchedMove: BenchedMove) = doThenEmit { benchedMoves.remove(benchedMove) }
@@ -134,21 +134,18 @@ class MoveSet : Iterable<Move> {
return json return json
} }
fun add(move: Move): Boolean { fun add(move: Move) {
if (any { it.template == move.template }) { if (any { it.template == move.template }) {
return false return
} }
for (i in 0 until MOVE_COUNT) { for (i in 0 until MOVE_COUNT) {
if (moves[i] == null) { if (moves[i] == null) {
moves[i] = move moves[i] = move
move.observable.subscribe { this.update() } move.observable.subscribe { this.update() }
update() update()
return true return
} }
} }
return false
} }
fun update() { fun update() {
@@ -57,7 +57,6 @@ class NPCClass {
var isInvulnerable = false var isInvulnerable = false
var isLeashable = true var isLeashable = true
var allowProjectileHits = true var allowProjectileHits = true
var hideNameTag = false
// If you're adding stuff here, add it to NPCPreset and NPCClassAdapter too // If you're adding stuff here, add it to NPCPreset and NPCClassAdapter too
@@ -98,7 +97,6 @@ class NPCClass {
buffer.writeBoolean(isInvulnerable) buffer.writeBoolean(isInvulnerable)
buffer.writeBoolean(isLeashable) buffer.writeBoolean(isLeashable)
buffer.writeBoolean(allowProjectileHits) buffer.writeBoolean(allowProjectileHits)
buffer.writeBoolean(hideNameTag)
} }
fun decode(buffer: RegistryFriendlyByteBuf) { fun decode(buffer: RegistryFriendlyByteBuf) {
@@ -150,6 +148,5 @@ class NPCClass {
isInvulnerable = buffer.readBoolean() isInvulnerable = buffer.readBoolean()
isLeashable = buffer.readBoolean() isLeashable = buffer.readBoolean()
allowProjectileHits = buffer.readBoolean() allowProjectileHits = buffer.readBoolean()
hideNameTag = buffer.readBoolean()
} }
} }
@@ -37,7 +37,6 @@ class NPCPreset {
var isInvulnerable: Boolean? = null var isInvulnerable: Boolean? = null
var isLeashable: Boolean? = null var isLeashable: Boolean? = null
var allowProjectileHits: Boolean? = null var allowProjectileHits: Boolean? = null
var hideNameTag: Boolean? = null
fun applyTo(npcClass: NPCClass) { fun applyTo(npcClass: NPCClass) {
resourceIdentifier?.let { npcClass.resourceIdentifier = it } resourceIdentifier?.let { npcClass.resourceIdentifier = it }
@@ -64,6 +63,5 @@ class NPCPreset {
isInvulnerable?.let { npcClass.isInvulnerable = it } isInvulnerable?.let { npcClass.isInvulnerable = it }
isLeashable?.let { npcClass.isLeashable = it } isLeashable?.let { npcClass.isLeashable = it }
allowProjectileHits?.let { npcClass.allowProjectileHits = it } allowProjectileHits?.let { npcClass.allowProjectileHits = it }
hideNameTag?.let { npcClass.hideNameTag = it }
} }
} }
@@ -78,7 +78,6 @@ any number of presets and the properties of those presets will be merged into th
"skill": 5, "skill": 5,
"autoHealParty": true, "autoHealParty": true,
"randomizePartyOrder": true, "randomizePartyOrder": true,
"hideNameTag": false,
"party": { "party": {
"type": "simple", "type": "simple",
"pokemon": [ "pokemon": [
@@ -320,7 +319,7 @@ a single battle challenge and this is a dynamic party, there will also be a `q.p
"pokemon": "weedle", "pokemon": "weedle",
"weight": "10", "weight": "10",
"selectableTimes": "2", "selectableTimes": "2",
"levelVariation": "2", "levelVariation": "2"
"npcLevels": "1-8" "npcLevels": "1-8"
}, },
{ {
@@ -412,7 +411,4 @@ Pokémon in the party.
### ai ### ai
The AI property is an array of brain configurations. This is used to configure the behaviours of the NPC. See The AI property is an array of brain configurations. This is used to configure the behaviours of the NPC. See
the documentation for brain configurations at [AI Configuration](../ai/config/README.md). the documentation for brain configurations at [AI Configuration](../ai/config/README.md).
### hideNameTag
Whether the NPC's nametag should be hidden or not. Defaults to false.
@@ -8,6 +8,8 @@
package com.cobblemon.mod.common.api.permission package com.cobblemon.mod.common.api.permission
import com.cobblemon.mod.common.command.AbandonMultiTeam
object CobblemonPermissions { object CobblemonPermissions {
private const val COMMAND_PREFIX = "command." private const val COMMAND_PREFIX = "command."
@@ -16,7 +18,6 @@ object CobblemonPermissions {
val CHANGE_EYE_HEIGHT = this.create("${COMMAND_PREFIX}changeeyeheight", PermissionLevel.ALL_COMMANDS) val CHANGE_EYE_HEIGHT = this.create("${COMMAND_PREFIX}changeeyeheight", PermissionLevel.ALL_COMMANDS)
val CHANGE_SCALE_AND_SIZE = this.create("${COMMAND_PREFIX}changescaleandsize", PermissionLevel.ALL_COMMANDS) val CHANGE_SCALE_AND_SIZE = this.create("${COMMAND_PREFIX}changescaleandsize", PermissionLevel.ALL_COMMANDS)
val CHANGE_WALK_SPEED = this.create("${COMMAND_PREFIX}changewalkspeed", PermissionLevel.ALL_COMMANDS) val CHANGE_WALK_SPEED = this.create("${COMMAND_PREFIX}changewalkspeed", PermissionLevel.ALL_COMMANDS)
val CHANGE_JOINT_SCALE = this.create("${COMMAND_PREFIX}changejointscale", PermissionLevel.ALL_COMMANDS)
val CHECKSPAWNS = this.create("${COMMAND_PREFIX}checkspawns", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS) val CHECKSPAWNS = this.create("${COMMAND_PREFIX}checkspawns", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
val GET_NBT = this.create("${COMMAND_PREFIX}getnbt", PermissionLevel.ALL_COMMANDS) val GET_NBT = this.create("${COMMAND_PREFIX}getnbt", PermissionLevel.ALL_COMMANDS)
@@ -63,9 +64,6 @@ object CobblemonPermissions {
val POKEBOX = this.create("${COMMAND_PREFIX}pokebox", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS) val POKEBOX = this.create("${COMMAND_PREFIX}pokebox", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
val RENAMEBOX = this.create("${COMMAND_PREFIX}renamebox", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
val CHANGE_WALLPAPER = this.create("${COMMAND_PREFIX}changewallpaper", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
val TEST_STORE = this.create("${COMMAND_PREFIX}teststore", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS) val TEST_STORE = this.create("${COMMAND_PREFIX}teststore", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
val QUERY_LEARNSET = this.create("${COMMAND_PREFIX}querylearnset", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS) val QUERY_LEARNSET = this.create("${COMMAND_PREFIX}querylearnset", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
@@ -86,8 +84,6 @@ object CobblemonPermissions {
val RUN_MOLANG_SCRIPT = this.create("${COMMAND_PREFIX}runmolangscript", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS) 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 fun all(): Iterable<Permission> = this.permissions
private fun create(node: String, level: PermissionLevel): Permission { private fun create(node: String, level: PermissionLevel): Permission {
@@ -202,8 +202,6 @@ object PokeBalls : JsonDataRegistry<PokeBall> {
// Luxury ball effect, low priority as it must be triggered before soothe bell as of gen 4 // Luxury ball effect, low priority as it must be triggered before soothe bell as of gen 4
CobblemonEvents.FRIENDSHIP_UPDATED.subscribe(priority = Priority.LOW) { event -> CobblemonEvents.FRIENDSHIP_UPDATED.subscribe(priority = Priority.LOW) { event ->
var increment = (event.newFriendship - event.pokemon.friendship).toFloat() var increment = (event.newFriendship - event.pokemon.friendship).toFloat()
if (increment <= 0) //these affects are only meant to affect positive gains
return@subscribe
if (increment <= 1F) { if (increment <= 1F) {
event.pokemon.caughtBall.effects.filterIsInstance<FriendshipEarningBoostEffect>() event.pokemon.caughtBall.effects.filterIsInstance<FriendshipEarningBoostEffect>()
.forEach { increment *= it.multiplier } .forEach { increment *= it.multiplier }
@@ -1,53 +0,0 @@
/*
* 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.api.pokeball.catching.calculators
import com.cobblemon.mod.common.api.pokeball.catching.CaptureContext
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.pokedex
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.LivingEntity
/**
* An influencer on capture results based on Pokedex data.
*/
interface PokedexStatusCaptureInfluencer {
/**
* Attempts to influence the [context] of a capture.
*
* @param thrower The [LivingEntity] that threw the Pokeball
* @param target The [PokemonEntity] attempting to capture.
* @param context The calculated [CaptureContext].
* @return The final [CaptureContext].
*/
fun influence(thrower: LivingEntity, target: PokemonEntity, context: CaptureContext): CaptureContext {
if (!context.isSuccessfulCapture) {
return context
}
val player = thrower as? ServerPlayer ?: return context
val pokedex = player.pokedex()
val speciesId = target.pokemon.species.resourceIdentifier
val formName = target.pokemon.form.name
val hasCaughtStatus = pokedex.getOrCreateSpeciesRecord(speciesId)
.getOrCreateFormRecord(formName)
.knowledge == PokedexEntryProgress.CAUGHT
// In modern games when the catch is a success and the Pokémon has already been registered to the Pokédex
// the catch becomes a critical capture and only requires one shake
return if (hasCaughtStatus) {
CaptureContext(
numberOfShakes = 1,
isSuccessfulCapture = true,
isCriticalCapture = true
)
} else context
}
}
@@ -42,10 +42,7 @@ class BaseStatModifier(
override fun behavior(thrower: LivingEntity, pokemon: Pokemon): CatchRateModifier.Behavior = CatchRateModifier.Behavior.MULTIPLY override fun behavior(thrower: LivingEntity, pokemon: Pokemon): CatchRateModifier.Behavior = CatchRateModifier.Behavior.MULTIPLY
override fun isValid(thrower: LivingEntity, pokemon: Pokemon): Boolean { override fun isValid(thrower: LivingEntity, pokemon: Pokemon): Boolean = pokemon.form.baseStats[this.stat] != null
val valStat = pokemon.form.baseStats[this.stat] ?: return false
return comparator(valStat)
}
override fun modifyCatchRate(currentCatchRate: Float, thrower: LivingEntity, pokemon: Pokemon): Float = this.behavior(thrower, pokemon).mutator(currentCatchRate, this.value(thrower, pokemon)) override fun modifyCatchRate(currentCatchRate: Float, thrower: LivingEntity, pokemon: Pokemon): Float = this.behavior(thrower, pokemon).mutator(currentCatchRate, this.value(thrower, pokemon))
@@ -96,21 +96,15 @@ abstract class AbstractPokedexManager {
} }
fun getNewInformation(pokedexEntityData: PokedexEntityData): PokedexLearnedInformation { fun getNewInformation(pokedexEntityData: PokedexEntityData): PokedexLearnedInformation {
val speciesRecord = getSpeciesRecord(pokedexEntityData.getApparentSpecies().resourceIdentifier) val speciesRecord = getSpeciesRecord(pokedexEntityData.species.resourceIdentifier)
if (speciesRecord == null || speciesRecord.getKnowledge() == PokedexEntryProgress.NONE) { if (speciesRecord == null || speciesRecord.getKnowledge() == PokedexEntryProgress.NONE) {
return PokedexLearnedInformation.SPECIES return PokedexLearnedInformation.SPECIES
} }
val formRecord = speciesRecord.getFormRecord(pokedexEntityData.getApparentForm().name) val formRecord = speciesRecord.getFormRecord(pokedexEntityData.form.name)
if (formRecord == null || formRecord.knowledge == PokedexEntryProgress.NONE) { if (formRecord == null || formRecord.knowledge == PokedexEntryProgress.NONE) {
return PokedexLearnedInformation.FORM return PokedexLearnedInformation.FORM
} }
if (pokedexEntityData.aspects.any{ !speciesRecord.hasAspect(it) } || pokedexEntityData.gender !in formRecord.getGenders() || !formRecord.hasSeenShinyState(pokedexEntityData.shiny)) {
// Can't update aspects on a disguise
if (pokedexEntityData.disguise != null) {
return PokedexLearnedInformation.NONE
}
if (pokedexEntityData.pokemon.aspects.any { !speciesRecord.hasAspect(it) } || pokedexEntityData.pokemon.gender !in formRecord.getGenders() || !formRecord.hasSeenShinyState(pokedexEntityData.pokemon.shiny)) {
return PokedexLearnedInformation.VARIATION return PokedexLearnedInformation.VARIATION
} }
return PokedexLearnedInformation.NONE return PokedexLearnedInformation.NONE
@@ -89,15 +89,21 @@ class FormDexRecord {
it.knowledge = knowledge it.knowledge = knowledge
} }
fun encountered(pokemon: Pokemon) {
if (wouldBeDifferent(pokemon, PokedexEntryProgress.ENCOUNTERED)) {
addInformation(pokemon, PokedexEntryProgress.ENCOUNTERED)
}
}
fun encountered(pokedexEntityData: PokedexEntityData) { fun encountered(pokedexEntityData: PokedexEntityData) {
if (wouldBeDifferent(pokedexEntityData, PokedexEntryProgress.ENCOUNTERED)) { if (wouldBeDifferent(pokedexEntityData, PokedexEntryProgress.ENCOUNTERED)) {
addInformation(pokedexEntityData, PokedexEntryProgress.ENCOUNTERED) addInformation(pokedexEntityData, PokedexEntryProgress.ENCOUNTERED)
} }
} }
fun caught(pokedexEntityData: PokedexEntityData) { fun caught(pokemon: Pokemon) {
if (wouldBeDifferent(pokedexEntityData, PokedexEntryProgress.CAUGHT)) { if (wouldBeDifferent(pokemon, PokedexEntryProgress.CAUGHT)) {
addInformation(pokedexEntityData, PokedexEntryProgress.CAUGHT) addInformation(pokemon, PokedexEntryProgress.CAUGHT)
} }
} }
@@ -119,18 +125,47 @@ class FormDexRecord {
speciesDexRecord.onFormRecordUpdated(this) speciesDexRecord.onFormRecordUpdated(this)
} }
private fun addInformation(pokemon: Pokemon, knowledge: PokedexEntryProgress) {
(speciesDexRecord.pokedexManager as? PokedexManager)?.let { pokedexManager ->
CobblemonEvents.POKEDEX_DATA_CHANGED_PRE.postThen(
PokedexDataChangedEvent.Pre(
Either.right(pokemon),
knowledge,
pokedexManager.uuid,
this
),
ifSucceeded = {
genders.add(pokemon.gender)
seenShinyStates.add(if (pokemon.shiny) "shiny" else "normal")
if (knowledge.ordinal > this.knowledge.ordinal) {
this.knowledge = knowledge
}
speciesDexRecord.addInformation(pokemon, knowledge)
speciesDexRecord.onFormRecordUpdated(this)
CobblemonEvents.POKEDEX_DATA_CHANGED_POST.post(
PokedexDataChangedEvent.Post(
Either.right(pokemon),
knowledge,
pokedexManager.uuid,
this
)
)
})
}
}
private fun addInformation(pokedexEntityData: PokedexEntityData, knowledge: PokedexEntryProgress) { private fun addInformation(pokedexEntityData: PokedexEntityData, knowledge: PokedexEntryProgress) {
(speciesDexRecord.pokedexManager as? PokedexManager)?.let { pokedexManager -> (speciesDexRecord.pokedexManager as? PokedexManager)?.let { pokedexManager ->
CobblemonEvents.POKEDEX_DATA_CHANGED_PRE.postThen( CobblemonEvents.POKEDEX_DATA_CHANGED_PRE.postThen(
PokedexDataChangedEvent.Pre( PokedexDataChangedEvent.Pre(
pokedexEntityData, Either.left(pokedexEntityData),
knowledge, knowledge,
pokedexManager.uuid, pokedexManager.uuid,
this this
), ),
ifSucceeded = { ifSucceeded = {
genders.add(pokedexEntityData.pokemon.gender) genders.add(pokedexEntityData.gender)
seenShinyStates.add(if (pokedexEntityData.pokemon.shiny) "shiny" else "normal") seenShinyStates.add(if (pokedexEntityData.shiny) "shiny" else "normal")
if (knowledge.ordinal > this.knowledge.ordinal) { if (knowledge.ordinal > this.knowledge.ordinal) {
this.knowledge = knowledge this.knowledge = knowledge
} }
@@ -138,10 +173,10 @@ class FormDexRecord {
speciesDexRecord.onFormRecordUpdated(this) speciesDexRecord.onFormRecordUpdated(this)
CobblemonEvents.POKEDEX_DATA_CHANGED_POST.post( CobblemonEvents.POKEDEX_DATA_CHANGED_POST.post(
PokedexDataChangedEvent.Post( PokedexDataChangedEvent.Post(
pokedexEntityData, Either.left(pokedexEntityData),
knowledge, knowledge,
pokedexManager.uuid, pokedexManager.uuid,
this this
) )
) )
} }
@@ -149,10 +184,19 @@ class FormDexRecord {
} }
} }
/** Returns whether the given [Pokemon] and [knowledge] would add new information to the Pokédex.*/
fun wouldBeDifferent(pokemon: Pokemon, knowledge: PokedexEntryProgress): Boolean {
return pokemon.gender !in genders
|| (pokemon.shiny && "shiny" !in seenShinyStates)
|| (!pokemon.shiny && "normal" !in seenShinyStates)
|| knowledge.ordinal > this.knowledge.ordinal
|| speciesDexRecord.wouldBeDifferent(pokemon)
}
fun wouldBeDifferent(pokedexEntityData: PokedexEntityData, knowledge: PokedexEntryProgress): Boolean { fun wouldBeDifferent(pokedexEntityData: PokedexEntityData, knowledge: PokedexEntryProgress): Boolean {
return pokedexEntityData.pokemon.gender !in genders return pokedexEntityData.gender !in genders
|| (pokedexEntityData.pokemon.shiny && "shiny" !in seenShinyStates) || (pokedexEntityData.shiny && "shiny" !in seenShinyStates)
|| (!pokedexEntityData.pokemon.shiny && "normal" !in seenShinyStates) || (!pokedexEntityData.shiny && "normal" !in seenShinyStates)
|| knowledge.ordinal > this.knowledge.ordinal || knowledge.ordinal > this.knowledge.ordinal
|| speciesDexRecord.wouldBeDifferent(pokedexEntityData) || speciesDexRecord.wouldBeDifferent(pokedexEntityData)
} }
@@ -30,19 +30,19 @@ class PokedexManager(
fun encounter(pokemon: Pokemon) { fun encounter(pokemon: Pokemon) {
val speciesId = pokemon.species.resourceIdentifier val speciesId = pokemon.species.resourceIdentifier
val formName = pokemon.form.name val formName = pokemon.form.name
getOrCreateSpeciesRecord(speciesId).getOrCreateFormRecord(formName).encountered(PokedexEntityData(pokemon = pokemon, disguise = null)) getOrCreateSpeciesRecord(speciesId).getOrCreateFormRecord(formName).encountered(pokemon)
} }
fun encounter(pokedexEntityData: PokedexEntityData) { fun encounter(pokedexEntityData: PokedexEntityData) {
val speciesId = pokedexEntityData.getApparentSpecies().resourceIdentifier val speciesId = pokedexEntityData.species.resourceIdentifier
val formName = pokedexEntityData.getApparentForm().name val formName = pokedexEntityData.form.name
getOrCreateSpeciesRecord(speciesId).getOrCreateFormRecord(formName).encountered(pokedexEntityData) getOrCreateSpeciesRecord(speciesId).getOrCreateFormRecord(formName).encountered(pokedexEntityData)
} }
fun catch(pokemon: Pokemon) { fun catch(pokemon: Pokemon) {
val speciesId = pokemon.species.resourceIdentifier val speciesId = pokemon.species.resourceIdentifier
val formName = pokemon.form.name val formName = pokemon.form.name
getOrCreateSpeciesRecord(speciesId).getOrCreateFormRecord(formName).caught(PokedexEntityData(pokemon = pokemon, disguise = null)) getOrCreateSpeciesRecord(speciesId).getOrCreateFormRecord(formName).caught(pokemon)
} }
override fun markDirty() { override fun markDirty() {
@@ -97,7 +97,7 @@ class SpeciesDexRecord {
} }
fun addInformation(pokedexEntityData: PokedexEntityData, knowledge: PokedexEntryProgress) { fun addInformation(pokedexEntityData: PokedexEntityData, knowledge: PokedexEntryProgress) {
aspects.addAll(pokedexEntityData.pokemon.aspects) aspects.addAll(pokedexEntityData.aspects)
} }
fun addAspects(addedAspects: Set<String>) { fun addAspects(addedAspects: Set<String>) {
@@ -107,7 +107,7 @@ class SpeciesDexRecord {
/** Returns true if the given Pokémon contains new information. Internal because it's only to be called from [FormDexRecord.wouldBeDifferent]. */ /** Returns true if the given Pokémon contains new information. Internal because it's only to be called from [FormDexRecord.wouldBeDifferent]. */
internal fun wouldBeDifferent(pokemon: Pokemon) = pokemon.aspects.any { it !in aspects } internal fun wouldBeDifferent(pokemon: Pokemon) = pokemon.aspects.any { it !in aspects }
internal fun wouldBeDifferent(pokedexEntityData: PokedexEntityData) = pokedexEntityData.pokemon.aspects.any { it !in aspects } internal fun wouldBeDifferent(pokedexEntityData: PokedexEntityData) = pokedexEntityData.aspects.any { it !in aspects }
fun getOrCreateFormRecord(formName: String): FormDexRecord { fun getOrCreateFormRecord(formName: String): FormDexRecord {
return formRecords.getOrPut(formName.lowercase()) { return formRecords.getOrPut(formName.lowercase()) {
@@ -8,6 +8,9 @@
package com.cobblemon.mod.common.api.pokemon package com.cobblemon.mod.common.api.pokemon
import com.bedrockk.molang.runtime.struct.VariableStruct
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.Cobblemon import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.abilities.Abilities import com.cobblemon.mod.common.api.abilities.Abilities
import com.cobblemon.mod.common.api.abilities.Ability import com.cobblemon.mod.common.api.abilities.Ability
@@ -465,10 +468,6 @@ open class PokemonProperties {
return this.commonMatches(pokemonEntity.pokemon) && this.customProperties.none { !it.matches(pokemonEntity) } return this.commonMatches(pokemonEntity.pokemon) && this.customProperties.none { !it.matches(pokemonEntity) }
} }
fun matches(properties: PokemonProperties): Boolean {
return properties.asString() == this.asString()
}
private fun commonMatches(pokemon: Pokemon): Boolean { private fun commonMatches(pokemon: Pokemon): Boolean {
level?.takeIf { it != pokemon.level }?.let { return false } level?.takeIf { it != pokemon.level }?.let { return false }
shiny?.takeIf { it != pokemon.shiny }?.let { return false } shiny?.takeIf { it != pokemon.shiny }?.let { return false }
@@ -772,6 +771,17 @@ open class PokemonProperties {
return pieces.joinToString(separator) return pieces.joinToString(separator)
} }
fun asStruct(): VariableStruct {
val struct = VariableStruct()
species?.let { struct.setDirectly("species", StringValue(it)) }
level?.let { struct.setDirectly("level", DoubleValue(it)) }
shiny?.let { struct.setDirectly("shiny", DoubleValue(it)) }
// add more of the optional properties to the struct as doubles or strings
gender?.let { struct.setDirectly("gender", StringValue(it.name)) }
friendship?.let { struct.setDirectly("friendship", DoubleValue(it)) }
return struct
}
fun updateAspects() { fun updateAspects() {
val aspects = mutableSetOf<String>() val aspects = mutableSetOf<String>()
AspectProvider.providers.forEach { aspects.addAll(it.provide(this)) } AspectProvider.providers.forEach { aspects.addAll(it.provide(this)) }
@@ -795,7 +805,7 @@ open class PokemonProperties {
private fun createAbility(id: String, form: FormData): Ability? { private fun createAbility(id: String, form: FormData): Ability? {
val ability = Abilities.get(id) ?: return null val ability = Abilities.get(id) ?: return null
val potentialAbility = form.abilities.firstOrNull { potential -> potential.template == ability } ?: return ability.create(true) val potentialAbility = form.abilities.firstOrNull { potential -> potential.template == ability } ?: return ability.create(true)
return potentialAbility.template.create(false, potentialAbility.priority) return potentialAbility.template.create(false)
} }
} }
@@ -1,22 +0,0 @@
/*
* 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.api.pokemon
import com.cobblemon.mod.common.pokemon.Pokemon
enum class PokemonSortMode(val comparator: Comparator<Pokemon?>, val reverseComparator: Comparator<Pokemon?>) {
NAME( { it?.getDisplayName()?.string } ),
LEVEL( { it?.level } ),
TYPE( { it?.primaryType?.name } );
constructor(mapper: (Pokemon?) -> Comparable<*>?) : this(compareBy({ it == null }, mapper),
compareBy<Pokemon?> { it == null }.thenComparing(compareBy(mapper).reversed()))
fun comparator(descending: Boolean) = if (descending) reverseComparator else comparator
}
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common.api.pokemon package com.cobblemon.mod.common.api.pokemon
import com.bedrockk.molang.Expression
import com.cobblemon.mod.common.Cobblemon import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.abilities.AbilityPool import com.cobblemon.mod.common.api.abilities.AbilityPool
import com.cobblemon.mod.common.api.abilities.AbilityTemplate import com.cobblemon.mod.common.api.abilities.AbilityTemplate
@@ -33,8 +32,6 @@ import com.cobblemon.mod.common.api.pokemon.moves.Learnset
import com.cobblemon.mod.common.api.pokemon.stats.Stat import com.cobblemon.mod.common.api.pokemon.stats.Stat
import com.cobblemon.mod.common.api.pokemon.stats.Stats import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.api.reactive.SimpleObservable import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.api.riding.controller.RideController
import com.cobblemon.mod.common.api.riding.stats.RidingStatDefinition
import com.cobblemon.mod.common.api.spawning.TimeRange import com.cobblemon.mod.common.api.spawning.TimeRange
import com.cobblemon.mod.common.api.types.ElementalType import com.cobblemon.mod.common.api.types.ElementalType
import com.cobblemon.mod.common.api.types.adapters.ElementalTypeAdapter import com.cobblemon.mod.common.api.types.adapters.ElementalTypeAdapter
@@ -45,19 +42,17 @@ import com.cobblemon.mod.common.pokemon.SpeciesAdditions
import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonEvolutionAdapter import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonEvolutionAdapter
import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonPreEvolutionAdapter import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonPreEvolutionAdapter
import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonRequirementAdapter import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonRequirementAdapter
import com.cobblemon.mod.common.pokemon.evolution.adapters.LegacyItemConditionWrapperAdapter import com.cobblemon.mod.common.pokemon.evolution.adapters.NbtItemPredicateAdapter
import com.cobblemon.mod.common.pokemon.evolution.predicate.NbtItemPredicate
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
import com.cobblemon.mod.common.util.adapters.* import com.cobblemon.mod.common.util.adapters.*
import com.cobblemon.mod.common.util.adapters.RideControllerAdapter
import com.cobblemon.mod.common.util.cobblemonResource import com.cobblemon.mod.common.util.cobblemonResource
import com.google.common.collect.HashBasedTable import com.google.common.collect.HashBasedTable
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.core.registries.BuiltInRegistries import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType import net.minecraft.server.packs.PackType
@@ -98,17 +93,13 @@ object PokemonSpecies : JsonDataRegistry<Species> {
.registerTypeAdapter(DropEntry::class.java, DropEntryAdapter) .registerTypeAdapter(DropEntry::class.java, DropEntryAdapter)
.registerTypeAdapter(CompoundTag::class.java, NbtCompoundAdapter) .registerTypeAdapter(CompoundTag::class.java, NbtCompoundAdapter)
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter) .registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
.registerTypeAdapter(Component::class.java, TextAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, BiomeLikeConditionAdapter) .registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, BiomeLikeConditionAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Block::class.java).type, BlockLikeConditionAdapter) .registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Block::class.java).type, BlockLikeConditionAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter) .registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Structure::class.java).type, StructureLikeConditionAdapter) .registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Structure::class.java).type, StructureLikeConditionAdapter)
.registerTypeAdapter(EggGroup::class.java, EggGroupAdapter) .registerTypeAdapter(EggGroup::class.java, EggGroupAdapter)
.registerTypeAdapter(MobEffect::class.java, RegistryElementAdapter<MobEffect>(BuiltInRegistries::MOB_EFFECT)) .registerTypeAdapter(MobEffect::class.java, RegistryElementAdapter<MobEffect>(BuiltInRegistries::MOB_EFFECT))
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter) .registerTypeAdapter(NbtItemPredicate::class.java, NbtItemPredicateAdapter)
.registerTypeAdapter(RideController::class.java, RideControllerAdapter)
.registerTypeAdapter(RidingStatDefinition::class.java, RidingStatDefinitionAdapter)
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
.disableHtmlEscaping() .disableHtmlEscaping()
.enableComplexMapKeySerialization() .enableComplexMapKeySerialization()
.create() .create()
@@ -13,7 +13,6 @@ import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.CobblemonSounds import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.advancement.CobblemonCriteria import com.cobblemon.mod.common.advancement.CobblemonCriteria
import com.cobblemon.mod.common.advancement.criterion.EvolvePokemonContext import com.cobblemon.mod.common.advancement.criterion.EvolvePokemonContext
import com.cobblemon.mod.common.api.drop.DropTable
import com.cobblemon.mod.common.api.events.CobblemonEvents import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.pokemon.PokemonGainedEvent import com.cobblemon.mod.common.api.events.pokemon.PokemonGainedEvent
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEvent import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEvent
@@ -33,8 +32,9 @@ import com.cobblemon.mod.common.pokemon.evolution.variants.LevelUpEvolution
import com.cobblemon.mod.common.pokemon.evolution.variants.TradeEvolution import com.cobblemon.mod.common.pokemon.evolution.variants.TradeEvolution
import com.cobblemon.mod.common.util.lang import com.cobblemon.mod.common.util.lang
import com.cobblemon.mod.common.util.party import com.cobblemon.mod.common.util.party
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules import net.minecraft.client.Minecraft
import net.minecraft.server.level.ServerLevel import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.network.protocol.game.ClientboundSoundPacket
import net.minecraft.sounds.SoundSource import net.minecraft.sounds.SoundSource
import net.minecraft.world.entity.Entity import net.minecraft.world.entity.Entity
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
@@ -80,11 +80,6 @@ interface Evolution : EvolutionLike {
*/ */
val learnableMoves: MutableSet<MoveTemplate> val learnableMoves: MutableSet<MoveTemplate>
/**
* The items that will drop once the evolution finishes.
*/
val drops: DropTable
/** /**
* Checks if the given [Pokemon] passes all the conditions and is ready to evolve. * Checks if the given [Pokemon] passes all the conditions and is ready to evolve.
* *
@@ -203,37 +198,19 @@ interface Evolution : EvolutionLike {
val movesToLearn = previousSpeciesLearnableMoves + this.learnableMoves val movesToLearn = previousSpeciesLearnableMoves + this.learnableMoves
movesToLearn.forEach { move -> movesToLearn.forEach { move ->
val couldAddMove = if (pokemon.moveSet.hasSpace()) {
if (pokemon.moveSet.hasSpace()) { pokemon.moveSet.add(move.create())
pokemon.moveSet.add(move.create()) } else {
} else { pokemon.benchedMoves.add(BenchedMove(move, 0))
pokemon.benchedMoves.add(BenchedMove(move, 0))
}
val previousSpeciesKnewMove = previousSpeciesLearnableMoves.any { move.name == it.name }
if (couldAddMove && !previousSpeciesKnewMove) {
pokemon.getOwnerPlayer()?.sendSystemMessage(lang("experience.learned_move", pokemon.getDisplayName(), move.displayName))
} }
pokemon.getOwnerPlayer()?.sendSystemMessage(lang("experience.learned_move", pokemon.getDisplayName(), move.displayName))
} }
// we want to instantly tick for example you might only evolve your Bulbasaur at level 34 so Venusaur should be immediately available // we want to instantly tick for example you might only evolve your Bulbasaur at level 34 so Venusaur should be immediately available
pokemon.evolutions.filterIsInstance<PassiveEvolution>().forEach { evolution -> evolution.attemptEvolution(pokemon) } pokemon.evolutions.filterIsInstance<PassiveEvolution>().forEach { evolution -> evolution.attemptEvolution(pokemon) }
pokemon.lockedEvolutions.filterIsInstance<PassiveEvolution>().forEach { evolution -> evolution.attemptEvolution(pokemon) } pokemon.lockedEvolutions.filterIsInstance<PassiveEvolution>().forEach { evolution -> evolution.attemptEvolution(pokemon) }
this.shed(pokemon) this.shed(pokemon)
val ownerPlayer = pokemon.getOwnerPlayer()
if (ownerPlayer != null && ownerPlayer.level().gameRules.getBoolean(CobblemonGameRules.DO_POKEMON_LOOT)) {
drops.drop(
pokemon.entity,
ownerPlayer.level() as ServerLevel,
pokemon.entity?.position() ?: ownerPlayer.position(),
ownerPlayer,
pokemon = pokemon
)
}
CobblemonEvents.EVOLUTION_COMPLETE.post(EvolutionCompleteEvent(pokemon, this)) CobblemonEvents.EVOLUTION_COMPLETE.post(EvolutionCompleteEvent(pokemon, this))
CobblemonEvents.POKEMON_GAINED.post(PokemonGainedEvent(pokemon.getOwnerUUID()!!, pokemon)) CobblemonEvents.POKEMON_GAINED.post(PokemonGainedEvent(pokemon.getOwnerUUID()!!, pokemon))
} }
@@ -241,4 +218,4 @@ interface Evolution : EvolutionLike {
fun applyTo(pokemon: Pokemon) { fun applyTo(pokemon: Pokemon) {
result.apply(pokemon) result.apply(pokemon)
} }
} }
@@ -21,12 +21,6 @@ object CobblemonPokemonLabels {
*/ */
const val LEGENDARY = "legendary" const val LEGENDARY = "legendary"
/**
* Represents a Pokémon who is typically banned or has restricted usage in competitive sanctions.
* For example usage see this [VGC](https://www.pokemon.com/us/pokemon-news/trainers-can-once-again-use-a-restricted-pokemon-in-ranked-battles-series-10-starting-august-1-2021) page.
*/
const val RESTRICTED = "restricted"
/** /**
* Represents a mythical Pokémon. * Represents a mythical Pokémon.
* In Cobblemon terms they do not exist since we do not share the concept of timed event only Pokémon but the official ones are still tagged. * In Cobblemon terms they do not exist since we do not share the concept of timed event only Pokémon but the official ones are still tagged.
@@ -34,21 +28,14 @@ object CobblemonPokemonLabels {
const val MYTHICAL = "mythical" const val MYTHICAL = "mythical"
/** /**
* Represents Pokémon that receive a boosted catch rate from the Beast Ball. (Due to Beast Boost) * Represents Pokémon that originate from Ultra Space.
* Does not include [thematically related](https://bulbapedia.bulbagarden.net/wiki/Ultra_Beast#Related_Pok%C3%A9mon) beasts.
*/ */
const val ULTRA_BEAST = "ultra_beast" const val ULTRA_BEAST = "ultra_beast"
/** /**
* Represents a Pokémon whose family could be derived from resurrecting a fossil. * Represents the pseudo legendary Pokémon.
*/ */
const val FOSSIL = "fossil" const val PSEUDO_LEGENDARY = "pseudo_legendary"
/**
* Represents the "pseudo-legendary" Pokémon. (Slow-rate three-stage lines with a base stat total of 600)
* Term reference on this [Pokémon Center](https://www.pokemoncenter.com/search/powerhouse) page.
*/
const val POWERHOUSE = "powerhouse"
/** /**
* Represents a baby Pokémon, this is not just a first stage Pokémon species, it is also unable to breed. * Represents a baby Pokémon, this is not just a first stage Pokémon species, it is also unable to breed.
@@ -65,55 +52,52 @@ object CobblemonPokemonLabels {
/** /**
* See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region. * See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region.
*/ */
const val KANTONIAN_FORM = "kantonian_form" const val REGIONAL_OF_KANTO = "kanto_regional"
/**
* See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region.
* Source for adjectival form: [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Johto#Trivia)
*/
const val JOHTONIAN_FORM = "johtonian_form"
/**
* See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region.
* Source for adjectival form:[Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Hoenn#Trivia)
*/
const val HOENNIAN_FORM = "hoennian_form"
/**
* See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region.
* Source for adjectival form:[Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Sinnoh#Trivia)
*/
const val SINNOHAN_FORM = "sinnohan_form"
/** /**
* See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region. * See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region.
*/ */
const val UNOVAN_FORM = "unovan_form" const val REGIONAL_OF_JOHTO = "johto_regional"
/** /**
* See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region. * See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region.
*/ */
const val KALOSIAN_FORM = "kalosian_form" const val REGIONAL_OF_HOENN = "hoenn_regional"
/**
* See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region.
*/
const val REGIONAL_OF_SINNOH = "sinnoh_regional"
/**
* See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region.
*/
const val REGIONAL_OF_UNOVA = "unova_regional"
/**
* See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region.
*/
const val REGIONAL_OF_KALOS = "kalos_regional"
/** /**
* See [REGIONAL] and this [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Regional_form#Alolan_Form) page. * See [REGIONAL] and this [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Regional_form#Alolan_Form) page.
*/ */
const val ALOLAN_FORM = "alolan_form" const val REGIONAL_OF_ALOLA = "alola_regional"
/** /**
* See [REGIONAL] and this [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Regional_form#Galarian_Form) page. * See [REGIONAL] and this [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Regional_form#Galarian_Form) page.
*/ */
const val GALARIAN_FORM = "galarian_form" const val REGIONAL_OF_GALAR = "galar_regional"
/** /**
* See [REGIONAL] and this [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Regional_form#Hisuian_Form) page. * See [REGIONAL] and this [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Regional_form#Hisuian_Form) page.
*/ */
const val HISUIAN_FORM = "hisuian_form" const val REGIONAL_OF_HISUI = "hisui_regional"
/** /**
* See [REGIONAL] and this [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Regional_form#Paldean_Form) page. * See [REGIONAL] and this [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Regional_form#Paldean_Form) page.
*/ */
const val PALDEAN_FORM = "paldean_form" const val REGIONAL_OF_PALDEA = "paldea_regional"
/** /**
* Represents a mega evolution. * Represents a mega evolution.
@@ -140,7 +124,7 @@ object CobblemonPokemonLabels {
const val TOTEM = "totem" const val TOTEM = "totem"
/** /**
* Represents Pokémon that trigger the Booster Energy item (due to Protosynthesis/Quark Drive) * Represents a Paradox species.
* For more information see the [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Paradox_Pok%C3%A9mon) page. * For more information see the [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Paradox_Pok%C3%A9mon) page.
*/ */
const val PARADOX = "paradox" const val PARADOX = "paradox"
@@ -187,24 +171,12 @@ object CobblemonPokemonLabels {
*/ */
const val GENERATION_7 = "gen7" const val GENERATION_7 = "gen7"
/**
* The "official" designation for Pokémon from Gen 7 (Unknown) and not the Alola region
* This may also include forms of Pokémon that had been previously introduced
*/
const val GENERATION_7B = "gen7b"
/** /**
* Pokémon from the national Pokédex of 810 to 905 * Pokémon from the national Pokédex of 810 to 905
* This may also include forms of Pokémon that had been previously introduced * This may also include forms of Pokémon that had been previously introduced
*/ */
const val GENERATION_8 = "gen8" const val GENERATION_8 = "gen8"
/**
* The "official" designation for Pokémon from Gen 8 (Hisui) and not the Galar region
* This may also include forms of Pokémon that had been previously introduced
*/
const val GENERATION_8A = "gen8a"
/** /**
* Pokémon from the national Pokédex from 906 to 1008 * Pokémon from the national Pokédex from 906 to 1008
* This may also include forms of Pokémon that had been previously introduced * This may also include forms of Pokémon that had been previously introduced
@@ -1,76 +0,0 @@
/*
* 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.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
@@ -53,7 +53,7 @@ enum class Stats(override val identifier: ResourceLocation, override val display
fun getStat(statKey: String) = when(statKey.lowercase()) { fun getStat(statKey: String) = when(statKey.lowercase()) {
"hp" -> HP "hp" -> HP
"atk", "attack" -> ATTACK // Hyper Cutter states the full stat name "Attack" "atk", "attack" -> ATTACK // Hyper Cutter states the full stat name "Attack"
"def", "defense", "defence" -> DEFENCE // Big Pecks states the full stat name "Defense" "def", "defense" -> DEFENCE // Big Pecks states the full stat name "Defense"
"spa" -> SPECIAL_ATTACK "spa" -> SPECIAL_ATTACK
"spd" -> SPECIAL_DEFENCE "spd" -> SPECIAL_DEFENCE
"spe", "speed" -> SPEED "spe", "speed" -> SPEED
@@ -45,15 +45,4 @@ open class CancelableObservable<T : Cancelable> : EventObservable<T>() {
} }
} }
} }
inline fun postThenFinally(event: T, ifCanceled: (T) -> Unit = {}, finally: (T) -> Unit = {},ifSucceeded: (T) -> Unit) {
post(event) {
if (it.isCanceled) {
ifCanceled(it)
} else {
ifSucceeded(it)
}
finally(it)
}
}
} }
@@ -1,25 +0,0 @@
/*
* 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.api.riding
import net.minecraft.world.entity.PlayerRideableJumping
/**
* Represents an entity that supports riding.
*
* @since 1.7.0
*/
interface Rideable : PlayerRideableJumping {
/**
* Denotes the manager responsible for handling any instance of riding taking place on an entity
*/
val riding: RidingManager
}
Loaded 100 of 3004 files, more files were not shown because too many files have changed in this diff. Show more