mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-21 06:36:25 -04:00
Compare commits
161
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5ac54cd16 | ||
|
|
dc703e67f7 | ||
|
|
f9dd1448e5 | ||
|
|
ecf5d57ad2 | ||
|
|
8663888abc | ||
|
|
f452cd9a05 | ||
|
|
4fe9cd7fd6 | ||
|
|
2c1d11ed11 | ||
|
|
b88adf0479 | ||
|
|
b1066671f5 | ||
|
|
387e85d4ad | ||
|
|
77ab58d823 | ||
|
|
1a9e736d8b | ||
|
|
aa39c1906e | ||
|
|
2e460e2ca2 | ||
|
|
a07ff7f442 | ||
|
|
5374569ea1 | ||
|
|
af9c1196bf | ||
|
|
09d5543469 | ||
|
|
49e4dd0298 | ||
|
|
c8e408c50a | ||
|
|
e8a0467643 | ||
|
|
2dd0b66b83 | ||
|
|
68374017e1 | ||
|
|
120520f51d | ||
|
|
e8dea9773a | ||
|
|
7b31e6bcc4 | ||
|
|
c6ffca639f | ||
|
|
c491a1f7ca | ||
|
|
0b333b743d | ||
|
|
95e79865e5 | ||
|
|
0e2860cd90 | ||
|
|
3259bf032c | ||
|
|
116205cdf1 | ||
|
|
43277d18dc | ||
|
|
86153419ee | ||
|
|
2b4d9c451c | ||
|
|
7f0e2fa9d8 | ||
|
|
e165095bd5 | ||
|
|
b8708d6e10 | ||
|
|
ef536390ca | ||
|
|
28befab173 | ||
|
|
c142439d5b | ||
|
|
1ca7335654 | ||
|
|
9197d9cdcd | ||
|
|
f75813e64d | ||
|
|
1f617c76a4 | ||
|
|
ebf573aa7a | ||
|
|
75363da470 | ||
|
|
cce4b932cc | ||
|
|
0973e1ced0 | ||
|
|
e7b5c84024 | ||
|
|
4001cc2a89 | ||
|
|
6e57d77d10 | ||
|
|
2206d96a6e | ||
|
|
33f05858f1 | ||
|
|
a4f204a5a3 | ||
|
|
31b6be2164 | ||
|
|
0dbf73067b | ||
|
|
775703e1f5 | ||
|
|
bcdfef4886 | ||
|
|
a19adb463b | ||
|
|
5004edbbb6 | ||
|
|
d8bdd6329a | ||
|
|
82d56637a0 | ||
|
|
7232a43816 | ||
|
|
098eb7d14b | ||
|
|
835b70ed48 | ||
|
|
9d828a86fb | ||
|
|
910551ee70 | ||
|
|
9beee548d4 | ||
|
|
6f3894f27b | ||
|
|
bbc9a5e62e | ||
|
|
94765da04a | ||
|
|
8caa82f123 | ||
|
|
8e1fcc6f14 | ||
|
|
2f87d53af6 | ||
|
|
131ef31492 | ||
|
|
b6b067b1d3 | ||
|
|
546f10eca7 | ||
|
|
542839ba69 | ||
|
|
efab1bba08 | ||
|
|
8f986bc326 | ||
|
|
e155d32aaf | ||
|
|
743e0b7d66 | ||
|
|
1518d703f9 | ||
|
|
af9d851d67 | ||
|
|
20ca91f1c9 | ||
|
|
6fb3c0e49a | ||
|
|
5cb4ff5f5f | ||
|
|
d035c08a5c | ||
|
|
fda7b13f50 | ||
|
|
fb4aaed220 | ||
|
|
c5e1b37ead | ||
|
|
2be9d303ea | ||
|
|
99ac6d213a | ||
|
|
f595724971 | ||
|
|
0511ba147b | ||
|
|
760f48d850 | ||
|
|
bf296b4921 | ||
|
|
6f4aae8b7d | ||
|
|
01e5e74e64 | ||
|
|
b6565a5dee | ||
|
|
49886389cf | ||
|
|
643bf9068b | ||
|
|
53f3258246 | ||
|
|
1e9895ec84 | ||
|
|
52dacb03ae | ||
|
|
85b0f3f393 | ||
|
|
a04a91bf24 | ||
|
|
5e814f7ab5 | ||
|
|
2780f491d6 | ||
|
|
2d3ec7aff1 | ||
|
|
cb7baf2696 | ||
|
|
5cc069df78 | ||
|
|
9222476c1f | ||
|
|
f220755f99 | ||
|
|
d55bbf237c | ||
|
|
83a9d44c3a | ||
|
|
c5a802eaf6 | ||
|
|
2e27875460 | ||
|
|
cd66887faa | ||
|
|
d665c87c21 | ||
|
|
044d3102b6 | ||
|
|
c421a93b06 | ||
|
|
2865aa2272 | ||
|
|
7c4aae3e9d | ||
|
|
d9f671f2a8 | ||
|
|
69733b530b | ||
|
|
d4471c30bc | ||
|
|
185f7e03f5 | ||
|
|
a45eb0eb21 | ||
|
|
ed67142379 | ||
|
|
13169c6848 | ||
|
|
8be134ee2f | ||
|
|
8c3206a413 | ||
|
|
4d4c071b95 | ||
|
|
b82c27754f | ||
|
|
63afec184e | ||
|
|
65699f045e | ||
|
|
90dc489547 | ||
|
|
b2142fed1d | ||
|
|
fef21516e9 | ||
|
|
95d43de79f | ||
|
|
92bccf620f | ||
|
|
15f8a9ee71 | ||
|
|
e5750cbba0 | ||
|
|
c6482c82cd | ||
|
|
c470894bd3 | ||
|
|
a940e32f8d | ||
|
|
b6b59eccad | ||
|
|
b520b94fae | ||
|
|
1969af65b9 | ||
|
|
905d63e098 | ||
|
|
1ea8ab7dcc | ||
|
|
a45d21b279 | ||
|
|
efe8f34413 | ||
|
|
6bb23582c4 | ||
|
|
56ccb43997 | ||
|
|
5fbbcb5707 | ||
|
|
580a24eac3 |
+64
-176
@@ -1,200 +1,88 @@
|
||||
# Changelog
|
||||
## [1.8.2 (MONTH xth, 2026)](#1-8-2)
|
||||
## [1.8.3 (MONTH xth, 2026)](#1-8-3)
|
||||
|
||||
### Additions
|
||||
- The following items can now be placed on the ground as blocks:
|
||||
- King's Rock, Galarica Cuff, Unremarkable Teacup, Masterpiece Teacup, Chipped Pot, Cracked Pot, Sachet, Metal Powder, Quick Powder, Bright Powder, Soft Sand, Electirizer, Magmarizer, Icy Rock, Heat Rock, Smooth Rock, Damp Rock, Destiny Knot, Luminous Moss, Never-Melt Ice, Wide Lens, Scope Lens, and Zoom Lens.
|
||||
- Iron Ball, Metal Coat, Throat Spray, Terrain Extender, Medicinal Brew, Moomoo Milk, HP Up, Protein, Iron, Carbos, Calcium, Zinc, PP Up, PP Max, Upgrade, Dubious Disc, and Loaded Dice.
|
||||
- The following items can now be placed on various surfaces:
|
||||
- Galarica Wreath, Magnet, Flame Orb, Life Orb, Toxic Orb, Light Ball, and Smoke Ball.
|
||||
- The following items can now be placed as blocks and have additional functionality:
|
||||
- Ring Target, Metronome, and Eject Button.
|
||||
- The following items can now be worn by Players and Pokémon:
|
||||
- Galarica Wreath, Cleanse Tag, Spell Tag, Sharp Beak, Covert Cloak, Shell Helmet, and Never-Melt Ice.
|
||||
- Wearable items can now be equipped by a player by holding it and right-clicking (or rebound use/interact)
|
||||
- Wearable items that can be placed down are exempt from this behaviour.
|
||||
- Mint Leaves can now be placed on the ground as Leaf Litter, or in Flower Pots
|
||||
- Added Oricorio Flowers
|
||||
- Added Terrain Plants
|
||||
- Berries can now be placed in Flower Pots
|
||||
- The evolution tree can now be viewed on the Pokédex, showing a Pokémon's full family line and what's needed to evolve into each stage.
|
||||
- Added custom sounds to a bunch of items that can be placed as blocks: liquid bottles, pill bottles, powders and dice.
|
||||
- New Cosmetic Item for Pikachu: Paper
|
||||
- Burmy changes its cloak after a battle it took part in, based on the biome: Trash Cloak in the Deep Dark, Nether and End, Plant Cloak in lush biomes such as forests, jungles, plains and swamps, and Sandy Cloak in sandy biomes, beaches and caves.
|
||||
|
||||
### Fixes
|
||||
- Medicinal Leeks can now be eaten when they aren't being planted, matching their food properties.
|
||||
- Sweeping attacks no longer set owned Pokémon on fire (e.g. with Fire Aspect) or knock them back.
|
||||
- Fixed #updateMovesOnFormChange not properly initializing a form-swapped Pokemon's non-form_change moves.
|
||||
### TEST
|
||||
### Pokémon Added
|
||||
#### Generation 4
|
||||
- Snover
|
||||
- Abomasnow
|
||||
- Burmy
|
||||
- Wormadam
|
||||
- Mothim
|
||||
|
||||
#### Generation 5
|
||||
- Tympole
|
||||
- Palpitoad
|
||||
- Seismitoad
|
||||
|
||||
#### Generation 6
|
||||
### Cries added/updated for the following Pokémon
|
||||
- Hoppip
|
||||
- Skiploom
|
||||
- Jumpluff
|
||||
- Houndour
|
||||
- Houndoom
|
||||
- Wurmple
|
||||
- Silcoon
|
||||
- Beautifly
|
||||
- Cascoon
|
||||
- Dustox
|
||||
- Surskit
|
||||
- Masquerain
|
||||
- Torkoal
|
||||
- Starly
|
||||
- Staravia
|
||||
- Staraptor
|
||||
- Combee
|
||||
- Vespiquen
|
||||
- Dusknoir
|
||||
- Helioptile
|
||||
- Heliolisk
|
||||
|
||||
#### Generation 7
|
||||
- Grubbin
|
||||
- Charjabug
|
||||
- Vikavolt
|
||||
- Minior
|
||||
|
||||
#### Generation 8
|
||||
- Eternatus
|
||||
|
||||
#### Generation 9
|
||||
- Greavard
|
||||
- Houndstone
|
||||
- Applin (updated)
|
||||
- Flapple (updated)
|
||||
- Appletun
|
||||
- Runerigus
|
||||
- Dipplin
|
||||
|
||||
### Model updates for the following Pokémon
|
||||
- Sudowoodo
|
||||
- Spheal
|
||||
- Cacnea
|
||||
- Cacturne
|
||||
- Binacle
|
||||
- Barbaracle
|
||||
- Glimmet
|
||||
- Glimmora
|
||||
- Deerling
|
||||
- Sawsbuck (All forms)
|
||||
- Absol
|
||||
- Poliwag
|
||||
- Politoed
|
||||
- Ekans
|
||||
- Oddish
|
||||
- Gloom
|
||||
- Vileplume
|
||||
- Bellossom
|
||||
- Shroomish
|
||||
- Chespin
|
||||
- Quilladin
|
||||
- Chesnaught
|
||||
- Fennekin
|
||||
- Braixen
|
||||
- Delphox
|
||||
- Froakie
|
||||
- Frogadier
|
||||
- Greninja
|
||||
- Shinx
|
||||
- Luxio
|
||||
- Luxray
|
||||
- Slakoth
|
||||
- Riolu
|
||||
- Lucario
|
||||
|
||||
### Animation updates for the following Pokémon
|
||||
- Treecko (New Shoulder Mount!)
|
||||
- Bonsly (New Shoulder Mount!)
|
||||
- Sudowoodo
|
||||
- Cacnea
|
||||
- Cacturne
|
||||
- Ekans
|
||||
- Arbok
|
||||
- Oddish
|
||||
- Gloom
|
||||
- Vileplume
|
||||
- Bellossom
|
||||
- Pichu
|
||||
- Pikachu
|
||||
- Raichu (+ Alolan)
|
||||
- Greninja
|
||||
- Slakoth
|
||||
- Vikavolt
|
||||
|
||||
### Changes
|
||||
- Terrain Seeds can now be planted
|
||||
- Terrain Seeds are now consumed during PvP and NPC battles
|
||||
- Glow Item Frames can be crafted using Bright Powder as an alternative to Glow Ink Sacs
|
||||
- Bright Powder can be used on Signs and Hanging Signs to make text glow, as an alternative to Glow Ink Sacs
|
||||
- Updated various recipes to display in Recipe Groups within the Recipe Book
|
||||
- Updated most recipes to display more logically/consistently within the Recipe Book's categories
|
||||
- Updated the following recipes
|
||||
- Never-Melt Ice, Focus Sash, Blunder Policy, Weakness Policy, Blank TM
|
||||
- Make ride rotations less jittery in multiplayer.
|
||||
- Changes Disc Shelf TMs to use textures instead of tinting and overlays to line up with item display
|
||||
- Blank TM can now be inserted into the Disc Shelf
|
||||
- Added TM creative tab
|
||||
- Recall animation now renders ball in hand with the player arm raised.
|
||||
- Made regional and Vivillon split-evo locations now mutually exclusive
|
||||
- Item evolutions now unlock **all** locked evolutions whose requirements are met instead of stopping after the first.
|
||||
- Exceptions being "forced" evolutions which will continue to stop after the first one
|
||||
- Removed Mega Drain as a TM
|
||||
- Vivillon's patterns are now viewable as forms with form names and unique Pokedex entries displayed.
|
||||
- Slowed the speed of Type Gem growth, and revamped their generation to grow in a more crystal-like shape
|
||||
- PokeSnacks (and other area spawns) will now start the vertical offset checking from the center rather than base coordinate
|
||||
- This will help PokeSnacks to work inside caves or tighter spaces better
|
||||
- Changed the Misc icon in the Campfire Pot Recipe Book to Health Candy
|
||||
- Moved EXP Candies from the Medicine recipe book category to the Misc category
|
||||
- Removed Dynamic Lights data from the Magmarizer item for consistency with the block
|
||||
- Added `doPokemonPredation` gamerule, which controls aggressiveness of Pokémon with `hate_entity` brain task defined
|
||||
- Added `predation_chance` server config value, which controls the possibility of attacking the hated entity found by `hate_entity` brain task
|
||||
- Prehistoric Eroded Pillar generates slightly more frequently
|
||||
|
||||
### Fixes
|
||||
- Correctly grants "They're Minerals!" advancement when planting a type gem
|
||||
- Shoulder mounted Pokémon now follow player body animations, improving their positioning with custom player animations and default actions.
|
||||
- Shoulder mounted Pokémon now sit slightly higher with chest armor equipped for better alignment, with a configurable blacklist.
|
||||
- Type Gem Blocks now have advancements to give you the recipe in the recipe book (the data for the advancements were inside the recipes somehow??)
|
||||
- Some other recipes without advancements have also been corrected
|
||||
- Corrected the TM Recipes for Charge Beam and Payday
|
||||
- Type Gem blocks now properly generate clusters off of the block.
|
||||
- Starter Screen Categories will no longer stop rendering if they are bigger than the viewport, and you are not viewing top or bottom edges
|
||||
- Random Starter option now properly handled in height calculation, so now it won't run off into other categories or be un-accessible due to scroll limits if it causes a new row
|
||||
- Mochi and Feathers no longer drop glass bottles on use
|
||||
- Fixed a rare set of concurrency bugs related to reloading packs on NeoForge; fixes a ModernFix issue
|
||||
- Removed unnecessary conditions for Mimikyu's standing pose. Hopefully fixes the rare instance of it using its shoulder animations during battle in multiplayer scenarios.
|
||||
- Fixed Rockruff line not blinking
|
||||
- Fixed Flygon sometimes using its running animation instead of walking
|
||||
- Fixed Bramblin always sleeping outside of battle
|
||||
- Fixed Dragonair using its battle idle as a normal idle
|
||||
- Fixed Lycanroc's head movement
|
||||
- Added head movement to Archaludon
|
||||
- Fixed Duraludon line not having any sleep animations
|
||||
- Fixed Diglett line not having their faint animations
|
||||
- Fixed Kingambit moving its legs while walking
|
||||
- Fixed Alolan Diglett's cry not playing
|
||||
- Fixed shiny alpha Snorlax using the non-shiny texture
|
||||
- Various Structure fixes
|
||||
- Fixed shiny Pokémon under certain circumstances forgetting taught TMs
|
||||
- Fixed certain Pokémon sounds sometimes being doubled when played at specific times in their animations
|
||||
- Fixed ball capture beam origin coming from behind the ball.
|
||||
- Fixed Safari Ball catch rate outside of battle
|
||||
- Fixed alpha eye (and other) particles not respecting client particle density setting in video options
|
||||
- Fixed TM-Machine UI not closing when player is moving away from it
|
||||
- Fixed config category for alpha/shiny chance config fields for fossil machine and honey log slathering to Spawning
|
||||
- Fixed crashes for addon species with non-Cobblemon namespaces, in evolution, fishing bait and Pokédex lookups.
|
||||
- Bees now grow Apricorns and the Galarica Nut Bush, which were in the bee growables tag but never handled, and correctly spend their nectar when they do
|
||||
- Saccharine Leaves can now be bone mealed
|
||||
- Fixed equipping a stack of items instead of one item of a stack
|
||||
- Fixed TM stack consumption in TMM screen when player teaches a move to species
|
||||
- Fixed every Miltank giving mushroom stew, not only mushroom variants
|
||||
- Fixed datapacks with item interaction evolutions that don't specify an item crashing the world on load.
|
||||
- Fixed the Pokédex evolution tree crashing when a datapack's dex entry is missing an evolution's form.
|
||||
- Fixed the Pokédex evolution tree crashing with a stack overflow on evolutions that loop back on themselves.
|
||||
- Fixed the Pokédex evolution tree crashing when looking at a dex that is not part of the "National Dex" aggregate.
|
||||
- Fixed evolution trees not building properly when a Pokémon has several Pokédex entries for different regions.
|
||||
- Fixed form-changing evolutions sometimes resolving to the source form in the Pokédex evolution tree.
|
||||
- Broken datapack evolutions are now logged and skipped in the Pokédex evolution tree instead of crashing.
|
||||
- Fixed the `alpha` property having no tab completion in commands such as `/pokespawn`, `/pokegive` and `/pokeedit`, and added the missing `dmax_level`, `gmax_factor` and `tradable` aliases to tab completion
|
||||
- Fixed friendship booster items not being recognised as such
|
||||
- Fixed conflicts with other mods that would make use of recipe books in certain ways (Farmer's Delight Cooking Pot)
|
||||
- Fixed Pokémon battles stalling when a sidemod cancels the `THROWN_POKEBALL_HIT` hit event
|
||||
- Fixed choice feature tab completion in `spawnpokemon/pokegive/pokeedit` commands
|
||||
- Fixed MoLang that's targeting players intermittedly failing when they have died, needing them to relog
|
||||
- Fixed a NeoForge bug where none of the Cobblemon plants/berries could be placed into pots
|
||||
- Fixed party overlay not hiding when the player opens the Pokédex scanner
|
||||
- Added compat for AppleSkin
|
||||
- Fixed some display names having unintended font colours
|
||||
- Fixed `hate_entity` task focusing on its own entity
|
||||
- Thus enabled deadly warfare between Zangoose and Seviper
|
||||
- Prehistoric Frozen Pond, Prehistoric Frozen Spike, and Prehistoric Lush Den now generate
|
||||
- Fixed Frogadier floating in its battle_idle animation
|
||||
- Fixed absence or incorrect mergers in spawning conditions, making max height/depth of conditions to use the min value instead
|
||||
- Added stricter riding checks on server side to prevent possible packet forgery when player tries to ride pokemon
|
||||
- Fixed Pokémon cries and animation sounds played from GUIs, such as the starter selection screen and the Pokédex, being tied to the Master volume slider instead of Friendly Creatures
|
||||
|
||||
### Developer
|
||||
- Evolution requirements can now set `pokedexIcon` and `pokedexTooltip` directly in their JSON to control how they're shown on the Pokédex's evolution tree, for example:
|
||||
```json
|
||||
{
|
||||
"variant": "attack_defence_ratio",
|
||||
"pokedexIcon": "minecraft:diamond_sword",
|
||||
"pokedexTooltip": "cobblemon.ui.pokedex.requirement.attack_defence_ratio.tooltip"
|
||||
}
|
||||
```
|
||||
- Fixed wrong order of operations in the code flow prior to the `FOSSIL_REVIVED` event causing pokemon to appear without entity link
|
||||
- Fixed TestPartySlot command not correctly comparing the provided spec with the target Pokémon
|
||||
- Bumped NeoForge to `21.1.195` to get access to MixinExtras `0.5` and the expressions annotation
|
||||
- New Platform Event `PLAYER_RESPAWN` which is fired when a player respawns (either through death or returning from the end)
|
||||
- Platform Events `SERVER_PLAYER_TICK_PRE` and `SERVER_PLAYER_TICK_POST` no longer fire when the player is dead
|
||||
- it is now tied much closer to the actual entity rather than the player (or their connection)
|
||||
|
||||
### Molang & Datapacks
|
||||
- A new `negate` variant for evolution requirements has been added, which will negate (invert) the provided inner condition.
|
||||
- Added Molang functions for individual Pokédex ids, wherein a subdex is passed in as a string to `dex_caught_count` etc.
|
||||
- Added a `battle_ended` callback, backed by the new `BATTLE_ENDED` event, which fires whenever a battle ends for any reason, alongside a multitude of flags not previously covered by `BATTLE_VICTORY`.
|
||||
- Added `battle_pokemon` to battle actor structs and `has_faced_opponents` to battle Pokémon structs.
|
||||
- Added the `cobblemon:form_change/bagworm_cloak/plant_cloak`, `sandy_cloak` and `trash_cloak` biome tags, which control Burmy's cloak after battle.
|
||||
|
||||
### Particles
|
||||
|
||||
#### New Move Animations
|
||||
- Fixed `q.pokemon.nature` returning class instance instead of proper string value (`cobblemon:adamant`)
|
||||
- Fixed `q.entity.is_looking_at` result being always `1` for whatever entity passed as target
|
||||
- Added hate chance optional parameter to `hate_entity` task. `1.0` will make an entity always attack the target
|
||||
|
||||
### Localization
|
||||
- Updated translations for:
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
- Added `cobblemon:catch_alpha_pokemon` advancement trigger and `totalAlphaCaptureCount` stat for captured Alpha Pokémon.
|
||||
|
||||
### New rideable Pokémon
|
||||
- Pidgeot
|
||||
- Crobat
|
||||
- Skarmory
|
||||
- Milotic
|
||||
@@ -106,7 +107,9 @@
|
||||
- Avalugg (Hisuian Form)
|
||||
|
||||
### Model updates for the following Pokémon
|
||||
|
||||
- Pidgey
|
||||
- Pidgeotto
|
||||
- Pidgeot
|
||||
- Sandshrew
|
||||
- Sandslash
|
||||
- Nidoking
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
# Changelog
|
||||
## [1.8.2 (October 11th, 2026)](#1-8-2)
|
||||
|
||||
### Additions
|
||||
- The following items can now be placed on the ground as blocks:
|
||||
- King's Rock, Galarica Cuff, Unremarkable Teacup, Masterpiece Teacup, Chipped Pot, Cracked Pot, Sachet, Metal Powder, Quick Powder, Bright Powder, Soft Sand, Electirizer, Magmarizer, Icy Rock, Heat Rock, Smooth Rock, Damp Rock, Destiny Knot, Luminous Moss, Never-Melt Ice, Wide Lens, Scope Lens, and Zoom Lens.
|
||||
- I wasn't finished. Iron Ball, Metal Coat, Throat Spray, Terrain Extender, Medicinal Brew, Moomoo Milk, HP Up, Protein, Iron, Carbos, Calcium, Zinc, PP Up, PP Max, Upgrade, Dubious Disc, and Loaded Dice.
|
||||
- The following items can now be placed on various surfaces:
|
||||
- Galarica Wreath, Magnet, Flame Orb, Life Orb, Toxic Orb, Light Ball, and Smoke Ball.
|
||||
- The following items can now be placed as blocks and have additional functionality:
|
||||
- Ring Target, Metronome, and Eject Button.
|
||||
- The following items can now be worn by Players and Pokémon:
|
||||
- Galarica Wreath, Cleanse Tag, Spell Tag, Sharp Beak, Covert Cloak, Shell Helmet, and Never-Melt Ice.
|
||||
- Wearable items can now be equipped by a player by holding it and right-clicking (or whatever you've rebound use/interact to).
|
||||
- Wearable items that can be placed down are exempt from this behaviour.
|
||||
- Mint Leaves can now be placed on the ground as Leaf Litter, or in Flower Pots.
|
||||
- The recall animation now renders the ball in hand with the player's arm raised.
|
||||
- Added Oricorio Flowers.
|
||||
- Added Terrain Plants, four plants grown from Electric, Grassy, Misty, and Psychic Seeds, which glow under specific environmental conditions and can be farmed for more of their seeds.
|
||||
- Berries can now be placed in Flower Pots.
|
||||
- The evolution tree for a Pokémon can now be viewed in the Pokédex, showing the Pokémon's full family line and what's needed to evolve into each stage.
|
||||
- Added custom sounds to a bunch of items that can be placed as blocks: liquid bottles, pill bottles, powders, and dice.
|
||||
- Added paper as a new cosmetic item for Pikachu.
|
||||
- Burmy changes its cloak after a battle it took part in, based on the biome.
|
||||
- Trash Cloak in the Deep Dark, Nether and End.
|
||||
- Plant Cloak in lush biomes such as forests, jungles, plains and swamps.
|
||||
- Sandy Cloak in sandy biomes, beaches and caves.
|
||||
|
||||
### Pokémon Added
|
||||
#### Generation 4
|
||||
- Snover
|
||||
- Abomasnow
|
||||
- Burmy
|
||||
- Wormadam
|
||||
- Mothim
|
||||
|
||||
#### Generation 5
|
||||
- Tympole
|
||||
- Palpitoad
|
||||
- Seismitoad
|
||||
|
||||
#### Generation 6
|
||||
- Helioptile
|
||||
- Heliolisk
|
||||
|
||||
#### Generation 7
|
||||
- Grubbin
|
||||
- Charjabug
|
||||
- Vikavolt
|
||||
- Minior
|
||||
|
||||
#### Generation 8
|
||||
- Eternatus
|
||||
|
||||
#### Generation 9
|
||||
- Greavard
|
||||
- Houndstone
|
||||
|
||||
### Model updates for the following Pokémon
|
||||
- Sudowoodo
|
||||
- Spheal
|
||||
- Cacnea
|
||||
- Cacturne
|
||||
- Binacle
|
||||
- Barbaracle
|
||||
- Glimmet
|
||||
- Glimmora
|
||||
- Deerling
|
||||
- Sawsbuck (All forms)
|
||||
- Absol
|
||||
- Poliwag
|
||||
- Politoed
|
||||
- Ekans
|
||||
- Oddish
|
||||
- Gloom
|
||||
- Vileplume
|
||||
- Bellossom
|
||||
- Shroomish
|
||||
- Chespin
|
||||
- Quilladin
|
||||
- Chesnaught
|
||||
- Fennekin
|
||||
- Braixen
|
||||
- Delphox
|
||||
- Froakie
|
||||
- Frogadier
|
||||
- Greninja
|
||||
- Shinx
|
||||
- Luxio
|
||||
- Luxray
|
||||
- Slakoth
|
||||
- Riolu
|
||||
- Lucario
|
||||
- Corsola
|
||||
- Mime Jr.
|
||||
|
||||
### Animation updates for the following Pokémon
|
||||
- Treecko (New Shoulder Mount!)
|
||||
- Bonsly (New Shoulder Mount!)
|
||||
- Sudowoodo
|
||||
- Cacnea
|
||||
- Cacturne
|
||||
- Ekans
|
||||
- Arbok
|
||||
- Oddish
|
||||
- Gloom
|
||||
- Vileplume
|
||||
- Bellossom
|
||||
- Pichu
|
||||
- Pikachu
|
||||
- Raichu (+ Alolan)
|
||||
- Greninja
|
||||
- Slakoth
|
||||
|
||||
### Changes
|
||||
- Slowed the speed of Type Gem growth, and revamped their generation to grow in a more crystal-like shape.
|
||||
- Terrain Seeds can now be planted.
|
||||
- Terrain Seeds are now consumed during PvP and NPC battles.
|
||||
- Glow Item Frames can be crafted using Bright Powder as an alternative to Glow Ink Sacs.
|
||||
- Bright Powder can be used on Signs and Hanging Signs to make text glow, as an alternative to Glow Ink Sacs.
|
||||
- Updated various recipes to display in Recipe Groups within the Recipe Book.
|
||||
- Updated most recipes to display more logically and consistently within the Recipe Book's categories.
|
||||
- Updated the following recipes
|
||||
- Never-Melt Ice, Focus Sash, Blunder Policy, Weakness Policy, Blank TM.
|
||||
- Made ride rotations less jittery in multiplayer.
|
||||
- Changes Disc Shelf TMs to use textures instead of tinting and overlays to line up with item display.
|
||||
- Blank TM can now be inserted into the Disc Shelf.
|
||||
- Added a TM creative tab.
|
||||
- Made regional and Vivillon split-evo locations mutually exclusive.
|
||||
- Vivillon's patterns are now viewable as forms with form names and unique Pokédex entries displayed.
|
||||
- Item evolutions now unlock **all** locked evolutions whose requirements are met instead of stopping after the first.
|
||||
- Exceptions being "forced" evolutions which stop after the first one.
|
||||
- Removed Mega Drain as a TM.
|
||||
- PokeSnacks (and other area spawns) will now start the vertical offset checking from the center rather than base coordinate
|
||||
- This will help PokeSnacks to work inside caves or tighter spaces better.
|
||||
|
||||
### Fixes
|
||||
- Type Gem blocks now properly generate clusters off of the block.
|
||||
- Correctly grant "They're Minerals!" advancement when planting a Type Gem.
|
||||
- Shoulder mounted Pokémon now follow player body animations, improving their positioning with custom player animations and default actions.
|
||||
- Shoulder mounted Pokémon now sit slightly higher with chest armor equipped for better alignment, with a configurable blacklist.
|
||||
- Type Gem Blocks now have advancements to give you the recipe in the recipe book (the data for the advancements were inside the recipes somehow??).
|
||||
- Some other recipes without advancements have also been corrected.
|
||||
- Corrected the TM Recipes for Charge Beam and Payday.
|
||||
- Starter Screen Categories will no longer stop rendering if they are bigger than the viewport and you are not viewing the top or bottom edges.
|
||||
- The Random Starter option no longer runs off into other categories or becomes unaccessible due to scroll limits if it causes a new row.
|
||||
- Mochi and Feathers no longer drop glass bottles on use.
|
||||
- Fixed a rare set of concurrency bugs related to reloading packs on NeoForge; fixes a ModernFix compatibility issue.
|
||||
- Removed unnecessary conditions for Mimikyu's standing pose. Hopefully fixes the rare instance of it using its shoulder animations during battle in multiplayer scenarios.
|
||||
- Fixed Rockruff line not blinking.
|
||||
- Fixed Flygon sometimes using its running animation instead of walking.
|
||||
- Fixed Bramblin always sleeping outside of battle.
|
||||
- Fixed Dragonair using its battle idle as a normal idle.
|
||||
- Fixed Lycanroc's head movement.
|
||||
- Added head movement to Archaludon.
|
||||
- Fixed Duraludon line not having any sleep animations.
|
||||
- Fixed Diglett line not having their faint animations.
|
||||
- Fixed Kingambit moving its legs while walking.
|
||||
- Fixed Alolan Diglett's cry not playing.
|
||||
- Fixed shiny alpha Snorlax using the non-shiny texture.
|
||||
- Fixed Crabominable's head breaking when looking around.
|
||||
- Fixed Shiny Dipplin and Hydrapple's textures.
|
||||
- Various structure fixes.
|
||||
- Fixed shiny Pokémon under certain circumstances forgetting taught TMs.
|
||||
- Fixed certain Pokémon sounds sometimes being doubled when played at specific times in their animations.
|
||||
- Fixed ball capture beam origin coming from behind the ball.
|
||||
- Fixed Safari Ball catch rate outside of battle.
|
||||
- Fixed alpha eye (and other) particles not respecting the client particle density setting in video options.
|
||||
- Fixed the TM Machine UI not closing when player is moving away from it.
|
||||
- Moved the config category for alpha/shiny chance config fields for fossil machine and honey log slathering to Spawning.
|
||||
- Fixed crashes for addon species with non-Cobblemon namespaces in evolution, fishing bait, and Pokédex lookups.
|
||||
- Bees will now grow Apricorns and the Galarica Nut Bush, which were in the bee growables tag but never handled, and correctly spend their nectar when they do.
|
||||
- Saccharine Leaves can now be bone mealed.
|
||||
- Fixed equipping a stack of wearable items instead of one item of a stack.
|
||||
- Fixed TM stack consumption in TM Machine screen when a player teaches a move to a Pokémon.
|
||||
- Fixed every Miltank giving mushroom stew, not only mushroom variants.
|
||||
- Medicinal Leeks can now be eaten when they aren't being planted, matching their food properties.
|
||||
- Sweeping attacks no longer set owned Pokémon on fire (e.g. with Fire Aspect) or knock them back. Friendly Fire is now off.
|
||||
- Fixed Pokémon not losing their previous form's signature moves when changing forms (e.g. Rotom keeping Overheat after leaving its Heat form).
|
||||
- Form-specific moves gained from a form change are now only granted if the Pokémon is high enough level to learn them, and no longer create duplicates in benched moves.
|
||||
- Spinda now learns Teeter Dance at level 32 instead of via TM.
|
||||
- Fixed Oricorio Pa'u form description in the Pokédex.
|
||||
- Fixed PC playing sound on close when opened via command.
|
||||
|
||||
### Developer
|
||||
- Evolution requirements can now set `pokedexIcon` and `pokedexTooltip` directly in their JSON to control how they're shown on the Pokédex's evolution tree, for example:
|
||||
```json
|
||||
{
|
||||
"variant": "attack_defence_ratio",
|
||||
"pokedexIcon": "minecraft:diamond_sword",
|
||||
"pokedexTooltip": "cobblemon.ui.pokedex.requirement.attack_defence_ratio.tooltip"
|
||||
}
|
||||
```
|
||||
- Fixed the wrong order of operations in the code flow prior to the `FOSSIL_REVIVED` event causing Pokémon to appear without the entity link.
|
||||
- Fixed TestPartySlot command not correctly comparing the provided spec with the target Pokémon.
|
||||
|
||||
### Molang & Datapacks
|
||||
- A new `negate` variant for evolution requirements has been added, which will negate (invert) the provided inner condition.
|
||||
- Added Molang functions for individual Pokédex ids, wherein a subdex is passed in as a string to `dex_caught_count` etc.
|
||||
- Added a `battle_ended` callback, backed by the new `BATTLE_ENDED` event, which fires whenever a battle ends for any reason, alongside a multitude of flags not previously covered by `BATTLE_VICTORY`.
|
||||
- Added `battle_pokemon` to battle actor structs and `has_faced_opponents` to battle Pokémon structs.
|
||||
- Added the `cobblemon:form_change/bagworm_cloak/plant_cloak`, `sandy_cloak` and `trash_cloak` biome tags, which control Burmy's cloak after battle.
|
||||
|
||||
### Localization
|
||||
- Updated translations for:
|
||||
- Brazilian Portuguese
|
||||
- Canadian French
|
||||
- Japanese
|
||||
- Korean
|
||||
- Russian
|
||||
- Ukrainian
|
||||
+7
-17
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.item.crafting.CookingPotShapelessRecipe;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import net.minecraft.client.ClientRecipeBook;
|
||||
import net.minecraft.client.RecipeBookCategories;
|
||||
import net.minecraft.client.gui.screens.recipebook.RecipeCollection;
|
||||
@@ -63,23 +64,12 @@ public abstract class ClientRecipeBookMixin {
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "setupCollections", at = @At("RETURN"))
|
||||
private void addCustomAggregateCategories(Iterable<RecipeHolder<?>> recipes, RegistryAccess registryAccess, CallbackInfo ci) {
|
||||
Map<RecipeBookCategories, List<List<RecipeHolder<?>>>> map = categorizeAndGroupRecipes(recipes);
|
||||
Map<RecipeBookCategories, List<RecipeCollection>> map2 = Maps.newHashMap();
|
||||
ImmutableList.Builder<RecipeCollection> builder = ImmutableList.builder();
|
||||
|
||||
map.forEach((recipeBookCategories, list) -> {
|
||||
List<RecipeCollection> collections = list.stream()
|
||||
.map(listx -> new RecipeCollection(registryAccess, listx))
|
||||
.peek(builder::add)
|
||||
.collect(ImmutableList.toImmutableList());
|
||||
map2.put(recipeBookCategories, collections);
|
||||
});
|
||||
RecipeBookCategories.AGGREGATE_CATEGORIES.forEach((recipeBookCategories, list) -> map2.put(recipeBookCategories, (List) list.stream().flatMap((recipeBookCategoriesx) -> ((List) map2.getOrDefault(recipeBookCategoriesx, ImmutableList.of())).stream()).collect(ImmutableList.toImmutableList())));
|
||||
@Inject(method = "setupCollections",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lcom/google/common/collect/ImmutableMap;copyOf(Ljava/util/Map;)Lcom/google/common/collect/ImmutableMap;"
|
||||
))
|
||||
private void addCustomAggregateCategories(Iterable<RecipeHolder<?>> recipes, RegistryAccess registryAccess, CallbackInfo ci, @Local(name = "map2") Map<RecipeBookCategories, List<RecipeCollection>> map2) {
|
||||
CobblemonRecipeCategories.Companion.getCustomAggregateCategories().forEach((recipeBookCategories, list) -> map2.put(recipeBookCategories, (List) list.stream().flatMap((recipeBookCategoriesx) -> ((List) map2.getOrDefault(recipeBookCategoriesx, ImmutableList.of())).stream()).collect(ImmutableList.toImmutableList())));
|
||||
|
||||
this.collectionsByTab = ImmutableMap.copyOf(map2);
|
||||
this.allCollections = builder.build();
|
||||
}
|
||||
}
|
||||
+13
-43
@@ -9,55 +9,25 @@
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonRecipeCategories;
|
||||
import net.minecraft.client.ClientRecipeBook;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import com.llamalad7.mixinextras.expression.Definition;
|
||||
import com.llamalad7.mixinextras.expression.Expression;
|
||||
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import net.minecraft.client.RecipeBookCategories;
|
||||
import net.minecraft.client.gui.screens.recipebook.RecipeBookComponent;
|
||||
import net.minecraft.client.gui.screens.recipebook.RecipeBookPage;
|
||||
import net.minecraft.client.gui.screens.recipebook.RecipeBookTabButton;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
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(RecipeBookComponent.class)
|
||||
public class RecipeBookComponentMixin {
|
||||
|
||||
@Shadow private ClientRecipeBook book;
|
||||
|
||||
@Shadow protected Minecraft minecraft;
|
||||
|
||||
@Shadow private int width;
|
||||
|
||||
@Shadow private int xOffset;
|
||||
|
||||
@Shadow private int height;
|
||||
|
||||
@Shadow @Final private RecipeBookPage recipeBookPage;
|
||||
|
||||
@Inject(method = "updateTabs", at = @At("HEAD"), cancellable = true)
|
||||
private void customUpdateTabs(CallbackInfo ci) {
|
||||
RecipeBookComponent instance = (RecipeBookComponent) (Object) this;
|
||||
int i = (width - 147) / 2 - xOffset - 30;
|
||||
int j = (height - 166) / 2 + 3;
|
||||
int k = 27;
|
||||
int l = 0;
|
||||
|
||||
for (RecipeBookTabButton recipeBookTabButton : instance.tabButtons) {
|
||||
RecipeBookCategories recipeBookCategories = recipeBookTabButton.getCategory();
|
||||
if (recipeBookCategories != RecipeBookCategories.CRAFTING_SEARCH && recipeBookCategories != RecipeBookCategories.FURNACE_SEARCH && recipeBookCategories != CobblemonRecipeCategories.COOKING_POT_SEARCH.toVanillaCategory()) {
|
||||
if (recipeBookTabButton.updateVisibility(book)) {
|
||||
recipeBookTabButton.setPosition(i, j + 27 * l++);
|
||||
recipeBookTabButton.startAnimation(minecraft);
|
||||
}
|
||||
} else {
|
||||
recipeBookTabButton.visible = true;
|
||||
recipeBookTabButton.setPosition(i, j + k * l++);
|
||||
}
|
||||
}
|
||||
|
||||
ci.cancel();
|
||||
@Definition(id = "recipeBookCategories", local = @Local(name = "recipeBookCategories"))
|
||||
@Definition(id = "FURNACE_SEARCH", field = "Lnet/minecraft/client/RecipeBookCategories;FURNACE_SEARCH:Lnet/minecraft/client/RecipeBookCategories;")
|
||||
@Expression("recipeBookCategories != FURNACE_SEARCH")
|
||||
@ModifyExpressionValue(
|
||||
method = "updateTabs",
|
||||
at = @At(value = "MIXINEXTRAS:EXPRESSION")
|
||||
)
|
||||
private boolean notCookingPotSearch(boolean original, @Local(name = "recipeBookCategories") RecipeBookCategories recipeBookCategories) {
|
||||
return original && recipeBookCategories != CobblemonRecipeCategories.COOKING_POT_SEARCH.toVanillaCategory();
|
||||
}
|
||||
}
|
||||
@@ -260,6 +260,9 @@ object Cobblemon {
|
||||
RequestManager.onLogoff(it.player)
|
||||
serverPlayerStructs.remove(it.player.uuid)
|
||||
}
|
||||
PlatformEvents.PLAYER_RESPAWN.subscribe {
|
||||
serverPlayerStructs.remove(it.player.uuid)
|
||||
}
|
||||
PlatformEvents.PLAYER_DEATH.subscribe {
|
||||
PCLinkManager.removeLink(it.player.uuid)
|
||||
battleRegistry.getBattleByParticipatingPlayer(it.player)?.stop()
|
||||
|
||||
@@ -845,54 +845,35 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val PEP_UP_FLOWER = this.create("pep_up_flower", FlowerBlock(MobEffects.LEVITATION, 10F, BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).noCollission().instabreak().sound(SoundType.GRASS).offsetType(BlockBehaviour.OffsetType.XZ).pushReaction(PushReaction.DESTROY)))
|
||||
@JvmField
|
||||
val POTTED_PEP_UP_FLOWER = this.create("potted_pep_up_flower", BlocksInvoker.createFlowerPotBlock(PEP_UP_FLOWER))
|
||||
@JvmField
|
||||
val HEARTY_GRAINS = this.create("hearty_grains", HeartyGrainsBlock(BlockBehaviour.Properties.of().pushReaction(PushReaction.DESTROY).ignitedByLava().mapColor(MapColor.PLANT).noCollission().randomTicks().instabreak()))
|
||||
|
||||
@JvmField
|
||||
val GALARICA_NUT_BUSH = this.create("galarica_nut_bush", NutBushBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).randomTicks().noCollission().sound(SoundType.SWEET_BERRY_BUSH).pushReaction(PushReaction.DESTROY)))
|
||||
|
||||
@JvmField
|
||||
val POTTED_RED_APRICORN_SAPLING = this.create("potted_red_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(RED_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_YELLOW_APRICORN_SAPLING = this.create("potted_yellow_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(YELLOW_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_GREEN_APRICORN_SAPLING = this.create("potted_green_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(GREEN_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_BLUE_APRICORN_SAPLING = this.create("potted_blue_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(BLUE_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_PINK_APRICORN_SAPLING = this.create("potted_pink_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(PINK_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_BLACK_APRICORN_SAPLING = this.create("potted_black_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(BLACK_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_WHITE_APRICORN_SAPLING = this.create("potted_white_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(WHITE_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_SACCHARINE_SAPLING = this.create("potted_saccharine_sapling", BlocksInvoker.createFlowerPotBlock(SACCHARINE_SAPLING))
|
||||
|
||||
@JvmField
|
||||
val RED_MINT_LEAF_LITTER = this.mintLitter("red_mint_leaf_litter", MapColor.COLOR_RED)
|
||||
@JvmField
|
||||
val POTTED_RED_MINT = this.pottedPlant("potted_red_mint", RED_MINT_LEAF_LITTER)
|
||||
val POTTED_RED_MINT = this.flowerPot("potted_red_mint", RED_MINT_LEAF_LITTER)
|
||||
@JvmField
|
||||
val BLUE_MINT_LEAF_LITTER = this.mintLitter("blue_mint_leaf_litter", MapColor.COLOR_BLUE)
|
||||
@JvmField
|
||||
val POTTED_BLUE_MINT = this.pottedPlant("potted_blue_mint", BLUE_MINT_LEAF_LITTER)
|
||||
val POTTED_BLUE_MINT = this.flowerPot("potted_blue_mint", BLUE_MINT_LEAF_LITTER)
|
||||
@JvmField
|
||||
val CYAN_MINT_LEAF_LITTER = this.mintLitter("cyan_mint_leaf_litter", MapColor.COLOR_CYAN)
|
||||
@JvmField
|
||||
val POTTED_CYAN_MINT = this.pottedPlant("potted_cyan_mint", CYAN_MINT_LEAF_LITTER)
|
||||
val POTTED_CYAN_MINT = this.flowerPot("potted_cyan_mint", CYAN_MINT_LEAF_LITTER)
|
||||
@JvmField
|
||||
val PINK_MINT_LEAF_LITTER = this.mintLitter("pink_mint_leaf_litter", MapColor.COLOR_PINK)
|
||||
@JvmField
|
||||
val POTTED_PINK_MINT = this.pottedPlant("potted_pink_mint", PINK_MINT_LEAF_LITTER)
|
||||
val POTTED_PINK_MINT = this.flowerPot("potted_pink_mint", PINK_MINT_LEAF_LITTER)
|
||||
@JvmField
|
||||
val GREEN_MINT_LEAF_LITTER = this.mintLitter("green_mint_leaf_litter", MapColor.COLOR_GREEN)
|
||||
@JvmField
|
||||
val POTTED_GREEN_MINT = this.pottedPlant("potted_green_mint", GREEN_MINT_LEAF_LITTER)
|
||||
val POTTED_GREEN_MINT = this.flowerPot("potted_green_mint", GREEN_MINT_LEAF_LITTER)
|
||||
@JvmField
|
||||
val WHITE_MINT_LEAF_LITTER = this.mintLitter("white_mint_leaf_litter", MapColor.SNOW)
|
||||
@JvmField
|
||||
val POTTED_WHITE_MINT = this.pottedPlant("potted_white_mint", WHITE_MINT_LEAF_LITTER)
|
||||
val POTTED_WHITE_MINT = this.flowerPot("potted_white_mint", WHITE_MINT_LEAF_LITTER)
|
||||
|
||||
@JvmField
|
||||
val LOBAILA = this.create("lobaila", LobailaFlowerBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).noCollission().instabreak().sound(SoundType.GRASS).offsetType(BlockBehaviour.OffsetType.XZ).ignitedByLava().pushReaction(PushReaction.DESTROY)))
|
||||
@@ -1104,145 +1085,163 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
//val BINDING_SOIL = this.create("binding_soil", BindingSoilBlock(BlockBehaviour.Properties.of()))
|
||||
|
||||
@JvmField
|
||||
val POTTED_AGUAV_BERRY = this.create("potted_aguav_berry", BlocksInvoker.createFlowerPotBlock(AGUAV_BERRY))
|
||||
val POTTED_AGUAV_BERRY = this.flowerPot("potted_aguav_berry", AGUAV_BERRY)
|
||||
@JvmField
|
||||
val POTTED_APICOT_BERRY = this.create("potted_apicot_berry", BlocksInvoker.createFlowerPotBlock(APICOT_BERRY))
|
||||
val POTTED_APICOT_BERRY = this.flowerPot("potted_apicot_berry", APICOT_BERRY)
|
||||
@JvmField
|
||||
val POTTED_ASPEAR_BERRY = this.create("potted_aspear_berry", BlocksInvoker.createFlowerPotBlock(ASPEAR_BERRY))
|
||||
val POTTED_ASPEAR_BERRY = this.flowerPot("potted_aspear_berry", ASPEAR_BERRY)
|
||||
@JvmField
|
||||
val POTTED_BABIRI_BERRY = this.create("potted_babiri_berry", BlocksInvoker.createFlowerPotBlock(BABIRI_BERRY))
|
||||
val POTTED_BABIRI_BERRY = this.flowerPot("potted_babiri_berry", BABIRI_BERRY)
|
||||
@JvmField
|
||||
val POTTED_BELUE_BERRY = this.create("potted_belue_berry", BlocksInvoker.createFlowerPotBlock(BELUE_BERRY))
|
||||
val POTTED_BELUE_BERRY = this.flowerPot("potted_belue_berry", BELUE_BERRY)
|
||||
@JvmField
|
||||
val POTTED_BLUK_BERRY = this.create("potted_bluk_berry", BlocksInvoker.createFlowerPotBlock(BLUK_BERRY))
|
||||
val POTTED_BLUK_BERRY = this.flowerPot("potted_bluk_berry", BLUK_BERRY)
|
||||
@JvmField
|
||||
val POTTED_CHARTI_BERRY = this.create("potted_charti_berry", BlocksInvoker.createFlowerPotBlock(CHARTI_BERRY))
|
||||
val POTTED_CHARTI_BERRY = this.flowerPot("potted_charti_berry", CHARTI_BERRY)
|
||||
@JvmField
|
||||
val POTTED_CHERI_BERRY = this.create("potted_cheri_berry", BlocksInvoker.createFlowerPotBlock(CHERI_BERRY))
|
||||
val POTTED_CHERI_BERRY = this.flowerPot("potted_cheri_berry", CHERI_BERRY)
|
||||
@JvmField
|
||||
val POTTED_CHESTO_BERRY = this.create("potted_chesto_berry", BlocksInvoker.createFlowerPotBlock(CHESTO_BERRY))
|
||||
val POTTED_CHESTO_BERRY = this.flowerPot("potted_chesto_berry", CHESTO_BERRY)
|
||||
@JvmField
|
||||
val POTTED_CHILAN_BERRY = this.create("potted_chilan_berry", BlocksInvoker.createFlowerPotBlock(CHILAN_BERRY))
|
||||
val POTTED_CHILAN_BERRY = this.flowerPot("potted_chilan_berry", CHILAN_BERRY)
|
||||
@JvmField
|
||||
val POTTED_CHOPLE_BERRY = this.create("potted_chople_berry", BlocksInvoker.createFlowerPotBlock(CHOPLE_BERRY))
|
||||
val POTTED_CHOPLE_BERRY = this.flowerPot("potted_chople_berry", CHOPLE_BERRY)
|
||||
@JvmField
|
||||
val POTTED_COBA_BERRY = this.create("potted_coba_berry", BlocksInvoker.createFlowerPotBlock(COBA_BERRY))
|
||||
val POTTED_COBA_BERRY = this.flowerPot("potted_coba_berry", COBA_BERRY)
|
||||
@JvmField
|
||||
val POTTED_COLBUR_BERRY = this.create("potted_colbur_berry", BlocksInvoker.createFlowerPotBlock(COLBUR_BERRY))
|
||||
val POTTED_COLBUR_BERRY = this.flowerPot("potted_colbur_berry", COLBUR_BERRY)
|
||||
@JvmField
|
||||
val POTTED_CORNN_BERRY = this.create("potted_cornn_berry", BlocksInvoker.createFlowerPotBlock(CORNN_BERRY))
|
||||
val POTTED_CORNN_BERRY = this.flowerPot("potted_cornn_berry", CORNN_BERRY)
|
||||
@JvmField
|
||||
val POTTED_CUSTAP_BERRY = this.create("potted_custap_berry", BlocksInvoker.createFlowerPotBlock(CUSTAP_BERRY))
|
||||
val POTTED_CUSTAP_BERRY = this.flowerPot("potted_custap_berry", CUSTAP_BERRY)
|
||||
@JvmField
|
||||
val POTTED_DURIN_BERRY = this.create("potted_durin_berry", BlocksInvoker.createFlowerPotBlock(DURIN_BERRY))
|
||||
val POTTED_DURIN_BERRY = this.flowerPot("potted_durin_berry", DURIN_BERRY)
|
||||
@JvmField
|
||||
val POTTED_EGGANT_BERRY = this.create("potted_eggant_berry", BlocksInvoker.createFlowerPotBlock(EGGANT_BERRY))
|
||||
val POTTED_EGGANT_BERRY = this.flowerPot("potted_eggant_berry", EGGANT_BERRY)
|
||||
@JvmField
|
||||
val POTTED_ENIGMA_BERRY = this.create("potted_enigma_berry", BlocksInvoker.createFlowerPotBlock(ENIGMA_BERRY))
|
||||
val POTTED_ENIGMA_BERRY = this.flowerPot("potted_enigma_berry", ENIGMA_BERRY)
|
||||
@JvmField
|
||||
val POTTED_FIGY_BERRY = this.create("potted_figy_berry", BlocksInvoker.createFlowerPotBlock(FIGY_BERRY))
|
||||
val POTTED_FIGY_BERRY = this.flowerPot("potted_figy_berry", FIGY_BERRY)
|
||||
@JvmField
|
||||
val POTTED_GANLON_BERRY = this.create("potted_ganlon_berry", BlocksInvoker.createFlowerPotBlock(GANLON_BERRY))
|
||||
val POTTED_GANLON_BERRY = this.flowerPot("potted_ganlon_berry", GANLON_BERRY)
|
||||
@JvmField
|
||||
val POTTED_GREPA_BERRY = this.create("potted_grepa_berry", BlocksInvoker.createFlowerPotBlock(GREPA_BERRY))
|
||||
val POTTED_GREPA_BERRY = this.flowerPot("potted_grepa_berry", GREPA_BERRY)
|
||||
@JvmField
|
||||
val POTTED_HABAN_BERRY = this.create("potted_haban_berry", BlocksInvoker.createFlowerPotBlock(HABAN_BERRY))
|
||||
val POTTED_HABAN_BERRY = this.flowerPot("potted_haban_berry", HABAN_BERRY)
|
||||
@JvmField
|
||||
val POTTED_HONDEW_BERRY = this.create("potted_hondew_berry", BlocksInvoker.createFlowerPotBlock(HONDEW_BERRY))
|
||||
val POTTED_HONDEW_BERRY = this.flowerPot("potted_hondew_berry", HONDEW_BERRY)
|
||||
@JvmField
|
||||
val POTTED_HOPO_BERRY = this.create("potted_hopo_berry", BlocksInvoker.createFlowerPotBlock(HOPO_BERRY))
|
||||
val POTTED_HOPO_BERRY = this.flowerPot("potted_hopo_berry", HOPO_BERRY)
|
||||
@JvmField
|
||||
val POTTED_IAPAPA_BERRY = this.create("potted_iapapa_berry", BlocksInvoker.createFlowerPotBlock(IAPAPA_BERRY))
|
||||
val POTTED_IAPAPA_BERRY = this.flowerPot("potted_iapapa_berry", IAPAPA_BERRY)
|
||||
@JvmField
|
||||
val POTTED_JABOCA_BERRY = this.create("potted_jaboca_berry", BlocksInvoker.createFlowerPotBlock(JABOCA_BERRY))
|
||||
val POTTED_JABOCA_BERRY = this.flowerPot("potted_jaboca_berry", JABOCA_BERRY)
|
||||
@JvmField
|
||||
val POTTED_KASIB_BERRY = this.create("potted_kasib_berry", BlocksInvoker.createFlowerPotBlock(KASIB_BERRY))
|
||||
val POTTED_KASIB_BERRY = this.flowerPot("potted_kasib_berry", KASIB_BERRY)
|
||||
@JvmField
|
||||
val POTTED_KEBIA_BERRY = this.create("potted_kebia_berry", BlocksInvoker.createFlowerPotBlock(KEBIA_BERRY))
|
||||
val POTTED_KEBIA_BERRY = this.flowerPot("potted_kebia_berry", KEBIA_BERRY)
|
||||
@JvmField
|
||||
val POTTED_KEE_BERRY = this.create("potted_kee_berry", BlocksInvoker.createFlowerPotBlock(KEE_BERRY))
|
||||
val POTTED_KEE_BERRY = this.flowerPot("potted_kee_berry", KEE_BERRY)
|
||||
@JvmField
|
||||
val POTTED_KELPSY_BERRY = this.create("potted_kelpsy_berry", BlocksInvoker.createFlowerPotBlock(KELPSY_BERRY))
|
||||
val POTTED_KELPSY_BERRY = this.flowerPot("potted_kelpsy_berry", KELPSY_BERRY)
|
||||
@JvmField
|
||||
val POTTED_LANSAT_BERRY = this.create("potted_lansat_berry", BlocksInvoker.createFlowerPotBlock(LANSAT_BERRY))
|
||||
val POTTED_LANSAT_BERRY = this.flowerPot("potted_lansat_berry", LANSAT_BERRY)
|
||||
@JvmField
|
||||
val POTTED_LEPPA_BERRY = this.create("potted_leppa_berry", BlocksInvoker.createFlowerPotBlock(LEPPA_BERRY))
|
||||
val POTTED_LEPPA_BERRY = this.flowerPot("potted_leppa_berry", LEPPA_BERRY)
|
||||
@JvmField
|
||||
val POTTED_LIECHI_BERRY = this.create("potted_liechi_berry", BlocksInvoker.createFlowerPotBlock(LIECHI_BERRY))
|
||||
val POTTED_LIECHI_BERRY = this.flowerPot("potted_liechi_berry", LIECHI_BERRY)
|
||||
@JvmField
|
||||
val POTTED_LUM_BERRY = this.create("potted_lum_berry", BlocksInvoker.createFlowerPotBlock(LUM_BERRY))
|
||||
val POTTED_LUM_BERRY = this.flowerPot("potted_lum_berry", LUM_BERRY)
|
||||
@JvmField
|
||||
val POTTED_MAGO_BERRY = this.create("potted_mago_berry", BlocksInvoker.createFlowerPotBlock(MAGO_BERRY))
|
||||
val POTTED_MAGO_BERRY = this.flowerPot("potted_mago_berry", MAGO_BERRY)
|
||||
@JvmField
|
||||
val POTTED_MAGOST_BERRY = this.create("potted_magost_berry", BlocksInvoker.createFlowerPotBlock(MAGOST_BERRY))
|
||||
val POTTED_MAGOST_BERRY = this.flowerPot("potted_magost_berry", MAGOST_BERRY)
|
||||
@JvmField
|
||||
val POTTED_MARANGA_BERRY = this.create("potted_maranga_berry", BlocksInvoker.createFlowerPotBlock(MARANGA_BERRY))
|
||||
val POTTED_MARANGA_BERRY = this.flowerPot("potted_maranga_berry", MARANGA_BERRY)
|
||||
@JvmField
|
||||
val POTTED_MICLE_BERRY = this.create("potted_micle_berry", BlocksInvoker.createFlowerPotBlock(MICLE_BERRY))
|
||||
val POTTED_MICLE_BERRY = this.flowerPot("potted_micle_berry", MICLE_BERRY)
|
||||
@JvmField
|
||||
val POTTED_NANAB_BERRY = this.create("potted_nanab_berry", BlocksInvoker.createFlowerPotBlock(NANAB_BERRY))
|
||||
val POTTED_NANAB_BERRY = this.flowerPot("potted_nanab_berry", NANAB_BERRY)
|
||||
@JvmField
|
||||
val POTTED_NOMEL_BERRY = this.create("potted_nomel_berry", BlocksInvoker.createFlowerPotBlock(NOMEL_BERRY))
|
||||
val POTTED_NOMEL_BERRY = this.flowerPot("potted_nomel_berry", NOMEL_BERRY)
|
||||
@JvmField
|
||||
val POTTED_OCCA_BERRY = this.create("potted_occa_berry", BlocksInvoker.createFlowerPotBlock(OCCA_BERRY))
|
||||
val POTTED_OCCA_BERRY = this.flowerPot("potted_occa_berry", OCCA_BERRY)
|
||||
@JvmField
|
||||
val POTTED_ORAN_BERRY = this.create("potted_oran_berry", BlocksInvoker.createFlowerPotBlock(ORAN_BERRY))
|
||||
val POTTED_ORAN_BERRY = this.flowerPot("potted_oran_berry", ORAN_BERRY)
|
||||
@JvmField
|
||||
val POTTED_PAMTRE_BERRY = this.create("potted_pamtre_berry", BlocksInvoker.createFlowerPotBlock(PAMTRE_BERRY))
|
||||
val POTTED_PAMTRE_BERRY = this.flowerPot("potted_pamtre_berry", PAMTRE_BERRY)
|
||||
@JvmField
|
||||
val POTTED_PASSHO_BERRY = this.create("potted_passho_berry", BlocksInvoker.createFlowerPotBlock(PASSHO_BERRY))
|
||||
val POTTED_PASSHO_BERRY = this.flowerPot("potted_passho_berry", PASSHO_BERRY)
|
||||
@JvmField
|
||||
val POTTED_PAYAPA_BERRY = this.create("potted_payapa_berry", BlocksInvoker.createFlowerPotBlock(PAYAPA_BERRY))
|
||||
val POTTED_PAYAPA_BERRY = this.flowerPot("potted_payapa_berry", PAYAPA_BERRY)
|
||||
@JvmField
|
||||
val POTTED_PECHA_BERRY = this.create("potted_pecha_berry", BlocksInvoker.createFlowerPotBlock(PECHA_BERRY))
|
||||
val POTTED_PECHA_BERRY = this.flowerPot("potted_pecha_berry", PECHA_BERRY)
|
||||
@JvmField
|
||||
val POTTED_PERSIM_BERRY = this.create("potted_persim_berry", BlocksInvoker.createFlowerPotBlock(PERSIM_BERRY))
|
||||
val POTTED_PERSIM_BERRY = this.flowerPot("potted_persim_berry", PERSIM_BERRY)
|
||||
@JvmField
|
||||
val POTTED_PETAYA_BERRY = this.create("potted_petaya_berry", BlocksInvoker.createFlowerPotBlock(PETAYA_BERRY))
|
||||
val POTTED_PETAYA_BERRY = this.flowerPot("potted_petaya_berry", PETAYA_BERRY)
|
||||
@JvmField
|
||||
val POTTED_PINAP_BERRY = this.create("potted_pinap_berry", BlocksInvoker.createFlowerPotBlock(PINAP_BERRY))
|
||||
val POTTED_PINAP_BERRY = this.flowerPot("potted_pinap_berry", PINAP_BERRY)
|
||||
@JvmField
|
||||
val POTTED_POMEG_BERRY = this.create("potted_pomeg_berry", BlocksInvoker.createFlowerPotBlock(POMEG_BERRY))
|
||||
val POTTED_POMEG_BERRY = this.flowerPot("potted_pomeg_berry", POMEG_BERRY)
|
||||
@JvmField
|
||||
val POTTED_QUALOT_BERRY = this.create("potted_qualot_berry", BlocksInvoker.createFlowerPotBlock(QUALOT_BERRY))
|
||||
val POTTED_QUALOT_BERRY = this.flowerPot("potted_qualot_berry", QUALOT_BERRY)
|
||||
@JvmField
|
||||
val POTTED_RABUTA_BERRY = this.create("potted_rabuta_berry", BlocksInvoker.createFlowerPotBlock(RABUTA_BERRY))
|
||||
val POTTED_RABUTA_BERRY = this.flowerPot("potted_rabuta_berry", RABUTA_BERRY)
|
||||
@JvmField
|
||||
val POTTED_RAWST_BERRY = this.create("potted_rawst_berry", BlocksInvoker.createFlowerPotBlock(RAWST_BERRY))
|
||||
val POTTED_RAWST_BERRY = this.flowerPot("potted_rawst_berry", RAWST_BERRY)
|
||||
@JvmField
|
||||
val POTTED_RAZZ_BERRY = this.create("potted_razz_berry", BlocksInvoker.createFlowerPotBlock(RAZZ_BERRY))
|
||||
val POTTED_RAZZ_BERRY = this.flowerPot("potted_razz_berry", RAZZ_BERRY)
|
||||
@JvmField
|
||||
val POTTED_RINDO_BERRY = this.create("potted_rindo_berry", BlocksInvoker.createFlowerPotBlock(RINDO_BERRY))
|
||||
val POTTED_RINDO_BERRY = this.flowerPot("potted_rindo_berry", RINDO_BERRY)
|
||||
@JvmField
|
||||
val POTTED_ROSELI_BERRY = this.create("potted_roseli_berry", BlocksInvoker.createFlowerPotBlock(ROSELI_BERRY))
|
||||
val POTTED_ROSELI_BERRY = this.flowerPot("potted_roseli_berry", ROSELI_BERRY)
|
||||
@JvmField
|
||||
val POTTED_ROWAP_BERRY = this.create("potted_rowap_berry", BlocksInvoker.createFlowerPotBlock(ROWAP_BERRY))
|
||||
val POTTED_ROWAP_BERRY = this.flowerPot("potted_rowap_berry", ROWAP_BERRY)
|
||||
@JvmField
|
||||
val POTTED_SALAC_BERRY = this.create("potted_salac_berry", BlocksInvoker.createFlowerPotBlock(SALAC_BERRY))
|
||||
val POTTED_SALAC_BERRY = this.flowerPot("potted_salac_berry", SALAC_BERRY)
|
||||
@JvmField
|
||||
val POTTED_SHUCA_BERRY = this.create("potted_shuca_berry", BlocksInvoker.createFlowerPotBlock(SHUCA_BERRY))
|
||||
val POTTED_SHUCA_BERRY = this.flowerPot("potted_shuca_berry", SHUCA_BERRY)
|
||||
@JvmField
|
||||
val POTTED_SITRUS_BERRY = this.create("potted_sitrus_berry", BlocksInvoker.createFlowerPotBlock(SITRUS_BERRY))
|
||||
val POTTED_SITRUS_BERRY = this.flowerPot("potted_sitrus_berry", SITRUS_BERRY)
|
||||
@JvmField
|
||||
val POTTED_SPELON_BERRY = this.create("potted_spelon_berry", BlocksInvoker.createFlowerPotBlock(SPELON_BERRY))
|
||||
val POTTED_SPELON_BERRY = this.flowerPot("potted_spelon_berry", SPELON_BERRY)
|
||||
@JvmField
|
||||
val POTTED_STARF_BERRY = this.create("potted_starf_berry", BlocksInvoker.createFlowerPotBlock(STARF_BERRY))
|
||||
val POTTED_STARF_BERRY = this.flowerPot("potted_starf_berry", STARF_BERRY)
|
||||
@JvmField
|
||||
val POTTED_TAMATO_BERRY = this.create("potted_tamato_berry", BlocksInvoker.createFlowerPotBlock(TAMATO_BERRY))
|
||||
val POTTED_TAMATO_BERRY = this.flowerPot("potted_tamato_berry", TAMATO_BERRY)
|
||||
@JvmField
|
||||
val POTTED_TANGA_BERRY = this.create("potted_tanga_berry", BlocksInvoker.createFlowerPotBlock(TANGA_BERRY))
|
||||
val POTTED_TANGA_BERRY = this.flowerPot("potted_tanga_berry", TANGA_BERRY)
|
||||
@JvmField
|
||||
val POTTED_TOUGA_BERRY = this.create("potted_touga_berry", BlocksInvoker.createFlowerPotBlock(TOUGA_BERRY))
|
||||
val POTTED_TOUGA_BERRY = this.flowerPot("potted_touga_berry", TOUGA_BERRY)
|
||||
@JvmField
|
||||
val POTTED_WACAN_BERRY = this.create("potted_wacan_berry", BlocksInvoker.createFlowerPotBlock(WACAN_BERRY))
|
||||
val POTTED_WACAN_BERRY = this.flowerPot("potted_wacan_berry", WACAN_BERRY)
|
||||
@JvmField
|
||||
val POTTED_WATMEL_BERRY = this.create("potted_watmel_berry", BlocksInvoker.createFlowerPotBlock(WATMEL_BERRY))
|
||||
val POTTED_WATMEL_BERRY = this.flowerPot("potted_watmel_berry", WATMEL_BERRY)
|
||||
@JvmField
|
||||
val POTTED_WEPEAR_BERRY = this.create("potted_wepear_berry", BlocksInvoker.createFlowerPotBlock(WEPEAR_BERRY))
|
||||
val POTTED_WEPEAR_BERRY = this.flowerPot("potted_wepear_berry", WEPEAR_BERRY)
|
||||
@JvmField
|
||||
val POTTED_WIKI_BERRY = this.create("potted_wiki_berry", BlocksInvoker.createFlowerPotBlock(WIKI_BERRY))
|
||||
val POTTED_WIKI_BERRY = this.flowerPot("potted_wiki_berry", WIKI_BERRY)
|
||||
@JvmField
|
||||
val POTTED_YACHE_BERRY = this.create("potted_yache_berry", BlocksInvoker.createFlowerPotBlock(YACHE_BERRY))
|
||||
val POTTED_YACHE_BERRY = this.flowerPot("potted_yache_berry", YACHE_BERRY)
|
||||
@JvmField
|
||||
val POTTED_PEP_UP_FLOWER = this.flowerPot("potted_pep_up_flower", PEP_UP_FLOWER)
|
||||
@JvmField
|
||||
val POTTED_RED_APRICORN_SAPLING = this.flowerPot("potted_red_apricorn_sapling", RED_APRICORN_SAPLING)
|
||||
@JvmField
|
||||
val POTTED_YELLOW_APRICORN_SAPLING = this.flowerPot("potted_yellow_apricorn_sapling", YELLOW_APRICORN_SAPLING)
|
||||
@JvmField
|
||||
val POTTED_GREEN_APRICORN_SAPLING = this.flowerPot("potted_green_apricorn_sapling", GREEN_APRICORN_SAPLING)
|
||||
@JvmField
|
||||
val POTTED_BLUE_APRICORN_SAPLING = this.flowerPot("potted_blue_apricorn_sapling", BLUE_APRICORN_SAPLING)
|
||||
@JvmField
|
||||
val POTTED_PINK_APRICORN_SAPLING = this.flowerPot("potted_pink_apricorn_sapling", PINK_APRICORN_SAPLING)
|
||||
@JvmField
|
||||
val POTTED_BLACK_APRICORN_SAPLING = this.flowerPot("potted_black_apricorn_sapling", BLACK_APRICORN_SAPLING)
|
||||
@JvmField
|
||||
val POTTED_WHITE_APRICORN_SAPLING = this.flowerPot("potted_white_apricorn_sapling", WHITE_APRICORN_SAPLING)
|
||||
@JvmField
|
||||
val POTTED_SACCHARINE_SAPLING = this.flowerPot("potted_saccharine_sapling", SACCHARINE_SAPLING)
|
||||
|
||||
init {
|
||||
/**
|
||||
@@ -1346,7 +1345,16 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
|
||||
fun typeGemClusters() = typeGemClusters.toMap()
|
||||
|
||||
private fun pottedPlant(name: String, flower: Block) = this.create(name, BlocksInvoker.createFlowerPotBlock(flower))
|
||||
private fun flowerPot(name: String, flower: Block) = this.create(
|
||||
name,
|
||||
FlowerPotBlock(
|
||||
flower,
|
||||
BlockBehaviour.Properties.of()
|
||||
.instabreak()
|
||||
.noOcclusion()
|
||||
.pushReaction(PushReaction.DESTROY)
|
||||
)
|
||||
)
|
||||
|
||||
private fun mintLitter(name: String, color: MapColor) = this.create(
|
||||
name,
|
||||
|
||||
@@ -425,7 +425,7 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(MovesRegistrySyncPacket.ID, MovesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(BerryRegistrySyncPacket.ID, BerryRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(SpeciesRegistrySyncPacket.ID, SpeciesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(SpeciesEvolutionSyncPacket.ID, SpeciesEvolutionSyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(DexEvolutionDisplaySyncPacket.ID, DexEvolutionDisplaySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(PropertiesCompletionRegistrySyncPacket.ID, PropertiesCompletionRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(StandardSpeciesFeatureSyncPacket.ID, StandardSpeciesFeatureSyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(GlobalSpeciesFeatureSyncPacket.ID, GlobalSpeciesFeatureSyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
|
||||
+31
-7
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
@@ -17,6 +18,7 @@ import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.mainThreadRuntime
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
@@ -34,6 +36,8 @@ import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
class HateEntityTaskConfig : SingleTaskConfig {
|
||||
val entityCondition: Expression = "true".asExpression()
|
||||
val range: ExpressionOrEntityVariable = Either.left("24".asExpression())
|
||||
val chance: Float = Cobblemon.config.predationChance
|
||||
private val coercedChance = chance.coerceIn(0f, 1f)
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
@@ -43,24 +47,44 @@ class HateEntityTaskConfig : SingleTaskConfig {
|
||||
val range = range.resolveFloat(behaviourConfigurationContext.runtime)
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
|
||||
MemoryModuleType.ANGRY_AT
|
||||
MemoryModuleType.ANGRY_AT,
|
||||
MemoryModuleType.ATTACK_TARGET
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
return BehaviorBuilder.create { instance ->
|
||||
instance.group(
|
||||
instance.present(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES),
|
||||
instance.registered(MemoryModuleType.ANGRY_AT)
|
||||
).apply(instance) { entities, angryAt ->
|
||||
instance.registered(MemoryModuleType.ANGRY_AT),
|
||||
instance.registered(MemoryModuleType.ATTACK_TARGET),
|
||||
).apply(instance) { entities, angryAt, attackTarget ->
|
||||
Trigger { world, entity, _ ->
|
||||
val target = instance.get(entities).findClosest {
|
||||
mainThreadRuntime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
// bail if gamerule is disabled
|
||||
if (!world.gameRules.getBoolean(CobblemonGameRules.DO_POKEMON_PREDATION)) return@Trigger false
|
||||
val target = instance.get(entities).findClosest { hated ->
|
||||
mainThreadRuntime.withQueryValue("entity", hated.asMostSpecificMoLangValue())
|
||||
return@findClosest mainThreadRuntime.resolveBoolean(entityCondition)
|
||||
}.orElse(null)
|
||||
|
||||
var shouldTrigger = false
|
||||
if (target != null && target.distanceTo(entity) <= range) {
|
||||
angryAt.set(target.uuid)
|
||||
shouldTrigger = when {
|
||||
// set always attacking if activity chance is equal to 1.0
|
||||
coercedChance == 1f -> {
|
||||
angryAt.set(target.uuid)
|
||||
attackTarget.set(target)
|
||||
true
|
||||
}
|
||||
// roll the dice in other way
|
||||
coercedChance != 1f && world.random.nextFloat() < coercedChance -> {
|
||||
angryAt.set(target.uuid)
|
||||
attackTarget.set(target)
|
||||
true
|
||||
}
|
||||
// fallback to peaceful behavior in unattended cases
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
return@Trigger true
|
||||
return@Trigger shouldTrigger
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-12
@@ -11,9 +11,6 @@ package com.cobblemon.mod.common.api.conditional
|
||||
import com.google.gson.JsonDeserializationContext
|
||||
import com.google.gson.JsonDeserializer
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonPrimitive
|
||||
import com.google.gson.JsonSerializationContext
|
||||
import com.google.gson.JsonSerializer
|
||||
import java.lang.reflect.Type
|
||||
|
||||
/**
|
||||
@@ -24,19 +21,11 @@ import java.lang.reflect.Type
|
||||
* @author Hiroku
|
||||
* @since July 17th, 2022
|
||||
*/
|
||||
interface RegistryLikeAdapter<B> : JsonDeserializer<RegistryLikeCondition<B>>, JsonSerializer<RegistryLikeCondition<B>> {
|
||||
interface RegistryLikeAdapter<B> : JsonDeserializer<RegistryLikeCondition<B>> {
|
||||
val registryLikeConditions: MutableList<(JsonElement) -> RegistryLikeCondition<B>?>
|
||||
|
||||
override fun deserialize(json: JsonElement, type: Type, ctx: JsonDeserializationContext): RegistryLikeCondition<B> {
|
||||
return registryLikeConditions.firstNotNullOfOrNull { it(json) }
|
||||
?: throw IllegalArgumentException("Unable to deserialize $json")
|
||||
}
|
||||
|
||||
override fun serialize(src: RegistryLikeCondition<B>, typeOfSrc: Type, ctx: JsonSerializationContext): JsonElement {
|
||||
return when (src) {
|
||||
is RegistryLikeTagCondition<B> -> JsonPrimitive(RegistryLikeTagCondition.PREFIX + src.tag.location())
|
||||
is RegistryLikeIdentifierCondition<B> -> JsonPrimitive(src.identifier.toString())
|
||||
else -> throw IllegalArgumentException("Unable to serialize $src")
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -98,14 +98,14 @@ object LivingEntityMoLangFunctions : AbstractMoLangFunctionHolder<LivingEntity>(
|
||||
val targetEntity = params.get<MoValue>(0)
|
||||
val maxDistance = params.getDoubleOrNull(1)?.toFloat() ?: 2.0F
|
||||
|
||||
val entity =
|
||||
val target =
|
||||
if (targetEntity is ObjectValue<*> && targetEntity.obj is Entity) {
|
||||
targetEntity.obj as Entity
|
||||
} else {
|
||||
return@isLookingAt DoubleValue.ZERO
|
||||
}
|
||||
|
||||
DoubleValue(entity.isLookingAt(entity, maxDistance))
|
||||
DoubleValue(entity.isLookingAt(target, maxDistance))
|
||||
}
|
||||
functions["is_living_entity"] = { DoubleValue.ONE }
|
||||
functions["is_flying"] = { DoubleValue(entity.isFallFlying) }
|
||||
|
||||
+1
-1
@@ -212,7 +212,7 @@ object PokemonMoLangFunctions : AbstractMoLangFunctionHolder<Pokemon>() {
|
||||
// Lol. Lmao, even.
|
||||
// TO-DO: Subscribe to [PokemonSpecies.observable].
|
||||
functions["pre_evolution"] = { pokemon.species.preEvolution ?: DoubleValue.ZERO }
|
||||
functions["nature"] = { StringValue(pokemon.nature.toString()) }
|
||||
functions["nature"] = { StringValue(pokemon.nature.name.toString()) }
|
||||
functions["is_wild"] = { DoubleValue(pokemon.entity?.let { it.ownerUUID == null } == true) }
|
||||
functions["is_shiny"] = { DoubleValue(pokemon.shiny) }
|
||||
functions["is_in_party"] = { DoubleValue(pokemon.storeCoordinates.get()?.store is PartyStore) }
|
||||
|
||||
@@ -10,9 +10,6 @@ package com.cobblemon.mod.common.api.pokedex
|
||||
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.pokedex.def.PokedexDef
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexForm
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.net.messages.client.data.PokedexDexSyncPacket
|
||||
import com.cobblemon.mod.common.util.adapters.CodecBackedAdapter
|
||||
@@ -64,38 +61,6 @@ object Dexes : JsonDataRegistry<PokedexDef> {
|
||||
PokedexDexSyncPacket(dexEntryMap.values).sendToPlayer(player)
|
||||
}
|
||||
|
||||
fun findDexEntryBySpeciesId(regionId: ResourceLocation, speciesId: ResourceLocation): PokedexEntry? {
|
||||
return dexEntryMap[regionId]?.getEntries()?.firstOrNull { it -> it.speciesId == speciesId }
|
||||
}
|
||||
|
||||
fun findDexEntryBySpeciesId(speciesId: ResourceLocation): PokedexEntry? {
|
||||
return findDexEntryBySpeciesId(cobblemonResource("national"), speciesId)
|
||||
}
|
||||
|
||||
fun findRootDexEntryBySpeciesId(speciesId: ResourceLocation, formName: String): Pair<PokedexEntry, PokedexForm> {
|
||||
var rootSpecies = PokemonSpecies.getByIdentifier(speciesId)!!
|
||||
val initialFormEquivalents = getFormEquivalents(formName)
|
||||
var rootForm = rootSpecies.forms.firstOrNull { initialFormEquivalents.contains(it.name.lowercase()) }
|
||||
?: rootSpecies.standardForm
|
||||
|
||||
var preEvolution = rootForm.preEvolution
|
||||
while (preEvolution != null) {
|
||||
rootSpecies = preEvolution.species
|
||||
rootForm = preEvolution.resolveForm(rootForm.aspects.toSet())
|
||||
preEvolution = rootForm.preEvolution
|
||||
}
|
||||
|
||||
val entry = findDexEntryBySpeciesId(rootSpecies.resourceIdentifier)
|
||||
?: throw RuntimeException("Root dex entry not found")
|
||||
|
||||
val formEquivalents = getFormEquivalents(rootForm.name)
|
||||
val form =
|
||||
entry.forms.firstOrNull { formEquivalents.contains(it.displayForm.lowercase()) } ?:
|
||||
entry.forms.first { it.displayForm.equals("Normal", ignoreCase = true) }
|
||||
|
||||
return entry to form
|
||||
}
|
||||
|
||||
fun getFormEquivalents(formName: String): List<String> {
|
||||
val key = equivalentFormsLookup[formName.lowercase()]
|
||||
return equivalentForms[key] ?: listOf(formName.lowercase())
|
||||
|
||||
@@ -8,13 +8,20 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.pokedex.entry
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.net.messages.client.data.DexEntrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.data.DexEvolutionDisplaySyncPacket
|
||||
import com.cobblemon.mod.common.pokemon.FormData
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
@@ -38,6 +45,8 @@ object DexEntries : JsonDataRegistry<PokedexEntry> {
|
||||
|
||||
val entries = mutableMapOf<ResourceLocation, PokedexEntry>()
|
||||
|
||||
val evolutionDisplays = mutableListOf<DexEvolutionDisplay>()
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, PokedexEntry>) {
|
||||
data.forEach { _, entry ->
|
||||
entries[entry.id] = entry
|
||||
@@ -50,6 +59,7 @@ object DexEntries : JsonDataRegistry<PokedexEntry> {
|
||||
}
|
||||
}
|
||||
}
|
||||
computeEvolutionDisplays()
|
||||
observable.emit(this)
|
||||
}
|
||||
|
||||
@@ -57,5 +67,58 @@ object DexEntries : JsonDataRegistry<PokedexEntry> {
|
||||
|
||||
override fun sync(player: ServerPlayer) {
|
||||
DexEntrySyncPacket(entries.values).sendToPlayer(player)
|
||||
DexEvolutionDisplaySyncPacket(evolutionDisplays).sendToPlayer(player)
|
||||
}
|
||||
}
|
||||
|
||||
fun computeEvolutionDisplays() {
|
||||
evolutionDisplays.clear()
|
||||
PokemonSpecies.species.forEach {
|
||||
try {
|
||||
evolutionDisplays.addAll(buildDisplays(it.standardForm) + it.forms.flatMap { form -> buildDisplays(form) })
|
||||
} catch (e: Exception) {
|
||||
Cobblemon.LOGGER.error("Failed to build dex evolution displays for ${it.resourceIdentifier}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun buildDisplays(form: FormData): List<DexEvolutionDisplay> {
|
||||
val result = mutableListOf<DexEvolutionDisplay>()
|
||||
(form.ownEvolutions ?: form.evolutions).forEach { evolution ->
|
||||
val requirements = mutableListOf<DexEvolutionRequirementDisplay>()
|
||||
getToolTipHeaderIcon(evolution)?.let { header ->
|
||||
requirements.add(header)
|
||||
}
|
||||
evolution.requirements.mapNotNull { resolveRequirementData(it) }.forEach { requirement ->
|
||||
requirements.add(requirement)
|
||||
}
|
||||
|
||||
listOfNotNull(evolution.result, evolution.shedder).forEach resultLoop@{ resultProperties ->
|
||||
val resultSpecies = resultProperties.species
|
||||
?.let { PokemonSpecies.getByIdentifier(it.asIdentifierDefaultingNamespace()) }
|
||||
?: return@resultLoop
|
||||
|
||||
// The result's own aspects win, otherwise carry the source form's aspects over
|
||||
// like a real evolution does (Alola-Bias Pichu -> Alola-Bias Pikachu)
|
||||
val resultForm = resultSpecies.getForm(resultProperties.aspects).takeIf { it != resultSpecies.standardForm }
|
||||
?: resultSpecies.getForm(form.aspects.toSet() + resultProperties.aspects)
|
||||
val toAspects = resultProperties.aspects + resultForm.aspects
|
||||
val resultRequirements = if (resultProperties === evolution.shedder) {
|
||||
requirements + CobblemonDexEvolutionRequirementDisplay(CobblemonItems.POKE_BALL, lang("ui.pokedex.evolution.shedder.tooltip"))
|
||||
} else {
|
||||
requirements
|
||||
}
|
||||
|
||||
result.add(DexEvolutionDisplay(
|
||||
fromSpecies = form.species.resourceIdentifier,
|
||||
fromForm = form.name,
|
||||
fromAspects = form.aspects.toSet(),
|
||||
toSpecies = resultSpecies.resourceIdentifier,
|
||||
toForm = resultForm.name,
|
||||
toAspects = toAspects,
|
||||
requirements = resultRequirements,
|
||||
))
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
+466
@@ -0,0 +1,466 @@
|
||||
/*
|
||||
* 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.pokedex.entry
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeIdentifierCondition
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeTagCondition
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.IntSpeciesFeatureProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.SpeciesFeatures
|
||||
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.text.add
|
||||
import com.cobblemon.mod.common.api.text.green
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.ItemInteractionEvolution
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.TradeEvolution
|
||||
import com.cobblemon.mod.common.pokemon.requirements.*
|
||||
import com.cobblemon.mod.common.util.adapters.RegistryAccessResolver
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.ExtraCodecs
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.level.biome.Biome
|
||||
import net.minecraft.world.level.levelgen.structure.Structure
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
|
||||
data class DexEvolutionDisplay(
|
||||
val fromSpecies: ResourceLocation,
|
||||
val fromForm: String,
|
||||
val fromAspects: Set<String>,
|
||||
val toSpecies: ResourceLocation,
|
||||
val toForm: String,
|
||||
val toAspects: Set<String>,
|
||||
val requirements: List<DexEvolutionRequirementDisplay>,
|
||||
)
|
||||
|
||||
interface DexEvolutionRequirementDisplay {
|
||||
val icon: Item
|
||||
val tooltip: MutableComponent
|
||||
}
|
||||
|
||||
data class CobblemonDexEvolutionRequirementDisplay(
|
||||
override val icon: Item,
|
||||
override val tooltip: MutableComponent,
|
||||
) : DexEvolutionRequirementDisplay
|
||||
|
||||
data class CobblemonBiomeDexEvolutionRequirementDisplay(
|
||||
override val icon: Item,
|
||||
override val tooltip: MutableComponent,
|
||||
val condition: ExtraCodecs.TagOrElementLocation? = null,
|
||||
val antiCondition: ExtraCodecs.TagOrElementLocation? = null,
|
||||
) : DexEvolutionRequirementDisplay
|
||||
|
||||
fun getToolTipHeaderIcon(evolution: Evolution): DexEvolutionRequirementDisplay? {
|
||||
when (evolution) {
|
||||
is ItemInteractionEvolution -> return getToolTipHeaderIcon(evolution)
|
||||
is TradeEvolution -> return getToolTipHeaderIcon(evolution)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
fun getToolTipHeaderIcon(itemInteractionEvolution: ItemInteractionEvolution): CobblemonDexEvolutionRequirementDisplay? {
|
||||
val item = itemInteractionEvolution.requiredContext.items.orElse(null)?.firstOrNull()?.value() ?: return null
|
||||
return CobblemonDexEvolutionRequirementDisplay(item, lang("ui.pokedex.evolution.item_interact.tooltip", item.description.plainCopy().green()))
|
||||
}
|
||||
|
||||
fun getToolTipHeaderIcon(tradeEvolution: TradeEvolution): CobblemonDexEvolutionRequirementDisplay {
|
||||
val species = tradeEvolution.requiredContext.species
|
||||
val tooltip = if (species == null) {
|
||||
lang("ui.pokedex.evolution.trade.tooltip.with_any_species")
|
||||
} else {
|
||||
PokemonSpecies.getByIdentifier(species.asIdentifierDefaultingNamespace())
|
||||
?.let { lang("ui.pokedex.evolution.trade.tooltip.with_species", it.translatedName.plainCopy().green()) }
|
||||
?: lang("ui.pokedex.evolution.trade.tooltip.with_any_species")
|
||||
}
|
||||
return CobblemonDexEvolutionRequirementDisplay(CobblemonItems.LINK_CABLE, tooltip)
|
||||
}
|
||||
|
||||
fun resolveRequirementData(requirement: Requirement): DexEvolutionRequirementDisplay? {
|
||||
val icon = requirement.pokedexIcon?.let {
|
||||
RegistryAccessResolver.getAccess().registryOrThrow(Registries.ITEM).get(it)
|
||||
}
|
||||
|
||||
val tooltip = requirement.pokedexTooltip?.let {
|
||||
Component.translatable(it)
|
||||
}
|
||||
|
||||
if (icon != null && tooltip != null) {
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
return buildRequirementData(requirement)
|
||||
}
|
||||
|
||||
fun buildRequirementData(requirement: Requirement): DexEvolutionRequirementDisplay? {
|
||||
when (requirement) {
|
||||
is AdvancementRequirement -> return buildAdvancementRequirement(requirement)
|
||||
is BattleCriticalHitsRequirement -> return buildBattleCriticalHitsRequirement(requirement)
|
||||
is BiomeRequirement -> return buildBiomeRequirement(requirement)
|
||||
is BlocksTraveledRequirement -> return buildBlocksTraveledRequirement(requirement)
|
||||
is DamageTakenRequirement -> return buildDamageTakenRequirement(requirement)
|
||||
is DefeatRequirement -> return buildDefeatRequirement(requirement)
|
||||
is FriendshipRequirement -> return buildFriendshipRequirement(requirement)
|
||||
is HeldItemRequirement -> return buildHeldItemRequirement(requirement)
|
||||
is LevelRequirement -> return buildLevelRequirement(requirement)
|
||||
is MoonPhaseRequirement -> return buildMoonPhaseRequirement(requirement)
|
||||
is MoveSetRequirement -> return buildMoveSetRequirement(requirement)
|
||||
is MoveTypeRequirement -> return buildMoveTypeRequirement(requirement)
|
||||
is NegateRequirement -> return buildNegateRequirement(requirement)
|
||||
is OwnerHoldsItemRequirement -> return buildOwnerHoldsItemRequirement(requirement)
|
||||
is PartyMemberRequirement -> return buildPartyMemberRequirement(requirement)
|
||||
is PokemonPropertiesRequirement -> return buildPokemonPropertiesRequirement(requirement)
|
||||
is PropertyRangeRequirement -> return buildPropertyRangeRequirement(requirement)
|
||||
is RecoilRequirement -> return buildRecoilRequirement(requirement)
|
||||
is StatCompareRequirement -> return buildStatCompareRequirement(requirement)
|
||||
is StatEqualRequirement -> return buildStatEqualRequirement(requirement)
|
||||
is StructureRequirement -> return buildStructureRequirement(requirement)
|
||||
is TimeRangeRequirement -> return buildTimeRangeRequirement(requirement)
|
||||
is UseMoveRequirement -> return buildUseMoveRequirement(requirement)
|
||||
is WeatherRequirement -> return buildWeatherRequirement(requirement)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun buildAdvancementRequirement(advancementRequirement: AdvancementRequirement): DexEvolutionRequirementDisplay {
|
||||
val icon = Items.BOOK
|
||||
val identifier = advancementRequirement.requiredAdvancement
|
||||
val advancementLanguageKey = "${identifier.namespace}.${identifier.path.substringAfterLast('/')}"
|
||||
val advancementComponent = Component.translatable("advancements.$advancementLanguageKey").green()
|
||||
val tooltip = lang("ui.pokedex.requirement.advancement.tooltip", advancementComponent)
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
fun buildBattleCriticalHitsRequirement(battleCriticalHitsRequirement: BattleCriticalHitsRequirement): DexEvolutionRequirementDisplay {
|
||||
val icon = CobblemonItems.MEDICINAL_LEEK
|
||||
val criticalsComponent = Component.literal(battleCriticalHitsRequirement.amount.toString()).green()
|
||||
val tooltip = lang("ui.pokedex.requirement.battle_critical_hits.tooltip", criticalsComponent)
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
private fun tagDisplayName(registry: String, id: ResourceLocation): MutableComponent {
|
||||
return Component.translatableWithFallback("tag.$registry.${id.namespace}.${id.path.replace('/', '.')}", prettifyPath(id.path))
|
||||
}
|
||||
|
||||
private fun prettifyPath(path: String): String {
|
||||
return path.substringAfterLast('/').removePrefix("is_").split('_').joinToString(" ") { part -> part.replaceFirstChar(Char::titlecase) }
|
||||
}
|
||||
|
||||
fun buildNegateRequirement(negateRequirement: NegateRequirement): DexEvolutionRequirementDisplay? {
|
||||
val inner = negateRequirement.inner
|
||||
when (inner) {
|
||||
is BiomeRequirement -> buildBiomeRequirement(inner, negated = true)?.let { return it }
|
||||
is StructureRequirement -> buildStructureRequirement(inner, negated = true)?.let { return it }
|
||||
}
|
||||
val innerDisplay = resolveRequirementData(inner) ?: return null
|
||||
return CobblemonDexEvolutionRequirementDisplay(innerDisplay.icon, lang("ui.pokedex.requirement.negate.tooltip", innerDisplay.tooltip))
|
||||
}
|
||||
|
||||
fun buildBiomeRequirement(biomeRequirement: BiomeRequirement, negated: Boolean = false): DexEvolutionRequirementDisplay? {
|
||||
// Negating "in X" is "not in X"; negating both a condition and an anticondition isn't expressible as one line
|
||||
if (negated && biomeRequirement.biomeCondition != null && biomeRequirement.biomeAnticondition != null) return null
|
||||
val condition = if (negated) biomeRequirement.biomeAnticondition else biomeRequirement.biomeCondition
|
||||
val antiCondition = if (negated) biomeRequirement.biomeCondition else biomeRequirement.biomeAnticondition
|
||||
if (condition == null && antiCondition == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
val icon = Items.COMPASS
|
||||
val displayName: (RegistryLikeCondition<Biome>) -> MutableComponent = {
|
||||
when (it) {
|
||||
is RegistryLikeTagCondition -> tagDisplayName("worldgen.biome", it.tag.location())
|
||||
is RegistryLikeIdentifierCondition -> Component.translatable("biome.${it.identifier.namespace}.${it.identifier.path}")
|
||||
else -> Component.literal(it.toString())
|
||||
}
|
||||
}
|
||||
|
||||
val tooltip = if (condition != null && antiCondition != null) {
|
||||
lang("ui.pokedex.requirement.biome.both.tooltip", displayName(condition).green(), displayName(antiCondition).green())
|
||||
} else if (condition != null) {
|
||||
lang("ui.pokedex.requirement.biome.tooltip", displayName(condition).green())
|
||||
} else {
|
||||
lang("ui.pokedex.requirement.biome.anticondition.tooltip", displayName(antiCondition!!).green())
|
||||
}
|
||||
|
||||
var conditionConverted: ExtraCodecs.TagOrElementLocation? = null
|
||||
if (condition != null) {
|
||||
val conditionIdentifier = if (condition is RegistryLikeIdentifierCondition) condition.identifier else (condition as RegistryLikeTagCondition).tag.location
|
||||
conditionConverted = ExtraCodecs.TagOrElementLocation(conditionIdentifier, condition is RegistryLikeTagCondition)
|
||||
}
|
||||
|
||||
var antiConditionConverted: ExtraCodecs.TagOrElementLocation? = null
|
||||
if (antiCondition != null) {
|
||||
val conditionIdentifier = if (antiCondition is RegistryLikeIdentifierCondition) antiCondition.identifier else (antiCondition as RegistryLikeTagCondition).tag.location
|
||||
antiConditionConverted = ExtraCodecs.TagOrElementLocation(conditionIdentifier, antiCondition is RegistryLikeTagCondition)
|
||||
}
|
||||
|
||||
return CobblemonBiomeDexEvolutionRequirementDisplay(icon, tooltip, conditionConverted, antiConditionConverted)
|
||||
}
|
||||
|
||||
fun buildBlocksTraveledRequirement(blocksTraveledRequirement: BlocksTraveledRequirement): DexEvolutionRequirementDisplay {
|
||||
val icon = Items.LEATHER_BOOTS
|
||||
val blocksComponent = Component.literal(blocksTraveledRequirement.amount.toString()).green()
|
||||
val tooltip = lang("ui.pokedex.requirement.blocks_traveled.tooltip", blocksComponent)
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
fun buildDamageTakenRequirement(damageTakenRequirement: DamageTakenRequirement): DexEvolutionRequirementDisplay {
|
||||
val icon = CobblemonItems.PUNCHING_GLOVE
|
||||
val blocksComponent = Component.literal(damageTakenRequirement.amount.toString()).green()
|
||||
val tooltip = lang("ui.pokedex.requirement.damage_taken.tooltip", blocksComponent)
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
fun buildDefeatRequirement(defeatRequirement: DefeatRequirement): DexEvolutionRequirementDisplay? {
|
||||
val description = describePokemonProperties(defeatRequirement.target) ?: return null
|
||||
val icon = CobblemonItems.PUNCHING_GLOVE
|
||||
val defeatedAmount = defeatRequirement.amount
|
||||
|
||||
val descriptionComponent = Component.literal(defeatedAmount.toString()).green().add(" ").add(description)
|
||||
val tooltip = lang("ui.pokedex.requirement.defeat.tooltip", descriptionComponent)
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
fun buildFriendshipRequirement(friendshipRequirement: FriendshipRequirement): DexEvolutionRequirementDisplay {
|
||||
val icon = CobblemonItems.SOOTHE_BELL
|
||||
val friendshipAmountComponent = Component.literal(friendshipRequirement.amount.toString()).green()
|
||||
val tooltip = lang("ui.pokedex.requirement.friendship.tooltip", friendshipAmountComponent)
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
fun buildHeldItemRequirement(heldItemRequirement: HeldItemRequirement): DexEvolutionRequirementDisplay? {
|
||||
val items = heldItemRequirement.itemCondition.items.getOrNull() ?: return null
|
||||
val item = items.firstOrNull()?.value() ?: return null
|
||||
val itemComponent = items.unwrapKey().map { tag ->
|
||||
val id = tag.location()
|
||||
val fallback = id.path.substringAfterLast('/').split('_').joinToString(" ") { part -> part.replaceFirstChar(Char::titlecase) }
|
||||
Component.translatableWithFallback("tag.item.${id.namespace}.${id.path.replace('/', '.')}", fallback)
|
||||
}.orElseGet { item.description.plainCopy() }
|
||||
val tooltip = lang("ui.pokedex.requirement.held_item.tooltip", itemComponent.green())
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(item, tooltip)
|
||||
}
|
||||
|
||||
fun buildLevelRequirement(levelRequirement: LevelRequirement): DexEvolutionRequirementDisplay {
|
||||
val minLevel = levelRequirement.minLevel
|
||||
val maxLevel = levelRequirement.maxLevel
|
||||
|
||||
val icon = CobblemonItems.RARE_CANDY
|
||||
val tooltip =
|
||||
if (minLevel == maxLevel || maxLevel == Int.MAX_VALUE)
|
||||
lang("ui.pokedex.requirement.level.tooltip.min", Component.literal(minLevel.toString()).green())
|
||||
else
|
||||
lang("ui.pokedex.requirement.level.tooltip.between", Component.literal(minLevel.toString()).green(), Component.literal(maxLevel.toString()).green())
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
fun buildMoonPhaseRequirement(moonPhaseRequirement: MoonPhaseRequirement): DexEvolutionRequirementDisplay {
|
||||
val icon = Items.CLOCK
|
||||
val moonPhaseComponent = moonPhaseRequirement.moonPhase.displayName().plainCopy().green()
|
||||
val tooltip = lang("ui.pokedex.requirement.moon_phase.tooltip", moonPhaseComponent)
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
fun buildMoveSetRequirement(moveSetRequirement: MoveSetRequirement): DexEvolutionRequirementDisplay {
|
||||
val icon = CobblemonItems.TECHNICAL_MACHINE
|
||||
val tooltip = lang("ui.pokedex.requirement.has_move.tooltip", moveSetRequirement.move.displayName.plainCopy().green())
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
fun buildMoveTypeRequirement(moveTypeRequirement: MoveTypeRequirement): DexEvolutionRequirementDisplay {
|
||||
val type = ElementalTypes.get(moveTypeRequirement.type.name)
|
||||
val icon = when (type) {
|
||||
ElementalTypes.NORMAL -> CobblemonItems.NORMAL_GEM
|
||||
ElementalTypes.FIRE -> CobblemonItems.FIRE_GEM
|
||||
ElementalTypes.WATER -> CobblemonItems.WATER_GEM
|
||||
ElementalTypes.GRASS -> CobblemonItems.GRASS_GEM
|
||||
ElementalTypes.ELECTRIC -> CobblemonItems.ELECTRIC_GEM
|
||||
ElementalTypes.ICE -> CobblemonItems.ICE_GEM
|
||||
ElementalTypes.FIGHTING -> CobblemonItems.FIGHTING_GEM
|
||||
ElementalTypes.POISON -> CobblemonItems.POISON_GEM
|
||||
ElementalTypes.GROUND -> CobblemonItems.GROUND_GEM
|
||||
ElementalTypes.FLYING -> CobblemonItems.FLYING_GEM
|
||||
ElementalTypes.PSYCHIC -> CobblemonItems.PSYCHIC_GEM
|
||||
ElementalTypes.BUG -> CobblemonItems.BUG_GEM
|
||||
ElementalTypes.ROCK -> CobblemonItems.ROCK_GEM
|
||||
ElementalTypes.GHOST -> CobblemonItems.GHOST_GEM
|
||||
ElementalTypes.DRAGON -> CobblemonItems.DRAGON_GEM
|
||||
ElementalTypes.DARK -> CobblemonItems.DARK_GEM
|
||||
ElementalTypes.STEEL -> CobblemonItems.STEEL_GEM
|
||||
ElementalTypes.FAIRY -> CobblemonItems.FAIRY_GEM
|
||||
else -> CobblemonItems.NORMAL_GEM
|
||||
}
|
||||
|
||||
val tooltip = lang("ui.pokedex.requirement.has_move_type.tooltip", moveTypeRequirement.type.displayName.plainCopy().green())
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
fun buildOwnerHoldsItemRequirement(ownerHoldsItemRequirement: OwnerHoldsItemRequirement): DexEvolutionRequirementDisplay? {
|
||||
val item = ownerHoldsItemRequirement.itemCondition.items.orElse(null)?.firstOrNull()?.value() ?: return null
|
||||
val tooltip = lang("ui.pokedex.requirement.owner_held_item.tooltip", item.description.plainCopy().green())
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(item, tooltip)
|
||||
}
|
||||
|
||||
fun buildPartyMemberRequirement(partyMemberRequirement: PartyMemberRequirement): DexEvolutionRequirementDisplay? {
|
||||
val description = describePokemonProperties(partyMemberRequirement.target) ?: return null
|
||||
val icon = CobblemonItems.POKE_BALL
|
||||
val tooltip = if (partyMemberRequirement.contains) {
|
||||
lang("ui.pokedex.requirement.party_member.tooltip", description)
|
||||
} else {
|
||||
lang("ui.pokedex.requirement.party_member.anticondition.tooltip", description)
|
||||
}
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
fun buildPokemonPropertiesRequirement(pokemonPropertiesRequirement: PokemonPropertiesRequirement): DexEvolutionRequirementDisplay? {
|
||||
val description = describePokemonProperties(pokemonPropertiesRequirement.target) ?: return null
|
||||
val icon = Items.NAME_TAG
|
||||
val tooltip = lang("ui.pokedex.requirement.pokemon_properties.tooltip", description)
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
fun buildPropertyRangeRequirement(propertyRangeRequirement: PropertyRangeRequirement): DexEvolutionRequirementDisplay? {
|
||||
val provider = SpeciesFeatures.getFeature(propertyRangeRequirement.feature) as? IntSpeciesFeatureProvider ?: return null
|
||||
val displayName = provider.display?.name?.takeIf { it.isNotBlank() }?.asTranslated()?.green() ?: return null
|
||||
val icon = provider.itemPoints.keys.firstOrNull()?.let { BuiltInRegistries.ITEM.get(it) } ?: Items.NAME_TAG
|
||||
|
||||
val range = propertyRangeRequirement.range
|
||||
val tooltip = lang(
|
||||
"ui.pokedex.requirement.property_range.tooltip",
|
||||
displayName,
|
||||
Component.literal(range.first.toString()).green(),
|
||||
Component.literal(range.last.toString()).green()
|
||||
)
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
fun buildRecoilRequirement(recoilRequirement: RecoilRequirement): DexEvolutionRequirementDisplay {
|
||||
val icon = CobblemonItems.LIFE_ORB
|
||||
val recoilComponent = Component.literal(recoilRequirement.amount.toString()).green()
|
||||
val tooltip = lang("ui.pokedex.requirement.recoil.tooltip", recoilComponent)
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
fun buildStatCompareRequirement(statCompareRequirement: StatCompareRequirement): DexEvolutionRequirementDisplay {
|
||||
val highStat = Stats.getStat(statCompareRequirement.highStat)
|
||||
val lowStat = Stats.getStat(statCompareRequirement.lowStat)
|
||||
|
||||
val icon = when (highStat) {
|
||||
Stats.HP, Stats.EVASION, Stats.ACCURACY -> CobblemonItems.HEALTH_MOCHI
|
||||
Stats.ATTACK -> CobblemonItems.MUSCLE_MOCHI
|
||||
Stats.DEFENCE -> CobblemonItems.RESIST_MOCHI
|
||||
Stats.SPECIAL_ATTACK -> CobblemonItems.GENIUS_MOCHI
|
||||
Stats.SPECIAL_DEFENCE -> CobblemonItems.CLEVER_MOCHI
|
||||
Stats.SPEED -> CobblemonItems.SWIFT_MOCHI
|
||||
}
|
||||
|
||||
val highStatComponent = highStat.displayName.plainCopy().green()
|
||||
val lowStatComponent = lowStat.displayName.plainCopy().green()
|
||||
val tooltip = lang("ui.pokedex.requirement.stat_compare.tooltip", highStatComponent, lowStatComponent)
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
fun buildStatEqualRequirement(statEqualRequirement: StatEqualRequirement): DexEvolutionRequirementDisplay {
|
||||
val statOne = Stats.getStat(statEqualRequirement.statOne)
|
||||
val statTwo = Stats.getStat(statEqualRequirement.statTwo)
|
||||
|
||||
val statOneComponent = statOne.displayName.plainCopy().green()
|
||||
val statTwoComponent = statTwo.displayName.plainCopy().green()
|
||||
|
||||
val icon = CobblemonItems.FRESH_START_MOCHI
|
||||
val tooltip = lang("ui.pokedex.requirement.stat_equal.tooltip", statOneComponent, statTwoComponent)
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
fun buildStructureRequirement(structureRequirement: StructureRequirement, negated: Boolean = false): DexEvolutionRequirementDisplay? {
|
||||
if (negated && structureRequirement.structureCondition != null && structureRequirement.structureAnticondition != null) return null
|
||||
val condition = if (negated) structureRequirement.structureAnticondition else structureRequirement.structureCondition
|
||||
val anticondition = if (negated) structureRequirement.structureCondition else structureRequirement.structureAnticondition
|
||||
if (condition == null && anticondition == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
val icon = Items.FILLED_MAP
|
||||
val displayName: (RegistryLikeCondition<Structure>) -> MutableComponent = {
|
||||
when (it) {
|
||||
is RegistryLikeTagCondition -> tagDisplayName("worldgen.structure", it.tag.location())
|
||||
is RegistryLikeIdentifierCondition -> Component.literal(prettifyPath(it.identifier.path))
|
||||
else -> Component.literal(it.toString())
|
||||
}
|
||||
}
|
||||
val tooltip = if (condition != null && anticondition != null) {
|
||||
lang("ui.pokedex.requirement.structure.both.tooltip", displayName(condition).green(), displayName(anticondition).green())
|
||||
} else if (condition != null) {
|
||||
lang("ui.pokedex.requirement.structure.tooltip", displayName(condition).green())
|
||||
} else {
|
||||
lang("ui.pokedex.requirement.structure.anticondition.tooltip", displayName(anticondition!!).green())
|
||||
}
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
fun buildTimeRangeRequirement(timeRangeRequirement: TimeRangeRequirement): DexEvolutionRequirementDisplay? {
|
||||
val icon = Items.CLOCK
|
||||
val timeRangeComponent = timeRangeRequirement.range.displayName()?.plainCopy() ?: return null
|
||||
val tooltip = lang("ui.pokedex.requirement.time_range.tooltip", timeRangeComponent.green())
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
fun buildUseMoveRequirement(useMoveRequirement: UseMoveRequirement): DexEvolutionRequirementDisplay {
|
||||
val icon = CobblemonItems.CHOICE_BAND
|
||||
val tooltip = lang("ui.pokedex.requirement.use_move.tooltip", useMoveRequirement.move.displayName.plainCopy().green())
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
fun buildWeatherRequirement(weatherRequirement: WeatherRequirement): DexEvolutionRequirementDisplay {
|
||||
val icon: Item
|
||||
val tooltip: MutableComponent
|
||||
|
||||
if (weatherRequirement.isThundering == true) {
|
||||
icon = Items.LIGHTNING_ROD
|
||||
tooltip = lang("ui.pokedex.requirement.weather.tooltip.thundering")
|
||||
} else {
|
||||
icon = Items.WATER_BUCKET
|
||||
tooltip = lang("ui.pokedex.requirement.weather.tooltip.raining")
|
||||
}
|
||||
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
+2
-2
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.pokedex.widgets.evolutiontree
|
||||
package com.cobblemon.mod.common.api.pokedex.entry
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.Natures
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
@@ -28,7 +28,7 @@ import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.world.item.Items
|
||||
|
||||
internal fun describePokemonProperties(properties: PokemonProperties): MutableComponent? {
|
||||
fun describePokemonProperties(properties: PokemonProperties): MutableComponent? {
|
||||
if (hasUndescribedProperty(properties)) {
|
||||
return null
|
||||
}
|
||||
@@ -26,7 +26,6 @@ import com.cobblemon.mod.common.api.moves.MoveTemplate
|
||||
import com.cobblemon.mod.common.api.moves.MovesetBuilder
|
||||
import com.cobblemon.mod.common.api.moves.adapters.MoveTemplateAdapter
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies.getByIdentifier
|
||||
import com.cobblemon.mod.common.api.pokemon.effect.ShoulderEffect
|
||||
import com.cobblemon.mod.common.api.pokemon.effect.adapter.ShoulderEffectAdapter
|
||||
import com.cobblemon.mod.common.api.pokemon.egg.EggGroup
|
||||
@@ -44,9 +43,6 @@ import com.cobblemon.mod.common.api.riding.sound.RideSoundSettingsList
|
||||
import com.cobblemon.mod.common.api.spawning.TimeRange
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.api.types.adapters.ElementalTypeAdapter
|
||||
import com.cobblemon.mod.common.net.messages.client.data.FormEvolutionOverride
|
||||
import com.cobblemon.mod.common.net.messages.client.data.SpeciesEvolutionEntry
|
||||
import com.cobblemon.mod.common.net.messages.client.data.SpeciesEvolutionSyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.data.SpeciesRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.pokemon.FormData
|
||||
import com.cobblemon.mod.common.pokemon.Species
|
||||
@@ -246,18 +242,6 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
|
||||
override fun sync(player: ServerPlayer) {
|
||||
SpeciesRegistrySyncPacket(species.toList()).sendToPlayer(player)
|
||||
// Sent after the species themselves so every species is already registered by the time this is decoded.
|
||||
val evolutionEntries = species.map { singleSpecies ->
|
||||
val formOverrides = singleSpecies.forms.mapNotNull { form ->
|
||||
if (form.ownEvolutions == null && form.ownPreEvolution == null) {
|
||||
null
|
||||
} else {
|
||||
FormEvolutionOverride(form.name, form.ownEvolutions, form.ownPreEvolution)
|
||||
}
|
||||
}
|
||||
SpeciesEvolutionEntry(singleSpecies.resourceIdentifier, singleSpecies.evolutions, singleSpecies.preEvolution, formOverrides)
|
||||
}
|
||||
SpeciesEvolutionSyncPacket(evolutionEntries).sendToPlayer(player)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,8 +25,6 @@ interface PreEvolution {
|
||||
|
||||
val form: FormData
|
||||
|
||||
fun resolveForm(extraAspects: Set<String> = emptySet()): FormData = form
|
||||
|
||||
companion object {
|
||||
|
||||
fun of(species: Species, form: FormData = species.standardForm): PreEvolution = StandardPreEvolution(species, form)
|
||||
|
||||
+2
-2
@@ -42,8 +42,8 @@ abstract class AreaTypeSpawningCondition<T : AreaSpawnablePosition> : SpawningCo
|
||||
override fun copyFrom(other: SpawningCondition<*>, merger: Merger) {
|
||||
super.copyFrom(other, merger)
|
||||
if (other is AreaTypeSpawningCondition) {
|
||||
merger.mergeSingle(minHeight, other.minHeight)
|
||||
merger.mergeSingle(maxHeight, other.maxHeight)
|
||||
minHeight = merger.mergeSingle(minHeight, other.minHeight)
|
||||
maxHeight = merger.mergeSingle(maxHeight, other.maxHeight)
|
||||
neededNearbyBlocks = merger.merge(neededNearbyBlocks, other.neededNearbyBlocks)?.toMutableList()
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ abstract class SubmergedTypeSpawningCondition<T : SubmergedSpawnablePosition> :
|
||||
super.copyFrom(other, merger)
|
||||
if (other is SubmergedTypeSpawningCondition) {
|
||||
minDepth = merger.mergeSingle(minDepth, other.minDepth)
|
||||
maxDepth = merger.mergeSingle(minDepth, other.minDepth)
|
||||
maxDepth = merger.mergeSingle(maxDepth, other.maxDepth)
|
||||
fluidIsSource = merger.mergeSingle(fluidIsSource, other.fluidIsSource)
|
||||
fluid = merger.mergeSingle(fluid, other.fluid)
|
||||
}
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ abstract class SurfaceTypeSpawningCondition<T : SurfaceSpawnablePosition> : Area
|
||||
super.copyFrom(other, merger)
|
||||
if (other is SurfaceTypeSpawningCondition) {
|
||||
minDepth = merger.mergeSingle(minDepth, other.minDepth)
|
||||
maxDepth = merger.mergeSingle(minDepth, other.minDepth)
|
||||
maxDepth = merger.mergeSingle(maxDepth, other.maxDepth)
|
||||
fluid = merger.mergeSingle(fluid, other.fluid)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ object CobblemonItemTags {
|
||||
@JvmField val DESTINY_KNOT = create("held/destiny_knot")
|
||||
@JvmField val EVERSTONE = create("held/everstone")
|
||||
@JvmField val EXPERIENCE_SHARE = create("held/experience_share")
|
||||
@JvmField val IS_FRIENDSHIP_BOOSTER = create("is_friendship_booster")
|
||||
@JvmField val IS_FRIENDSHIP_BOOSTER = create("held/is_friendship_booster")
|
||||
@JvmField val ANY_HELD_ITEM = create("held/is_held_item")
|
||||
@JvmField val BLACKLISTED_ITEMS_TO_HOLD = create("held/blacklisted_items_to_hold")
|
||||
@JvmField val WHITELISTED_ITEMS_TO_HOLD = create("held/whitelisted_items_to_hold")
|
||||
|
||||
@@ -85,6 +85,7 @@ class PartyOverlay : Gui(Minecraft.getInstance()) {
|
||||
if (HidePartyBinding.shouldHide) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -558,4 +559,4 @@ class PartyOverlay : Gui(Minecraft.getInstance()) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,8 @@ class PCGUI(
|
||||
val party: ClientParty,
|
||||
val configuration: PCGUIConfiguration,
|
||||
val openOnBox: Int = CobblemonClient.lastPcBoxViewed,
|
||||
val unseenWallpapers: MutableSet<ResourceLocation> = mutableSetOf()
|
||||
val unseenWallpapers: MutableSet<ResourceLocation> = mutableSetOf(),
|
||||
val silent: Boolean = false
|
||||
) : Screen(Component.translatable("cobblemon.ui.pc.title")), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
@@ -703,7 +704,7 @@ class PCGUI(
|
||||
}
|
||||
|
||||
fun closeNormally(unlink: Boolean = true) {
|
||||
playSound(CobblemonSounds.PC_OFF)
|
||||
if (!silent) playSound(CobblemonSounds.PC_OFF)
|
||||
Minecraft.getInstance().setScreen(null)
|
||||
if (unlink) {
|
||||
UnlinkPlayerFromPCPacket().sendToServer()
|
||||
@@ -748,7 +749,7 @@ class PCGUI(
|
||||
|
||||
if (isInventoryKeyPressed(minecraft, keyCode, scanCode) && !boxNameFocused && !filterFocused) {
|
||||
saveMarkings(isPreviewInParty ?: false)
|
||||
playSound(CobblemonSounds.PC_OFF)
|
||||
if (!silent) playSound(CobblemonSounds.PC_OFF)
|
||||
UnlinkPlayerFromPCPacket().sendToServer()
|
||||
Minecraft.getInstance().setScreen(null)
|
||||
return true
|
||||
@@ -759,7 +760,7 @@ class PCGUI(
|
||||
if (!filterFocused && !boxNameFocused) {
|
||||
when (keyCode) {
|
||||
InputConstants.KEY_ESCAPE -> {
|
||||
playSound(CobblemonSounds.PC_OFF)
|
||||
if (!silent) playSound(CobblemonSounds.PC_OFF)
|
||||
UnlinkPlayerFromPCPacket().sendToServer()
|
||||
onClose()
|
||||
return true
|
||||
@@ -831,4 +832,4 @@ class PCGUI(
|
||||
markingsWidget.setActivePokemon(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.BASE_HEIG
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.BASE_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HEADER_BAR_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.ICONS_ARROW_PADDING_AROUND
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.ICONS_PADDING_AROUND
|
||||
@@ -52,8 +51,7 @@ import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.TAB_MOVES
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.TAB_SIZE
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.TAB_STATS
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.*
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.evolutiontree.EvolutionTreeWidget
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.evolutiontree.debugEvolutionRequirementRendering
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.EvolutionTreeWidget
|
||||
import com.cobblemon.mod.common.client.pokedex.PokedexType
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.net.messages.server.block.AdjustBlockEntityViewerCountPacket
|
||||
@@ -194,6 +192,7 @@ class PokedexGUI private constructor(
|
||||
public override fun init() {
|
||||
super.init()
|
||||
clearWidgets()
|
||||
evolutionTreeExpanded = false
|
||||
|
||||
availableRegions = Dexes.dexEntryMap.keys.toList()
|
||||
selectedRegionIndex = 0
|
||||
@@ -828,10 +827,6 @@ class PokedexGUI private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
if (tabInfoIndex == TAB_EVOLUTION_TREE && keyCode == InputConstants.KEY_SEMICOLON) {
|
||||
debugEvolutionRequirementRendering()
|
||||
}
|
||||
|
||||
return super.keyPressed(keyCode, scanCode, modifiers)
|
||||
}
|
||||
|
||||
|
||||
+23
-2
@@ -16,13 +16,17 @@ import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.network.chat.Style
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import java.util.Optional
|
||||
|
||||
private val tooltipEdge = cobblemonResource("textures/gui/pokedex/tooltip_edge.png")
|
||||
private val tooltipBackground = cobblemonResource("textures/gui/pokedex/tooltip_background.png")
|
||||
|
||||
private const val TOOLTIP_SLICE_SIZE = 11
|
||||
private const val TOOLTIP_MAX_TEXT_WIDTH = 160
|
||||
|
||||
fun renderTooltip(
|
||||
context: GuiGraphics,
|
||||
@@ -49,7 +53,12 @@ fun renderTooltip(
|
||||
posY: Int,
|
||||
delta: Float,
|
||||
offsetY: Int = 0,
|
||||
maxTextWidth: Int = TOOLTIP_MAX_TEXT_WIDTH,
|
||||
) {
|
||||
val text = text.flatMap { wrapTooltipLine(it, maxTextWidth) }
|
||||
// Only a tooltip that fits on a single line is centered; wrapped text is left-aligned
|
||||
val centered = text.size == 1
|
||||
|
||||
val poseStack = context.pose()
|
||||
val textWidth = text.maxOf { Minecraft.getInstance().font.width(it.font(CobblemonResources.DEFAULT_LARGE)) }
|
||||
val tooltipPadding = 6
|
||||
@@ -78,8 +87,6 @@ fun renderTooltip(
|
||||
blitSlicedVertical(poseStack, tooltipBackground, posX - (tooltipWidth / 2), tooltipTop, tooltipWidth, totalHeight)
|
||||
blitSlicedVertical(poseStack, tooltipEdge, posX + (tooltipWidth / 2), tooltipTop, 1, totalHeight)
|
||||
|
||||
val centered = text.size == 1
|
||||
|
||||
text.forEachIndexed { index, it ->
|
||||
drawScaledText(
|
||||
context = context,
|
||||
@@ -95,6 +102,20 @@ fun renderTooltip(
|
||||
poseStack.popPose()
|
||||
}
|
||||
|
||||
private fun wrapTooltipLine(line: MutableComponent, maxWidth: Int): List<MutableComponent> {
|
||||
val styled = line.copy().font(CobblemonResources.DEFAULT_LARGE)
|
||||
if (Minecraft.getInstance().font.width(styled) <= maxWidth) return listOf(line)
|
||||
|
||||
return Minecraft.getInstance().font.splitter.splitLines(styled, maxWidth, Style.EMPTY).map { wrapped ->
|
||||
val component = Component.empty()
|
||||
wrapped.visit({ style, string ->
|
||||
component.append(Component.literal(string).withStyle(style))
|
||||
Optional.empty<Unit>()
|
||||
}, Style.EMPTY)
|
||||
component
|
||||
}
|
||||
}
|
||||
|
||||
// Stretching the whole 11px image over an arbitrary height thickens the caps as more lines are added, so
|
||||
// instead the caps are drawn 1:1 and only the flat fill row is stretched to cover the remaining height
|
||||
private fun blitSlicedVertical(
|
||||
|
||||
+178
-81
@@ -6,20 +6,18 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.pokedex.widgets.evolutiontree
|
||||
package com.cobblemon.mod.common.client.gui.pokedex.widgets
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.gui.*
|
||||
import com.cobblemon.mod.common.api.pokedex.Dexes
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexForm
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.*
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
|
||||
import com.cobblemon.mod.common.api.text.add
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.green
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUI
|
||||
@@ -29,18 +27,22 @@ import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.POKEMON_D
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.SCROLL_SLOT_SIZE
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.ScaledButton
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.renderTooltip
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.PokemonSlotWidget
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.SoundlessWidget
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.renderScaledGuiItemIcon
|
||||
import com.cobblemon.mod.common.pokemon.FormData
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.pokemon.RenderablePokemon
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.locale.Language
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.tags.TagKey
|
||||
|
||||
class EvolutionTreeWidget(
|
||||
val parent: PokedexGUI,
|
||||
@@ -92,6 +94,8 @@ class EvolutionTreeWidget(
|
||||
|
||||
private var hoveredTooltips: List<MutableComponent>? = null
|
||||
|
||||
private var viewedForm: FormData? = null
|
||||
|
||||
private val expandButton: ScaledButton = ScaledButton(
|
||||
0f,
|
||||
0f,
|
||||
@@ -100,11 +104,14 @@ class EvolutionTreeWidget(
|
||||
resource = expandResource,
|
||||
clickAction = {
|
||||
parent.evolutionTreeExpanded = !parent.evolutionTreeExpanded
|
||||
expandButton.resource = if (parent.evolutionTreeExpanded) minimizeResource else expandResource
|
||||
updatePositioning()
|
||||
}
|
||||
).apply { addWidget(this) }
|
||||
|
||||
init {
|
||||
updatePositioning()
|
||||
}
|
||||
|
||||
override fun renderWidget(
|
||||
guiGraphics: GuiGraphics,
|
||||
mouseX: Int,
|
||||
@@ -146,9 +153,31 @@ class EvolutionTreeWidget(
|
||||
if (pokedexEntry == null || pokedexForm == null) return
|
||||
|
||||
updatePositioning()
|
||||
var rootSpecies = pokedexEntry
|
||||
var rootForm = pokedexForm
|
||||
var preEvolution = findPreEvolution(rootSpecies, rootForm)
|
||||
// Stop at whatever the dex can't resolve, and at cycles (datapacks)
|
||||
val visited = mutableSetOf(rootSpecies.speciesId to rootForm.displayForm)
|
||||
while (preEvolution != null) {
|
||||
val preEvolutionSpecies = DexEntries.entries.values.firstOrNull { it.speciesId == preEvolution.fromSpecies &&
|
||||
it.forms.any {form -> form.displayForm.equals(preEvolution.fromForm, ignoreCase = true)}} ?: break
|
||||
val preEvolutionForm = preEvolutionSpecies.forms.firstOrNull { it.displayForm.equals(preEvolution.fromForm, ignoreCase = true) } ?: break
|
||||
if (!visited.add(preEvolutionSpecies.speciesId to preEvolutionForm.displayForm)) break
|
||||
rootSpecies = preEvolutionSpecies
|
||||
rootForm = preEvolutionForm
|
||||
preEvolution = findPreEvolution(rootSpecies, rootForm)
|
||||
}
|
||||
|
||||
val (rootPokedexEntry, rootPokedexForm) = Dexes.findRootDexEntryBySpeciesId(pokedexEntry.speciesId, pokedexForm.displayForm)
|
||||
val rootEvolutionNode = buildEvolutionTree(rootPokedexEntry, rootPokedexForm, null)
|
||||
val viewedFormEquivalents = Dexes.getFormEquivalents(pokedexForm.displayForm)
|
||||
viewedForm = PokemonSpecies.getByIdentifier(pokedexEntry.speciesId)
|
||||
?.forms?.firstOrNull { viewedFormEquivalents.contains(it.name.lowercase()) }
|
||||
|
||||
val formEquivalents = Dexes.getFormEquivalents(rootForm.displayForm)
|
||||
val form =
|
||||
rootSpecies.forms.firstOrNull { formEquivalents.contains(it.displayForm.lowercase()) } ?:
|
||||
rootSpecies.forms.first { it.displayForm.equals("Normal", ignoreCase = true) }
|
||||
|
||||
val rootEvolutionNode = buildEvolutionTree(rootSpecies, form)
|
||||
|
||||
// val isSameEntry = previousRootPokedexEntry != null && pokedexEntry?.id == previousRootPokedexEntry?.id
|
||||
// val isSameForm =
|
||||
@@ -172,6 +201,13 @@ class EvolutionTreeWidget(
|
||||
panningY = 0.0
|
||||
}
|
||||
|
||||
/** The evolution leading to [form]; the standard form falls back to any form of the species (no evolution leads to regular Vivillon). */
|
||||
private fun findPreEvolution(entry: PokedexEntry, form: PokedexForm): DexEvolutionDisplay? {
|
||||
return DexEntries.evolutionDisplays.firstOrNull { it.toSpecies == entry.speciesId && form.displayForm.equals(it.toForm, ignoreCase = true) }
|
||||
?: DexEntries.evolutionDisplays.takeIf { form.displayForm.equals("Normal", ignoreCase = true) }
|
||||
?.firstOrNull { it.toSpecies == entry.speciesId }
|
||||
}
|
||||
|
||||
fun updatePositioning() {
|
||||
x = pX + X_MARGIN
|
||||
y = pY + if (parent.evolutionTreeExpanded) Y_MARGIN_EXPANDED else Y_MARGIN_MINIMIZED
|
||||
@@ -180,6 +216,7 @@ class EvolutionTreeWidget(
|
||||
panningX = 0.0
|
||||
panningY = 0.0
|
||||
|
||||
expandButton.resource = if (parent.evolutionTreeExpanded) minimizeResource else expandResource
|
||||
expandButton.buttonX = x + EXPAND_BUTTON_X_MARGIN
|
||||
expandButton.buttonY = y + EXPAND_BUTTON_Y_MARGIN
|
||||
}
|
||||
@@ -187,61 +224,62 @@ class EvolutionTreeWidget(
|
||||
private fun buildEvolutionTree(
|
||||
pokedexEntry: PokedexEntry,
|
||||
pokedexForm: PokedexForm,
|
||||
evolution: Evolution? = null,
|
||||
resultProperties: PokemonProperties? = evolution?.result,
|
||||
renderData: RenderEvolutionData? = evolution?.let { renderEvolutionData(it) }
|
||||
aspects: Set<String> = emptySet(),
|
||||
ancestors: Set<Pair<ResourceLocation, String>> = emptySet(),
|
||||
): EvolutionNode {
|
||||
val species = PokemonSpecies.getByIdentifier(pokedexEntry.speciesId)!!
|
||||
// Datapack evolutions can loop back (A -> B -> A), so stop at anything already on this branch
|
||||
val path = ancestors + (pokedexEntry.speciesId to pokedexForm.displayForm.lowercase())
|
||||
val discoveryLevel = CobblemonClient.clientPokedexData.getHighestKnowledgeFor(pokedexEntry, pokedexForm, aspects.toMutableSet())
|
||||
|
||||
val formEquivalents = Dexes.getFormEquivalents(pokedexForm.displayForm)
|
||||
val form = species.forms.firstOrNull { formEquivalents.contains(it.name.lowercase()) }
|
||||
val parentSpecies = Dexes.findDexEntryBySpeciesId(species.resourceIdentifier)!!
|
||||
val parentPokedexForm = parentSpecies.forms.first { formEquivalents.contains(it.displayForm.lowercase()) }
|
||||
val evolutions = DexEntries.evolutionDisplays.filter { it.fromSpecies == pokedexEntry.speciesId && formEquivalents.contains(it.fromForm.lowercase()) }
|
||||
|
||||
val aspects = resultProperties?.aspects?.toMutableSet() ?: mutableSetOf()
|
||||
form?.aspects?.let { aspects.addAll(it) }
|
||||
|
||||
val discoveryLevel = CobblemonClient.clientPokedexData.getHighestKnowledgeFor(pokedexEntry, pokedexForm, aspects)
|
||||
|
||||
val evolutions = form?.evolutions ?: species.evolutions
|
||||
|
||||
// Avoid evolution.result.create() here: it builds a full battle-ready Pokemon (initializeMovesetFromDefault
|
||||
// etc.) which relies on server-only data like CobblemonMovesetBuilders and crashes on the client
|
||||
val children = evolutions.flatMap { evolution ->
|
||||
val baseRenderData = renderEvolutionData(evolution)
|
||||
|
||||
listOfNotNull(evolution.result, evolution.shedder).mapNotNull { resultProperties ->
|
||||
val resultSpecies = resultProperties.species
|
||||
?.let { PokemonSpecies.getByIdentifier(it.asIdentifierDefaultingNamespace()) }
|
||||
?: return@mapNotNull null
|
||||
|
||||
val resultForm = resultSpecies.getForm(aspects + resultProperties.aspects)
|
||||
|
||||
val speciesId = resultSpecies.resourceIdentifier
|
||||
val childPokedexEntry = Dexes.findDexEntryBySpeciesId(speciesId)
|
||||
|
||||
if (childPokedexEntry == null) {
|
||||
Cobblemon.LOGGER.warn("Dex entry not found for species: $speciesId")
|
||||
return@mapNotNull null
|
||||
}
|
||||
|
||||
val formEquivalents = Dexes.getFormEquivalents(resultForm.name.lowercase())
|
||||
val childPokedexForm = childPokedexEntry.forms.first { formEquivalents.contains(it.displayForm.lowercase()) }
|
||||
|
||||
val childRenderData = if (resultProperties === evolution.shedder) {
|
||||
RenderEvolutionData(
|
||||
icons = (baseRenderData?.icons ?: emptyList()) + CobblemonItems.POKE_BALL,
|
||||
tooltips = (baseRenderData?.tooltips ?: emptyList()) + lang("ui.pokedex.evolution.shedder.tooltip"),
|
||||
)
|
||||
} else {
|
||||
baseRenderData
|
||||
}
|
||||
|
||||
return@mapNotNull buildEvolutionTree(childPokedexEntry, childPokedexForm, evolution, resultProperties, childRenderData)
|
||||
val children = evolutions.mapNotNull {
|
||||
val childPokedexEntry = DexEntries.entries.values.firstOrNull { entry -> entry.speciesId == it.toSpecies &&
|
||||
entry.forms.any {form -> form.displayForm.equals(it.toForm, ignoreCase = true)}}
|
||||
if (childPokedexEntry == null) {
|
||||
Cobblemon.LOGGER.warn("Dex entry not found for species: ${it.toSpecies}")
|
||||
return@mapNotNull null
|
||||
}
|
||||
val formEquivalents = Dexes.getFormEquivalents(it.toForm.lowercase())
|
||||
val childPokedexForm = childPokedexEntry.forms.firstOrNull { formEquivalents.contains(it.displayForm.lowercase()) }
|
||||
if (childPokedexForm == null) {
|
||||
Cobblemon.LOGGER.warn("Dex form ${it.toForm} not found for species: ${it.toSpecies}")
|
||||
return@mapNotNull null
|
||||
}
|
||||
if ((childPokedexEntry.speciesId to childPokedexForm.displayForm.lowercase()) in path) {
|
||||
Cobblemon.LOGGER.warn("Evolution loop found at species: ${it.toSpecies} form: ${it.toForm}")
|
||||
return@mapNotNull null
|
||||
}
|
||||
buildEvolutionTree(childPokedexEntry, childPokedexForm, it.toAspects, path)
|
||||
}
|
||||
|
||||
return EvolutionNode(pokedexEntry, parentPokedexForm, aspects, discoveryLevel, children, renderData)
|
||||
return EvolutionNode(
|
||||
pokedexEntry = pokedexEntry,
|
||||
pokedexForm = pokedexForm,
|
||||
aspects = aspects,
|
||||
pokedexEntryProgress = discoveryLevel,
|
||||
children = mergeEquivalentChildren(children),
|
||||
renderDataAlternatives = evolutions,
|
||||
)
|
||||
}
|
||||
|
||||
private fun mergeEquivalentChildren(children: List<EvolutionNode>): List<EvolutionNode> {
|
||||
return children
|
||||
.groupBy { Triple(it.pokedexEntry.speciesId, it.pokedexForm.displayForm.lowercase(), it.aspects) }
|
||||
.values
|
||||
.map { group ->
|
||||
if (group.size == 1) return@map group.first()
|
||||
val first = group.first()
|
||||
EvolutionNode(
|
||||
first.pokedexEntry,
|
||||
first.pokedexForm,
|
||||
first.aspects,
|
||||
first.pokedexEntryProgress,
|
||||
first.children,
|
||||
group.flatMap { it.renderDataAlternatives }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderTreeDrawingNode(
|
||||
@@ -258,15 +296,19 @@ class EvolutionTreeWidget(
|
||||
val (childX, _) = getDrawingCoordinates(child)
|
||||
|
||||
val lineStartX = treeX + SCROLL_SLOT_SIZE
|
||||
val lineEndX = childX
|
||||
val lineY = treeY + SCROLL_SLOT_SIZE / 2
|
||||
|
||||
child.value.renderData?.let { renderData ->
|
||||
val formEquivalents = Dexes.getFormEquivalents(child.value.pokedexForm.displayForm)
|
||||
val alternatives = treeDrawingNode.value.renderDataAlternatives.filter {
|
||||
it.toSpecies == child.value.pokedexEntry.speciesId && formEquivalents.contains(it.toForm.lowercase()) && it.toAspects == child.value.aspects
|
||||
}
|
||||
|
||||
alternatives.takeIf { it.isNotEmpty() }?.let {
|
||||
drawEvolutionInfo(
|
||||
guiGraphics,
|
||||
renderData,
|
||||
it,
|
||||
lineStartX,
|
||||
lineEndX,
|
||||
childX,
|
||||
lineY,
|
||||
mouseX,
|
||||
mouseY,
|
||||
@@ -298,16 +340,19 @@ class EvolutionTreeWidget(
|
||||
treeDrawingNode.children.forEach { child ->
|
||||
val (childX, childY) = getDrawingCoordinates(child)
|
||||
|
||||
val lineStartX = treeForkEnd
|
||||
val lineEndX = childX
|
||||
val lineY = childY + SCROLL_SLOT_SIZE / 2
|
||||
|
||||
child.value.renderData?.let { renderData ->
|
||||
val formEquivalents = Dexes.getFormEquivalents(child.value.pokedexForm.displayForm)
|
||||
val alternatives = treeDrawingNode.value.renderDataAlternatives.filter {
|
||||
it.toSpecies == child.value.pokedexEntry.speciesId && formEquivalents.contains(it.toForm.lowercase()) && it.toAspects == child.value.aspects
|
||||
}
|
||||
|
||||
alternatives.takeIf { it.isNotEmpty() }?.let {
|
||||
drawEvolutionInfo(
|
||||
guiGraphics,
|
||||
renderData,
|
||||
lineStartX,
|
||||
lineEndX,
|
||||
it,
|
||||
treeForkEnd,
|
||||
childX,
|
||||
lineY,
|
||||
mouseX,
|
||||
mouseY,
|
||||
@@ -346,7 +391,7 @@ class EvolutionTreeWidget(
|
||||
if (formName == "normal") null
|
||||
else lang("ui.pokedex.info.form.${species}-${formName.replace("-", "")}")
|
||||
|
||||
formComponent?.add(" ")?.add(speciesComponent) ?: speciesComponent
|
||||
formComponent?.let { speciesComponent.copy().add(" (").add(it).add(")") } ?: speciesComponent
|
||||
}
|
||||
|
||||
guiGraphics.disableScissor()
|
||||
@@ -408,7 +453,7 @@ class EvolutionTreeWidget(
|
||||
|
||||
private fun drawEvolutionInfo(
|
||||
guiGraphics: GuiGraphics,
|
||||
renderData: RenderEvolutionData,
|
||||
renderDataAlternatives: List<DexEvolutionDisplay>,
|
||||
lineStartX: Int,
|
||||
lineEndX: Int,
|
||||
lineY: Int,
|
||||
@@ -416,6 +461,26 @@ class EvolutionTreeWidget(
|
||||
mouseY: Int,
|
||||
delta: Float,
|
||||
) {
|
||||
val icons = renderDataAlternatives.flatMap { it.requirements.filter(::isDisplayable).map { req -> req.icon } }.distinct()
|
||||
val playerBiome = Minecraft.getInstance().player?.let { it.level().getBiome(it.blockPosition()) }
|
||||
val alternativeTooltips = renderDataAlternatives.map { alternative ->
|
||||
alternative.requirements.filter(::isDisplayable).map { req ->
|
||||
if (req is CobblemonBiomeDexEvolutionRequirementDisplay) {
|
||||
val tooltip = req.tooltip.copy()
|
||||
if (playerBiome != null) {
|
||||
val conditionFits = req.condition?.let { if (it.tag) playerBiome.`is`(TagKey.create(Registries.BIOME, it.id)) else playerBiome.`is`(it.id) } ?: true
|
||||
val antiConditionFits = req.antiCondition?.let { if (it.tag) playerBiome.`is`(TagKey.create(Registries.BIOME, it.id)) else playerBiome.`is`(it.id) } ?: false
|
||||
val isMet = conditionFits && !antiConditionFits
|
||||
tooltip.add(if (isMet) Component.literal(" ✔").green() else Component.literal(" ✘").red())
|
||||
}
|
||||
tooltip
|
||||
} else {
|
||||
req.tooltip
|
||||
}
|
||||
}
|
||||
}
|
||||
val tooltips = combineAlternativeTooltips(alternativeTooltips)
|
||||
|
||||
val lineXMiddle = (lineStartX + lineEndX) / 2
|
||||
val iconX = (lineXMiddle + ICON_X_PADDING - ICON_SLOT_HALF_PADDING).toInt()
|
||||
val iconY = (lineY + ICON_Y_PADDING - ICON_SLOT_HALF_PADDING).toInt()
|
||||
@@ -431,7 +496,7 @@ class EvolutionTreeWidget(
|
||||
return
|
||||
}
|
||||
|
||||
if (renderData.icons.isEmpty()) {
|
||||
if (icons.isEmpty()) {
|
||||
guiGraphics.hLine(
|
||||
lineStartX,
|
||||
lineEndX,
|
||||
@@ -462,8 +527,8 @@ class EvolutionTreeWidget(
|
||||
height = iconSize,
|
||||
)
|
||||
|
||||
val index = (System.currentTimeMillis() / MILLIS_BETWEEN_ICONS_CYCLE) % renderData.icons.size
|
||||
val item = renderData.icons[index.toInt()]
|
||||
val index = (System.currentTimeMillis() / MILLIS_BETWEEN_ICONS_CYCLE) % icons.size
|
||||
val item = icons[index.toInt()]
|
||||
|
||||
renderScaledGuiItemIcon(
|
||||
itemStack = item.defaultInstance,
|
||||
@@ -478,17 +543,49 @@ class EvolutionTreeWidget(
|
||||
val isIconHovered = isElementHovered(
|
||||
mouseX,
|
||||
mouseY,
|
||||
iconX.toInt(),
|
||||
iconX.toInt() + iconSize,
|
||||
iconY.toInt(),
|
||||
iconY.toInt() + iconSize,
|
||||
iconX,
|
||||
iconX + iconSize,
|
||||
iconY,
|
||||
iconY + iconSize,
|
||||
)
|
||||
|
||||
if (renderData.tooltips.isNotEmpty() &&
|
||||
if (tooltips.isNotEmpty() &&
|
||||
(isLineHovered || isIconHovered) &&
|
||||
this.isHovered(mouseX.toDouble(), mouseY.toDouble())
|
||||
) {
|
||||
hoveredTooltips = renderData.tooltips
|
||||
hoveredTooltips = tooltips.map { it.copy() }
|
||||
}
|
||||
}
|
||||
|
||||
/** Hides biome requirements naming untranslated biomes, e.g. from mods that aren't installed (aether:skyroot_forest) */
|
||||
private fun isDisplayable(requirement: DexEvolutionRequirementDisplay): Boolean {
|
||||
if (requirement !is CobblemonBiomeDexEvolutionRequirementDisplay) return true
|
||||
return listOfNotNull(requirement.condition, requirement.antiCondition).all {
|
||||
it.tag || Language.getInstance().has("biome.${it.id.namespace}.${it.id.path}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun combineAlternativeTooltips(alternatives: List<List<Component>>): List<Component> {
|
||||
val groups = alternatives.filter { it.isNotEmpty() }
|
||||
if (groups.size <= 1) return groups.firstOrNull() ?: emptyList()
|
||||
|
||||
val sharedStrings = groups.map { group -> group.map { it.string }.toSet() }.reduce { acc, strings -> acc intersect strings }
|
||||
val shared = groups.first().filter { it.string in sharedStrings }.distinctBy { it.string }
|
||||
val remainders = groups
|
||||
.map { group -> group.filter { it.string !in sharedStrings } }
|
||||
.distinctBy { group -> group.map { it.string } }
|
||||
|
||||
// An alternative needing nothing beyond the shared lines makes the others irrelevant
|
||||
if (remainders.any { it.isEmpty() }) return shared
|
||||
if (remainders.size == 1) return shared + remainders.first()
|
||||
|
||||
return if (remainders.size >= 3 && remainders.all { it.size == 1 }) {
|
||||
shared + lang("ui.pokedex.evolution.one_of").bold() + remainders.map { it.first() }
|
||||
} else {
|
||||
// Show each alternative in full, otherwise it's unclear where the first one starts
|
||||
groups.distinctBy { group -> group.map { it.string } }.flatMapIndexed { index, group ->
|
||||
if (index == 0) group else listOf(lang("ui.pokedex.evolution.or").bold()) + group
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -566,6 +663,6 @@ class EvolutionTreeWidget(
|
||||
val aspects: Set<String>,
|
||||
val pokedexEntryProgress: PokedexEntryProgress,
|
||||
override val children: List<EvolutionNode>,
|
||||
val renderData: RenderEvolutionData?,
|
||||
val renderDataAlternatives: List<DexEvolutionDisplay>,
|
||||
) : TreeNode<EvolutionNode>
|
||||
}
|
||||
-48
@@ -1,48 +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.client.gui.pokedex.widgets.evolutiontree
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
fun debugEvolutionRequirementRendering() {
|
||||
if (!Cobblemon.config.enableDebugKeys) {
|
||||
return
|
||||
}
|
||||
|
||||
val gaps = mutableListOf<Pair<String, String>>()
|
||||
|
||||
for (species in PokemonSpecies.implemented) {
|
||||
val evolutions = species.evolutions + species.forms.flatMap { it.evolutions }
|
||||
for (evolution in evolutions) {
|
||||
if (renderEvolutionData(evolution) == null) {
|
||||
gaps.add("Evolution: ${evolution::class.simpleName}" to species.showdownId())
|
||||
}
|
||||
for (requirement in evolution.requirements) {
|
||||
if (resolveRequirementData(requirement) == null) {
|
||||
gaps.add("Requirement: ${requirement::class.simpleName}" to species.showdownId())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val player = Minecraft.getInstance().player
|
||||
if (gaps.isEmpty()) {
|
||||
player?.sendSystemMessage(Component.literal("Evolution render debug: no gaps found."))
|
||||
return
|
||||
}
|
||||
|
||||
val byType = gaps.groupBy({ it.first }, { it.second })
|
||||
println("Evolution render debug found ${gaps.size} gap(s) across ${byType.size} type(s):")
|
||||
byType.forEach { (type, species) -> println(" $type: ${species.distinct().joinToString(", ")}") }
|
||||
|
||||
player?.sendSystemMessage(Component.literal("Evolution render debug: ${gaps.size} gap(s) across ${byType.size} type(s), see log for details."))
|
||||
}
|
||||
-123
@@ -1,123 +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.client.gui.pokedex.widgets.evolutiontree
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
|
||||
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
|
||||
import com.cobblemon.mod.common.api.text.green
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.BlockClickEvolution
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.DummyEvolution
|
||||
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.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.itemRegistry
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.world.item.Item
|
||||
|
||||
data class RenderEvolutionData(
|
||||
val icons: List<Item>,
|
||||
val tooltips: List<MutableComponent>,
|
||||
)
|
||||
|
||||
internal fun resolveRequirementData(requirement: Requirement): RenderRequirementData? {
|
||||
val icon = requirement.pokedexIcon?.let {
|
||||
Minecraft.getInstance()?.player?.level()?.itemRegistry?.get(it)
|
||||
}
|
||||
|
||||
val tooltip = requirement.pokedexTooltip?.let {
|
||||
Component.translatable(it)
|
||||
}
|
||||
|
||||
if (icon != null && tooltip != null) {
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
return renderRequirementData(requirement)
|
||||
}
|
||||
|
||||
fun renderEvolutionData(evolution: Evolution): RenderEvolutionData? {
|
||||
when (evolution) {
|
||||
is BlockClickEvolution -> return renderBlockClickEvolution(evolution)
|
||||
is DummyEvolution -> return renderDummyEvolution(evolution)
|
||||
is ItemInteractionEvolution -> return renderItemInteractionEvolution(evolution)
|
||||
is LevelUpEvolution -> return renderLevelUpEvolution(evolution)
|
||||
is TradeEvolution -> return renderTradeEvolution(evolution)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun renderBlockClickEvolution(blockClickEvolution: BlockClickEvolution): RenderEvolutionData? {
|
||||
return null
|
||||
}
|
||||
|
||||
// TODO: Use dummyEvolution?
|
||||
fun renderDummyEvolution(evolution: Evolution): RenderEvolutionData? {
|
||||
return null
|
||||
}
|
||||
|
||||
fun renderItemInteractionEvolution(itemInteractionEvolution: ItemInteractionEvolution): RenderEvolutionData? {
|
||||
val item = itemInteractionEvolution.requiredContext.items.get().first().value()
|
||||
val icons = mutableListOf(item)
|
||||
val tooltips =
|
||||
mutableListOf(lang("ui.pokedex.evolution.item_interact.tooltip", item.description.plainCopy().green()))
|
||||
|
||||
val requirementsDataList = itemInteractionEvolution.requirements.mapNotNull { requirement ->
|
||||
resolveRequirementData(requirement)
|
||||
}
|
||||
|
||||
requirementsDataList.forEach { requirement ->
|
||||
icons.add(requirement.icon)
|
||||
tooltips.add(requirement.tooltip)
|
||||
}
|
||||
|
||||
return RenderEvolutionData(icons, tooltips)
|
||||
}
|
||||
|
||||
fun renderLevelUpEvolution(levelUpEvolution: LevelUpEvolution): RenderEvolutionData? {
|
||||
val requirementsDataList = levelUpEvolution.requirements.map { requirement ->
|
||||
resolveRequirementData(requirement)
|
||||
}
|
||||
|
||||
val icons = requirementsDataList.mapNotNull { requirementData -> requirementData?.icon }
|
||||
val tooltips = requirementsDataList.mapNotNull { requirementData -> requirementData?.tooltip }
|
||||
|
||||
return RenderEvolutionData(icons, tooltips)
|
||||
}
|
||||
|
||||
fun renderTradeEvolution(tradeEvolution: TradeEvolution): RenderEvolutionData? {
|
||||
val icons = mutableListOf<Item>(CobblemonItems.LINK_CABLE)
|
||||
val tooltips = mutableListOf<MutableComponent>()
|
||||
|
||||
val species = tradeEvolution.requiredContext.species
|
||||
if (species == null) {
|
||||
tooltips.add(lang("ui.pokedex.evolution.trade.tooltip.with_any_species"))
|
||||
} else {
|
||||
PokemonSpecies.getByIdentifier(species.asIdentifierDefaultingNamespace())?.let {
|
||||
tooltips.add(lang("ui.pokedex.evolution.trade.tooltip.with_species", it.translatedName.green()))
|
||||
}
|
||||
}
|
||||
|
||||
val requirementsDataList = tradeEvolution.requirements.mapNotNull { requirement ->
|
||||
resolveRequirementData(requirement)
|
||||
}
|
||||
|
||||
requirementsDataList.forEach { requirement ->
|
||||
icons.add(requirement.icon)
|
||||
tooltips.add(requirement.tooltip)
|
||||
}
|
||||
|
||||
return RenderEvolutionData(icons, tooltips)
|
||||
}
|
||||
-379
@@ -1,379 +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.client.gui.pokedex.widgets.evolutiontree
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeIdentifierCondition
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeTagCondition
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.IntSpeciesFeatureProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.SpeciesFeatures
|
||||
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.text.add
|
||||
import com.cobblemon.mod.common.api.text.green
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.pokemon.requirements.*
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.level.biome.Biome
|
||||
import net.minecraft.world.level.levelgen.structure.Structure
|
||||
|
||||
data class RenderRequirementData(
|
||||
val icon: Item,
|
||||
val tooltip: MutableComponent,
|
||||
)
|
||||
|
||||
fun renderRequirementData(requirement: Requirement): RenderRequirementData? {
|
||||
when (requirement) {
|
||||
is AdvancementRequirement -> return renderAdvancementRequirement(requirement)
|
||||
is AnyRequirement -> return renderAnyRequirement(requirement)
|
||||
is AreaRequirement -> return renderAreaRequirement(requirement)
|
||||
is AttackDefenceRatioRequirement -> return renderAttackDefenceRatioRequirement(requirement)
|
||||
is BattleCriticalHitsRequirement -> return renderBattleCriticalHitsRequirement(requirement)
|
||||
is BiomeRequirement -> return renderBiomeRequirement(requirement)
|
||||
is BlocksTraveledRequirement -> return renderBlocksTraveledRequirement(requirement)
|
||||
is DamageTakenRequirement -> return renderDamageTakenRequirement(requirement)
|
||||
is DefeatRequirement -> return renderDefeatRequirement(requirement)
|
||||
is FriendshipRequirement -> return renderFriendshipRequirement(requirement)
|
||||
is HeldItemRequirement -> return renderHeldItemRequirement(requirement)
|
||||
is LevelRequirement -> return renderLevelRequirement(requirement)
|
||||
is MoonPhaseRequirement -> return renderMoonPhaseRequirement(requirement)
|
||||
is MoveSetRequirement -> return renderMoveSetRequirement(requirement)
|
||||
is MoveTypeRequirement -> return renderMoveTypeRequirement(requirement)
|
||||
is OwnerHoldsItemRequirement -> return renderOwnerHoldsItemRequirement(requirement)
|
||||
is PartyMemberRequirement -> return renderPartyMemberRequirement(requirement)
|
||||
is PokemonPropertiesRequirement -> return renderPokemonPropertiesRequirement(requirement)
|
||||
is PropertyRangeRequirement -> return renderPropertyRangeRequirement(requirement)
|
||||
is RecoilRequirement -> return renderRecoilRequirement(requirement)
|
||||
is StatCompareRequirement -> return renderStatCompareRequirement(requirement)
|
||||
is StatEqualRequirement -> return renderStatEqualRequirement(requirement)
|
||||
is StructureRequirement -> return renderStructureRequirement(requirement)
|
||||
is TimeRangeRequirement -> return renderTimeRangeRequirement(requirement)
|
||||
is UseMoveRequirement -> return renderUseMoveRequirement(requirement)
|
||||
is WeatherRequirement -> return renderWeatherRequirement(requirement)
|
||||
is WorldRequirement -> return renderWorldRequirement(requirement)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun renderAdvancementRequirement(advancementRequirement: AdvancementRequirement): RenderRequirementData? {
|
||||
val icon = Items.BOOK
|
||||
val identifier = advancementRequirement.requiredAdvancement
|
||||
val advancementLanguageKey = "${identifier.namespace}.${identifier.path.substringAfterLast('/')}"
|
||||
val advancementComponent = Component.translatable("advancements.$advancementLanguageKey").green()
|
||||
val tooltip = lang("ui.pokedex.requirement.advancement.tooltip", advancementComponent)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderAnyRequirement(anyRequirement: AnyRequirement): RenderRequirementData? {
|
||||
return null
|
||||
}
|
||||
|
||||
fun renderAreaRequirement(areaRequirement: AreaRequirement): RenderRequirementData? {
|
||||
return null
|
||||
}
|
||||
|
||||
fun renderAttackDefenceRatioRequirement(attackDefenceRatioRequirement: AttackDefenceRatioRequirement): RenderRequirementData? {
|
||||
return null
|
||||
}
|
||||
|
||||
fun renderBattleCriticalHitsRequirement(battleCriticalHitsRequirement: BattleCriticalHitsRequirement): RenderRequirementData? {
|
||||
val icon = CobblemonItems.MEDICINAL_LEEK
|
||||
val criticalsComponent = Component.literal(battleCriticalHitsRequirement.amount.toString()).green()
|
||||
val tooltip = lang("ui.pokedex.requirement.battle_critical_hits.tooltip", criticalsComponent)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderBiomeRequirement(biomeRequirement: BiomeRequirement): RenderRequirementData? {
|
||||
val condition = biomeRequirement.biomeCondition
|
||||
val anticondition = biomeRequirement.biomeAnticondition
|
||||
if (condition == null && anticondition == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
val icon = Items.COMPASS
|
||||
val displayName: (RegistryLikeCondition<Biome>) -> MutableComponent = {
|
||||
when (it) {
|
||||
is RegistryLikeTagCondition -> Component.literal(it.tag.location().path.substringAfterLast('/').split('_').joinToString(" ") { part -> part.replaceFirstChar(Char::titlecase) })
|
||||
is RegistryLikeIdentifierCondition -> Component.translatable("biome.${it.identifier.namespace}.${it.identifier.path}")
|
||||
else -> Component.literal(it.toString())
|
||||
}
|
||||
}
|
||||
val tooltip = if (condition != null && anticondition != null) {
|
||||
lang("ui.pokedex.requirement.biome.both.tooltip", displayName(condition).green(), displayName(anticondition).green())
|
||||
} else if (condition != null) {
|
||||
lang("ui.pokedex.requirement.biome.tooltip", displayName(condition).green())
|
||||
} else {
|
||||
lang("ui.pokedex.requirement.biome.anticondition.tooltip", displayName(anticondition!!).green())
|
||||
}
|
||||
|
||||
val playerBiome = Minecraft.getInstance()?.player?.let { it.level().getBiome(it.blockPosition()) }
|
||||
if (playerBiome != null) {
|
||||
val isMet = (condition == null || condition.fits(playerBiome)) && (anticondition == null || !anticondition.fits(playerBiome))
|
||||
tooltip.add(if (isMet) Component.literal(" ✔").green() else Component.literal(" ✘").red())
|
||||
}
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderBlocksTraveledRequirement(blocksTraveledRequirement: BlocksTraveledRequirement): RenderRequirementData? {
|
||||
val icon = Items.LEATHER_BOOTS
|
||||
val blocksComponent = Component.literal(blocksTraveledRequirement.amount.toString()).green()
|
||||
val tooltip = lang("ui.pokedex.requirement.blocks_traveled.tooltip", blocksComponent)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderDamageTakenRequirement(damageTakenRequirement: DamageTakenRequirement): RenderRequirementData? {
|
||||
val icon = CobblemonItems.PUNCHING_GLOVE
|
||||
val blocksComponent = Component.literal(damageTakenRequirement.amount.toString()).green()
|
||||
val tooltip = lang("ui.pokedex.requirement.damage_taken.tooltip", blocksComponent)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderDefeatRequirement(defeatRequirement: DefeatRequirement): RenderRequirementData? {
|
||||
val description = describePokemonProperties(defeatRequirement.target) ?: return null
|
||||
val icon = CobblemonItems.PUNCHING_GLOVE
|
||||
val defeatedAmount = defeatRequirement.amount
|
||||
|
||||
val descriptionComponent = Component.literal(defeatedAmount.toString()).green().add(" ").add(description)
|
||||
val tooltip = lang("ui.pokedex.requirement.defeat.tooltip", descriptionComponent)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderFriendshipRequirement(friendshipRequirement: FriendshipRequirement): RenderRequirementData? {
|
||||
val icon = CobblemonItems.SOOTHE_BELL
|
||||
val friendshipAmountComponent = Component.literal(friendshipRequirement.amount.toString()).green()
|
||||
val tooltip = lang("ui.pokedex.requirement.friendship.tooltip", friendshipAmountComponent)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderHeldItemRequirement(heldItemRequirement: HeldItemRequirement): RenderRequirementData? {
|
||||
val item = heldItemRequirement.itemCondition.items.get().first().value()
|
||||
val tooltip = lang("ui.pokedex.requirement.held_item.tooltip", item.description.plainCopy().green())
|
||||
|
||||
return RenderRequirementData(item, tooltip)
|
||||
}
|
||||
|
||||
fun renderLevelRequirement(levelRequirement: LevelRequirement): RenderRequirementData? {
|
||||
val minLevel = levelRequirement.minLevel
|
||||
val maxLevel = levelRequirement.maxLevel
|
||||
|
||||
val icon = CobblemonItems.RARE_CANDY
|
||||
val tooltip =
|
||||
if (minLevel == maxLevel || maxLevel == Int.MAX_VALUE)
|
||||
lang("ui.pokedex.requirement.level.tooltip.min", Component.literal(minLevel.toString()).green())
|
||||
else
|
||||
lang("ui.pokedex.requirement.level.tooltip.between", Component.literal(minLevel.toString()).green(), Component.literal(maxLevel.toString()).green())
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderMoonPhaseRequirement(moonPhaseRequirement: MoonPhaseRequirement): RenderRequirementData? {
|
||||
val icon = Items.CLOCK
|
||||
val moonPhaseComponent = moonPhaseRequirement.moonPhase.displayName().green()
|
||||
val tooltip = lang("ui.pokedex.requirement.moon_phase.tooltip", moonPhaseComponent)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderMoveSetRequirement(moveSetRequirement: MoveSetRequirement): RenderRequirementData? {
|
||||
val icon = CobblemonItems.TECHNICAL_MACHINE
|
||||
val tooltip = lang("ui.pokedex.requirement.has_move.tooltip", moveSetRequirement.move.displayName.green())
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderMoveTypeRequirement(moveTypeRequirement: MoveTypeRequirement): RenderRequirementData? {
|
||||
val type = ElementalTypes.get(moveTypeRequirement.type.name)
|
||||
val icon = when (type) {
|
||||
ElementalTypes.NORMAL -> CobblemonItems.NORMAL_GEM
|
||||
ElementalTypes.FIRE -> CobblemonItems.FIRE_GEM
|
||||
ElementalTypes.WATER -> CobblemonItems.WATER_GEM
|
||||
ElementalTypes.GRASS -> CobblemonItems.GRASS_GEM
|
||||
ElementalTypes.ELECTRIC -> CobblemonItems.ELECTRIC_GEM
|
||||
ElementalTypes.ICE -> CobblemonItems.ICE_GEM
|
||||
ElementalTypes.FIGHTING -> CobblemonItems.FIGHTING_GEM
|
||||
ElementalTypes.POISON -> CobblemonItems.POISON_GEM
|
||||
ElementalTypes.GROUND -> CobblemonItems.GROUND_GEM
|
||||
ElementalTypes.FLYING -> CobblemonItems.FLYING_GEM
|
||||
ElementalTypes.PSYCHIC -> CobblemonItems.PSYCHIC_GEM
|
||||
ElementalTypes.BUG -> CobblemonItems.BUG_GEM
|
||||
ElementalTypes.ROCK -> CobblemonItems.ROCK_GEM
|
||||
ElementalTypes.GHOST -> CobblemonItems.GHOST_GEM
|
||||
ElementalTypes.DRAGON -> CobblemonItems.DRAGON_GEM
|
||||
ElementalTypes.DARK -> CobblemonItems.DARK_GEM
|
||||
ElementalTypes.STEEL -> CobblemonItems.STEEL_GEM
|
||||
ElementalTypes.FAIRY -> CobblemonItems.FAIRY_GEM
|
||||
else -> CobblemonItems.NORMAL_GEM
|
||||
}
|
||||
|
||||
val tooltip = lang("ui.pokedex.requirement.has_move_type.tooltip", moveTypeRequirement.type.displayName.green())
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderOwnerHoldsItemRequirement(ownerHoldsItemRequirement: OwnerHoldsItemRequirement): RenderRequirementData? {
|
||||
val item = ownerHoldsItemRequirement.itemCondition.items.get().first().value()
|
||||
val tooltip = lang("ui.pokedex.requirement.owner_held_item.tooltip", item.description.plainCopy().green())
|
||||
|
||||
return RenderRequirementData(item, tooltip)
|
||||
}
|
||||
|
||||
fun renderPartyMemberRequirement(partyMemberRequirement: PartyMemberRequirement): RenderRequirementData? {
|
||||
val description = describePokemonProperties(partyMemberRequirement.target) ?: return null
|
||||
val icon = CobblemonItems.POKE_BALL
|
||||
val tooltip = if (partyMemberRequirement.contains) {
|
||||
lang("ui.pokedex.requirement.party_member.tooltip", description)
|
||||
} else {
|
||||
lang("ui.pokedex.requirement.party_member.anticondition.tooltip", description)
|
||||
}
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderPokemonPropertiesRequirement(pokemonPropertiesRequirement: PokemonPropertiesRequirement): RenderRequirementData? {
|
||||
val description = describePokemonProperties(pokemonPropertiesRequirement.target) ?: return null
|
||||
val icon = Items.NAME_TAG
|
||||
val tooltip = lang("ui.pokedex.requirement.pokemon_properties.tooltip", description)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderPropertyRangeRequirement(propertyRangeRequirement: PropertyRangeRequirement): RenderRequirementData? {
|
||||
val provider = SpeciesFeatures.getFeature(propertyRangeRequirement.feature) as? IntSpeciesFeatureProvider ?: return null
|
||||
val displayName = provider.display?.name?.takeIf { it.isNotBlank() }?.asTranslated()?.green() ?: return null
|
||||
val icon = provider.itemPoints.keys.firstOrNull()?.let { BuiltInRegistries.ITEM.get(it) } ?: Items.NAME_TAG
|
||||
|
||||
val range = propertyRangeRequirement.range
|
||||
val tooltip = lang(
|
||||
"ui.pokedex.requirement.property_range.tooltip",
|
||||
displayName,
|
||||
Component.literal(range.first.toString()).green(),
|
||||
Component.literal(range.last.toString()).green()
|
||||
)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderRecoilRequirement(recoilRequirement: RecoilRequirement): RenderRequirementData? {
|
||||
val icon = CobblemonItems.LIFE_ORB
|
||||
val recoilComponent = Component.literal(recoilRequirement.amount.toString()).green()
|
||||
val tooltip = lang("ui.pokedex.requirement.recoil.tooltip", recoilComponent)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderStatCompareRequirement(statCompareRequirement: StatCompareRequirement): RenderRequirementData? {
|
||||
val highStat = Stats.getStat(statCompareRequirement.highStat)
|
||||
val lowStat = Stats.getStat(statCompareRequirement.lowStat)
|
||||
|
||||
val icon = when (highStat) {
|
||||
Stats.HP, Stats.EVASION, Stats.ACCURACY -> CobblemonItems.HEALTH_MOCHI
|
||||
Stats.ATTACK -> CobblemonItems.MUSCLE_MOCHI
|
||||
Stats.DEFENCE -> CobblemonItems.RESIST_MOCHI
|
||||
Stats.SPECIAL_ATTACK -> CobblemonItems.GENIUS_MOCHI
|
||||
Stats.SPECIAL_DEFENCE -> CobblemonItems.CLEVER_MOCHI
|
||||
Stats.SPEED -> CobblemonItems.SWIFT_MOCHI
|
||||
}
|
||||
|
||||
val highStatComponent = highStat.displayName.plainCopy().green()
|
||||
val lowStatComponent = lowStat.displayName.plainCopy().green()
|
||||
val tooltip = lang("ui.pokedex.requirement.stat_compare.tooltip", highStatComponent, lowStatComponent)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderStatEqualRequirement(statEqualRequirement: StatEqualRequirement): RenderRequirementData? {
|
||||
val statOne = Stats.getStat(statEqualRequirement.statOne)
|
||||
val statTwo = Stats.getStat(statEqualRequirement.statTwo)
|
||||
|
||||
val statOneComponent = statOne.displayName.plainCopy().green()
|
||||
val statTwoComponent = statTwo.displayName.plainCopy().green()
|
||||
|
||||
val icon = CobblemonItems.FRESH_START_MOCHI
|
||||
val tooltip = lang("ui.pokedex.requirement.stat_equal.tooltip", statOneComponent, statTwoComponent)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderStructureRequirement(structureRequirement: StructureRequirement): RenderRequirementData? {
|
||||
val condition = structureRequirement.structureCondition
|
||||
val anticondition = structureRequirement.structureAnticondition
|
||||
if (condition == null && anticondition == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
val icon = Items.STRUCTURE_BLOCK
|
||||
val displayName: (RegistryLikeCondition<Structure>) -> MutableComponent = {
|
||||
val path = when (it) {
|
||||
is RegistryLikeTagCondition -> it.tag.location().path
|
||||
is RegistryLikeIdentifierCondition -> it.identifier.path
|
||||
else -> it.toString()
|
||||
}
|
||||
Component.literal(path.substringAfterLast('/').split('_').joinToString(" ") { part -> part.replaceFirstChar(Char::titlecase) })
|
||||
}
|
||||
val tooltip = if (condition != null && anticondition != null) {
|
||||
lang("ui.pokedex.requirement.structure.both.tooltip", displayName(condition).green(), displayName(anticondition).green())
|
||||
} else if (condition != null) {
|
||||
lang("ui.pokedex.requirement.structure.tooltip", displayName(condition).green())
|
||||
} else {
|
||||
lang("ui.pokedex.requirement.structure.anticondition.tooltip", displayName(anticondition!!).green())
|
||||
}
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderTimeRangeRequirement(timeRangeRequirement: TimeRangeRequirement): RenderRequirementData? {
|
||||
val icon = Items.CLOCK
|
||||
val timeRangeComponent = timeRangeRequirement.range.displayName() ?: return null
|
||||
val tooltip = lang("ui.pokedex.requirement.time_range.tooltip", timeRangeComponent.green())
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderUseMoveRequirement(useMoveRequirement: UseMoveRequirement): RenderRequirementData? {
|
||||
val icon = CobblemonItems.CHOICE_BAND
|
||||
val tooltip = lang("ui.pokedex.requirement.use_move.tooltip", useMoveRequirement.move.displayName.green())
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderWeatherRequirement(weatherRequirement: WeatherRequirement): RenderRequirementData? {
|
||||
val icon: Item
|
||||
val tooltip: MutableComponent
|
||||
|
||||
if (weatherRequirement.isThundering == true) {
|
||||
icon = Items.LIGHTNING_ROD
|
||||
tooltip = lang("ui.pokedex.requirement.weather.tooltip.thundering")
|
||||
} else {
|
||||
icon = Items.WATER_BUCKET
|
||||
tooltip = lang("ui.pokedex.requirement.weather.tooltip.raining")
|
||||
}
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
fun renderWorldRequirement(worldRequirement: WorldRequirement): RenderRequirementData? {
|
||||
return null
|
||||
}
|
||||
+3
-2
@@ -24,8 +24,9 @@ object OpenPCHandler : ClientNetworkPacketHandler<OpenPCPacket> {
|
||||
party = CobblemonClient.storage.party,
|
||||
configuration = PCGUIConfiguration(),
|
||||
openOnBox = packet.box ?: CobblemonClient.lastPcBoxViewed,
|
||||
unseenWallpapers = packet.unseenWallpapers.toMutableSet()
|
||||
unseenWallpapers = packet.unseenWallpapers.toMutableSet(),
|
||||
silent = packet.silent
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -34,6 +34,7 @@ import com.cobblemon.mod.common.client.render.models.blockbench.bedrock.animatio
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.quirk.ModelQuirk
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.quirk.QuirkData
|
||||
import com.cobblemon.mod.common.client.sound.instances.UIEntitySoundInstance
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
@@ -44,7 +45,6 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.multiplayer.ClientLevel
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.commands.arguments.item.ItemParser
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.world.entity.Entity
|
||||
@@ -289,7 +289,7 @@ abstract class PosableState : Schedulable {
|
||||
entity.level().playLocalSound(entity, soundEvent, entity.soundSource, volume, pitch)
|
||||
}
|
||||
} else {
|
||||
Minecraft.getInstance().soundManager.play(SimpleSoundInstance.forUI(soundEvent, volume, pitch))
|
||||
Minecraft.getInstance().soundManager.play(UIEntitySoundInstance(soundEvent, volume, pitch))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -19,6 +19,7 @@ import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
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.sound.instances.AlphaCrySoundInstance
|
||||
import com.cobblemon.mod.common.client.sound.instances.UIEntitySoundInstance
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.effectiveName
|
||||
import com.cobblemon.mod.common.util.genericRuntime
|
||||
@@ -31,7 +32,6 @@ import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.client.multiplayer.ClientLevel
|
||||
import net.minecraft.client.resources.sounds.EntityBoundSoundInstance
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.world.entity.Entity
|
||||
@@ -121,7 +121,7 @@ class BedrockSoundKeyframe(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Minecraft.getInstance().soundManager.play(SimpleSoundInstance.forUI(soundEvent, 1F, 1F))
|
||||
Minecraft.getInstance().soundManager.play(UIEntitySoundInstance(soundEvent))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-98
@@ -1,98 +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.client.render.models.blockbench.pokemon.gen1
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.createTransformation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.CobblemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.ModelPartTransformation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class CaterpieModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("caterpie")
|
||||
override val head = getPart("head")
|
||||
|
||||
override var portraitScale = 2.1F
|
||||
override var portraitTranslation = Vec3(-0.55, -1.55, 0.0)
|
||||
override var profileScale = 0.8F
|
||||
override var profileTranslation = Vec3(0.0, 0.55, 0.0)
|
||||
|
||||
lateinit var sleep: Pose
|
||||
lateinit var standing: Pose
|
||||
lateinit var walk: Pose
|
||||
lateinit var shoulderLeft: CobblemonPose
|
||||
lateinit var shoulderRight: CobblemonPose
|
||||
|
||||
val shoulderOffset = 3
|
||||
|
||||
|
||||
override val cryAnimation = CryProvider { bedrockStateful("caterpie", "cry") }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk { bedrockStateful("caterpie", "blink")}
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
transformTicks = 10,
|
||||
animations = arrayOf(bedrock("caterpie", "sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = STATIONARY_POSES + UI_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("caterpie", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walking",
|
||||
poseTypes = MOVING_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("caterpie", "ground_walk")
|
||||
)
|
||||
)
|
||||
|
||||
shoulderLeft = registerPose(
|
||||
poseType = PoseType.SHOULDER_LEFT,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
bedrock("caterpie", "ground_idle")
|
||||
),
|
||||
transformedParts = arrayOf(
|
||||
rootPart.createTransformation().addPosition(ModelPartTransformation.X_AXIS, shoulderOffset)
|
||||
)
|
||||
)
|
||||
|
||||
shoulderRight = registerPose(
|
||||
poseType = PoseType.SHOULDER_RIGHT,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
bedrock("caterpie", "ground_idle")
|
||||
),
|
||||
transformedParts = arrayOf(
|
||||
rootPart.createTransformation().addPosition(ModelPartTransformation.X_AXIS, -shoulderOffset)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun getFaintAnimation(state: PosableState) = bedrockStateful("caterpie", "faint")
|
||||
}
|
||||
-98
@@ -1,98 +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.client.render.models.blockbench.pokemon.gen1
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.createTransformation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.ModelPartTransformation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class WeedleModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("weedle")
|
||||
override val head = getPart("head")
|
||||
|
||||
override var portraitScale = 2.2F
|
||||
override var portraitTranslation = Vec3(-0.31, -1.83, 0.0)
|
||||
override var profileScale = 0.8F
|
||||
override var profileTranslation = Vec3(0.1, 0.6, 0.0)
|
||||
|
||||
lateinit var sleep: Pose
|
||||
lateinit var standing: Pose
|
||||
lateinit var walk: Pose
|
||||
lateinit var shoulderLeft: Pose
|
||||
lateinit var shoulderRight: Pose
|
||||
|
||||
val shoulderOffset = 3.8
|
||||
val shoulderZOffset = -3
|
||||
|
||||
override val cryAnimation = CryProvider { bedrockStateful("weedle", "cry") }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk { bedrockStateful("weedle", "blink")}
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
animations = arrayOf(bedrock("weedle", "sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = STATIONARY_POSES + UI_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("weedle", "ground_idle2")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = MOVING_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("weedle", "ground_walk")
|
||||
)
|
||||
)
|
||||
|
||||
shoulderLeft = registerPose(
|
||||
poseType = PoseType.SHOULDER_LEFT,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
bedrock("weedle", "ground_idle")
|
||||
),
|
||||
transformedParts = arrayOf(
|
||||
rootPart.createTransformation().addPosition(ModelPartTransformation.X_AXIS, shoulderOffset),
|
||||
rootPart.createTransformation().addPosition(ModelPartTransformation.Z_AXIS, shoulderZOffset)
|
||||
)
|
||||
)
|
||||
|
||||
shoulderRight = registerPose(
|
||||
poseType = PoseType.SHOULDER_RIGHT,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
bedrock("weedle", "ground_idle")
|
||||
),
|
||||
transformedParts = arrayOf(
|
||||
rootPart.createTransformation().addPosition(ModelPartTransformation.X_AXIS, -shoulderOffset),
|
||||
rootPart.createTransformation().addPosition(ModelPartTransformation.Z_AXIS, shoulderZOffset)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun getFaintAnimation(state: PosableState) = bedrockStateful("weedle", "faint")
|
||||
}
|
||||
+3
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonP
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
@@ -28,6 +29,8 @@ class MasquerainModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame
|
||||
lateinit var walk: Pose
|
||||
lateinit var standing: Pose
|
||||
override fun registerPoses() {
|
||||
animations["cry"] = "q.bedrock_stateful('masquerain', 'cry')".asExpressionLike()
|
||||
|
||||
val blink = quirk { bedrockStateful("masquerain", "blink") }
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
|
||||
+3
@@ -14,6 +14,7 @@ import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonP
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.ModelPartTransformation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.isInWater
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
@@ -36,6 +37,8 @@ class SurskitModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
|
||||
val wateroffset = -8
|
||||
|
||||
override fun registerPoses() {
|
||||
animations["cry"] = "q.bedrock_stateful('surskit', 'cry')".asExpressionLike()
|
||||
|
||||
val blink = quirk { bedrockStateful("surskit", "blink") }
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
|
||||
+3
@@ -14,6 +14,7 @@ import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonP
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.ModelPartTransformation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
@@ -36,6 +37,8 @@ class CombeeModel (root: ModelPart) : PokemonPosableModel(root) {
|
||||
val shoulderZOffset = 8
|
||||
|
||||
override fun registerPoses() {
|
||||
animations["cry"] = "q.bedrock_stateful('combee', 'cry')".asExpressionLike()
|
||||
|
||||
val blink1 = quirk { bedrockStateful("combee", "blink_right") }
|
||||
val blink2 = quirk { bedrockStateful("combee", "blink_gender") }
|
||||
val blink3 = quirk { bedrockStateful("combee", "blink_left") }
|
||||
|
||||
+3
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonP
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
@@ -30,6 +31,8 @@ class VespiquenModel (root: ModelPart) : PokemonPosableModel(root) {
|
||||
lateinit var standing: Pose
|
||||
|
||||
override fun registerPoses() {
|
||||
animations["cry"] = "q.bedrock_stateful('vespiquen', 'cry')".asExpressionLike()
|
||||
|
||||
val blink1 = quirk { bedrockStateful("vespiquen", "blink") }
|
||||
val wingsleep = quirk { bedrockStateful("vespiquen", "sleep_flap") }
|
||||
|
||||
|
||||
-59
@@ -1,59 +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.client.render.models.blockbench.pokemon.gen5
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.CobblemonPose
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class JellicentModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("jellicent")
|
||||
override val head = getPart("head")
|
||||
|
||||
override var portraitScale = 1.13F
|
||||
override var portraitTranslation = Vec3(-0.56, 1.64, 0.0)
|
||||
|
||||
override var profileScale = 0.51F
|
||||
override var profileTranslation = Vec3(0.0, 1.05, 0.0)
|
||||
|
||||
lateinit var standing: CobblemonPose
|
||||
lateinit var walk: CobblemonPose
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk { bedrockStateful("jellicent", "blink") }
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("jellicent", "render")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("jellicent", "render")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PosableState<PokemonEntity>
|
||||
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("jellicent", "faint") else null
|
||||
}
|
||||
-62
@@ -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.client.render.models.blockbench.pokemon.gen5
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class SerperiorModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("serperior")
|
||||
override val head = getPart("head_ai")
|
||||
|
||||
override var portraitScale = 2.5F
|
||||
override var portraitTranslation = Vec3(-0.3, 1.25, 0.0)
|
||||
|
||||
override var profileScale = 0.6F
|
||||
override var profileTranslation = Vec3(0.0, 0.8, 0.0)
|
||||
|
||||
lateinit var standing: Pose
|
||||
lateinit var walk: Pose
|
||||
lateinit var sleep: Pose
|
||||
|
||||
override val cryAnimation = CryProvider { bedrockStateful("serperior", "cry") }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk { bedrockStateful("serperior", "blink") }
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
animations = arrayOf(bedrock("serperior", "sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("serperior", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("serperior", "ground_walk")
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
-70
@@ -1,70 +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.client.render.models.blockbench.pokemon.gen5
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BimanualFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class ServineModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame, BipedFrame, BimanualFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("servine")
|
||||
override val head = getPart("head_ai")
|
||||
override val rightArm = getPart("arm_right")
|
||||
override val leftArm = getPart("arm_left")
|
||||
override val rightLeg = getPart("leg_right")
|
||||
override val leftLeg = getPart("leg_left")
|
||||
|
||||
override var portraitScale = 2.6F
|
||||
override var portraitTranslation = Vec3(-0.15, 0.75, 0.0)
|
||||
override var profileScale = 0.8F
|
||||
override var profileTranslation = Vec3(0.0, 0.55, 0.0)
|
||||
|
||||
lateinit var sleep: Pose
|
||||
lateinit var standing: Pose
|
||||
lateinit var walk: Pose
|
||||
|
||||
override val cryAnimation = CryProvider { bedrockStateful("servine", "cry") }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk { bedrockStateful("servine", "blink") }
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
transformTicks = 10,
|
||||
animations = arrayOf(bedrock("servine", "sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("servine", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walking",
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("servine", "ground_walk")
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
-70
@@ -1,70 +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.client.render.models.blockbench.pokemon.gen5
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BimanualFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class SnivyModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame, BipedFrame, BimanualFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("snivy")
|
||||
override val head = getPart("head_ai")
|
||||
override val rightArm = getPart("arm_right")
|
||||
override val leftArm = getPart("arm_left")
|
||||
override val rightLeg = getPart("leg_right")
|
||||
override val leftLeg = getPart("leg_left")
|
||||
|
||||
override var portraitScale = 2.0F
|
||||
override var portraitTranslation = Vec3(-0.15, 0.32, 0.0)
|
||||
override var profileScale = 0.8F
|
||||
override var profileTranslation = Vec3(0.0, 0.55, 0.0)
|
||||
|
||||
lateinit var sleep: Pose
|
||||
lateinit var standing: Pose
|
||||
lateinit var walk: Pose
|
||||
|
||||
override val cryAnimation = CryProvider { bedrockStateful("snivy", "cry") }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk { bedrockStateful("snivy", "blink") }
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
transformTicks = 10,
|
||||
animations = arrayOf(bedrock("snivy", "sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("snivy", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walking",
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("snivy", "ground_walk")
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
-85
@@ -1,85 +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.client.render.models.blockbench.pokemon.gen6
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class GourgeistModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("gourgeist")
|
||||
override val head = getPart("head")
|
||||
|
||||
override var portraitScale = 4.0F
|
||||
override var portraitTranslation = Vec3(-0.1, 0.6, 0.0)
|
||||
|
||||
override var profileScale = 0.8F
|
||||
override var profileTranslation = Vec3(0.0, 0.55, 0.0)
|
||||
|
||||
lateinit var standing: Pose
|
||||
lateinit var walk: Pose
|
||||
lateinit var hovering: Pose
|
||||
lateinit var fly: Pose
|
||||
lateinit var sleep: Pose
|
||||
|
||||
override val cryAnimation = CryProvider { bedrockStateful("gourgeist", "cry") }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk { bedrockStateful("gourgeist", "blink") }
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = PoseType.UI_POSES + PoseType.STAND,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("gourgeist", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseType = PoseType.WALK,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
bedrock("gourgeist", "ground_walk")
|
||||
)
|
||||
)
|
||||
|
||||
hovering = registerPose(
|
||||
poseName = "hovering",
|
||||
poseType = PoseType.HOVER,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
bedrock("gourgeist", "air_idle")
|
||||
)
|
||||
)
|
||||
|
||||
fly = registerPose(
|
||||
poseName = "fly",
|
||||
poseType = PoseType.FLY,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
bedrock("gourgeist", "air_fly")
|
||||
)
|
||||
)
|
||||
|
||||
sleep = registerPose(
|
||||
poseName = "sleep",
|
||||
poseType = PoseType.SLEEP,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
bedrock("gourgeist", "sleep")
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
-77
@@ -1,77 +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.client.render.models.blockbench.pokemon.gen6
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.CobblemonPose
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class PumpkabooModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("pumpkaboo")
|
||||
override val head = getPart("head")
|
||||
|
||||
override var portraitScale = 3.5F
|
||||
override var portraitTranslation = Vec3(0.0, -1.5, 0.0)
|
||||
|
||||
override var profileScale = 1.0F
|
||||
override var profileTranslation = Vec3(0.0, 0.25, 0.0)
|
||||
|
||||
lateinit var standing: CobblemonPose
|
||||
lateinit var walk: CobblemonPose
|
||||
lateinit var battleidle: CobblemonPose
|
||||
lateinit var sleep: CobblemonPose
|
||||
|
||||
override val cryAnimation = CryProvider { bedrockStateful("pumpkaboo", "cry") }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk { bedrockStateful("pumpkaboo", "blink") }
|
||||
val quirk = quirk { bedrockStateful("pumpkaboo", "quirk_idle") }
|
||||
|
||||
sleep = registerPose(
|
||||
poseName = "sleep",
|
||||
poseType = PoseType.SLEEP,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
bedrock("pumpkaboo", "sleep")
|
||||
)
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
quirks = arrayOf(blink, quirk),
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("pumpkaboo", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
bedrock("pumpkaboo", "ground_walk")
|
||||
)
|
||||
)
|
||||
|
||||
battleidle = registerPose(
|
||||
poseName = "battleidle",
|
||||
poseTypes = PoseType.STATIONARY_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
bedrock("pumpkaboo", "battle_idle")
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
-57
@@ -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.client.render.models.blockbench.pokemon.gen7
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class CrabominableModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("crabominable")
|
||||
override val head = getPart("head")
|
||||
|
||||
override var portraitScale = 1.0F
|
||||
override var portraitTranslation = Vec3(-0.55, 1.65, 0.0)
|
||||
|
||||
override var profileScale = 0.3F
|
||||
override var profileTranslation = Vec3(0.0, 1.2, 0.0)
|
||||
|
||||
lateinit var standing: Pose
|
||||
lateinit var walk: Pose
|
||||
|
||||
override fun registerPoses() {
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = PoseType.STATIONARY_POSES + UI_POSES,
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("crabominable", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("crabominable", "ground_idle"),
|
||||
bedrock("crabominable", "ground_walk")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PosableState<PokemonEntity>
|
||||
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("crabominable", "faint") else null
|
||||
}
|
||||
-9
@@ -220,10 +220,8 @@ object VaryingModelRepository {
|
||||
|
||||
inbuilt("squirtle", ::SquirtleModel)
|
||||
inbuilt("wartortle", ::WartortleModel)
|
||||
inbuilt("caterpie", ::CaterpieModel)
|
||||
inbuilt("metapod", ::MetapodModel)
|
||||
inbuilt("butterfree", ::ButterfreeModel)
|
||||
inbuilt("weedle", ::WeedleModel)
|
||||
inbuilt("beedrill", ::BeedrillModel)
|
||||
inbuilt("raticate", ::RaticateModel)
|
||||
inbuilt("raticate_alolan", ::RaticateAlolanModel)
|
||||
@@ -324,8 +322,6 @@ object VaryingModelRepository {
|
||||
inbuilt("loudred", :: LoudredModel)
|
||||
inbuilt("exploud", :: ExploudModel)
|
||||
inbuilt("cryogonal", :: CryogonalModel)
|
||||
inbuilt("pumpkaboo", :: PumpkabooModel)
|
||||
inbuilt("gourgeist", :: GourgeistModel)
|
||||
inbuilt("eiscue", :: EiscueModel)
|
||||
inbuilt("wooloo", :: WoolooModel)
|
||||
inbuilt("dubwool", :: DubwoolModel)
|
||||
@@ -342,9 +338,6 @@ object VaryingModelRepository {
|
||||
inbuilt("thwackey", ::ThwackeyModel)
|
||||
inbuilt("rillaboom", ::RillaboomModel)
|
||||
inbuilt("samurott", ::SamurottModel)
|
||||
inbuilt("snivy", ::SnivyModel)
|
||||
inbuilt("servine", ::ServineModel)
|
||||
inbuilt("serperior", ::SerperiorModel)
|
||||
inbuilt("slugma", ::SlugmaModel)
|
||||
inbuilt("magcargo", ::MagcargoModel)
|
||||
inbuilt("slugma_shiny", ::SlugmaShinyModel)
|
||||
@@ -446,7 +439,6 @@ object VaryingModelRepository {
|
||||
inbuilt("bayleef", ::BayleefModel)
|
||||
inbuilt("meganium", ::MeganiumModel)
|
||||
inbuilt("crabrawler", ::CrabrawlerModel)
|
||||
inbuilt("crabominable", ::CrabominableModel)
|
||||
inbuilt("wimpod", ::WimpodModel)
|
||||
inbuilt("golisopod", ::GolisopodModel)
|
||||
inbuilt("ralts", ::RaltsModel)
|
||||
@@ -502,7 +494,6 @@ object VaryingModelRepository {
|
||||
inbuilt("woobat", ::WoobatModel)
|
||||
inbuilt("swoobat", ::SwoobatModel)
|
||||
inbuilt("frillish", ::FrillishModel)
|
||||
inbuilt("jellicent", ::JellicentModel)
|
||||
inbuilt("cubchoo", ::CubchooModel)
|
||||
inbuilt("beartic", ::BearticModel)
|
||||
inbuilt("dreepy", ::DreepyModel)
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.sound.instances
|
||||
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.client.resources.sounds.SoundInstance
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.sounds.SoundSource
|
||||
|
||||
/**
|
||||
* Plays a sound for a Pokémon rendered in a GUI, where there is no entity to take the sound source from.
|
||||
* Unlike [SimpleSoundInstance.forUI] this uses [SoundSource.NEUTRAL] so the Friendly Creatures slider applies.
|
||||
*/
|
||||
class UIEntitySoundInstance(sound: SoundEvent, volume: Float = 1F, pitch: Float = 1F) :
|
||||
SimpleSoundInstance(sound.location, SoundSource.NEUTRAL, volume, pitch, SoundInstance.createUnseededRandom(),
|
||||
false, 0, SoundInstance.Attenuation.NONE, 0.0, 0.0, 0.0, true)
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.command
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.permission.CobblemonPermissions
|
||||
import com.cobblemon.mod.common.api.storage.pc.link.PCLinkManager
|
||||
import com.cobblemon.mod.common.api.storage.pc.link.PermissiblePcLink
|
||||
@@ -54,8 +53,8 @@ object PcCommand {
|
||||
throw SimpleCommandExceptionType(lang("command.pc.invalid-box", box, pc.boxes.size).red()).create()
|
||||
}
|
||||
PCLinkManager.addLink(PermissiblePcLink(pc, player, CobblemonPermissions.PC))
|
||||
OpenPCPacket(pc, box = if (box != null) (box - 1) else null).sendToPlayer(player)
|
||||
OpenPCPacket(pc, box = if (box != null) (box - 1) else null, silent = true).sendToPlayer(player)
|
||||
return Command.SINGLE_SUCCESS
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,6 +164,9 @@ class CobblemonConfig {
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "experience_multiplier", SERVER)
|
||||
var experienceMultiplier = 2F
|
||||
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "predation_chance", SERVER)
|
||||
var predationChance = 0.05F
|
||||
|
||||
@CobblemonConfigField(Category.Spawning, lang = "pokemon_per_chunk", SERVER)
|
||||
var pokemonPerChunk = 1F
|
||||
|
||||
|
||||
@@ -269,6 +269,7 @@ class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragMod
|
||||
attemptCatch(pokemonEntity)
|
||||
},
|
||||
ifCanceled = {
|
||||
captureFuture.complete(false)
|
||||
drop()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1294,16 +1294,7 @@ open class PokemonEntity(
|
||||
}
|
||||
|
||||
private fun showInteractionWheel(player: ServerPlayer, itemStack: ItemStack) {
|
||||
val canRide = ifRidingAvailableSupply(false) { behaviour, settings, state ->
|
||||
if (platform != PlatformType.NONE) return@ifRidingAvailableSupply false
|
||||
if (tethering != null) return@ifRidingAvailableSupply false;
|
||||
if (seats.isEmpty()) return@ifRidingAvailableSupply false;
|
||||
if ((owner as? ServerPlayer)?.isInBattle() == true) return@ifRidingAvailableSupply false;
|
||||
if (this.owner != player && this.passengers.isEmpty()) return@ifRidingAvailableSupply false;
|
||||
if(pokemon.effectiveScale < Cobblemon.config.minimumRidingScale) return@ifRidingAvailableSupply false;
|
||||
if(beamMode == 3) return@ifRidingAvailableSupply false;
|
||||
return@ifRidingAvailableSupply behaviour.isActive(settings, state, this);
|
||||
}
|
||||
val canRide = isRideableFor(player)
|
||||
if (pokemon.getOwnerPlayer() == player) {
|
||||
val cosmeticItemDefinition = CobblemonCosmeticItems.findValidCosmeticForPokemonAndItem(
|
||||
player.level().registryAccess(),
|
||||
@@ -1325,6 +1316,18 @@ open class PokemonEntity(
|
||||
}
|
||||
}
|
||||
|
||||
fun isRideableFor(player: ServerPlayer): Boolean = ifRidingAvailableSupply(false) canRide@{ behaviour, settings, state ->
|
||||
if (!player.canInteractWithEntity(this, player.entityInteractionRange())) return@canRide false
|
||||
if (platform != PlatformType.NONE) return@canRide false
|
||||
if (tethering != null) return@canRide false
|
||||
if (seats.isEmpty()) return@canRide false
|
||||
if ((owner as? ServerPlayer)?.isInBattle() == true) return@canRide false
|
||||
if (this.owner != player && this.passengers.isEmpty()) return@canRide false
|
||||
if (pokemon.effectiveScale < Cobblemon.config.minimumRidingScale) return@canRide false
|
||||
if (beamMode == 3) return@canRide false
|
||||
return@canRide behaviour.isActive(settings, state, this)
|
||||
}
|
||||
|
||||
override fun getDimensions(pose: Pose): EntityDimensions {
|
||||
val scale = effects.mockEffect?.scale ?: (form.baseScale * pokemon.effectiveScale)
|
||||
var result = this.exposedForm.hitbox.scale(scale)
|
||||
@@ -1606,9 +1609,8 @@ open class PokemonEntity(
|
||||
|| stack.`is`(CobblemonItemTags.WHITELISTED_ITEMS_TO_HOLD)
|
||||
|
||||
fun tryRidingPokemon(player: ServerPlayer): Boolean {
|
||||
if (pokemon.effectiveScale < Cobblemon.config.minimumRidingScale) {
|
||||
return false
|
||||
}
|
||||
if (!isRideableFor(player)) return false
|
||||
|
||||
val event = RidePokemonEvent.Pre(player, this)
|
||||
CobblemonEvents.RIDE_EVENT_PRE.post(event)
|
||||
if (!event.isCanceled) {
|
||||
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.net.messages.client.data
|
||||
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.CobblemonBiomeDexEvolutionRequirementDisplay
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.CobblemonDexEvolutionRequirementDisplay
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.DexEntries
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.DexEvolutionDisplay
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.DexEvolutionRequirementDisplay
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readIdentifier
|
||||
import com.cobblemon.mod.common.util.readNullable
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.readText
|
||||
import com.cobblemon.mod.common.util.writeIdentifier
|
||||
import com.cobblemon.mod.common.util.writeNullable
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import com.cobblemon.mod.common.util.writeText
|
||||
import com.google.common.collect.Lists
|
||||
import com.google.common.collect.Sets
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.util.ExtraCodecs
|
||||
|
||||
class DexEvolutionDisplaySyncPacket(entries: MutableList<DexEvolutionDisplay>)
|
||||
: DataRegistrySyncPacket<DexEvolutionDisplay, DexEvolutionDisplaySyncPacket>(entries) {
|
||||
|
||||
override val id = ID
|
||||
|
||||
override fun encodeEntry(buffer: RegistryFriendlyByteBuf, entry: DexEvolutionDisplay) {
|
||||
buffer.writeIdentifier(entry.fromSpecies)
|
||||
buffer.writeString(entry.fromForm)
|
||||
buffer.writeCollection(entry.fromAspects) { _, aspect -> buffer.writeString(aspect) }
|
||||
buffer.writeIdentifier(entry.toSpecies)
|
||||
buffer.writeString(entry.toForm)
|
||||
buffer.writeCollection(entry.toAspects) { _, aspect -> buffer.writeString(aspect) }
|
||||
buffer.writeCollection(entry.requirements) { _, req ->
|
||||
when (req) {
|
||||
is CobblemonBiomeDexEvolutionRequirementDisplay -> {
|
||||
buffer.writeByte(1)
|
||||
buffer.writeIdentifier(BuiltInRegistries.ITEM.getKey(req.icon))
|
||||
buffer.writeText(req.tooltip)
|
||||
buffer.writeNullable(req.condition) { b, cond ->
|
||||
b.writeIdentifier(cond.id)
|
||||
b.writeBoolean(cond.tag)
|
||||
}
|
||||
buffer.writeNullable(req.antiCondition) { b, cond ->
|
||||
b.writeIdentifier(cond.id)
|
||||
b.writeBoolean(cond.tag)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
buffer.writeByte(0)
|
||||
buffer.writeIdentifier(BuiltInRegistries.ITEM.getKey(req.icon))
|
||||
buffer.writeText(req.tooltip)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun decodeEntry(buffer: RegistryFriendlyByteBuf): DexEvolutionDisplay? {
|
||||
val fromSpecies = buffer.readIdentifier()
|
||||
val fromForm = buffer.readString()
|
||||
val fromAspects = buffer.readCollection(Sets::newHashSetWithExpectedSize) { buffer.readString() }
|
||||
val toSpecies = buffer.readIdentifier()
|
||||
val toForm = buffer.readString()
|
||||
val toAspects = buffer.readCollection(Sets::newHashSetWithExpectedSize) { buffer.readString() }
|
||||
val requirements = buffer.readCollection(Lists::newArrayListWithExpectedSize) {
|
||||
val type = buffer.readByte().toInt()
|
||||
val icon = BuiltInRegistries.ITEM.get(buffer.readIdentifier())
|
||||
val tooltip = buffer.readText().copy()
|
||||
if (type == 1) {
|
||||
val condition = buffer.readNullable { b ->
|
||||
val id = b.readIdentifier()
|
||||
val tag = b.readBoolean()
|
||||
ExtraCodecs.TagOrElementLocation(id, tag)
|
||||
}
|
||||
val antiCondition = buffer.readNullable { b ->
|
||||
val id = b.readIdentifier()
|
||||
val tag = b.readBoolean()
|
||||
ExtraCodecs.TagOrElementLocation(id, tag)
|
||||
}
|
||||
CobblemonBiomeDexEvolutionRequirementDisplay(icon, tooltip, condition, antiCondition)
|
||||
} else {
|
||||
CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
}.toList()
|
||||
return DexEvolutionDisplay(fromSpecies, fromForm, fromAspects, toSpecies, toForm, toAspects, requirements)
|
||||
}
|
||||
|
||||
override fun synchronizeDecoded(entries: Collection<DexEvolutionDisplay>) {
|
||||
DexEntries.evolutionDisplays.clear()
|
||||
DexEntries.evolutionDisplays.addAll(entries)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("dex_evolution_display_sync")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): DexEvolutionDisplaySyncPacket =
|
||||
DexEvolutionDisplaySyncPacket(mutableListOf()).apply { decodeBuffer(buffer) }
|
||||
}
|
||||
}
|
||||
-100
@@ -1,100 +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.net.messages.client.data
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.PreEvolution
|
||||
import com.cobblemon.mod.common.pokemon.FormData
|
||||
import com.cobblemon.mod.common.pokemon.Species
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readIdentifier
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeIdentifier
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
/**
|
||||
* Carries the evolutions/preEvolution of every [Species] (and any [FormData] overrides), sent right after
|
||||
* [SpeciesRegistrySyncPacket] so that every species is already registered by the time this is decoded. This avoids
|
||||
* the cross-species lookup ordering hazards that come with resolving evolutions during the species sync itself.
|
||||
*/
|
||||
class SpeciesEvolutionSyncPacket(entries: Collection<SpeciesEvolutionEntry>) : DataRegistrySyncPacket<SpeciesEvolutionEntry, SpeciesEvolutionSyncPacket>(entries) {
|
||||
|
||||
override val id = ID
|
||||
|
||||
override fun encodeEntry(buffer: RegistryFriendlyByteBuf, entry: SpeciesEvolutionEntry) {
|
||||
try {
|
||||
buffer.writeIdentifier(entry.speciesIdentifier)
|
||||
buffer.writeString(PokemonSpecies.gson.toJson(entry.evolutions, EVOLUTION_SET_TYPE))
|
||||
buffer.writeNullable(entry.preEvolution) { _, preEvolution -> buffer.writeString(PokemonSpecies.gson.toJson(preEvolution, PreEvolution::class.java)) }
|
||||
buffer.writeCollection(entry.formOverrides) { _, override ->
|
||||
buffer.writeString(override.formName)
|
||||
buffer.writeNullable(override.evolutions) { _, evolutions -> buffer.writeString(PokemonSpecies.gson.toJson(evolutions, EVOLUTION_SET_TYPE)) }
|
||||
buffer.writeNullable(override.preEvolution) { _, preEvolution -> buffer.writeString(PokemonSpecies.gson.toJson(preEvolution, PreEvolution::class.java)) }
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Cobblemon.LOGGER.error("Caught exception encoding evolution data for species {}", entry.speciesIdentifier, e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun decodeEntry(buffer: RegistryFriendlyByteBuf): SpeciesEvolutionEntry? {
|
||||
val identifier = buffer.readIdentifier()
|
||||
return try {
|
||||
val evolutions: MutableSet<Evolution> = PokemonSpecies.gson.fromJson(buffer.readString(), EVOLUTION_SET_TYPE)
|
||||
val preEvolution = buffer.readNullable { _ -> PokemonSpecies.gson.fromJson(buffer.readString(), PreEvolution::class.java) }
|
||||
val formOverrides = buffer.readList { _ ->
|
||||
val formName = buffer.readString()
|
||||
val formEvolutions = buffer.readNullable { _ -> PokemonSpecies.gson.fromJson<MutableSet<Evolution>>(buffer.readString(), EVOLUTION_SET_TYPE) }
|
||||
val formPreEvolution = buffer.readNullable { _ -> PokemonSpecies.gson.fromJson(buffer.readString(), PreEvolution::class.java) }
|
||||
FormEvolutionOverride(formName, formEvolutions, formPreEvolution)
|
||||
}
|
||||
SpeciesEvolutionEntry(identifier, evolutions, preEvolution, formOverrides)
|
||||
} catch (e: Exception) {
|
||||
Cobblemon.LOGGER.error("Caught exception decoding evolution data for species {}", identifier, e)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun synchronizeDecoded(entries: Collection<SpeciesEvolutionEntry>) {
|
||||
entries.forEach { entry ->
|
||||
val species = PokemonSpecies.getByIdentifier(entry.speciesIdentifier)
|
||||
if (species == null) {
|
||||
Cobblemon.LOGGER.error("Received evolution data for unknown species {}", entry.speciesIdentifier)
|
||||
return@forEach
|
||||
}
|
||||
species.applyEvolutionData(entry.evolutions, entry.preEvolution)
|
||||
entry.formOverrides.forEach { override ->
|
||||
species.getFormByName(override.formName).applyEvolutionData(override.evolutions, override.preEvolution)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("species_evolution_sync")
|
||||
private val EVOLUTION_SET_TYPE = TypeToken.getParameterized(MutableSet::class.java, Evolution::class.java).type
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): SpeciesEvolutionSyncPacket = SpeciesEvolutionSyncPacket(emptyList()).apply { decodeBuffer(buffer) }
|
||||
}
|
||||
}
|
||||
|
||||
class SpeciesEvolutionEntry(
|
||||
val speciesIdentifier: ResourceLocation,
|
||||
val evolutions: MutableSet<Evolution>,
|
||||
val preEvolution: PreEvolution?,
|
||||
val formOverrides: List<FormEvolutionOverride>
|
||||
)
|
||||
|
||||
class FormEvolutionOverride(
|
||||
val formName: String,
|
||||
val evolutions: MutableSet<Evolution>?,
|
||||
val preEvolution: PreEvolution?
|
||||
)
|
||||
+8
-4
@@ -34,17 +34,19 @@ class OpenPCPacket : NetworkPacket<OpenPCPacket> {
|
||||
val storeID: UUID
|
||||
val box: Int?
|
||||
val unseenWallpapers: Set<ResourceLocation>
|
||||
val silent: Boolean
|
||||
|
||||
@JvmOverloads
|
||||
@Deprecated("Use the constructor with the PCStore object instead, this will become private in a future title update", level = DeprecationLevel.WARNING)
|
||||
constructor(storeID: UUID, box: Int? = null, unseenWallpapers: Set<ResourceLocation> = emptySet()) {
|
||||
constructor(storeID: UUID, box: Int? = null, unseenWallpapers: Set<ResourceLocation> = emptySet(), silent: Boolean? = false) {
|
||||
this.storeID = storeID
|
||||
this.box = box
|
||||
this.unseenWallpapers = unseenWallpapers
|
||||
this.silent = silent ?: false
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
constructor(pc: PCStore, box: Int? = null): this(pc.uuid, box, pc.unseenWallpapers)
|
||||
constructor(pc: PCStore, box: Int? = null, silent: Boolean? = false): this(pc.uuid, box, pc.unseenWallpapers, silent ?: false)
|
||||
|
||||
override val id = ID
|
||||
|
||||
@@ -52,6 +54,7 @@ class OpenPCPacket : NetworkPacket<OpenPCPacket> {
|
||||
buffer.writeUUID(storeID)
|
||||
buffer.writeNullable(box) { buf, value -> buf.writeInt(value)}
|
||||
buffer.writeCollection(unseenWallpapers) { _, it -> buffer.writeResourceLocation(it) }
|
||||
buffer.writeBoolean(silent)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -59,7 +62,8 @@ class OpenPCPacket : NetworkPacket<OpenPCPacket> {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = OpenPCPacket(
|
||||
buffer.readUUID(),
|
||||
buffer.readNullable { it.readInt() },
|
||||
buffer.readList { buffer.readResourceLocation() }.toSet()
|
||||
buffer.readList { buffer.readResourceLocation() }.toSet(),
|
||||
buffer.readBoolean()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,8 @@ object PlatformEvents {
|
||||
@JvmField
|
||||
val CLIENT_PLAYER_LOGOUT = EventObservable<ClientPlayerEvent.Logout>()
|
||||
@JvmField
|
||||
val PLAYER_RESPAWN = EventObservable<ServerPlayerEvent.Respawn>()
|
||||
@JvmField
|
||||
val PLAYER_DEATH = CancelableObservable<ServerPlayerEvent.Death>()
|
||||
@JvmField
|
||||
val RIGHT_CLICK_BLOCK = CancelableObservable<ServerPlayerEvent.RightClickBlock>()
|
||||
|
||||
@@ -50,6 +50,11 @@ interface ServerPlayerEvent {
|
||||
*/
|
||||
data class Logout(override val player: ServerPlayer) : ServerPlayerEvent
|
||||
|
||||
/**
|
||||
* Fired when the [player] respawns (either by coming back from the end or dying).
|
||||
*/
|
||||
data class Respawn(override val player: ServerPlayer) : ServerPlayerEvent
|
||||
|
||||
/**
|
||||
* Fired when the [player] dies.
|
||||
* If canceled the death will be prevented but healing is required in order to not be stuck in a loop.
|
||||
|
||||
@@ -76,7 +76,7 @@ class FormData(
|
||||
@SerializedName("moves")
|
||||
private var _moves: Learnset? = null,
|
||||
@SerializedName("evolutions")
|
||||
private var _evolutions: MutableSet<Evolution>? = null,
|
||||
private val _evolutions: MutableSet<Evolution>? = null,
|
||||
@SerializedName("abilities")
|
||||
private var _abilities: AbilityPool? = null,
|
||||
@SerializedName("drops")
|
||||
@@ -84,7 +84,7 @@ class FormData(
|
||||
@SerializedName("pokedex")
|
||||
private var _pokedex: MutableList<String>? = null,
|
||||
@SerializedName("preEvolution")
|
||||
private var _preEvolution: PreEvolution? = null,
|
||||
private val _preEvolution: PreEvolution? = null,
|
||||
private var standingEyeHeight: Float? = null,
|
||||
private var swimmingEyeHeight: Float? = null,
|
||||
private var flyingEyeHeight: Float? = null,
|
||||
@@ -269,22 +269,13 @@ class FormData(
|
||||
this.species = species
|
||||
this.behaviour.parent = species.behaviour
|
||||
Cobblemon.statProvider.provide(this)
|
||||
this._lightingData?.let { this._lightingData = it.copy(lightLevel = it.lightLevel.coerceIn(0, 15)) }
|
||||
behaviour.herd.initialize()
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies decoded evolution data onto this form, received separately via [com.cobblemon.mod.common.net.messages.client.data.SpeciesEvolutionSyncPacket]
|
||||
* after every species has already been registered.
|
||||
*/
|
||||
internal fun applyEvolutionData(evolutions: MutableSet<Evolution>?, preEvolution: PreEvolution?) {
|
||||
this._evolutions = evolutions
|
||||
this._preEvolution = preEvolution
|
||||
// These properties are lazy, force resolution now that every species is guaranteed to be registered
|
||||
// These properties are lazy, these need all species to be reloaded but SpeciesAdditions is what will eventually trigger this after all species have been loaded
|
||||
this.preEvolution?.species
|
||||
this.preEvolution?.form
|
||||
this.evolutions.size
|
||||
this._lightingData?.let { this._lightingData = it.copy(lightLevel = it.lightLevel.coerceIn(0, 15)) }
|
||||
behaviour.herd.initialize()
|
||||
return this
|
||||
}
|
||||
|
||||
internal fun resolveEvolutionMoves() {
|
||||
|
||||
@@ -181,20 +181,11 @@ class Species : ShowdownIdentifiable {
|
||||
this.forms.add(0, this.standardForm)
|
||||
}
|
||||
this.lightingData?.let { this.lightingData = it.copy(lightLevel = it.lightLevel.coerceIn(0, 15)) }
|
||||
behaviour.herd.initialize()
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies decoded evolution data onto this species, received separately via [com.cobblemon.mod.common.net.messages.client.data.SpeciesEvolutionSyncPacket]
|
||||
* after every species has already been registered.
|
||||
*/
|
||||
internal fun applyEvolutionData(evolutions: MutableSet<Evolution>, preEvolution: PreEvolution?) {
|
||||
// Mutate in place rather than reassign: standardForm may have already captured this.evolutions by reference.
|
||||
this.evolutions.clear()
|
||||
this.evolutions.addAll(evolutions)
|
||||
this.preEvolution = preEvolution
|
||||
// These properties are lazy, these need all species to be reloaded but SpeciesAdditions is what will eventually trigger this after all species have been loaded
|
||||
this.preEvolution?.species
|
||||
this.preEvolution?.form
|
||||
this.evolutions.size
|
||||
behaviour.herd.initialize()
|
||||
}
|
||||
|
||||
// Ran after initialize due to us creating a Pokémon here which requires all the properties in #initialize to be present for both this and the results, this is the easiest way to quickly resolve species + form
|
||||
|
||||
+2
-10
@@ -25,20 +25,12 @@ internal class CobblemonLazyPreEvolution(private val rawData: String) : PreEvolu
|
||||
this.properties.species?.asIdentifierDefaultingNamespace()?.let { PokemonSpecies.getByIdentifier(it) } ?: throw IllegalArgumentException("A PreEvolution needs a valid species")
|
||||
}
|
||||
|
||||
private fun computeForm(extraAspects: Set<String>): FormData {
|
||||
val properties = this.properties
|
||||
return properties.form?.let { formId -> this.species.forms.firstOrNull { it.formOnlyShowdownId().equals(formId, true) } }
|
||||
?: this.species.getForm(properties.aspects + this.rawData.split(" ").map { it.lowercase() }.toSet() + extraAspects)
|
||||
private val lazyForm: FormData by lazy {
|
||||
this.properties.form?.let { formId -> this.species.forms.firstOrNull { it.formOnlyShowdownId().equals(formId, true) } } ?: this.species.standardForm
|
||||
}
|
||||
|
||||
private val lazyForm: FormData by lazy { computeForm(emptySet()) }
|
||||
|
||||
override val species: Species
|
||||
get() = this.lazySpecies
|
||||
override val form: FormData
|
||||
get() = this.lazyForm
|
||||
|
||||
override fun resolveForm(extraAspects: Set<String>): FormData {
|
||||
return if (extraAspects.isEmpty()) this.form else computeForm(extraAspects)
|
||||
}
|
||||
}
|
||||
|
||||
+12
-6
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.api.abilities.Abilities
|
||||
import com.cobblemon.mod.common.api.data.DataRegistry
|
||||
import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.api.pokemon.Natures
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.AbstractChoiceSpeciesFeatureProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
import com.cobblemon.mod.common.api.properties.CustomPokemonProperty
|
||||
@@ -134,17 +135,18 @@ internal object PropertiesCompletionProvider : DataRegistry {
|
||||
private fun addDefaults() {
|
||||
this.inject(setOf("level", "lvl", "l"), setOf("1", "${Cobblemon.config.maxPokemonLevel}") )
|
||||
this.inject(setOf("shiny", "s"), setOf("yes", "no"))
|
||||
this.inject(setOf("gender"), Gender.values().map { it.name.lowercase() })
|
||||
this.inject(setOf("alpha", "is_alpha"), setOf("yes", "no"))
|
||||
this.inject(setOf("gender"), Gender.entries.map { it.name.lowercase() })
|
||||
this.inject(setOf("friendship"), setOf("0", Cobblemon.config.maxPokemonFriendship.toString()))
|
||||
this.inject(setOf("fullness"), setOf("0", "255"))
|
||||
this.inject(setOf("pokeball"), PokeBalls.all().map { it.name.simplify() })
|
||||
this.inject(setOf("nature"), Natures.all().map { it.name.simplify() })
|
||||
this.inject(setOf("ability"), Abilities.all().map { if (it.name.asIdentifierDefaultingNamespace().namespace == Cobblemon.MODID) it.name.asIdentifierDefaultingNamespace().path else it.name })
|
||||
this.inject(setOf("dmax"), setOf("0", Cobblemon.config.maxDynamaxLevel.toString()))
|
||||
this.inject(setOf("gmax"), setOf("yes", "no"))
|
||||
this.inject(setOf("dmax_level", "dmax"), setOf("0", Cobblemon.config.maxDynamaxLevel.toString()))
|
||||
this.inject(setOf("gmax_factor", "gmax"), setOf("yes", "no"))
|
||||
this.inject(setOf("type", "elemental_type"), ElementalTypes.all().map { it.name })
|
||||
this.inject(setOf("tera_type", "tera"), TeraTypes.map { it.id.simplify() })
|
||||
this.inject(setOf("tradeable"), setOf("yes", "no"))
|
||||
this.inject(setOf("tradeable", "tradable"), setOf("yes", "no"))
|
||||
this.inject(setOf("originaltrainer", "ot"), setOf(""))
|
||||
this.inject(setOf("originaltrainertype", "ottype"), setOf("None", "Player", "NPC"))
|
||||
this.inject(setOf("nickname", "nick"), setOf(""))
|
||||
@@ -164,7 +166,11 @@ internal object PropertiesCompletionProvider : DataRegistry {
|
||||
private fun addCustom() {
|
||||
CustomPokemonProperty.properties.forEach { property ->
|
||||
// We won't tab complete properties that have no key attached to them as it would be fairly hard to determine which one to suggest
|
||||
if (property.needsKey) {
|
||||
if (property.needsKey && property !is AbstractChoiceSpeciesFeatureProvider<*>) {
|
||||
this.inject(property.keys, property.examples())
|
||||
}
|
||||
// Except choice features that fill examples with all available choices - Gito
|
||||
if (property is AbstractChoiceSpeciesFeatureProvider<*>) {
|
||||
this.inject(property.keys, property.examples())
|
||||
}
|
||||
}
|
||||
@@ -175,4 +181,4 @@ internal object PropertiesCompletionProvider : DataRegistry {
|
||||
val suggestions: Collection<String>
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,12 +12,10 @@ import com.google.gson.JsonDeserializationContext
|
||||
import com.google.gson.JsonDeserializer
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonSerializationContext
|
||||
import com.google.gson.JsonSerializer
|
||||
import java.lang.reflect.Type
|
||||
import net.minecraft.world.phys.AABB
|
||||
|
||||
object BoxAdapter : JsonDeserializer<AABB>, JsonSerializer<AABB> {
|
||||
object BoxAdapter : JsonDeserializer<AABB> {
|
||||
override fun deserialize(json: JsonElement, type: Type, ctx: JsonDeserializationContext): AABB {
|
||||
json as JsonObject
|
||||
return AABB(
|
||||
@@ -29,15 +27,4 @@ object BoxAdapter : JsonDeserializer<AABB>, JsonSerializer<AABB> {
|
||||
json.get("maxZ")?.asDouble ?: 9999999.0
|
||||
)
|
||||
}
|
||||
|
||||
override fun serialize(src: AABB, typeOfSrc: Type, ctx: JsonSerializationContext): JsonElement {
|
||||
val json = JsonObject()
|
||||
json.addProperty("minX", src.minX)
|
||||
json.addProperty("minY", src.minY)
|
||||
json.addProperty("minZ", src.minZ)
|
||||
json.addProperty("maxX", src.maxX)
|
||||
json.addProperty("maxY", src.maxY)
|
||||
json.addProperty("maxZ", src.maxZ)
|
||||
return json
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,6 @@ import com.google.gson.JsonDeserializationContext
|
||||
import com.google.gson.JsonDeserializer
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonSerializationContext
|
||||
import com.google.gson.JsonSerializer
|
||||
import java.lang.reflect.Type
|
||||
|
||||
/**
|
||||
@@ -24,7 +22,7 @@ import java.lang.reflect.Type
|
||||
* @author Hiroku
|
||||
* @since July 24th, 2022
|
||||
*/
|
||||
object DropEntryAdapter : JsonDeserializer<DropEntry>, JsonSerializer<DropEntry> {
|
||||
object DropEntryAdapter : JsonDeserializer<DropEntry> {
|
||||
override fun deserialize(json: JsonElement, type: Type, ctx: JsonDeserializationContext): DropEntry {
|
||||
json as JsonObject
|
||||
val entryClass = json.get("type")?.asString
|
||||
@@ -32,12 +30,4 @@ object DropEntryAdapter : JsonDeserializer<DropEntry>, JsonSerializer<DropEntry>
|
||||
?: DropEntry.defaultType
|
||||
return ctx.deserialize(json, entryClass)
|
||||
}
|
||||
|
||||
override fun serialize(src: DropEntry, typeOfSrc: Type, ctx: JsonSerializationContext): JsonElement {
|
||||
val json = ctx.serialize(src, src::class.java).asJsonObject
|
||||
val name = DropEntry.entryTypes.entries.find { it.value == src::class.java }?.key
|
||||
?: throw IllegalArgumentException("Cannot resolve drop entry type for ${src::class.qualifiedName}")
|
||||
json.addProperty("type", name)
|
||||
return json
|
||||
}
|
||||
}
|
||||
@@ -10,21 +10,13 @@ package com.cobblemon.mod.common.util.adapters
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.MoLang
|
||||
import com.cobblemon.mod.common.util.getString
|
||||
import com.google.gson.JsonDeserializationContext
|
||||
import com.google.gson.JsonDeserializer
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonPrimitive
|
||||
import com.google.gson.JsonSerializationContext
|
||||
import com.google.gson.JsonSerializer
|
||||
import java.lang.reflect.Type
|
||||
|
||||
object ExpressionAdapter : JsonDeserializer<Expression>, JsonSerializer<Expression> {
|
||||
object ExpressionAdapter : JsonDeserializer<Expression> {
|
||||
override fun deserialize(json: JsonElement, typeOfT: Type, ctx: JsonDeserializationContext): Expression {
|
||||
return MoLang.createParser(json.asString).parseExpression()
|
||||
}
|
||||
|
||||
override fun serialize(src: Expression, typeOfSrc: Type, ctx: JsonSerializationContext): JsonElement {
|
||||
return JsonPrimitive(src.getString())
|
||||
}
|
||||
}
|
||||
+1
-8
@@ -13,9 +13,6 @@ import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.google.gson.JsonDeserializationContext
|
||||
import com.google.gson.JsonDeserializer
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonPrimitive
|
||||
import com.google.gson.JsonSerializationContext
|
||||
import com.google.gson.JsonSerializer
|
||||
import java.lang.reflect.Type
|
||||
|
||||
/**
|
||||
@@ -25,7 +22,7 @@ import java.lang.reflect.Type
|
||||
* @author Hiroku
|
||||
* @since October 22nd, 2023
|
||||
*/
|
||||
object ExpressionLikeAdapter : JsonDeserializer<ExpressionLike>, JsonSerializer<ExpressionLike> {
|
||||
object ExpressionLikeAdapter : JsonDeserializer<ExpressionLike> {
|
||||
override fun deserialize(json: JsonElement, type: Type, ctx: JsonDeserializationContext): ExpressionLike {
|
||||
return if (json.isJsonPrimitive) {
|
||||
json.asString.asExpressionLike()
|
||||
@@ -35,8 +32,4 @@ object ExpressionLikeAdapter : JsonDeserializer<ExpressionLike>, JsonSerializer<
|
||||
throw IllegalArgumentException("Invalid expression JSON: $json")
|
||||
}
|
||||
}
|
||||
|
||||
override fun serialize(src: ExpressionLike, typeOfSrc: Type, ctx: JsonSerializationContext): JsonElement {
|
||||
return JsonPrimitive(src.getString())
|
||||
}
|
||||
}
|
||||
|
||||
+5
-7
@@ -11,23 +11,22 @@ package com.cobblemon.mod.common.util.adapters
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Environment
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import com.google.gson.JsonElement
|
||||
import com.mojang.serialization.DynamicOps
|
||||
import com.mojang.serialization.JsonOps
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.core.RegistryAccess
|
||||
import net.minecraft.resources.RegistryOps
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
|
||||
/**
|
||||
* Utility for getting RegistryAccess with the correct client/server registry access.
|
||||
* Used when as a fallback when manually encoding/decoding registry-backed values (e.g., items, predicates).
|
||||
*/
|
||||
object RegistryAccessResolver {
|
||||
private val builtInAccess: RegistryAccess by lazy { RegistryAccess.fromRegistryOfRegistries(BuiltInRegistries.REGISTRY) }
|
||||
|
||||
fun getAccess(): RegistryAccess {
|
||||
try {
|
||||
Cobblemon.implementation
|
||||
} catch (e: UninitializedPropertyAccessException) {
|
||||
return RegistryAccess.EMPTY
|
||||
return builtInAccess
|
||||
}
|
||||
if (Cobblemon.implementation.environment() == Environment.CLIENT) {
|
||||
val minecraft = Minecraft.getInstance()
|
||||
@@ -35,13 +34,12 @@ object RegistryAccessResolver {
|
||||
return minecraft.level!!.registryAccess()
|
||||
}
|
||||
|
||||
|
||||
if (Cobblemon.implementation.environment() == Environment.SERVER) {
|
||||
val server = server()
|
||||
if (server != null)
|
||||
return server.registryAccess()
|
||||
}
|
||||
|
||||
return RegistryAccess.EMPTY
|
||||
return builtInAccess
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -26,5 +26,6 @@ object CobblemonGameRules {
|
||||
val SHINY_STARTERS: GameRules.Key<GameRules.BooleanValue> = Cobblemon.implementation.registerGameRule("doShinyStarters", GameRules.Category.MISC, BooleanRuleInvoker.`cobblemon$create`(false))
|
||||
@JvmField
|
||||
val HEALERS_HEAL_PC: GameRules.Key<GameRules.BooleanValue> = Cobblemon.implementation.registerGameRule("healersHealPC", GameRules.Category.MISC, BooleanRuleInvoker.`cobblemon$create`(false))
|
||||
|
||||
@JvmField
|
||||
val DO_POKEMON_PREDATION: GameRules.Key<GameRules.BooleanValue> = Cobblemon.implementation.registerGameRule("doPokemonPredation", GameRules.Category.MOBS, BooleanRuleInvoker.`cobblemon$create`(true))
|
||||
}
|
||||
+1
-1
@@ -217,7 +217,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.raichu_cap.water_swim": {
|
||||
"animation.raichu_cap.water_surface_swim": {
|
||||
"loop": true,
|
||||
"animation_length": 1,
|
||||
"bones": {
|
||||
|
||||
+8
@@ -364,6 +364,14 @@
|
||||
"rotation": [-22.5, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.wurmple.cry": {
|
||||
"animation_length": 1.25,
|
||||
"sound_effects": {
|
||||
"0.0": {
|
||||
"effect": "pokemon.wurmple.cry"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -212,6 +212,14 @@
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.silcoon.cry": {
|
||||
"animation_length": 1.25,
|
||||
"sound_effects": {
|
||||
"0.0": {
|
||||
"effect": "pokemon.silcoon.cry"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -361,6 +361,14 @@
|
||||
"rotation": [0, 20, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.beautifly.cry": {
|
||||
"animation_length": 1.25,
|
||||
"sound_effects": {
|
||||
"0.0": {
|
||||
"effect": "pokemon.beautifly.cry"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -194,6 +194,14 @@
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.cascoon.cry": {
|
||||
"animation_length": 1.25,
|
||||
"sound_effects": {
|
||||
"0.0": {
|
||||
"effect": "pokemon.cascoon.cry"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+24
@@ -255,6 +255,30 @@
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.dustox.cry": {
|
||||
"animation_length": 1,
|
||||
"bones": {
|
||||
"mouth_closed_smile": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.0833": {"pre": [0, 0, 0], "post": [0, 0, 0.1]},
|
||||
"0.625": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"mouth_open": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.0833": {"pre": [0, 0, 0], "post": [0, 0, -0.1]},
|
||||
"0.625": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sound_effects": {
|
||||
"0.0833": {
|
||||
"effect": "pokemon.dustox.cry"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -149,6 +149,14 @@
|
||||
"rotation": [0, 0, 22.5]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.surskit.cry": {
|
||||
"animation_length": 1.25,
|
||||
"sound_effects": {
|
||||
"0.0": {
|
||||
"effect": "pokemon.surskit.cry"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"geckolib_format_version": 2
|
||||
|
||||
+5
@@ -158,6 +158,11 @@
|
||||
"0.75": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"sound_effects": {
|
||||
"0.0": {
|
||||
"effect": "pokemon.masquerain.cry"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+5
@@ -447,6 +447,11 @@
|
||||
"1.5": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"sound_effects": {
|
||||
"0.0": {
|
||||
"effect": "pokemon.starly.cry"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -331,6 +331,11 @@
|
||||
"1.5": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"sound_effects": {
|
||||
"0.0": {
|
||||
"effect": "pokemon.staravia.cry"
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.staravia.blink": {
|
||||
|
||||
+5
@@ -464,6 +464,11 @@
|
||||
"1.5": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"sound_effects": {
|
||||
"0.0": {
|
||||
"effect": "pokemon.combee.cry"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -824,6 +824,14 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.vespiquen.cry": {
|
||||
"animation_length": 1.25,
|
||||
"sound_effects": {
|
||||
"0.0": {
|
||||
"effect": "pokemon.vespiquen.cry"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+2438
-11
File diff suppressed because it is too large
Load Diff
+11
-11
@@ -364,7 +364,7 @@
|
||||
"bones": {
|
||||
"body": {
|
||||
"rotation": [55, 0, 0],
|
||||
"position": [0, "-8+Math.cos((query.anim_time) * 90 * 2) * 0.2", -1]
|
||||
"position": [0, "-3+Math.cos((query.anim_time) * 90 * 2) * 0.2", -1]
|
||||
},
|
||||
"torso2": {
|
||||
"rotation": ["-12.5+Math.cos((query.anim_time-0.4) * 90 * 2) * 2", 0, 0]
|
||||
@@ -426,16 +426,16 @@
|
||||
"body": {
|
||||
"rotation": [55, 0, 0],
|
||||
"position": {
|
||||
"0.0": [0, "-9+Math.cos((query.anim_time) * 90 * (2+2/3)) * 0.2", -1.5],
|
||||
"0.25": [0, "-9+Math.cos((query.anim_time) * 90 * (2+2/3)) * 0.2", 0.5],
|
||||
"0.5": [0, "-9+Math.cos((query.anim_time) * 90 * (2+2/3)) * 0.2", 3.5],
|
||||
"0.6667": [0, "-9+Math.cos((query.anim_time) * 90 * (2+2/3)) * 0.2", 5.17],
|
||||
"0.75": [0, "-9+Math.cos((query.anim_time) * 90 * (2+2/3)) * 0.2", 5.25],
|
||||
"0.7917": [0, "-9+Math.cos((query.anim_time) * 90 * (2+2/3)) * 0.2", 3.92],
|
||||
"1.0": [0, "-9+Math.cos((query.anim_time) * 90 * (2+2/3)) * 0.2", 1],
|
||||
"1.2083": [0, "-9+Math.cos((query.anim_time) * 90 * (2+2/3)) * 0.2", -1.25],
|
||||
"1.375": [0, "-9+Math.cos((query.anim_time) * 90 * (2+2/3)) * 0.2", -1.75],
|
||||
"1.5": [0, "-9+Math.cos((query.anim_time) * 90 * (2+2/3)) * 0.2", -1.5]
|
||||
"0.0": [0, "-3+Math.cos((query.anim_time) * 90 * (2+2/3)) * 0.2", -1.5],
|
||||
"0.25": [0, "-3+Math.cos((query.anim_time) * 90 * (2+2/3)) * 0.2", 0.5],
|
||||
"0.5": [0, "-3+Math.cos((query.anim_time) * 90 * (2+2/3)) * 0.2", 3.5],
|
||||
"0.6667": [0, "-3+Math.cos((query.anim_time) * 90 * (2+2/3)) * 0.2", 5.17],
|
||||
"0.75": [0, "-3+Math.cos((query.anim_time) * 90 * (2+2/3)) * 0.2", 5.25],
|
||||
"0.7917": [0, "-3+Math.cos((query.anim_time) * 90 * (2+2/3)) * 0.2", 3.92],
|
||||
"1.0": [0, "-3+Math.cos((query.anim_time) * 90 * (2+2/3)) * 0.2", 1],
|
||||
"1.2083": [0, "-3+Math.cos((query.anim_time) * 90 * (2+2/3)) * 0.2", -1.25],
|
||||
"1.375": [0, "-3+Math.cos((query.anim_time) * 90 * (2+2/3)) * 0.2", -1.75],
|
||||
"1.5": [0, "-3+Math.cos((query.anim_time) * 90 * (2+2/3)) * 0.2", -1.5]
|
||||
}
|
||||
},
|
||||
"torso2": {
|
||||
|
||||
+3
-3
@@ -313,7 +313,7 @@
|
||||
"bones": {
|
||||
"body": {
|
||||
"rotation": [47.5, 0, 0],
|
||||
"position": [0, "-10+Math.cos((query.anim_time) * 90 * 1) * 0.3", 0]
|
||||
"position": [0, "-6+Math.cos((query.anim_time) * 90 * 1) * 0.3", 0]
|
||||
},
|
||||
"torso": {
|
||||
"rotation": [35, 0, 0],
|
||||
@@ -426,7 +426,7 @@
|
||||
"bones": {
|
||||
"body": {
|
||||
"rotation": [47.5, 0, 0],
|
||||
"position": [0, -10, "Math.cos((query.anim_time-0.5) * 90 * (2+2/3)) * 4"]
|
||||
"position": [0, -6, "Math.cos((query.anim_time-0.5) * 90 * (2+2/3)) * 4"]
|
||||
},
|
||||
"torso": {
|
||||
"rotation": [35, 0, 0],
|
||||
@@ -589,7 +589,7 @@
|
||||
"animation.frogadier.battle_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"frogadier": {
|
||||
"body": {
|
||||
"position": [0, -8, 0]
|
||||
},
|
||||
"torso": {
|
||||
|
||||
+1
-1
@@ -1925,7 +1925,7 @@
|
||||
},
|
||||
"body": {
|
||||
"rotation": ["68.5-Math.cos((query.anim_time)*360/1-20)*-3", 0, 0],
|
||||
"position": [0, "-24+Math.cos((query.anim_time)*360/1-90)*-0.5", "-1+Math.cos((query.anim_time)*360/1-45)*4"]
|
||||
"position": [0, "Math.cos((query.anim_time)*360/1-90)*-0.5", "-1+Math.cos((query.anim_time)*360/1-45)*4"]
|
||||
},
|
||||
"neck": {
|
||||
"rotation": [-7.5, 0, 0]
|
||||
|
||||
+24
@@ -400,6 +400,30 @@
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.helioptile.cry": {
|
||||
"animation_length": 1.2083,
|
||||
"bones": {
|
||||
"mouth_closed": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.0833": {"pre": [0, 0, 0], "post": [0, 0, 0.1]},
|
||||
"1.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"mouth_open": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.0833": {"pre": [0, 0, 0], "post": [0, 0, -0.1]},
|
||||
"1.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sound_effects": {
|
||||
"0.0833": {
|
||||
"effect": "pokemon.helioptile.cry"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -563,6 +563,14 @@
|
||||
"position": [0.1, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.heliolisk.cry": {
|
||||
"animation_length": 1.25,
|
||||
"sound_effects": {
|
||||
"0.0": {
|
||||
"effect": "pokemon.heliolisk.cry"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -125,6 +125,11 @@
|
||||
"0.5417": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sound_effects": {
|
||||
"0.0417": {
|
||||
"effect": "pokemon.grubbin.cry"
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.grubbin.physical": {
|
||||
|
||||
+5
@@ -38,6 +38,11 @@
|
||||
"0.625": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sound_effects": {
|
||||
"0.0833": {
|
||||
"effect": "pokemon.charjabug.cry"
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.charjabug.ditto_face": {
|
||||
|
||||
+6098
-351
File diff suppressed because it is too large
Load Diff
+8
@@ -326,6 +326,14 @@
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.runerigus.cry": {
|
||||
"animation_length": 1.25,
|
||||
"sound_effects": {
|
||||
"0.0": {
|
||||
"effect": "pokemon.runerigus.cry"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-9
@@ -96,13 +96,13 @@
|
||||
"parent": "head",
|
||||
"pivot": [0, 6, 0.25],
|
||||
"cubes": [
|
||||
{"origin": [-2.4, 4.4, -5.28], "size": [1, 1, 0], "inflate": 0.01, "pivot": [-2, 5, 0], "rotation": [0, 0, -45], "uv": [12, 19]},
|
||||
{"origin": [-1.75, 5.25, 5.76], "size": [1, 1, 0], "pivot": [-2, 5, 0], "rotation": [0, 0, -45], "uv": [8, 10]},
|
||||
{"origin": [1.25, 1.25, 5.76], "size": [1, 1, 0], "pivot": [-2, 5, 0], "rotation": [0, 0, -45], "uv": [9, 2]},
|
||||
{"origin": [-4.51, 6, -2.75], "size": [0, 1, 1], "pivot": [-2, 6.5, -2.25], "rotation": [-45, 0, 0], "uv": [7, 1]},
|
||||
{"origin": [4.51, 6.75, -2.75], "size": [0, 1, 1], "pivot": [-2, 6.5, -2.25], "rotation": [-45, 0, 0], "uv": [0, 5]},
|
||||
{"origin": [4.51, 8, 0.5], "size": [0, 1, 1], "pivot": [-2, 6.5, -2.25], "rotation": [-45, 0, 0], "uv": [0, 1]},
|
||||
{"origin": [-4.51, 6.5, 1.25], "size": [0, 1, 1], "pivot": [-2, 7, 1.75], "rotation": [-45, 0, 0], "uv": [0, 6]}
|
||||
{"origin": [-2.5, 4.4, -5.28], "size": [1, 1, 0], "uv": [12, 19]},
|
||||
{"origin": [-2.5, 5.5, 5.76], "size": [1, 1, 0], "uv": [8, 10]},
|
||||
{"origin": [2.5, 4.5, 5.76], "size": [1, 1, 0], "uv": [9, 2]},
|
||||
{"origin": [-4.51, 6, -2.75], "size": [0, 1, 1], "uv": [7, 1]},
|
||||
{"origin": [4.51, 6.5, -2.25], "size": [0, 1, 1], "uv": [0, 5]},
|
||||
{"origin": [4.51, 5, 0.75], "size": [0, 1, 1], "uv": [0, 1]},
|
||||
{"origin": [-4.51, 6.5, 1.75], "size": [0, 1, 1], "uv": [0, 6]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -119,7 +119,6 @@
|
||||
"name": "eye_right",
|
||||
"parent": "eyes",
|
||||
"pivot": [-1.5, 5.75, -5.25],
|
||||
"rotation": [0, 0, 5],
|
||||
"cubes": [
|
||||
{"origin": [-2.5, 6, -5.26], "size": [1, 2, 0], "uv": [8, 19]}
|
||||
]
|
||||
@@ -152,7 +151,6 @@
|
||||
"name": "eye_left",
|
||||
"parent": "eyes",
|
||||
"pivot": [1.5, 5.75, -5.25],
|
||||
"rotation": [0, 0, -5],
|
||||
"cubes": [
|
||||
{"origin": [1.5, 6, -5.26], "size": [1, 2, 0], "uv": [8, 8]}
|
||||
]
|
||||
|
||||
+29
-21
@@ -112,7 +112,7 @@
|
||||
{
|
||||
"name": "head",
|
||||
"parent": "neck",
|
||||
"pivot": [0, 9, -0.25],
|
||||
"pivot": [0, 8.25, -0.25],
|
||||
"cubes": [
|
||||
{"origin": [-4, 7.5, -3.75], "size": [8, 6, 7], "uv": [0, 0]},
|
||||
{"origin": [-1.25, 9.25, -4.75], "size": [2, 2, 1], "inflate": 0.01, "uv": [23, 1]},
|
||||
@@ -151,67 +151,75 @@
|
||||
{
|
||||
"name": "eye_left",
|
||||
"parent": "eyes",
|
||||
"pivot": [2.75, 11, -3.76],
|
||||
"rotation": [0, 0, -7.5],
|
||||
"pivot": [2.75, 10.75, -3.76]
|
||||
},
|
||||
{
|
||||
"name": "iris_left",
|
||||
"parent": "eye_left",
|
||||
"pivot": [2.75, 10.875, -3.765],
|
||||
"cubes": [
|
||||
{"origin": [2, 10, -3.76], "size": [1.5, 2, 0], "uv": [0, 0]}
|
||||
{"origin": [2, 9.75, -3.76], "size": [1.5, 2, 0], "uv": [0, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "pupil_left",
|
||||
"parent": "eye_left",
|
||||
"pivot": [2.75, 11.25, -3.77],
|
||||
"parent": "iris_left",
|
||||
"pivot": [2.75, 11, -3.77],
|
||||
"cubes": [
|
||||
{"origin": [2.25, 10.5, -3.77], "size": [1, 1, 0], "uv": [2, 0]}
|
||||
{"origin": [2.25, 10.25, -3.77], "size": [1, 1, 0], "uv": [2, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "locator_eye_left",
|
||||
"parent": "pupil_left",
|
||||
"pivot": [2.75, 11, -4],
|
||||
"pivot": [2.75, 10.75, -4],
|
||||
"locators": {
|
||||
"eye2": [2.75, 11, -4]
|
||||
"eye2": [2.75, 10.75, -4]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "eyelid_left",
|
||||
"parent": "eye_left",
|
||||
"pivot": [2.75, 11, -3.17],
|
||||
"pivot": [2.75, 10.75, -3.17],
|
||||
"cubes": [
|
||||
{"origin": [1.75, 10, -3.67], "size": [2, 2, 1], "inflate": 0.01, "uv": [1, 3]}
|
||||
{"origin": [1.75, 9.75, -3.67], "size": [2, 2, 1], "inflate": 0.01, "uv": [1, 3]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "eye_right",
|
||||
"parent": "eyes",
|
||||
"pivot": [-2.75, 11, -3.76],
|
||||
"rotation": [0, 0, 7.5],
|
||||
"pivot": [-2.75, 10.75, -3.76]
|
||||
},
|
||||
{
|
||||
"name": "iris_right",
|
||||
"parent": "eye_right",
|
||||
"pivot": [-2.75, 10.875, -3.765],
|
||||
"cubes": [
|
||||
{"origin": [-3.5, 10, -3.76], "size": [1.5, 2, 0], "uv": [0, 2], "mirror": true}
|
||||
{"origin": [-3.5, 9.75, -3.76], "size": [1.5, 2, 0], "uv": [0, 2], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "pupil_right",
|
||||
"parent": "eye_right",
|
||||
"pivot": [-2.75, 11.25, -3.77],
|
||||
"parent": "iris_right",
|
||||
"pivot": [-2.75, 11, -3.77],
|
||||
"cubes": [
|
||||
{"origin": [-3.25, 10.5, -3.77], "size": [1, 1, 0], "uv": [2, 1], "mirror": true}
|
||||
{"origin": [-3.25, 10.25, -3.77], "size": [1, 1, 0], "uv": [2, 1], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "locator_eye_right",
|
||||
"parent": "pupil_right",
|
||||
"pivot": [-2.75, 11, -4],
|
||||
"pivot": [-2.75, 10.75, -4],
|
||||
"locators": {
|
||||
"eye1": [-2.75, 11, -4]
|
||||
"eye1": [-2.75, 10.75, -4]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "eyelid_right",
|
||||
"parent": "eye_right",
|
||||
"pivot": [-2.75, 11, -3.17],
|
||||
"pivot": [-2.75, 10.75, -3.17],
|
||||
"cubes": [
|
||||
{"origin": [-3.75, 10, -3.67], "size": [2, 2, 1], "inflate": 0.01, "uv": [1, 15], "mirror": true}
|
||||
{"origin": [-3.75, 9.75, -3.67], "size": [2, 2, 1], "inflate": 0.01, "uv": [1, 15], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@
|
||||
"parent": "torso",
|
||||
"pivot": [0, 13, 2],
|
||||
"locators": {
|
||||
"seat": [0, 13, 2]
|
||||
"seat_1": [0, 13, 2]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
+5
-15
@@ -247,9 +247,7 @@
|
||||
"pivot": [0, 8.5, 0],
|
||||
"cubes": [
|
||||
{"origin": [-2, 12, -2], "size": [4, 4, 4], "inflate": -0.25, "uv": [31, 2]},
|
||||
{"origin": [2, 16, 2], "size": [-4, -4, -4], "uv": [17, 30]},
|
||||
{"origin": [-1, 14.25, -1], "size": [2, 3, 2], "uv": [44, 0]},
|
||||
{"origin": [1, 17.25, 1], "size": [-2, -1, -2], "inflate": -0.25, "uv": [21, 29]}
|
||||
{"origin": [-1, 14.25, -1], "size": [2, 3, 2], "uv": [44, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -267,9 +265,7 @@
|
||||
"rotation": [0, 0, 67.5],
|
||||
"cubes": [
|
||||
{"origin": [-2, 12, -2], "size": [4, 4, 4], "inflate": -0.25, "uv": [67, 2]},
|
||||
{"origin": [2, 16, 2], "size": [-4, -4, -4], "uv": [49, 30]},
|
||||
{"origin": [-1, 14.25, -1], "size": [2, 3, 2], "uv": [80, 0]},
|
||||
{"origin": [1, 17.25, 1], "size": [-2, -1, -2], "inflate": -0.25, "uv": [37, 29]}
|
||||
{"origin": [-1, 14.25, -1], "size": [2, 3, 2], "uv": [80, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -279,9 +275,7 @@
|
||||
"rotation": [0, 0, -67.5],
|
||||
"cubes": [
|
||||
{"origin": [-2, 12, -2], "size": [4, 4, 4], "inflate": -0.25, "uv": [49, 2]},
|
||||
{"origin": [2, 16, 2], "size": [-4, -4, -4], "uv": [33, 30]},
|
||||
{"origin": [-1, 14.25, -1], "size": [2, 3, 2], "uv": [62, 0]},
|
||||
{"origin": [1, 17.25, 1], "size": [-2, -1, -2], "inflate": -0.25, "uv": [69, 29]}
|
||||
{"origin": [-1, 14.25, -1], "size": [2, 3, 2], "uv": [62, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -299,9 +293,7 @@
|
||||
"rotation": [0, 0, -137.5],
|
||||
"cubes": [
|
||||
{"origin": [-2, 12, -2], "size": [4, 4, 4], "inflate": -0.25, "uv": [85, 2]},
|
||||
{"origin": [2, 16, 2], "size": [-4, -4, -4], "uv": [81, 30]},
|
||||
{"origin": [-1, 14.25, -1], "size": [2, 3, 2], "uv": [98, 0]},
|
||||
{"origin": [1, 17.25, 1], "size": [-2, -1, -2], "inflate": -0.25, "uv": [85, 29]}
|
||||
{"origin": [-1, 14.25, -1], "size": [2, 3, 2], "uv": [98, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -311,9 +303,7 @@
|
||||
"rotation": [0, 0, 137.5],
|
||||
"cubes": [
|
||||
{"origin": [-2, 12, -2], "size": [4, 4, 4], "inflate": -0.25, "uv": [103, 2]},
|
||||
{"origin": [2, 16, 2], "size": [-4, -4, -4], "uv": [65, 30]},
|
||||
{"origin": [-1, 14.25, -1], "size": [2, 3, 2], "uv": [116, 0]},
|
||||
{"origin": [1, 17.25, 1], "size": [-2, -1, -2], "inflate": -0.25, "uv": [53, 29]}
|
||||
{"origin": [-1, 14.25, -1], "size": [2, 3, 2], "uv": [116, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"portraitScale": 2.1,
|
||||
"portraitTranslation": [ -0.55, -1.55, 0 ],
|
||||
"profileScale": 0.80,
|
||||
"profileTranslation": [ 0, 0.55, 0 ],
|
||||
"rootBone": "caterpie",
|
||||
"animations": {
|
||||
"cry": "q.bedrock_stateful('caterpie', 'cry')",
|
||||
"faint": "q.bedrock_primary('caterpie', 'faint', q.curve('one'))"
|
||||
},
|
||||
"poses": {
|
||||
"standing": {
|
||||
"poseTypes": ["STAND", "NONE", "FLOAT", "PORTRAIT", "PROFILE"],
|
||||
"animations": [
|
||||
"q.look('head')",
|
||||
"q.bedrock('caterpie', 'ground_idle')"
|
||||
],
|
||||
"quirks": ["q.bedrock_quirk('caterpie', 'blink')"]
|
||||
},
|
||||
"walking": {
|
||||
"poseTypes": ["WALK"],
|
||||
"animations": [
|
||||
"q.look('head')",
|
||||
"q.bedrock('caterpie', 'ground_walk')"
|
||||
],
|
||||
"quirks": ["q.bedrock_quirk('caterpie', 'blink')"]
|
||||
},
|
||||
"swimming": {
|
||||
"poseTypes": ["WALK","SWIM"],
|
||||
"isTouchingWater": true,
|
||||
"animations": [
|
||||
"q.pitch_tilt('body')",
|
||||
"q.look('head')",
|
||||
"q.bedrock('caterpie', 'ground_walk')"
|
||||
],
|
||||
"quirks": ["q.bedrock_quirk('caterpie', 'blink')"]
|
||||
},
|
||||
"sleep": {
|
||||
"poseTypes": ["SLEEP"],
|
||||
"namedAnimations": {
|
||||
"cry": "q.bedrock_stateful('dummy', 'cry')"
|
||||
},
|
||||
"animations": ["q.bedrock('caterpie', 'sleep')"]
|
||||
},
|
||||
"shoulder_left": {
|
||||
"poseTypes": ["SHOULDER_LEFT"],
|
||||
"animations": ["q.look('head')", "q.bedrock('caterpie', 'ground_idle')"],
|
||||
"quirks": ["q.bedrock_quirk('caterpie', 'blink')"],
|
||||
"transformedParts": [
|
||||
{
|
||||
"part": "body",
|
||||
"position": [3, 0, 0]
|
||||
}
|
||||
]
|
||||
},
|
||||
"shoulder_right": {
|
||||
"poseTypes": ["SHOULDER_RIGHT"],
|
||||
"animations": ["q.look('head')", "q.bedrock('caterpie', 'ground_idle')"],
|
||||
"quirks": ["q.bedrock_quirk('caterpie', 'blink')"],
|
||||
"transformedParts": [
|
||||
{
|
||||
"part": "body",
|
||||
"position": [-3, 0, 0]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"portraitScale": 2.3,
|
||||
"portraitTranslation": [-0.53, -1.9, 0],
|
||||
"profileScale": 0.80,
|
||||
"profileTranslation": [0, 0.51, 0],
|
||||
"rootBone": "weedle",
|
||||
"animations": {
|
||||
"cry": "q.bedrock_stateful('weedle', 'cry')",
|
||||
"faint": "q.bedrock_primary('weedle', 'faint', q.curve('one'))"
|
||||
},
|
||||
"poses": {
|
||||
"standing": {
|
||||
"poseTypes": ["STAND", "NONE", "FLOAT", "PORTRAIT", "PROFILE"],
|
||||
"animations": [
|
||||
"q.look('head')",
|
||||
"q.bedrock('weedle', 'ground_idle2')"
|
||||
],
|
||||
"quirks": ["q.bedrock_quirk('weedle', 'blink')"]
|
||||
},
|
||||
"walking": {
|
||||
"poseTypes": ["WALK"],
|
||||
"animations": [
|
||||
"q.look('head')",
|
||||
"q.bedrock('weedle', 'ground_walk')"
|
||||
],
|
||||
"quirks": ["q.bedrock_quirk('weedle', 'blink')"]
|
||||
},
|
||||
"swimming": {
|
||||
"poseTypes": ["WALK","SWIM"],
|
||||
"isTouchingWater": true,
|
||||
"animations": [
|
||||
"q.pitch_tilt('body')",
|
||||
"q.look('head')",
|
||||
"q.bedrock('weedle', 'ground_walk')"
|
||||
],
|
||||
"quirks": ["q.bedrock_quirk('weedle', 'blink')"]
|
||||
},
|
||||
"sleep": {
|
||||
"poseTypes": ["SLEEP"],
|
||||
"namedAnimations": {
|
||||
"cry": "q.bedrock_stateful('dummy', 'cry')"
|
||||
},
|
||||
"animations": ["q.bedrock('weedle', 'sleep')"]
|
||||
},
|
||||
"shoulder_left": {
|
||||
"poseTypes": ["SHOULDER_LEFT"],
|
||||
"animations": ["q.look('head')", "q.bedrock('weedle', 'ground_idle')"],
|
||||
"quirks": ["q.bedrock_quirk('weedle', 'blink')"],
|
||||
"transformedParts": [
|
||||
{
|
||||
"part": "body",
|
||||
"position": [3.8, 0, -3]
|
||||
}
|
||||
]
|
||||
},
|
||||
"shoulder_right": {
|
||||
"poseTypes": ["SHOULDER_RIGHT"],
|
||||
"animations": ["q.look('head')", "q.bedrock('weedle', 'ground_idle')"],
|
||||
"quirks": ["q.bedrock_quirk('weedle', 'blink')"],
|
||||
"transformedParts": [
|
||||
{
|
||||
"part": "body",
|
||||
"position": [-3.8, 0, -3]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
"animations": {
|
||||
"cry": "q.bedrock_stateful('pidgeot', 'cry')",
|
||||
"recoil": "q.bedrock_stateful('pidgeot', 'recoil')",
|
||||
"special": "q.bedrock_primary('pidgeot', 'special', q.curve('symmetrical'))"
|
||||
"status": "q.bedrock_primary('pidgeot', 'status', q.curve('symmetrical_wide'))"
|
||||
},
|
||||
"firstPersonCameraOffset": {
|
||||
"seat_1": [0, 0.45, 0]
|
||||
|
||||
+2
-2
@@ -64,7 +64,7 @@
|
||||
"q.sine_wing_flap(0.9, 0.9, 25, 'z', 'wing_open_left', 'wing_open_right')",
|
||||
"q.look('neck', 1, 1, 70, -10, 20, -20)",
|
||||
"q.look('head')",
|
||||
"q.bedrock('spearow', 'air_idle')"
|
||||
"q.bedrock('spearow', 'ground_idle')"
|
||||
],
|
||||
"quirks": ["q.bedrock_quirk('spearow', 'blink')"],
|
||||
"transformedParts": [
|
||||
@@ -93,7 +93,7 @@
|
||||
"q.sine_wing_flap(0.9, 0.9, 25, 'z', 'wing_open_left', 'wing_open_right')",
|
||||
"q.look('neck', 1, 1, 70, -10, 20, -20)",
|
||||
"q.look('head')",
|
||||
"q.bedrock('spearow', 'air_idle')"
|
||||
"q.bedrock('spearow', 'ground_idle')"
|
||||
],
|
||||
"quirks": ["q.bedrock_quirk('spearow', 'blink')"],
|
||||
"transformedParts": [
|
||||
|
||||
-3
@@ -16,9 +16,6 @@
|
||||
"q.look('head_ai', 1, 1, 8, -18, 10, -10)",
|
||||
"q.bedrock('oddish', 'battle_idle')"
|
||||
],
|
||||
"namedAnimations": {
|
||||
"cry": "q.bedrock_stateful('oddish', 'battle_cry')"
|
||||
},
|
||||
"quirks": ["q.bedrock_quirk('oddish', 'blink')"]
|
||||
},
|
||||
"standing": {
|
||||
|
||||
-3
@@ -16,9 +16,6 @@
|
||||
"q.look('head_ai', 1, 1, 6, -18, 10, -10)",
|
||||
"q.bedrock('gloom', 'battle_idle')"
|
||||
],
|
||||
"namedAnimations": {
|
||||
"cry": "q.bedrock_stateful('gloom', 'battle_cry')"
|
||||
},
|
||||
"quirks": ["q.bedrock_quirk('gloom', 'blink')"]
|
||||
},
|
||||
"standing": {
|
||||
|
||||
-3
@@ -16,9 +16,6 @@
|
||||
"q.look('head_ai', 1, 1, 6, -18, 10, -10)",
|
||||
"q.bedrock('vileplume', 'battle_idle')"
|
||||
],
|
||||
"namedAnimations": {
|
||||
"cry": "q.bedrock_stateful('vileplume', 'battle_cry')"
|
||||
},
|
||||
"quirks": [
|
||||
"q.bedrock_quirk('vileplume', 'blink')",
|
||||
"q.bedrock_primary_quirk('vileplume', 'quirk', 20, 40, 1, q.curve('symmetrical_wide'))"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user