mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-25 00:26:26 -04:00
Compare commits
36
Commits
1.8.2
...
trainer-card
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6aaca2b302 | ||
|
|
0dcb9c5802 | ||
|
|
5a3d47bf2e | ||
|
|
1c4934fa53 | ||
|
|
5004edbbb6 | ||
|
|
d8bdd6329a | ||
|
|
82d56637a0 | ||
|
|
7232a43816 | ||
|
|
098eb7d14b | ||
|
|
835b70ed48 | ||
|
|
9d828a86fb | ||
|
|
910551ee70 | ||
|
|
6f3894f27b | ||
|
|
bbc9a5e62e | ||
|
|
94765da04a | ||
|
|
8caa82f123 | ||
|
|
2f87d53af6 | ||
|
|
131ef31492 | ||
|
|
b6b067b1d3 | ||
|
|
542839ba69 | ||
|
|
efab1bba08 | ||
|
|
8f986bc326 | ||
|
|
e155d32aaf | ||
|
|
743e0b7d66 | ||
|
|
1518d703f9 | ||
|
|
af9d851d67 | ||
|
|
20ca91f1c9 | ||
|
|
6fb3c0e49a | ||
|
|
5cb4ff5f5f | ||
|
|
d035c08a5c | ||
|
|
fda7b13f50 | ||
|
|
f595724971 | ||
|
|
0511ba147b | ||
|
|
760f48d850 | ||
|
|
bf296b4921 | ||
|
|
49886389cf |
+24
-184
@@ -1,215 +1,55 @@
|
||||
# Changelog
|
||||
## [1.8.2 (October 11th, 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.
|
||||
- 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.
|
||||
- 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
|
||||
|
||||
### 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.
|
||||
- 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 pokemon has several pokedex 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 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 all pots of mod on NeoForge
|
||||
- Fixed party overlay not hiding when player opens the pokedex scanner
|
||||
- Added compat for AppleSkin
|
||||
|
||||
### 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.
|
||||
- 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
|
||||
|
||||
### Localization
|
||||
- Updated translations for:
|
||||
- Brazilian Portuguese
|
||||
- Canadian French
|
||||
- Japanese
|
||||
- Korean
|
||||
- Russian
|
||||
- Ukrainian
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -60,6 +60,8 @@ import com.cobblemon.mod.common.api.storage.pc.PCStore
|
||||
import com.cobblemon.mod.common.api.storage.pc.link.PCLinkManager
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreManager
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreTypes
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.BadgeMongoBackend
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.BadgeNbtBackend
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.DexDataMongoBackend
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.DexDataNbtBackend
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.PlayerDataJsonBackend
|
||||
@@ -260,6 +262,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()
|
||||
@@ -388,10 +393,13 @@ object Cobblemon {
|
||||
|
||||
val tmMoveFactory = CachedPlayerDataStoreFactory(TMMoveNbtBackend())
|
||||
tmMoveFactory.setup(server)
|
||||
val badgeFactory = CachedPlayerDataStoreFactory(BadgeNbtBackend())
|
||||
badgeFactory.setup(server)
|
||||
|
||||
playerDataManager.setFactory(generalJsonFactory, PlayerInstancedDataStoreTypes.GENERAL)
|
||||
playerDataManager.setFactory(pokedexNbtFactory, PlayerInstancedDataStoreTypes.POKEDEX)
|
||||
playerDataManager.setFactory(tmMoveFactory, PlayerInstancedDataStoreTypes.TM_MOVES)
|
||||
playerDataManager.setFactory(badgeFactory, PlayerInstancedDataStoreTypes.BADGES)
|
||||
|
||||
if (config.storageFormat == "nbt") {
|
||||
NBTStoreAdapter(pokemonStoreRoot.absolutePath, useNestedFolders = true, folderPerClass = true)
|
||||
@@ -422,10 +430,15 @@ object Cobblemon {
|
||||
TMMoveMongoBackend(mongoClient, config.mongoDBDatabaseName, "TMMovesCollection")
|
||||
)
|
||||
tmMovesMongoFactory.setup(server)
|
||||
val badgesMongoFactory = CachedPlayerDataStoreFactory(
|
||||
BadgeMongoBackend(mongoClient, config.mongoDBDatabaseName, "BadgesCollection")
|
||||
)
|
||||
badgesMongoFactory.setup(server)
|
||||
|
||||
playerDataManager.setFactory(generalMongoFactory, PlayerInstancedDataStoreTypes.GENERAL)
|
||||
playerDataManager.setFactory(pokedexMongoFactory, PlayerInstancedDataStoreTypes.POKEDEX)
|
||||
playerDataManager.setFactory(tmMovesMongoFactory, PlayerInstancedDataStoreTypes.TM_MOVES)
|
||||
playerDataManager.setFactory(badgesMongoFactory, PlayerInstancedDataStoreTypes.BADGES)
|
||||
MongoDBStoreAdapter(mongoClient, config.mongoDBDatabaseName)
|
||||
} catch (e: ClassNotFoundException) {
|
||||
LOGGER.error("MongoDB driver not found.")
|
||||
@@ -610,6 +623,7 @@ object Cobblemon {
|
||||
this.implementation.registerCommandArgument(cobblemonResource("transform_type"), TransformTypeArgumentType::class, SingletonArgumentInfo.contextFree(TransformTypeArgumentType::transformType))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("model_part"), ModelPartArgumentType::class, SingletonArgumentInfo.contextFree(ModelPartArgumentType::modelPart))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("tm"), TmArgumentType::class, SingletonArgumentInfo.contextFree(TmArgumentType::tm))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("badge"), BadgeArgumentType::class, SingletonArgumentInfo.contextFree(BadgeArgumentType::badge))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -73,6 +73,7 @@ object CobblemonCommands {
|
||||
PcTakeCommand.register(dispatcher)
|
||||
GiveTmCommand.register(dispatcher)
|
||||
TmCommand.register(dispatcher)
|
||||
BadgeCommand.register(dispatcher)
|
||||
|
||||
// Possibly lock down registration if and only if under dev environment or running in an environment
|
||||
// with a certain system environment variable set
|
||||
|
||||
@@ -432,6 +432,7 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(SpeciesFeatureAssignmentSyncPacket.ID, SpeciesFeatureAssignmentSyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(NaturalMaterialRegistrySyncPacket.ID, NaturalMaterialRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(FossilRegistrySyncPacket.ID, FossilRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(BadgeRegistrySyncPacket.ID, BadgeRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(NPCRegistrySyncPacket.ID, NPCRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(PokeRodRegistrySyncPacket.ID, PokeRodRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(ScriptRegistrySyncPacket.ID, ScriptRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.cobblemon.mod.common.api.badges
|
||||
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.StringRepresentable
|
||||
|
||||
class Badge(
|
||||
identifier: ResourceLocation,
|
||||
val name: String,
|
||||
val texture: ResourceLocation,
|
||||
val order: Int
|
||||
): StringRepresentable {
|
||||
|
||||
@Transient
|
||||
var identifier: ResourceLocation = identifier
|
||||
internal set
|
||||
|
||||
override fun getSerializedName(): String {
|
||||
return identifier.toString()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.cobblemon.mod.common.api.badges
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.storage.player.InstancedPlayerData
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreTypes
|
||||
import com.cobblemon.mod.common.api.storage.player.client.ClientBadgeManager
|
||||
import com.cobblemon.mod.common.net.messages.client.SetClientPlayerDataPacket
|
||||
import com.cobblemon.mod.common.util.getPlayer
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import java.util.UUID
|
||||
|
||||
class BadgeManager(
|
||||
override val uuid: UUID,
|
||||
val obtainedBadges: MutableSet<ResourceLocation> = mutableSetOf()
|
||||
) : InstancedPlayerData {
|
||||
|
||||
val storeType = PlayerInstancedDataStoreTypes.BADGES
|
||||
|
||||
override fun toClientData() = ClientBadgeManager(obtainedBadges.toMutableSet())
|
||||
|
||||
fun give(badge: Badge): Boolean {
|
||||
if (!obtainedBadges.add(badge.identifier)) return false
|
||||
syncAndSave()
|
||||
return true
|
||||
}
|
||||
|
||||
fun remove(badge: Badge): Boolean {
|
||||
if (!obtainedBadges.remove(badge.identifier)) return false
|
||||
syncAndSave()
|
||||
return true
|
||||
}
|
||||
|
||||
private fun syncAndSave() {
|
||||
uuid.getPlayer()?.sendPacket(SetClientPlayerDataPacket(storeType, toClientData()))
|
||||
Cobblemon.playerDataManager.saveSingle(this, storeType)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CODEC: Codec<BadgeManager> = RecordCodecBuilder.create { instance ->
|
||||
instance.group(
|
||||
Codec.STRING.xmap(UUID::fromString, UUID::toString)
|
||||
.fieldOf("uuid")
|
||||
.forGetter { it.uuid },
|
||||
Codec.list(ResourceLocation.CODEC)
|
||||
.xmap({ it.toMutableSet() }, { it.toList() })
|
||||
.fieldOf("obtainedBadges")
|
||||
.forGetter { it.obtainedBadges }
|
||||
).apply(instance, ::BadgeManager)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.cobblemon.mod.common.api.badges
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.net.messages.client.data.BadgeRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
|
||||
object Badges : JsonDataRegistry<Badge> {
|
||||
|
||||
override val id: ResourceLocation = cobblemonResource("badges")
|
||||
override val type: PackType = PackType.SERVER_DATA
|
||||
override val observable = SimpleObservable<Badges>()
|
||||
|
||||
override val gson: Gson = GsonBuilder()
|
||||
.disableHtmlEscaping()
|
||||
.setPrettyPrinting()
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.create()
|
||||
|
||||
override val typeToken: TypeToken<Badge> = TypeToken.get(Badge::class.java)
|
||||
override val resourcePath: String = "badges"
|
||||
|
||||
private val badges = hashMapOf<ResourceLocation, Badge>()
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, Badge>) {
|
||||
this.badges.clear()
|
||||
data.forEach { (id, badge) ->
|
||||
try {
|
||||
badge.identifier = id
|
||||
this.badges[id] = badge
|
||||
} catch (e: Exception) {
|
||||
Cobblemon.LOGGER.error("Skipped loading the {} badge", id, e)
|
||||
}
|
||||
}
|
||||
Cobblemon.LOGGER.info("Loaded {} badges", this.badges.size)
|
||||
this.observable.emit(this)
|
||||
}
|
||||
|
||||
override fun sync(player: ServerPlayer) {
|
||||
BadgeRegistrySyncPacket(this.all()).sendToPlayer(player)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all loaded [Badge]s.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun all() = this.badges.values.toList()
|
||||
|
||||
/**
|
||||
* Gets a [Badge] by its [ResourceLocation].
|
||||
* @param identifier The identifier of the badge.
|
||||
* @return The [Badge], if loaded, otherwise null.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getByIdentifier(identifier: ResourceLocation): Badge? = this.badges[identifier]
|
||||
}
|
||||
+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) }
|
||||
|
||||
@@ -145,6 +145,8 @@ object CobblemonPermissions {
|
||||
val SPECTATE_BATTLE = this.create("${COMMAND_PREFIX}spectatebattle", PermissionLevel.ALL_COMMANDS)
|
||||
@JvmStatic
|
||||
val TECHNICAL_MACHINE = this.create("${COMMAND_PREFIX}technicalmachine", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
@JvmStatic
|
||||
val BADGE = this.create("${COMMAND_PREFIX}badge", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
@JvmStatic
|
||||
val SEE_HIDDEN_NPCS = this.create("seehiddennpcs", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
@@ -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,14 +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 getFormEquivalents(formName: String): List<String> {
|
||||
val key = equivalentFormsLookup[formName.lowercase()]
|
||||
return equivalentForms[key] ?: listOf(formName.lowercase())
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
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
|
||||
@@ -72,8 +73,11 @@ object DexEntries : JsonDataRegistry<PokedexEntry> {
|
||||
fun computeEvolutionDisplays() {
|
||||
evolutionDisplays.clear()
|
||||
PokemonSpecies.species.forEach {
|
||||
evolutionDisplays.addAll(buildDisplays(it.standardForm))
|
||||
evolutionDisplays.addAll(it.forms.flatMap { form -> buildDisplays(form) })
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,8 +97,10 @@ object DexEntries : JsonDataRegistry<PokedexEntry> {
|
||||
?.let { PokemonSpecies.getByIdentifier(it.asIdentifierDefaultingNamespace()) }
|
||||
?: return@resultLoop
|
||||
|
||||
// Carry the source form's aspects over like a real evolution does (Alola-Bias Pichu -> Alola-Bias Pikachu)
|
||||
val resultForm = resultSpecies.getForm(form.aspects.toSet() + resultProperties.aspects)
|
||||
// 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"))
|
||||
@@ -115,4 +121,4 @@ object DexEntries : JsonDataRegistry<PokedexEntry> {
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-5
@@ -77,8 +77,8 @@ fun getToolTipHeaderIcon(evolution: Evolution): DexEvolutionRequirementDisplay?
|
||||
}
|
||||
|
||||
|
||||
fun getToolTipHeaderIcon(itemInteractionEvolution: ItemInteractionEvolution): CobblemonDexEvolutionRequirementDisplay {
|
||||
val item = itemInteractionEvolution.requiredContext.items.get().first().value()
|
||||
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()))
|
||||
}
|
||||
|
||||
@@ -87,7 +87,9 @@ fun getToolTipHeaderIcon(tradeEvolution: TradeEvolution): CobblemonDexEvolutionR
|
||||
val tooltip = if (species == null) {
|
||||
lang("ui.pokedex.evolution.trade.tooltip.with_any_species")
|
||||
} else {
|
||||
lang("ui.pokedex.evolution.trade.tooltip.with_species", PokemonSpecies.getByIdentifier(species.asIdentifierDefaultingNamespace())!!.translatedName.green())
|
||||
PokemonSpecies.getByIdentifier(species.asIdentifierDefaultingNamespace())
|
||||
?.let { lang("ui.pokedex.evolution.trade.tooltip.with_species", it.translatedName.green()) }
|
||||
?: lang("ui.pokedex.evolution.trade.tooltip.with_any_species")
|
||||
}
|
||||
return CobblemonDexEvolutionRequirementDisplay(CobblemonItems.LINK_CABLE, tooltip)
|
||||
}
|
||||
@@ -322,8 +324,8 @@ fun buildMoveTypeRequirement(moveTypeRequirement: MoveTypeRequirement): DexEvolu
|
||||
return CobblemonDexEvolutionRequirementDisplay(icon, tooltip)
|
||||
}
|
||||
|
||||
fun buildOwnerHoldsItemRequirement(ownerHoldsItemRequirement: OwnerHoldsItemRequirement): DexEvolutionRequirementDisplay {
|
||||
val item = ownerHoldsItemRequirement.itemCondition.items.get().first().value()
|
||||
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)
|
||||
|
||||
@@ -29,8 +29,12 @@ object CobblemonStats {
|
||||
@JvmField
|
||||
val BATTLES_WON: CobblemonStat = CobblemonStat("battles_won")
|
||||
@JvmField
|
||||
val PVP_BATTLES_WON: CobblemonStat = CobblemonStat("pvp_battles_won")
|
||||
@JvmField
|
||||
val BATTLES_LOST: CobblemonStat = CobblemonStat("battles_lost")
|
||||
@JvmField
|
||||
val PVP_BATTLES_LOST: CobblemonStat = CobblemonStat("pvp_battles_lost")
|
||||
@JvmField
|
||||
val BATTLES_FLED: CobblemonStat = CobblemonStat("battles_fled")
|
||||
@JvmField
|
||||
val BATTLES_TOTAL: CobblemonStat = CobblemonStat("battles_total")
|
||||
@@ -68,7 +72,9 @@ object CobblemonStats {
|
||||
stats["evolved"] = EVOLVED
|
||||
stats["level_up"] = LEVEL_UP
|
||||
stats["battles_won"] = BATTLES_WON
|
||||
stats["pvp_battles_won"] = PVP_BATTLES_WON
|
||||
stats["battles_lost"] = BATTLES_LOST
|
||||
stats["pvp_battles_lost"] = PVP_BATTLES_LOST
|
||||
stats["battles_fled"] = BATTLES_FLED
|
||||
stats["battles_total"] = BATTLES_TOTAL
|
||||
stats["dex_entries"] = DEX_ENTRIES
|
||||
|
||||
+14
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.api.storage.player
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Cobblemon.MODID
|
||||
import com.cobblemon.mod.common.api.badges.BadgeManager
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexManager
|
||||
import com.cobblemon.mod.common.api.scheduling.ScheduledTask
|
||||
import com.cobblemon.mod.common.api.scheduling.ServerTaskTracker
|
||||
@@ -76,6 +77,14 @@ open class PlayerInstancedDataStoreManager {
|
||||
.infiniteIterations()
|
||||
.tracker(ServerTaskTracker)
|
||||
.build()
|
||||
|
||||
saveTasks[PlayerInstancedDataStoreTypes.BADGES] = ScheduledTask.Builder()
|
||||
.execute { saveAllOfOneType(PlayerInstancedDataStoreTypes.BADGES) }
|
||||
.delay(30F)
|
||||
.interval(120F)
|
||||
.infiniteIterations()
|
||||
.tracker(ServerTaskTracker)
|
||||
.build()
|
||||
}
|
||||
|
||||
open fun get(playerId: UUID, dataType: PlayerInstancedDataStoreType): InstancedPlayerData {
|
||||
@@ -148,4 +157,9 @@ open class PlayerInstancedDataStoreManager {
|
||||
}
|
||||
return data as TMMoveManager
|
||||
}
|
||||
|
||||
fun getBadgeData(player: ServerPlayer): BadgeManager = getBadgeData(player.uuid)
|
||||
|
||||
fun getBadgeData(playerId: UUID): BadgeManager =
|
||||
get(playerId, PlayerInstancedDataStoreTypes.BADGES) as BadgeManager
|
||||
}
|
||||
|
||||
+7
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.storage.player
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.storage.player.client.ClientBadgeManager
|
||||
import com.cobblemon.mod.common.api.storage.player.client.ClientPokedexManager
|
||||
import com.cobblemon.mod.common.api.storage.player.client.ClientGeneralPlayerData
|
||||
import com.cobblemon.mod.common.api.storage.player.client.ClientTMMoveManager
|
||||
@@ -35,6 +36,12 @@ object PlayerInstancedDataStoreTypes {
|
||||
ClientTMMoveManager::runAction,
|
||||
ClientTMMoveManager::runIncremental
|
||||
))
|
||||
val BADGES = register(PlayerInstancedDataStoreType(
|
||||
cobblemonResource("badge_collection"),
|
||||
ClientBadgeManager::decode,
|
||||
ClientBadgeManager::runAction,
|
||||
ClientBadgeManager::runIncremental
|
||||
))
|
||||
|
||||
fun register(type: PlayerInstancedDataStoreType): PlayerInstancedDataStoreType {
|
||||
Cobblemon.LOGGER.debug("Registering PlayerInstancedDataStoreType: {}", type.id)
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.storage.player.adapter
|
||||
|
||||
import com.cobblemon.mod.common.api.badges.BadgeManager
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreTypes
|
||||
import com.cobblemon.mod.common.util.adapters.CodecBackedAdapter
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.mongodb.client.MongoClient
|
||||
import java.util.UUID
|
||||
|
||||
class BadgeMongoBackend(
|
||||
mongoClient: MongoClient,
|
||||
databaseName: String,
|
||||
collectionName: String
|
||||
) : MongoBackedPlayerDataStoreBackend<BadgeManager>(
|
||||
mongoClient,
|
||||
databaseName,
|
||||
collectionName,
|
||||
PlayerInstancedDataStoreTypes.BADGES
|
||||
) {
|
||||
override val gson = GsonBuilder()
|
||||
.registerTypeAdapter(BadgeManager::class.java, CodecBackedAdapter(BadgeManager.CODEC))
|
||||
.create()
|
||||
override val classToken = TypeToken.get(BadgeManager::class.java)
|
||||
override val defaultData = defaultDataFunc
|
||||
|
||||
companion object {
|
||||
val defaultDataFunc = { uuid: UUID -> BadgeManager(uuid) }
|
||||
}
|
||||
}
|
||||
+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.api.storage.player.adapter
|
||||
|
||||
import com.cobblemon.mod.common.api.badges.BadgeManager
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreTypes
|
||||
import java.util.UUID
|
||||
|
||||
class BadgeNbtBackend : NbtBackedPlayerData<BadgeManager>("badges", PlayerInstancedDataStoreTypes.BADGES) {
|
||||
override val codec = BadgeManager.CODEC
|
||||
override val defaultData = defaultDataFunc
|
||||
|
||||
companion object {
|
||||
val defaultDataFunc = { uuid: UUID -> BadgeManager(uuid) }
|
||||
}
|
||||
}
|
||||
+6
-4
@@ -52,7 +52,7 @@ abstract class FileBasedPlayerDataStoreBackend<T : InstancedPlayerData>(
|
||||
val playerFile = filePath(uuid)
|
||||
val playerFileOld = filePath(uuid, OLD_FILE_EXTENSION)
|
||||
playerFile.parentFile.mkdirs()
|
||||
val loadFallback: () -> T = {
|
||||
val loadFallback: (Boolean) -> T = { primaryFileCorrupt ->
|
||||
playerFile.delete()
|
||||
if (playerFileOld.exists() && playerFileOld.length() > 0L) {
|
||||
try {
|
||||
@@ -68,7 +68,9 @@ abstract class FileBasedPlayerDataStoreBackend<T : InstancedPlayerData>(
|
||||
}
|
||||
}
|
||||
else {
|
||||
Cobblemon.LOGGER.error(".old File $subfolder for $uuid is corrupt or missing. Data is lost")
|
||||
if (primaryFileCorrupt) {
|
||||
Cobblemon.LOGGER.error(".old File $subfolder for $uuid is corrupt or missing. Data is lost")
|
||||
}
|
||||
playerFileOld.delete()
|
||||
defaultData.invoke(uuid).also(::save)
|
||||
}
|
||||
@@ -80,10 +82,10 @@ abstract class FileBasedPlayerDataStoreBackend<T : InstancedPlayerData>(
|
||||
catch (e: Exception) {
|
||||
Cobblemon.LOGGER.warn("Failed to load $subfolder for $uuid due to ${e.message}")
|
||||
Cobblemon.LOGGER.warn(e)
|
||||
loadFallback()
|
||||
loadFallback(true)
|
||||
}
|
||||
} else {
|
||||
loadFallback()
|
||||
loadFallback(false)
|
||||
}.also { it.initialize() }
|
||||
}
|
||||
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package com.cobblemon.mod.common.api.storage.player.client
|
||||
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreTypes
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.net.messages.client.SetClientPlayerDataPacket
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class ClientBadgeManager(
|
||||
val obtainedBadges: MutableSet<ResourceLocation>
|
||||
) : ClientInstancedPlayerData {
|
||||
|
||||
override fun encode(buf: RegistryFriendlyByteBuf) {
|
||||
buf.writeCollection(obtainedBadges) { _, id, -> buf.writeString(id.toString()) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buf: RegistryFriendlyByteBuf): SetClientPlayerDataPacket {
|
||||
val badges = buf.readCollection(
|
||||
{ mutableSetOf<ResourceLocation>() },
|
||||
{ buf.readString().let(ResourceLocation::tryParse) ?: ResourceLocation("minecraft", "empty") }
|
||||
)
|
||||
return SetClientPlayerDataPacket(
|
||||
PlayerInstancedDataStoreTypes.BADGES,
|
||||
ClientBadgeManager(badges)
|
||||
)
|
||||
}
|
||||
|
||||
fun runAction(data: ClientInstancedPlayerData) {
|
||||
if (data !is ClientBadgeManager) return
|
||||
CobblemonClient.clientBadgeData = data
|
||||
}
|
||||
|
||||
fun runIncremental(data: ClientInstancedPlayerData) {
|
||||
if (data !is ClientBadgeManager) return
|
||||
CobblemonClient.clientBadgeData.obtainedBadges.addAll(data.obtainedBadges)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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")
|
||||
|
||||
@@ -17,12 +17,12 @@ import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.CobblemonMenuType
|
||||
import com.cobblemon.mod.common.api.berry.Berries
|
||||
import com.cobblemon.mod.common.api.scheduling.ClientTaskTracker
|
||||
import com.cobblemon.mod.common.api.storage.player.client.ClientBadgeManager
|
||||
import com.cobblemon.mod.common.api.storage.player.client.ClientGeneralPlayerData
|
||||
import com.cobblemon.mod.common.api.storage.player.client.ClientPokedexManager
|
||||
import com.cobblemon.mod.common.api.storage.player.client.ClientTMMoveManager
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.block.entity.TintBlockEntity
|
||||
import com.cobblemon.mod.common.block.sign.CobblemonSignBlock
|
||||
import com.cobblemon.mod.common.client.battle.ClientBattle
|
||||
import com.cobblemon.mod.common.client.gui.PartyOverlay
|
||||
import com.cobblemon.mod.common.client.gui.PartyOverlayDataControl
|
||||
@@ -101,6 +101,7 @@ object CobblemonClient {
|
||||
var clientPlayerData = ClientGeneralPlayerData()
|
||||
var clientPokedexData = ClientPokedexManager(mutableMapOf())
|
||||
var clientTMMoveData = ClientTMMoveManager(mutableSetOf())
|
||||
var clientBadgeData = ClientBadgeManager(mutableSetOf())
|
||||
|
||||
/** If true then we won't bother them anymore about choosing a starter even if it's a thing they can do. */
|
||||
var checkedStarterScreen = false
|
||||
@@ -118,6 +119,7 @@ object CobblemonClient {
|
||||
teamData = ClientPlayerTeamData()
|
||||
clientPokedexData = ClientPokedexManager(mutableMapOf())
|
||||
clientTMMoveData = ClientTMMoveManager(mutableSetOf())
|
||||
clientBadgeData = ClientBadgeManager(mutableSetOf())
|
||||
storage.onLogin()
|
||||
// CobblemonDataProvider.canReload = false
|
||||
}
|
||||
|
||||
@@ -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()) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+29
-22
@@ -9,19 +9,11 @@
|
||||
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.CobblemonBiomeDexEvolutionRequirementDisplay
|
||||
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.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
|
||||
@@ -41,7 +33,6 @@ 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
|
||||
@@ -50,6 +41,7 @@ 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(
|
||||
@@ -164,25 +156,28 @@ class EvolutionTreeWidget(
|
||||
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) {
|
||||
rootSpecies = Dexes.findDexEntryBySpeciesId(preEvolution.fromSpecies)!!
|
||||
rootForm = rootSpecies.forms.first { it.displayForm.equals(preEvolution.fromForm, ignoreCase = true) }
|
||||
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 entry = Dexes.findDexEntryBySpeciesId(rootSpecies.speciesId)
|
||||
?: throw RuntimeException("Root dex entry not found")
|
||||
|
||||
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 =
|
||||
entry.forms.firstOrNull { formEquivalents.contains(it.displayForm.lowercase()) } ?:
|
||||
entry.forms.first { it.displayForm.equals("Normal", ignoreCase = true) }
|
||||
rootSpecies.forms.firstOrNull { formEquivalents.contains(it.displayForm.lowercase()) } ?:
|
||||
rootSpecies.forms.first { it.displayForm.equals("Normal", ignoreCase = true) }
|
||||
|
||||
val rootEvolutionNode = buildEvolutionTree(entry, form)
|
||||
val rootEvolutionNode = buildEvolutionTree(rootSpecies, form)
|
||||
|
||||
// val isSameEntry = previousRootPokedexEntry != null && pokedexEntry?.id == previousRootPokedexEntry?.id
|
||||
// val isSameForm =
|
||||
@@ -208,7 +203,7 @@ class EvolutionTreeWidget(
|
||||
|
||||
/** 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 && it.toForm == form.displayForm }
|
||||
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 }
|
||||
}
|
||||
@@ -230,21 +225,33 @@ class EvolutionTreeWidget(
|
||||
pokedexEntry: PokedexEntry,
|
||||
pokedexForm: PokedexForm,
|
||||
aspects: Set<String> = emptySet(),
|
||||
ancestors: Set<Pair<ResourceLocation, String>> = emptySet(),
|
||||
): EvolutionNode {
|
||||
// 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 evolutions = DexEntries.evolutionDisplays.filter { it.fromSpecies == pokedexEntry.speciesId && formEquivalents.contains(it.fromForm.lowercase()) }
|
||||
|
||||
val children = evolutions.mapNotNull {
|
||||
val childPokedexEntry = Dexes.findDexEntryBySpeciesId(it.toSpecies)
|
||||
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.first { formEquivalents.contains(it.displayForm.lowercase()) }
|
||||
buildEvolutionTree(childPokedexEntry, childPokedexForm, it.toAspects)
|
||||
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(
|
||||
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
package com.cobblemon.mod.common.client.gui.trainercard
|
||||
|
||||
import com.cobblemon.mod.common.api.badges.Badge
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.gui.ScrollingWidget
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.renderTooltip
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.util.FastColor
|
||||
import net.minecraft.util.Mth
|
||||
|
||||
class BadgesScrollingWidget(
|
||||
x: Int,
|
||||
y: Int,
|
||||
width: Int,
|
||||
height: Int,
|
||||
private val columns: Int
|
||||
) : ScrollingWidget<BadgesScrollingWidget.BadgeRow>(
|
||||
width = width,
|
||||
height = height,
|
||||
left = x,
|
||||
top = y - height,
|
||||
slotHeight = SLOT_SIZE + SLOT_SPACING
|
||||
) {
|
||||
|
||||
private var tooltip: MutableComponent? = null
|
||||
private var tooltipX = 0
|
||||
private var tooltipY = 0
|
||||
|
||||
companion object {
|
||||
const val SLOT_SIZE = 16
|
||||
const val SLOT_SPACING = 3
|
||||
const val MAX_VISIBLE_ROWS = 2
|
||||
}
|
||||
|
||||
fun createEntries(badges: List<Badge>) {
|
||||
|
||||
val obtainedBadgeList = badges.filter { CobblemonClient.clientBadgeData.obtainedBadges.contains(it.identifier) }
|
||||
.sortedBy { it.order }
|
||||
val unobtainedBadgesList = badges.filter { !obtainedBadgeList.contains(it) }
|
||||
.sortedBy { it.order }
|
||||
val sortedBadgeList = obtainedBadgeList.plus(unobtainedBadgesList)
|
||||
|
||||
sortedBadgeList.chunked(columns).forEach { listChunk ->
|
||||
addEntry(BadgeRow(this, listChunk))
|
||||
}
|
||||
}
|
||||
|
||||
private val visibleRows: Int
|
||||
get() = (height / itemHeight).coerceAtLeast(1)
|
||||
|
||||
private fun hasScrollbar(): Boolean = children().size > visibleRows
|
||||
|
||||
override fun getRowLeft(): Int = if (hasScrollbar()) left + 1 else left
|
||||
override fun getScrollbarPosition(): Int = rowLeft + width - 3
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
tooltip = null
|
||||
super.renderWidget(context, mouseX, mouseY, delta)
|
||||
tooltip?.let { renderTooltip(context, it, tooltipX, tooltipY, delta) }
|
||||
}
|
||||
|
||||
fun setTooltip(text: MutableComponent, mouseX: Int, mouseY: Int) {
|
||||
if (mouseX in left until left + width && mouseY in this.y until bottom) {
|
||||
tooltip = text
|
||||
tooltipX = mouseX + 20
|
||||
tooltipY = mouseY - 10
|
||||
}
|
||||
}
|
||||
|
||||
override fun renderScrollbar(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
if (hasScrollbar()) {
|
||||
val xLeft = this.scrollbarPosition
|
||||
val xRight = xLeft + 3
|
||||
|
||||
val barHeight = this.bottom - this.y
|
||||
|
||||
var yBottom = ((barHeight * barHeight).toFloat() / this.maxPosition.toFloat()).toInt()
|
||||
yBottom = Mth.clamp(yBottom, minOf(32, barHeight), maxOf(minOf(32, barHeight), barHeight - 8))
|
||||
var yTop = scrollAmount.toInt() * (barHeight - yBottom) / this.maxScroll + this.y
|
||||
if (yTop < this.y) {
|
||||
yTop = this.y
|
||||
}
|
||||
|
||||
context.fill(xLeft, this.y, xRight, this.bottom, FastColor.ARGB32.color(255, 75, 75, 75))
|
||||
context.fill(xLeft, yTop, xRight, yTop + yBottom, FastColor.ARGB32.color(255, 141, 141, 141))
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderEntry(context: GuiGraphics, mouseX: Int, mouseY: Int, index: Int, x: Int, y: Int) {
|
||||
getEntry(index).renderRow(context, y, x, mouseX, mouseY)
|
||||
}
|
||||
|
||||
override fun renderListItems(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
val rowX = rowLeft
|
||||
|
||||
for (index in 0 until this.itemCount) {
|
||||
val rowY = this.getRowTop(index)
|
||||
val o = this.getRowBottom(index)
|
||||
if (o >= this.y && rowY <= this.bottom) {
|
||||
this.renderEntry(context, mouseX, mouseY, index, rowX, rowY)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, dragX: Double, dragY: Double): Boolean =
|
||||
if (hasScrollbar()) super.mouseDragged(mouseX, mouseY, button, dragX, dragY) else true
|
||||
|
||||
override fun mouseScrolled(mouseX: Double, mouseY: Double, scrollX: Double, scrollY: Double): Boolean =
|
||||
if (hasScrollbar()) super.mouseScrolled(mouseX, mouseY, scrollX, scrollY) else true
|
||||
|
||||
class BadgeRow(
|
||||
val parent: BadgesScrollingWidget,
|
||||
val badgeList: List<Badge?>
|
||||
) : Slot<BadgeRow>() {
|
||||
|
||||
fun renderRow(context: GuiGraphics, y: Int, x: Int, mouseX: Int, mouseY: Int) {
|
||||
badgeList.forEachIndexed { index, badge ->
|
||||
val startPosX = x + ((SLOT_SPACING + SLOT_SIZE) * index)
|
||||
val startPosY = y + SLOT_SPACING
|
||||
|
||||
if (badge != null) {
|
||||
val obtained = CobblemonClient.clientBadgeData.obtainedBadges.contains(badge.identifier)
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = badge.texture,
|
||||
x = startPosX,
|
||||
y = startPosY,
|
||||
width = SLOT_SIZE,
|
||||
height = SLOT_SIZE,
|
||||
red = if (obtained) 1 else 0,
|
||||
green = if (obtained) 1 else 0,
|
||||
blue = if (obtained) 1 else 0
|
||||
)
|
||||
if (mouseX in startPosX until startPosX + SLOT_SIZE &&
|
||||
mouseY in startPosY until startPosY + SLOT_SIZE
|
||||
) {
|
||||
parent.setTooltip(
|
||||
if (obtained) Component.translatable(badge.name) else lang("badge.unobtained"),
|
||||
mouseX, mouseY
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getNarration(): Component? {
|
||||
return badgeList.firstOrNull()?.let { Component.translatable(it.name) }
|
||||
}
|
||||
|
||||
override fun render(
|
||||
guiGraphics: GuiGraphics,
|
||||
index: Int,
|
||||
top: Int,
|
||||
left: Int,
|
||||
width: Int,
|
||||
height: Int,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
hovering: Boolean,
|
||||
partialTick: Float
|
||||
) {}
|
||||
}
|
||||
}
|
||||
+221
@@ -0,0 +1,221 @@
|
||||
package com.cobblemon.mod.common.client.gui.trainercard
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.badges.Badges
|
||||
import com.cobblemon.mod.common.api.pokedex.CaughtCount
|
||||
import com.cobblemon.mod.common.api.stats.CobblemonStats.getStat
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
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.client.gui.components.Button
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.client.gui.screens.inventory.InventoryScreen
|
||||
import net.minecraft.client.sounds.SoundManager
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.protocol.game.ServerboundClientCommandPacket
|
||||
import net.minecraft.stats.Stats
|
||||
import net.minecraft.util.CommonColors
|
||||
import kotlin.math.ceil
|
||||
|
||||
class TrainerCardMenu : Screen(
|
||||
Component.translatable("cobblemon.ui.trainercard.title")
|
||||
), CobblemonRenderable {
|
||||
|
||||
private var elapsedTicks = 0
|
||||
private var lastSyncedTimePlayed = 0
|
||||
private var panelLeft = 0
|
||||
private var panelTop = 0
|
||||
private lateinit var badgeScrollList: BadgesScrollingWidget
|
||||
private lateinit var leftPageArrow: TrainerCardPageArrow
|
||||
private lateinit var rightPageArrow: TrainerCardPageArrow
|
||||
private var currentPage = 0
|
||||
private val maxPages = 3
|
||||
|
||||
override fun isPauseScreen(): Boolean = false
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
elapsedTicks = 0
|
||||
lastSyncedTimePlayed = getTimePlayed()
|
||||
// stats need to update when we open the menu, otherwise time played only updates when stats menu is opened
|
||||
Minecraft.getInstance().connection?.send(
|
||||
ServerboundClientCommandPacket(ServerboundClientCommandPacket.Action.REQUEST_STATS)
|
||||
)
|
||||
|
||||
val badges = Badges.all().sortedBy { it.order }
|
||||
val panelWidth = minOf(220, (width - 16).coerceAtLeast(1))
|
||||
panelLeft = (width - panelWidth) / 2
|
||||
val leftColumnWidth = panelWidth / 2
|
||||
val badgeAreaWidth = panelWidth - leftColumnWidth - 8
|
||||
val columns = ((badgeAreaWidth + BadgesScrollingWidget.SLOT_SPACING) /
|
||||
(BadgesScrollingWidget.SLOT_SIZE + BadgesScrollingWidget.SLOT_SPACING)).coerceIn(1, 4)
|
||||
val badgeWidth = columns * BadgesScrollingWidget.SLOT_SIZE +
|
||||
(columns - 1) * BadgesScrollingWidget.SLOT_SPACING + 4
|
||||
val rowCount = ceil(badges.size.toDouble() / columns).toInt().coerceAtLeast(1)
|
||||
val rowHeight = BadgesScrollingWidget.SLOT_SIZE + BadgesScrollingWidget.SLOT_SPACING
|
||||
val badgeHeight = minOf(rowCount, BadgesScrollingWidget.MAX_VISIBLE_ROWS) * rowHeight
|
||||
val panelHeight = maxOf(92, badgeHeight + 20)
|
||||
panelTop = ((height - panelHeight) / 2).coerceAtLeast(8)
|
||||
|
||||
badgeScrollList = BadgesScrollingWidget(
|
||||
x = panelLeft + panelWidth - badgeWidth,
|
||||
y = panelTop + 10,
|
||||
width = badgeWidth,
|
||||
height = badgeHeight,
|
||||
columns = columns
|
||||
)
|
||||
badgeScrollList.createEntries(badges)
|
||||
addRenderableWidget(badgeScrollList)
|
||||
|
||||
leftPageArrow = TrainerCardPageArrow(
|
||||
buttonX = panelLeft - 10,
|
||||
buttonY = panelTop,
|
||||
width = 16,
|
||||
height = 16,
|
||||
onPress = {},
|
||||
parent = this,
|
||||
isRight = false
|
||||
)
|
||||
rightPageArrow = TrainerCardPageArrow(
|
||||
buttonX = panelLeft + panelWidth + 10,
|
||||
buttonY = panelTop,
|
||||
width = 16,
|
||||
height = 16,
|
||||
onPress = {},
|
||||
parent = this,
|
||||
isRight = true
|
||||
)
|
||||
|
||||
addRenderableWidget(leftPageArrow)
|
||||
addRenderableWidget(rightPageArrow)
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
super.tick()
|
||||
// make our own live playtime update, otherwise we have to send a packet a second to retrieve the playtime stat
|
||||
val timePlayed = getTimePlayed()
|
||||
if (timePlayed != lastSyncedTimePlayed) {
|
||||
lastSyncedTimePlayed = timePlayed
|
||||
elapsedTicks = 0
|
||||
} else { elapsedTicks++ }
|
||||
}
|
||||
|
||||
override fun render(context: GuiGraphics, mouseX: Int, mouseY: Int, partialTick: Float) {
|
||||
when(currentPage) {
|
||||
0 -> {
|
||||
val portraitX = panelLeft
|
||||
val portraitY = minOf(panelTop + 48, (height - 32).coerceAtLeast(0))
|
||||
val portraitSize = 30
|
||||
val statsTextWidth = (badgeScrollList.x - panelLeft - 8).coerceAtLeast(1)
|
||||
|
||||
val player = Minecraft.getInstance().player ?: return // unsure of why this would ever not return a player but if you're here maybe it's because it did
|
||||
val entity = Minecraft.getInstance().level?.getPlayerByUUID(player.uuid) ?: return
|
||||
|
||||
context.enableScissor(portraitX, portraitY, portraitX + portraitSize, portraitY + portraitSize)
|
||||
InventoryScreen.renderEntityInInventoryFollowsMouse(context,
|
||||
portraitX, portraitY, portraitX + portraitSize, portraitY + portraitSize, 28, 0.5f, mouseX.toFloat(), mouseY.toFloat(),
|
||||
entity
|
||||
)
|
||||
|
||||
context.disableScissor()
|
||||
|
||||
val totalSeconds = (getTimePlayed() + elapsedTicks) / 20
|
||||
val timePlayed = "%d:%02d:%02d:%02d".format(
|
||||
totalSeconds / 86_400, // days
|
||||
totalSeconds % 86_400 / 3_600, // hours
|
||||
totalSeconds % 3_600 / 60, // minutes
|
||||
totalSeconds % 60 // seconds
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.trainermenu.timeplayed", timePlayed),
|
||||
x = panelLeft,
|
||||
y = panelTop + 4,
|
||||
maxCharacterWidth = statsTextWidth
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.trainermenu.pokemon_registered",
|
||||
CobblemonClient.clientPokedexData.getDexCalculatedValue(cobblemonResource("national"), CaughtCount)),
|
||||
x = panelLeft,
|
||||
y = panelTop + 14,
|
||||
maxCharacterWidth = statsTextWidth
|
||||
)
|
||||
|
||||
val playerBattlesWon = player.stats.getValue(Stats.CUSTOM.get(getStat(Cobblemon.statistics.PVP_BATTLES_WON)))
|
||||
val playerBattlesLost = player.stats.getValue(Stats.CUSTOM.get(getStat(Cobblemon.statistics.PVP_BATTLES_LOST)))
|
||||
|
||||
if (playerBattlesWon > 0 || playerBattlesLost > 0) {
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.trainermenu.battle_stats",
|
||||
playerBattlesWon,
|
||||
playerBattlesLost
|
||||
),
|
||||
x = panelLeft,
|
||||
y = panelTop + 24,
|
||||
maxCharacterWidth = statsTextWidth
|
||||
)
|
||||
}
|
||||
|
||||
badgeScrollList.render(context, mouseX, mouseY, partialTick)
|
||||
}
|
||||
}
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = Component.literal("$currentPage"),
|
||||
x = panelLeft - 30,
|
||||
y = panelTop
|
||||
)
|
||||
|
||||
if (leftPageArrow.shouldExist()) {
|
||||
leftPageArrow.render(context, mouseX, mouseY, partialTick)
|
||||
}
|
||||
|
||||
if (rightPageArrow.shouldExist()) {
|
||||
rightPageArrow.render(context, mouseX, mouseY, partialTick)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class TrainerCardPageArrow(
|
||||
buttonX: Int,
|
||||
buttonY: Int, width: Int, height: Int, onPress: OnPress,
|
||||
val parent: TrainerCardMenu,
|
||||
val isRight: Boolean
|
||||
): Button(
|
||||
buttonX, buttonY, width, height, "".text(), onPress, DEFAULT_NARRATION
|
||||
) {
|
||||
|
||||
fun shouldExist(): Boolean {
|
||||
if (isRight && parent.currentPage == parent.maxPages - 1) return false
|
||||
if (!isRight && parent.currentPage == 0) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, partialTick: Float) {
|
||||
context.fill(x, y, x + width, y + height, CommonColors.WHITE)
|
||||
}
|
||||
|
||||
override fun playDownSound(handler: SoundManager) {
|
||||
if (shouldExist()) super.playDownSound(handler)
|
||||
}
|
||||
|
||||
override fun onClick(mouseX: Double, mouseY: Double) {
|
||||
if (!shouldExist()) return
|
||||
parent.currentPage += if (isRight) 1 else -1
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTimePlayed(): Int =
|
||||
Minecraft.getInstance().player?.stats?.getValue(Stats.CUSTOM.get(Stats.PLAY_TIME)) ?: 0
|
||||
|
||||
}
|
||||
@@ -39,6 +39,7 @@ object CobblemonKeyBinds {
|
||||
val PARTY_OVERLAY_UP = this.queue(UpShiftPartyBinding)
|
||||
val SEND_OUT_POKEMON = this.queue(PartySendBinding)
|
||||
val RIDING_FREELOOK = this.queue(RidingFreelookBinding)
|
||||
val TRAINER_MENU = this.queue(TrainerMenuBinding)
|
||||
|
||||
fun register(registrar: (KeyMapping) -> Unit) {
|
||||
this.keyBinds.forEach(registrar::invoke)
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.keybind.keybinds
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.gui.summary.Summary
|
||||
import com.cobblemon.mod.common.client.gui.trainercard.TrainerCardMenu
|
||||
import com.cobblemon.mod.common.client.keybind.CobblemonPartyLockedKeyBinding
|
||||
import com.cobblemon.mod.common.client.keybind.KeybindCategories
|
||||
import com.mojang.blaze3d.platform.InputConstants
|
||||
import net.minecraft.client.Minecraft
|
||||
|
||||
object TrainerMenuBinding : CobblemonPartyLockedKeyBinding(
|
||||
"key.cobblemon.trainermenu",
|
||||
InputConstants.Type.KEYSYM,
|
||||
InputConstants.KEY_N,
|
||||
KeybindCategories.COBBLEMON_CATEGORY
|
||||
) {
|
||||
override fun onPress() {
|
||||
Minecraft.getInstance().setScreen(TrainerCardMenu())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.cobblemon.mod.common.command
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.permission.CobblemonPermissions
|
||||
import com.cobblemon.mod.common.command.argument.BadgeArgumentType
|
||||
import com.cobblemon.mod.common.util.permission
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.CommandDispatcher
|
||||
import com.mojang.brigadier.context.CommandContext
|
||||
import net.minecraft.commands.CommandSourceStack
|
||||
import net.minecraft.commands.Commands
|
||||
import net.minecraft.commands.arguments.EntityArgument
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
object BadgeCommand {
|
||||
|
||||
private const val NAME = "badge"
|
||||
private const val GIVE = "give"
|
||||
private const val REMOVE = "remove"
|
||||
private const val PLAYER = "player"
|
||||
|
||||
fun register(dispatcher: CommandDispatcher<CommandSourceStack>) {
|
||||
val command =
|
||||
Commands.literal(NAME)
|
||||
.permission(CobblemonPermissions.BADGE)
|
||||
.then(Commands.literal(GIVE)
|
||||
.then(Commands.argument(PLAYER, EntityArgument.player())
|
||||
.then(Commands.argument(BADGE, BadgeArgumentType.badge())
|
||||
.executes { executeGive(it, EntityArgument.getPlayer(it, PLAYER)) }
|
||||
)
|
||||
)
|
||||
)
|
||||
.then(Commands.literal(REMOVE)
|
||||
.then(Commands.argument(PLAYER, EntityArgument.player())
|
||||
.then(Commands.argument(BADGE, BadgeArgumentType.badge())
|
||||
.executes { executeRemove(it, EntityArgument.getPlayer(it, PLAYER)) }
|
||||
)
|
||||
)
|
||||
)
|
||||
dispatcher.register(command)
|
||||
}
|
||||
|
||||
private fun executeGive(context: CommandContext<CommandSourceStack>, player: ServerPlayer): Int {
|
||||
val badge = BadgeArgumentType.getBadge(context, BADGE)
|
||||
val changed = Cobblemon.playerDataManager.getBadgeData(player).give(badge)
|
||||
val message = if (changed) {
|
||||
"Gave ${badge.name} to ${player.name.string}."
|
||||
} else {
|
||||
"${player.name.string} already has ${badge.name}."
|
||||
}
|
||||
context.source.sendSuccess({ Component.literal(message) }, true)
|
||||
return Command.SINGLE_SUCCESS
|
||||
}
|
||||
|
||||
private fun executeRemove(context: CommandContext<CommandSourceStack>, player: ServerPlayer): Int {
|
||||
val badge = BadgeArgumentType.getBadge(context, BADGE)
|
||||
val changed = Cobblemon.playerDataManager.getBadgeData(player).remove(badge)
|
||||
val message = if (changed) {
|
||||
"Removed ${badge} from ${player.name.string}." // TODO move this to lang
|
||||
} else {
|
||||
"${player.name.string} does not have ${badge.name}."
|
||||
}
|
||||
context.source.sendSuccess({ Component.literal(message) }, true)
|
||||
return Command.SINGLE_SUCCESS
|
||||
}
|
||||
|
||||
private const val BADGE = "badge"
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.command.argument
|
||||
|
||||
import com.cobblemon.mod.common.api.badges.Badge
|
||||
import com.cobblemon.mod.common.api.badges.Badges
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.mojang.brigadier.StringReader
|
||||
import com.mojang.brigadier.arguments.ArgumentType
|
||||
import com.mojang.brigadier.context.CommandContext
|
||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType
|
||||
import com.mojang.brigadier.suggestion.Suggestions
|
||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder
|
||||
import net.minecraft.commands.SharedSuggestionProvider
|
||||
import net.minecraft.network.chat.Component
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
class BadgeArgumentType : ArgumentType<Badge> {
|
||||
|
||||
override fun parse(reader: StringReader): Badge {
|
||||
val identifier = try {
|
||||
reader.asIdentifierDefaultingNamespace()
|
||||
} catch (exception: Exception) {
|
||||
throw SimpleCommandExceptionType(INVALID_BADGE).createWithContext(reader)
|
||||
}
|
||||
return Badges.getByIdentifier(identifier)
|
||||
?: throw SimpleCommandExceptionType(INVALID_BADGE).createWithContext(reader)
|
||||
}
|
||||
|
||||
override fun <S : Any> listSuggestions(
|
||||
context: CommandContext<S>,
|
||||
builder: SuggestionsBuilder
|
||||
): CompletableFuture<Suggestions> {
|
||||
return SharedSuggestionProvider.suggest(Badges.all().map { it.identifier.toString() }, builder)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val INVALID_BADGE = Component.translatable("cobblemon.command.badge.invalid")
|
||||
|
||||
fun badge() = BadgeArgumentType()
|
||||
|
||||
fun <S> getBadge(context: CommandContext<S>, name: String): Badge =
|
||||
context.getArgument(name, Badge::class.java)
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.data
|
||||
import com.cobblemon.mod.common.*
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.api.abilities.Abilities
|
||||
import com.cobblemon.mod.common.api.badges.Badges
|
||||
import com.cobblemon.mod.common.api.berry.Berries
|
||||
import com.cobblemon.mod.common.api.cooking.Seasonings
|
||||
import com.cobblemon.mod.common.api.data.DataProvider
|
||||
@@ -120,6 +121,7 @@ object CobblemonDataProvider : DataProvider {
|
||||
this.register(SpawnBaitEffects, reloadable = false)
|
||||
this.register(CobblemonRideSettings, reloadable = true)
|
||||
this.register(TechnicalMachines, reloadable = false)
|
||||
this.register(Badges, reloadable = true)
|
||||
SpawnBait.Effects.setupEffects()
|
||||
|
||||
PlatformEvents.SERVER_PLAYER_LOGOUT.subscribe {
|
||||
|
||||
@@ -269,6 +269,7 @@ class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragMod
|
||||
attemptCatch(pokemonEntity)
|
||||
},
|
||||
ifCanceled = {
|
||||
captureFuture.complete(false)
|
||||
drop()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -78,10 +78,21 @@ object StatHandler : EventHandler {
|
||||
|
||||
fun onWinBattle(event : BattleVictoryEvent) {
|
||||
if (!event.wasWildCapture) {
|
||||
if(event.battle.isPvP) {
|
||||
event.winners
|
||||
.flatMap { it.getPlayerUUIDs().mapNotNull(UUID::getPlayer) }
|
||||
.forEach { player -> player.awardStat(getStat(Cobblemon.statistics.PVP_BATTLES_WON)) }
|
||||
event.losers
|
||||
.flatMap { it.getPlayerUUIDs().mapNotNull(UUID::getPlayer) }
|
||||
.forEach { player -> player.awardStat(getStat(Cobblemon.statistics.PVP_BATTLES_LOST)) }
|
||||
}
|
||||
if (event.battle.isPvW) {
|
||||
event.winners
|
||||
.flatMap { it.getPlayerUUIDs().mapNotNull(UUID::getPlayer) }
|
||||
.forEach { player -> player.awardStat(getStat(Cobblemon.statistics.BATTLES_WON)) }
|
||||
event.losers
|
||||
.flatMap { it.getPlayerUUIDs().mapNotNull(UUID::getPlayer) }
|
||||
.forEach { player -> player.awardStat(getStat(Cobblemon.statistics.BATTLES_LOST)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.badges.Badge
|
||||
import com.cobblemon.mod.common.api.badges.Badges
|
||||
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 net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class BadgeRegistrySyncPacket(badges: List<Badge>) : DataRegistrySyncPacket<Badge, BadgeRegistrySyncPacket>(badges) {
|
||||
companion object {
|
||||
val ID = cobblemonResource("badges")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = BadgeRegistrySyncPacket(emptyList()).apply { decodeBuffer(buffer) }
|
||||
}
|
||||
|
||||
|
||||
override val id = ID
|
||||
override fun encodeEntry(buffer: RegistryFriendlyByteBuf, entry: Badge) {
|
||||
buffer.writeIdentifier(entry.identifier)
|
||||
buffer.writeString(entry.name)
|
||||
buffer.writeResourceLocation(entry.texture)
|
||||
buffer.writeInt(entry.order)
|
||||
}
|
||||
|
||||
override fun decodeEntry(buffer: RegistryFriendlyByteBuf): Badge {
|
||||
return Badge(
|
||||
order = buffer.readInt(),
|
||||
texture = buffer.readResourceLocation(),
|
||||
name = buffer.readString(),
|
||||
identifier = buffer.readIdentifier()
|
||||
)
|
||||
}
|
||||
|
||||
override fun synchronizeDecoded(entries: Collection<Badge>) {
|
||||
Badges.reload(entries.associateBy { it.identifier })
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
+8
-3
@@ -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,7 +135,7 @@ 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("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() })
|
||||
@@ -164,7 +165,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 +180,4 @@ internal object PropertiesCompletionProvider : DataRegistry {
|
||||
val suggestions: Collection<String>
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -844,6 +844,19 @@
|
||||
"cobblemon.fossil.root": "Root",
|
||||
"cobblemon.fossil.sail": "Sail",
|
||||
"cobblemon.fossil.skull": "Skull",
|
||||
|
||||
"cobblemon.badge.unobtained": "?????",
|
||||
"cobblemon.badge.awesome_badge": "Awesome Badge",
|
||||
"cobblemon.badge.awesome_badge2": "Awesome Badge 2",
|
||||
"cobblemon.badge.dummy_badge": "Dummy Badge",
|
||||
"cobblemon.badge.dummy_badge2": "Dummy Badge 2",
|
||||
"cobblemon.badge.funny_badge": "Funny Badge",
|
||||
"cobblemon.badge.funny_badge2": "Funny Badge 2",
|
||||
"cobblemon.badge.interesting_badge": "Interesting Badge",
|
||||
"cobblemon.badge.interesting_badge2": "Interesting Badge 2",
|
||||
"cobblemon.badge.weird_badge": "Weird Badge",
|
||||
"cobblemon.badge.weird_badge2": "Weird Badge 2",
|
||||
|
||||
"cobblemon.gender.female": "Female",
|
||||
"cobblemon.gender.male": "Male",
|
||||
"cobblemon.gender.genderless": "Genderless",
|
||||
@@ -1199,10 +1212,13 @@
|
||||
"cobblemon.ui.edit.habitat.validation.min_light": "Min Light must be between 0 and 15.",
|
||||
"cobblemon.ui.edit.habitat.validation.max_light": "Max Light must be between 0 and 15.",
|
||||
|
||||
|
||||
"cobblemon.ui.pokenav.title": "PokéNav",
|
||||
"cobblemon.ui.pokenav.narrator.backbutton": "PokéNav button pressed",
|
||||
|
||||
"cobblemon.ui.trainermenu.timeplayed": "Time played: %1$s",
|
||||
"cobblemon.ui.trainermenu.pokemon_registered": "Pokémon registered: %1$s",
|
||||
"cobblemon.ui.trainermenu.battle_stats": "Win/loss rate: %1$s/%2$s",
|
||||
|
||||
"cobblemon.ui.summary.title": "Summary",
|
||||
"cobblemon.ui.starter.title": "Starter Selection",
|
||||
"cobblemon.ui.starter.choosebutton": "I choose you!",
|
||||
@@ -2387,6 +2403,7 @@
|
||||
"cobblemon.command.takemark": "%1$s was taken from %2$s's %3$s.",
|
||||
"cobblemon.command.takemark.does_not_have": "%1$s's %2$s does not have a %3$s!",
|
||||
"cobblemon.command.mark.invalid": "Invalid mark name.",
|
||||
"cobblemon.command.badge.invalid": "Invalid badge identifier.",
|
||||
"cobblemon.command.molang.out": "MoLang output: %1$s",
|
||||
"cobblemon.command.pokeheal.in_battle": "You cannot heal your party while in a battle!",
|
||||
"cobblemon.command.spawnpokemonfrompool": "A %1$s has spawned in the area.",
|
||||
@@ -9584,8 +9601,10 @@
|
||||
"cobblemon.snapshots.warning.dont_show_again_tip": "This setting may be ignored on newer Cobblemon snapshots (e.g. 1.7.0 vs 1.8.0)",
|
||||
"stat.cobblemon.battles_fled": "Pokémon Battles Fled",
|
||||
"stat.cobblemon.battles_lost": "Pokémon Battles Lost",
|
||||
"stat.cobblemon.pvp_battles_lost": "Trainer Battles Lost",
|
||||
"stat.cobblemon.battles_total": "Pokémon Total Battles",
|
||||
"stat.cobblemon.battles_won": "Pokémon Battles Won",
|
||||
"stat.cobblemon.pvp_battles_won": "Trainer Battles Won",
|
||||
"stat.cobblemon.captured": "Pokémon Captured",
|
||||
"stat.cobblemon.dex_entries": "Pokémon Pokédex Entries",
|
||||
"stat.cobblemon.eggs_collected": "Pokémon Eggs Collected",
|
||||
|
||||
@@ -5224,29 +5224,29 @@
|
||||
"cobblemon.species.kingambit.name": "ドドゲザン",
|
||||
"cobblemon.species.kingambit.desc": "ドドゲザンに 進化できるのは 大軍勢の 頂点に 立った 1匹の キリキザンだけなのだ。",
|
||||
"cobblemon.species.greattusk.name": "イダイナキバ",
|
||||
"cobblemon.species.greattusk.desc": "近年 目撃例が ある。 イダイナキバという 名は ある本に 記された 生物から 取られた。 ”§oパルデア未確認ファイル§r §oNo.09 太古から 生き続ける 恐竜!? 謎の生物 イダイナキバ§r §oパルデア某所にある 乾燥地帯において 謎の生物の 目撃が§r §o報告されている。 一見 ドンファンに 似た その生物は§r §o巨大な牙と 強固な鱗を 備えており 好戦的な性質を§r §o示したという。 現代に 生き残る 恐竜というのが 有力な説だが§r §oその正体は 不明。 イダイナキバ という名は かの奇書§r §oスカーレットブックに 記された 謎の生物から 命名されたと いわれる。§r” -謎のオカルト雑誌より引用",
|
||||
"cobblemon.species.greattusk.desc": "近年 目撃例が ある。 イダイナキバという 名は ある本に 記された 生物から 取られた。 ”パルデア未確認ファイル No.09 太古から 生き続ける 恐竜!? 謎の生物 イダイナキバ パルデア某所にある 乾燥地帯において 謎の生物の 目撃が 報告されている。 一見 ドンファンに 似た その生物は 巨大な牙と 強固な鱗を 備えており 好戦的な性質を 示したという。 現代に 生き残る 恐竜というのが 有力な説だが§r §oその正体は 不明。 イダイナキバ という名は かの奇書 スカーレットブックに 記された 謎の生物から 命名されたと いわれる。” §o-謎のオカルト雑誌より引用§r",
|
||||
"cobblemon.species.screamtail.name": "サケブシッポ",
|
||||
"cobblemon.species.screamtail.desc": "10億年前の プリンと オカルト雑誌が 紹介した 謎の ポケモンに 似ている。 ”§oパルデア未確認ファイル No.10§r §o10億年前の プリン 発見!? 謎の生物 サケブシッポ§r §oパルデア某所の 森で 目撃された 謎の生物が サケブシッポ§r §oである。 プリンに 酷似した 愛くるしさを 持っているが§r §o攻撃的な性質で 近づくものに 襲いかかるという。§r §o原始的な姿と 凶暴性から 一説には 10億年前の プリンと§r §o噂されている。 奇書 スカーレットブックに 記された§r §o叫ぶ尻尾と 呼ばれる 謎の生物が 名前の由来 である。§r” -謎のオカルト雑誌より引用",
|
||||
"cobblemon.species.screamtail.desc": "10億年前の プリンと オカルト雑誌が 紹介した 謎の ポケモンに 似ている。 ”パルデア未確認ファイル No.10 10億年前の プリン 発見!? 謎の生物 サケブシッポ パルデア某所の 森で 目撃された 謎の生物が サケブシッポ である。 プリンに 酷似した 愛くるしさを 持っているが 攻撃的な性質で 近づくものに 襲いかかるという。 原始的な姿と 凶暴性から 一説には 10億年前の プリンと 噂されている。 奇書 スカーレットブックに 記された 叫ぶ尻尾と 呼ばれる 謎の生物が 名前の由来 である。” §o-謎のオカルト雑誌より引用§r",
|
||||
"cobblemon.species.brutebonnet.name": "アラブルタケ",
|
||||
"cobblemon.species.brutebonnet.desc": "怪しい 雑誌が 恐竜と キノコの 合成と 紹介した ポケモンに 少し 似ているのだ。 ”§oパルデア未確認ファイル No.06§r §o恐竜?モロバレル? 謎の生物 アラブルタケ§r §o恐竜の特徴とモロバレルの特徴を あわせ持つと 噂される§r §o奇妙な生物。 奇書と 名高い スカーレットブックで 紹介された§r §o荒ぶる茸と 呼ばれる 謎の生物と おおむね 特徴が 一致。§r §oそこから この未確認生物は アラブルタケと 呼ばれるように§r §oなった。 通常の モロバレルより はるかに 身体は 巨大だが§r §o知性は低いようで 凶暴な ハードパンチャーらしい。§r” -謎のオカルト雑誌より引用",
|
||||
"cobblemon.species.brutebonnet.desc": "怪しい 雑誌が 恐竜と キノコの 合成と 紹介した ポケモンに 少し 似ているのだ。 ”パルデア未確認ファイル No.06 恐竜? モロバレル? 謎の生物 アラブルタケ 恐竜の特徴とモロバレルの特徴を あわせ持つと 噂される 奇妙な生物。 奇書と 名高い スカーレットブックで 紹介された 荒ぶる茸と 呼ばれる 謎の生物と おおむね 特徴が 一致。 そこから この未確認生物は アラブルタケと 呼ばれるように なった。 通常の モロバレルより はるかに 身体は 巨大だが 知性は低いようで 凶暴な ハードパンチャーらしい。” §o-謎のオカルト雑誌より引用§r",
|
||||
"cobblemon.species.fluttermane.name": "ハバタクカミ",
|
||||
"cobblemon.species.fluttermane.desc": "オカルト雑誌で 取り上げられた 翼竜の 幽霊と 特徴だけは 似ているのだ。 ”§oパルデア未確認ファイル No.05§r §o翼竜のゴースト!? 謎の生物 ハバタクカミ§r §oその名はスカーレットブックと 呼ばれる 奇書の中に 登場する§r §o謎の生物から 名づけられた。 長い体毛を くねらせ 夜空を§r §oゆらゆらと 飛びまわると いわれる。 目撃者からの§r §o証言によると 一見 巨大なムウマの ようだが 気性が§r §oとても荒く 好戦的とのこと。 古代に 生息した 翼竜の魂から§r §o生まれた ゴーストという 説もある。§r” -謎のオカルト雑誌より引用",
|
||||
"cobblemon.species.fluttermane.desc": "オカルト雑誌で 取り上げられた 翼竜の 幽霊と 特徴だけは 似ているのだ。 ”パルデア未確認ファイル No.05 翼竜のゴースト!? 謎の生物 ハバタクカミその名は スカーレットブックと 呼ばれる 奇書の中に 登場する 謎の生物から 名づけられた。 長い体毛を くねらせ 夜空を ゆらゆらと 飛びまわると いわれる。 目撃者からの 証言によると 一見 巨大なムウマの ようだが 気性が とても荒く 好戦的とのこと。 古代に 生息した 翼竜の魂から 生まれた ゴーストという 説もある。” §o-謎のオカルト雑誌より引用§r",
|
||||
"cobblemon.species.slitherwing.name": "チヲハウハネ",
|
||||
"cobblemon.species.slitherwing.desc": "古い 本で チヲハウハネと 紹介されている 生物に 似た点が ある 謎のポケモン。 ”§oパルデア未確認ファイル No.08§r §o蘇った太古の ウルガモス!? 謎の生物 チヲハウハネ§r §o目撃情報が少なく 極めて 謎の多い 未確認生物が チヲハウハネ§r §oである。 その名は 奇書として 知られる スカーレットブックに§r §o記された 謎の生物に ちなんで 名づけられた。 かつて 本誌が§r §oとりあげた 原始時代の ウルガモスと 共通する特徴が あり§r §o化石から 復元したとも 考えられる。 だが 過去に§r §oウルガモスの化石が 発見された記録は 存在していない。§r” -謎のオカルト雑誌より引用",
|
||||
"cobblemon.species.slitherwing.desc": "古い 本で チヲハウハネと 紹介されている 生物に 似た点が ある 謎のポケモン。 ”パルデア未確認ファイル No.08 蘇った太古の ウルガモス!? 謎の生物 チヲハウハネ 目撃情報が少なく 極めて 謎の多い 未確認生物が チヲハウハネ である。 その名は 奇書として 知られる スカーレットブックに 記された 謎の生物に ちなんで 名づけられた。 かつて 本誌が§r §oとりあげた 原始時代の ウルガモスと 共通する特徴が あり 化石から 復元したとも 考えられる。 だが 過去に ウルガモスの化石が 発見された記録は 存在していない。§r” §o-謎のオカルト雑誌より引用§r",
|
||||
"cobblemon.species.sandyshocks.name": "スナノケガワ",
|
||||
"cobblemon.species.sandyshocks.desc": "オカルト雑誌の 記事にあった 1万年 生きた レアコイルの 姿に やや 似ている。 ”§oパルデア未確認ファイル No.07§r §o寿命1万年の レアコイル!? 謎の生物 スナノケガワ§r §o1万年生きた レアコイルの姿だと 主張する 科学者もいる§r §o謎の生物。 パルデアの 乾燥地帯を 中心に 数件の 目撃報告が§r §oあるものの いまだ 捕獲されたという 記録はない。§r §o攻撃的な性質で 目撃者が 襲われるケースも あるという。§r §o世紀の奇書 スカーレットブックで 紹介された 砂の毛皮と§r §o呼ばれる 謎の生物と 特徴が 一致している。§r” -謎のオカルト雑誌より引用",
|
||||
"cobblemon.species.sandyshocks.desc": "オカルト雑誌の 記事にあった 1万年 生きた レアコイルの 姿に やや 似ている。 ”パルデア未確認ファイル No.07 寿命1万年の レアコイル!? 謎の生物 スナノケガワ 1万年生きた レアコイルの姿だと 主張する 科学者もいる 謎の生物。 パルデアの 乾燥地帯を 中心に 数件の 目撃報告が あるものの いまだ 捕獲されたという 記録はない。 攻撃的な性質で 目撃者が 襲われるケースも あるという。 世紀の奇書 スカーレットブックで 紹介された 砂の毛皮と 呼ばれる 謎の生物と 特徴が 一致している。” §o-謎のオカルト雑誌より引用§r",
|
||||
"cobblemon.species.irontreads.name": "テツノワダチ",
|
||||
"cobblemon.species.irontreads.desc": "オカルト雑誌が 紹介した 宇宙人が 送り込んできた 科学兵器に よく 似ている。 ”§oパルデア未確認ファイル No.09§r §o宇宙人の科学兵器か!? 謎の物体 テツノワダチ§r §oパルデア某所にある 乾燥地帯において 謎の生物の 目撃が§r §o報告されている。 一見 ドンファンに 似た その生物は 突如§r §o球体に 変化すると 高速で 回転し 襲いかかってきたという。§r §o宇宙人の 科学兵器では ないかという 噂もあるが 真相は§r §o不明。 テツノワダチ という名は かの奇書§r §oバイオレットブックに 記された 謎の物体から 命名されたと§r §oいわれる。§r” -謎のオカルト雑誌より引用",
|
||||
"cobblemon.species.irontreads.desc": "オカルト雑誌が 紹介した 宇宙人が 送り込んできた 科学兵器に よく 似ている。 ”パルデア未確認ファイル No.09 宇宙人の科学兵器か!? 謎の物体 テツノワダチ パルデア某所にある 乾燥地帯において 謎の生物の 目撃が 報告されている。 一見 ドンファンに 似た その生物は 突如 球体に 変化すると 高速で 回転し 襲いかかってきたという。 宇宙人の 科学兵器では ないかという 噂もあるが 真相は 不明。 テツノワダチ という名は かの奇書 バイオレットブックに 記された 謎の物体から 命名されたと いわれる。” §o-謎のオカルト雑誌より引用§r",
|
||||
"cobblemon.species.ironbundle.name": "テツノツツミ",
|
||||
"cobblemon.species.ironbundle.desc": "オカルト雑誌の 記事になった 太古の 文明が 生み出した ロボットに 形が 似ている。 ”§oパルデア未確認ファイル No.10§r §o太古の文明が 生んだ ロボット!? 謎の物体 テツノツツミ§r §o奇書バイオレットブックに 書かれた 謎の物体が 名前の由来§r §oである。 デリバードに 似た 形状をしており 球体の装置から§r §o膨大な氷を 噴射し 雪原を 移動するという。 正体に 関しては§r §o多くの説が あるが 超古代文明の産物 という説が 有力。§r §o太古の文献に テツノツツミ らしき 機械を 設計し§r §o使役していたという 記録が 残っているのだ。§r” -謎のオカルト雑誌より引用",
|
||||
"cobblemon.species.ironbundle.desc": "オカルト雑誌の 記事になった 太古の 文明が 生み出した ロボットに 形が 似ている。 ”パルデア未確認ファイル No.10 太古の文明が 生んだ ロボット!? 謎の物体 テツノツツミ 奇書 バイオレットブックに 書かれた 謎の物体が 名前の由来 である。 デリバードに 似た 形状をしており 球体の装置から 膨大な氷を 噴射し 雪原を 移動するという。 正体に 関しては 多くの説が あるが 超古代文明の産物 という説が 有力。 太古の文献に テツノツツミ らしき 機械を 設計し 使役していたという 記録が 残っているのだ。” §o-謎のオカルト雑誌より引用§r",
|
||||
"cobblemon.species.ironhands.name": "テツノカイナ",
|
||||
"cobblemon.species.ironhands.desc": "あるアスリートが 改造された 姿だと オカルト雑誌が スクープした サイボーグに 近い。 ”§oパルデア未確認ファイル§r §oNo.05 その正体は サイボーグ!? 謎の物体 テツノカイナ§r §o世紀の奇書 バイオレットブックに 記された 鉄の腕と 呼ばれる§r §o謎の物体から 命名された。 自在に動く 掌で 高速で§r §o走っていた 大型車両を 投げ飛ばしたという。 テツノカイナの§r §o正体として 有力なのは 瀕死の重傷を 負った アスリートが§r §oサイボーグ化した という説である。 ただ 何故 ハリテヤマを§r §o模した姿に なったのかは 謎に つつまれているのだ。§r” -謎のオカルト雑誌より引用",
|
||||
"cobblemon.species.ironhands.desc": "あるアスリートが 改造された 姿だと オカルト雑誌が スクープした サイボーグに 近い。 ”パルデア未確認ファイル No.05 その正体は サイボーグ!? 謎の物体 テツノカイナ 世紀の奇書 バイオレットブックに 記された 鉄の腕と 呼ばれる 謎の物体から 命名された。 自在に動く 掌で 高速で 走っていた 大型車両を 投げ飛ばしたという。 テツノカイナの 正体として 有力なのは 瀕死の重傷を 負った アスリートが サイボーグ化した という説である。 ただ 何故 ハリテヤマを 模した姿に なったのかは 謎に つつまれているのだ。” §o-謎のオカルト雑誌より引用§r",
|
||||
"cobblemon.species.ironjugulis.name": "テツノコウベ",
|
||||
"cobblemon.species.ironjugulis.desc": "ロボットに 恋した サザンドラの 子どもと オカルト雑誌が 取り上げた ポケモンに 似ている。 ”§oパルデア未確認ファイル§r §oNo.07 機械!? ポケモン!? 謎の物体 テツノコウベ§r §oパルデア某所にて 目撃された サザンドラに 似た 危険な§r §o飛行物体。 高エネルギーを 放射し 建造物を 徹底的に§r §o破壊すると 次の標的を 求めるように§r §o飛び去っていったという。 サザンドラの凶暴性と§r §o機械の冷酷さを あわせ持つため 機械と サザンドラの§r §oハイブリッドなのではと 噂される。 奇書§r §oバイオレットブックに 書かれた 謎の物体が 名前の由来§r §oである。§r” -謎のオカルト雑誌より引用",
|
||||
"cobblemon.species.ironjugulis.desc": "ロボットに 恋した サザンドラの 子どもと オカルト雑誌が 取り上げた ポケモンに 似ている。 ”パルデア未確認ファイル No.07 機械!? ポケモン!? 謎の物体 テツノコウベ パルデア某所にて 目撃された サザンドラに 似た 危険な 飛行物体。 高エネルギーを 放射し 建造物を 徹底的に 破壊すると 次の標的を 求めるように 飛び去っていったという。 サザンドラの凶暴性と 機械の冷酷さを あわせ持つため 機械と サザンドラの ハイブリッドなのではと 噂される。 奇書 バイオレットブックに 書かれた 謎の物体が 名前の由来 である。” §o-謎のオカルト雑誌より引用§r",
|
||||
"cobblemon.species.ironmoth.name": "テツノドクガ",
|
||||
"cobblemon.species.ironmoth.desc": "人類を 監視する UFOだと オカルト雑誌が 紹介した 未知の 物体に 似ている。 ”§oパルデア未確認ファイル No.08§r §o人類を監視する UFO!? 謎の物体 テツノドクガ§r §o世紀の奇書バイオレットブックに 登場する 謎の物体から§r §o命名された。 ウルガモスに 似た 飛行物体であり 上空から§r §o地上の人々を 追尾し 時に 襲いかかってくることが§r §oあるという。 攻撃的な性質を 持つ 理由として テツノドクガの§r §o正体は 宇宙人が あやつる UFOだという 説がある。§r §oテツノドクガを 使い 人類を 監視し 侵略の機会を§r §oうかがっているかもしれない。§r” -謎のオカルト雑誌より引用",
|
||||
"cobblemon.species.ironmoth.desc": "人類を 監視する UFOだと オカルト雑誌が 紹介した 未知の 物体に 似ている。 ”パルデア未確認ファイル No.08 人類を監視する UFO!? 謎の物体 テツノドクガ 世紀の奇書 バイオレットブックに 登場する 謎の物体から 命名された。 ウルガモスに 似た 飛行物体であり 上空から 地上の人々を 追尾し 時に 襲いかかってくることが あるという。 攻撃的な性質を 持つ 理由として テツノドクガの 正体は 宇宙人が あやつる UFOだという 説がある。 テツノドクガを 使い 人類を 監視し 侵略の機会を うかがっているかもしれない。” §o-謎のオカルト雑誌より引用§r",
|
||||
"cobblemon.species.ironthorns.name": "テツノイバラ",
|
||||
"cobblemon.species.ironthorns.desc": "10億年後の バンギラスと 怪しい 雑誌が 取り上げていた ポケモンに 似た 部分が ある。 ”§oパルデア未確認ファイル§r §oNo.06 10億年後の バンギラス!? 謎の物体 テツノイバラ§r §oパルデア某所 とある洞くつで 目撃された 謎の物体が§r §oテツノイバラ である。 バンギラスに 酷似しているが 極めて§r §o冷徹な性質を 持つとともに 無駄な争いを 好まないという。§r §o金属質の装甲や 高い知性から 10億年後の バンギラスと§r §o噂されている。 奇書 バイオレットブックに 記された 鉄の茨と§r §o呼ばれる 謎の物体が 名前の由来に なっている。§r” -謎のオカルト雑誌より引用",
|
||||
"cobblemon.species.ironthorns.desc": "10億年後の バンギラスと 怪しい 雑誌が 取り上げていた ポケモンに 似た 部分が ある。 ”パルデア未確認ファイル No.06 10億年後の バンギラス!? 謎の物体 テツノイバラ パルデア某所 とある洞くつで 目撃された 謎の物体が テツノイバラ である。 バンギラスに 酷似しているが 極めて 冷徹な性質を 持つとともに 無駄な争いを 好まないという。 金属質の装甲や 高い知性から 10億年後の バンギラスと 噂されている。 奇書 バイオレットブックに 記された 鉄の茨と 呼ばれる 謎の物体が 名前の由来に なっている。” §o-謎のオカルト雑誌より引用§r",
|
||||
"cobblemon.species.frigibax.name": "セビエ",
|
||||
"cobblemon.species.frigibax.desc": "背びれで 熱を 吸収して 氷エネルギーに 変換する。 高温ほど エネルギーが 溜まる。",
|
||||
"cobblemon.species.arctibax.name": "セゴール",
|
||||
@@ -5266,9 +5266,9 @@
|
||||
"cobblemon.species.chiyu.name": "イーユイ",
|
||||
"cobblemon.species.chiyu.desc": "多くの 争いの 火種となった 勾玉に 集まった 妬みが 炎を まとい ポケモンとなった。",
|
||||
"cobblemon.species.roaringmoon.name": "トドロクツキ",
|
||||
"cobblemon.species.roaringmoon.desc": "謎の 多い 探検記の中で トドロクツキという 名で 記された 生物の 可能性が ある。 ”§oパルデア未確認ファイル No.04§r §o原始の ボーマンダ!? §o謎の生物 トドロクツキ§r §o奇書スカーレットブックに 書かれた 謎の生物が 名前の由来に§r §oなっている。 その姿は ほかの地方で ボーマンダに 発生する§r §oとある現象の 結果に 酷似しているが 関連性は 不明。 羽毛を§r §oまき散らしながら 高速で 飛びまわり 獲物を 襲う。 その§r §o凶暴な性質は ボーマンダ以上と 考えられており§r §o遭遇することが あっても 絶対に 接触を 避けるべきである。§r” -謎のオカルト雑誌より引用",
|
||||
"cobblemon.species.roaringmoon.desc": "謎の 多い 探検記の中で トドロクツキという 名で 記された 生物の 可能性が ある。 ”パルデア未確認ファイル No.04 原始の ボーマンダ!? 謎の生物 トドロクツキ 奇書 スカーレットブックに 書かれた 謎の生物が 名前の由来に なっている。 その姿は ほかの地方で ボーマンダに 発生する とある現象の 結果に 酷似しているが 関連性は 不明。 羽毛を まき散らしながら 高速で 飛びまわり 獲物を 襲う。 その 凶暴な性質は ボーマンダ以上と 考えられており 遭遇することが あっても 絶対に 接触を 避けるべきである。” §o-謎のオカルト雑誌より引用§r",
|
||||
"cobblemon.species.ironvaliant.name": "テツノブジン",
|
||||
"cobblemon.species.ironvaliant.desc": "オカルト雑誌の 記事に あった マッドサイエンティストの 発明と 近い 特徴が いくつかある。 ”§oパルデア未確認ファイル§r §oNo.04 博士の 異常な発明!? 謎の物体 テツノブジン§r §o奇書バイオレットブックに 書かれた 謎の物体が 名前の由来に§r §oなっている。 最強の エスパーポケモンを 求める§r §oマッドサイエンティストに よって 造られた ロボットという§r §o説がある。 数少ない 目撃者からの 証言によるとサーナイトと§r §oエルレイド どちらにも見えるような 奇妙な姿を§r §oしており対峙する者は 光りかがやく刃で 躊躇なく 切り捨てる§r §o残酷さを 持っているという。§r” -謎のオカルト雑誌より引用",
|
||||
"cobblemon.species.ironvaliant.desc": "オカルト雑誌の 記事に あった マッドサイエンティストの 発明と 近い 特徴が いくつかある。 ”パルデア未確認ファイル No.04 博士の 異常な発明!? 謎の物体 テツノブジン 奇書 バイオレットブックに 書かれた 謎の物体が 名前の由来に なっている。 最強の エスパーポケモンを 求める マッドサイエンティストに よって 造られた ロボットという 説がある。 数少ない 目撃者からの 証言によるとサーナイトと エルレイド どちらにも見えるような 奇妙な姿を しており対峙する者は 光りかがやく刃で 躊躇なく 切り捨てる 残酷さを 持っているという。” §o-謎のオカルト雑誌より引用§r",
|
||||
"cobblemon.species.koraidon.name": "コライドン",
|
||||
"cobblemon.species.koraidon.desc": "拳で 大地を 引き裂いたと 古い 探検記に 記された §oツバサノオウ§rの 正体らしい。",
|
||||
"cobblemon.species.miraidon.name": "ミライドン",
|
||||
@@ -5957,7 +5957,7 @@
|
||||
"item.cobblemon.galarica_nuts": "ガラナツのナッツ",
|
||||
"cobblemon.pokerod.apply": "右クリックでエサを付ける",
|
||||
"item.cobblemon.npc_editor": "NPCのトレーナーカード",
|
||||
"item.cobblemon.link_cable.tooltip": "なにかしらのつながりを感じさせる 不思議なエネルギーを秘めているヒモ。 ポケモン交換で進化するポケモンを進化させる。",
|
||||
"item.cobblemon.link_cable.tooltip": "ポケモン交換で進化するポケモンを進化させられるヒモ。",
|
||||
"item.cobblemon.dragon_scale.tooltip": "硬くて 丈夫な ウロコ。 シードラに持たせてポケモン交換すると キングドラに進化する。",
|
||||
"item.cobblemon.kings_rock.tooltip_1": "持たせると 攻撃して ダメージを 与えたときに 相手を ひるませることが ある。",
|
||||
"item.cobblemon.metal_coat.tooltip_1": "特殊な金属の 膜。 持たせると はがねタイプの 技の威力が 上がる。",
|
||||
@@ -5968,11 +5968,11 @@
|
||||
"item.cobblemon.deep_sea_scale.tooltip_2": "パールルに持たせてポケモン交換すると サクラビスに進化する。",
|
||||
"item.cobblemon.deep_sea_tooth.tooltip_1": "パールルに 持たせると 特攻が あがる キバ。",
|
||||
"item.cobblemon.deep_sea_tooth.tooltip_2": "パールルに持たせてポケモン交換すると ハンテールに進化する。",
|
||||
"item.cobblemon.electirizer.tooltip": "とてつもない 電気の エネルギーが 蓄えられている 箱。 エレブーに持たせてポケモン交換すると エレキブルに進化する。",
|
||||
"item.cobblemon.magmarizer.tooltip": "とてつもない マグマの エネルギーが 蓄えられている 箱。 ブーバーに持たせてポケモン交換すると ブーバーンに進化する。",
|
||||
"item.cobblemon.electirizer.tooltip": "電気が蓄えられた箱。 エレブーに持たせてポケモン交換すると エレキブルに進化する。",
|
||||
"item.cobblemon.magmarizer.tooltip": "マグマが蓄えられた箱。 ブーバーに持たせてポケモン交換すると ブーバーンに進化する。",
|
||||
"item.cobblemon.oval_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。 たまのように まるい。",
|
||||
"item.cobblemon.reaper_cloth.tooltip": "おそろしく 強い霊力が こめられている 布。 サマヨールに持たせてポケモン交換すると ヨノワールに進化する。",
|
||||
"item.cobblemon.sachet.tooltip": "ちょっと きつめの 香りをだす 香料を 詰めた 袋。 シュシュプに持たせてポケモン交換すると フレフワンに進化する。",
|
||||
"item.cobblemon.sachet.tooltip": "きつめの 香料を 詰めた 袋。 シュシュプに持たせてポケモン交換すると フレフワンに進化する。",
|
||||
"item.cobblemon.strawberry_sweet.tooltip": "いちごの形をした アメ細工。 マホミルに使うと いちごのアメざいくを身に付けた マホイップになる。",
|
||||
"item.cobblemon.berry_sweet.tooltip": "ベリーの形をした アメ細工。 マホミルに使うと ベリーのアメざいくを身に付けた マホイップになる。",
|
||||
"item.cobblemon.clover_sweet.tooltip": "よつばの形をした アメ細工。 マホミルに使うと よつばのアメざいくを身に付けた マホイップになる。",
|
||||
@@ -6052,7 +6052,7 @@
|
||||
"item.cobblemon.grass_gem.tooltip_2": "使うとなくなる。",
|
||||
"item.cobblemon.dragon_gem.tooltip_2": "使うとなくなる。",
|
||||
"item.cobblemon.ghost_gem.tooltip_2": "使うとなくなる。",
|
||||
"item.cobblemon.whipped_dream.tooltip": "ふんわり ふわふわに 泡立てた ほんのり 甘い クリーム。 ペロッパフに持たせてポケモン交換すると ペロリームに進化する。",
|
||||
"item.cobblemon.whipped_dream.tooltip": "ふわふわに 泡立てた クリーム。 ペロッパフに持たせてポケモン交換すると ペロリームに進化する。",
|
||||
"item.cobblemon.sun_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。 太陽のように 赤い。",
|
||||
"item.cobblemon.prism_scale.tooltip": "にじ色に 輝く 不思議なウロコ。 ヒンバスに持たせてポケモン交換すると ミロカロスに進化する。",
|
||||
"item.cobblemon.love_sweet.tooltip": "ハートの形をした アメ細工。 マホミルに使うと ハートのアメざいくを身に付けた マホイップになる。",
|
||||
@@ -6115,7 +6115,7 @@
|
||||
"item.cobblemon.poison_barb.tooltip": "どくのある ちいさな ハリ。 持たせると どくタイプの 技の威力が あがる。",
|
||||
"item.cobblemon.punching_glove.tooltip": "こぶしを 保護する グローブ。 持たせると パンチ技の 威力が あがり 相手に 接触しない パンチに なる。",
|
||||
"item.cobblemon.quick_claw.tooltip": "軽くて 鋭い ツメ。 持たせると 相手より 先に 行動できることが ある。",
|
||||
"item.cobblemon.razor_fang.tooltip_1": "鋭く とがった キバ。持たせると ダメージを 与えたとき ひるませることが ある。",
|
||||
"item.cobblemon.razor_fang.tooltip_1": "鋭く とがった キバ。 持たせると ダメージを 与えたとき ひるませることが ある。",
|
||||
"item.cobblemon.razor_fang.tooltip_2": "グライガーに 持たせると、 夜にグライオンに進化する。",
|
||||
"item.cobblemon.red_card.tooltip_1": "不思議な ちからのある カード。 持たせると ダメージを 与えてきた 相手を 控えに 退場させることが できる。",
|
||||
"item.cobblemon.rocky_helmet.tooltip": "ポケモンに 持たせると 自分に さわった相手に ダメージを 与える。",
|
||||
@@ -6254,7 +6254,7 @@
|
||||
"cobblemon.trade.accept.receiver": "あなたは %1$s の交換リクエストを受け入れました!",
|
||||
"item.cobblemon.safety_goggles.tooltip": "天候の ダメージだけでなく 粉を だす 技の 効果も 防げる ゴーグル。",
|
||||
"item.cobblemon.shell_bell.tooltip": "持たせた ポケモンが 攻撃して 相手に ダメージを あたえたとき HPを 少し 回復できる。",
|
||||
"item.cobblemon.shell_helmet.tooltip": "とあるポケモンが身に付けていた殻。 カブルモに使うと シュバルゴに進化する。",
|
||||
"item.cobblemon.shell_helmet.tooltip": "とあるポケモンが 身に付けていた 殻。 カブルモに使うと シュバルゴに進化する。",
|
||||
"cobblemon.trade.expired.sender": "%1$s との交換リクエストがタイムアウトしました。",
|
||||
"item.cobblemon.ground_gem.tooltip_1": "じめんのタイプの ジュエル。 持たせると 1度だけ じめんの 技の威力が 強まる。",
|
||||
"item.cobblemon.x_attack.tooltip": "戦闘中の ポケモンの 攻撃を 2段階 あげる 道具。 ひっこめると 元に 戻る。",
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "cobblemon.badge.awesome_badge",
|
||||
"texture": "cobblemon:textures/gui/mark/mark_alpha.png",
|
||||
"order": 2
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "cobblemon.badge.awesome_badge2",
|
||||
"texture": "cobblemon:textures/gui/mark/mark_alpha.png",
|
||||
"order": 6
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "cobblemon.badge.dummy_badge",
|
||||
"texture": "cobblemon:textures/gui/mark/mark_gourmand.png",
|
||||
"order": 1
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "cobblemon.badge.dummy_badge",
|
||||
"texture": "cobblemon:textures/gui/mark/mark_gourmand.png",
|
||||
"order": 7
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "cobblemon.badge.funny_badge",
|
||||
"texture": "cobblemon:textures/gui/mark/mark_destiny.png",
|
||||
"order": 5
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "cobblemon.badge.funny_badge",
|
||||
"texture": "cobblemon:textures/gui/mark/mark_destiny.png",
|
||||
"order": 8
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "cobblemon.badge.interesting_badge",
|
||||
"texture": "cobblemon:textures/gui/mark/mark_fishing.png",
|
||||
"order": 4
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "cobblemon.badge.interesting_badge",
|
||||
"texture": "cobblemon:textures/gui/mark/mark_fishing.png",
|
||||
"order": 9
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "cobblemon.badge.weird_badge",
|
||||
"texture": "cobblemon:textures/gui/mark/mark_curry.png",
|
||||
"order": 3
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "cobblemon.badge.weird_badge",
|
||||
"texture": "cobblemon:textures/gui/mark/mark_curry.png",
|
||||
"order": 10
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"type": "cobblemon:cooking_pot_shapeless",
|
||||
"category": "medicines",
|
||||
"category": "misc",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "cobblemon:exp_candy_m"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"type": "cobblemon:cooking_pot_shapeless",
|
||||
"category": "medicines",
|
||||
"category": "misc",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "cobblemon:exp_candy_s"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"type": "cobblemon:cooking_pot_shapeless",
|
||||
"category": "medicines",
|
||||
"category": "misc",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "cobblemon:exp_candy_xs"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"type": "cobblemon:cooking_pot_shapeless",
|
||||
"category": "medicines",
|
||||
"category": "misc",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "cobblemon:exp_candy_l"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"type": "cobblemon:cooking_pot_shapeless",
|
||||
"category": "medicines",
|
||||
"category": "misc",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "minecraft:sculk"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"injectors": {
|
||||
"maxShiftBy": 2
|
||||
},
|
||||
"mixinextras": {"minVersion": "0.5.0"},
|
||||
"client": [
|
||||
"BuiltinModelItemRendererMixin",
|
||||
"EntityRenderDispatcherMixin",
|
||||
|
||||
@@ -85,6 +85,9 @@ dependencies {
|
||||
|
||||
minecraftServerLibraries(libs.icu4j)
|
||||
|
||||
// AppleSkin stores api under `api` classifier in their coordinates
|
||||
// Because of that, we cannot just add it to integrations bundle
|
||||
modCompileOnly(variantOf(libs.appleskin.api.fabric) { classifier("api") })
|
||||
}
|
||||
|
||||
publishing {
|
||||
|
||||
@@ -56,7 +56,7 @@ public class RecipeBookCategoriesMixin {
|
||||
types.add(cobblemon$createCategory("COBBLEMON_COOKING_POT_FOODS", $VALUES.length + 1, new ItemStack(CobblemonItems.LEEK_AND_POTATO_STEW)));
|
||||
types.add(cobblemon$createCategory("COBBLEMON_COOKING_POT_MEDICINES", $VALUES.length + 2, new ItemStack(CobblemonItems.POTION)));
|
||||
types.add(cobblemon$createCategory("COBBLEMON_COOKING_POT_COMPLEX_DISHES", $VALUES.length + 3, new ItemStack(CobblemonItems.APRIJUICE_RED)));
|
||||
types.add(cobblemon$createCategory("COBBLEMON_COOKING_POT_MISC", $VALUES.length + 4, new ItemStack(CobblemonItems.PROTEIN)));
|
||||
types.add(cobblemon$createCategory("COBBLEMON_COOKING_POT_MISC", $VALUES.length + 4, new ItemStack(CobblemonItems.HEALTH_CANDY)));
|
||||
$VALUES = types.toArray(RecipeBookCategories[]::new);
|
||||
}
|
||||
|
||||
|
||||
+6
-11
@@ -11,27 +11,22 @@ package com.cobblemon.mod.fabric.mixin;
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents;
|
||||
import com.cobblemon.mod.common.platform.events.ServerPlayerTickEvent;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(Player.class)
|
||||
public class PlayerMixin {
|
||||
@Mixin(ServerPlayer.class)
|
||||
public class ServerPlayerMixin {
|
||||
@Inject(method = "tick", at = @At("HEAD"))
|
||||
private void onPreTick(CallbackInfo ci) {
|
||||
Player player = (Player)(Object)this;
|
||||
if (player instanceof ServerPlayer) {
|
||||
PlatformEvents.SERVER_PLAYER_TICK_PRE.emit(new ServerPlayerTickEvent.Pre((ServerPlayer)player));
|
||||
}
|
||||
ServerPlayer player = (ServerPlayer)(Object)this;
|
||||
PlatformEvents.SERVER_PLAYER_TICK_PRE.emit(new ServerPlayerTickEvent.Pre(player));
|
||||
}
|
||||
|
||||
@Inject(method = "tick", at = @At("TAIL"))
|
||||
private void onPostTick(CallbackInfo ci) {
|
||||
Player player = (Player)(Object)this;
|
||||
if (player instanceof ServerPlayer) {
|
||||
PlatformEvents.SERVER_PLAYER_TICK_POST.emit(new ServerPlayerTickEvent.Post((ServerPlayer)player));
|
||||
}
|
||||
ServerPlayer player = (ServerPlayer)(Object)this;
|
||||
PlatformEvents.SERVER_PLAYER_TICK_POST.emit(new ServerPlayerTickEvent.Post(player));
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback
|
||||
import net.fabricmc.fabric.api.entity.event.v1.EntitySleepEvents
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerEntityWorldChangeEvents
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents
|
||||
import net.fabricmc.fabric.api.event.player.UseBlockCallback
|
||||
@@ -175,6 +176,7 @@ object CobblemonFabric : CobblemonImplementation {
|
||||
ServerPlayConnectionEvents.DISCONNECT.register { handler, server ->
|
||||
if (!server.isStopped) server.executeIfPossible { PlatformEvents.SERVER_PLAYER_LOGOUT.post(ServerPlayerEvent.Logout(handler.player)) }
|
||||
}
|
||||
ServerPlayerEvents.AFTER_RESPAWN.register { oldPlayer, newPlayer, alive -> PlatformEvents.PLAYER_RESPAWN.post(ServerPlayerEvent.Respawn(newPlayer)) }
|
||||
ServerLivingEntityEvents.ALLOW_DEATH.register { entity, _, _ ->
|
||||
if (entity is ServerPlayer) {
|
||||
PlatformEvents.PLAYER_DEATH.postThen(
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.fabric.client.integration.appleskin
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import squeek.appleskin.api.AppleSkinApi
|
||||
import squeek.appleskin.api.event.HUDOverlayEvent
|
||||
|
||||
class AppleSkinClientEventHandler: AppleSkinApi {
|
||||
override fun registerEvents() {
|
||||
HUDOverlayEvent.Exhaustion.EVENT.register(::checkIsScanning)
|
||||
HUDOverlayEvent.Saturation.EVENT.register(::checkIsScanning)
|
||||
HUDOverlayEvent.HealthRestored.EVENT.register(::checkIsScanning)
|
||||
HUDOverlayEvent.HungerRestored.EVENT.register(::checkIsScanning)
|
||||
}
|
||||
|
||||
private fun checkIsScanning(e: HUDOverlayEvent) {
|
||||
if (CobblemonClient.pokedexUsageContext.scanningGuiOpen) {
|
||||
e.isCanceled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,9 @@
|
||||
],
|
||||
"modmenu": [
|
||||
"com.cobblemon.mod.fabric.client.integration.modmenu.CobblemonModMenu"
|
||||
],
|
||||
"appleskin": [
|
||||
"com.cobblemon.mod.fabric.client.integration.appleskin.AppleSkinClientEventHandler"
|
||||
]
|
||||
},
|
||||
"mixins": [
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"EntityMixin",
|
||||
"FabricBrewingStandMenuMixin",
|
||||
"FabricSoundEngineMixin",
|
||||
"PlayerMixin",
|
||||
"ServerPlayerMixin",
|
||||
"RecipeBookSettingsMixin",
|
||||
"RecipeBookTypeMixin",
|
||||
"ServerEntityMixin"
|
||||
|
||||
+2
-2
@@ -14,7 +14,7 @@ parchment_version = 2024.07.28@zip
|
||||
java_version = 21
|
||||
|
||||
mod_id=cobblemon
|
||||
mod_version=1.8.2
|
||||
snapshot=false
|
||||
mod_version=1.8.3
|
||||
snapshot=true
|
||||
|
||||
fabric.loom.multiProjectOptimisation=false
|
||||
@@ -37,6 +37,9 @@ repositories {
|
||||
//JEI
|
||||
maven("https://maven.blamejared.com/")
|
||||
maven("https://maven.parchmentmc.org")
|
||||
|
||||
// AppleSkin
|
||||
maven("https://maven.ryanliptak.com/")
|
||||
}
|
||||
|
||||
license {
|
||||
|
||||
@@ -16,6 +16,7 @@ moddev = "1.0.11"
|
||||
# Common
|
||||
molang = "1.1.20"
|
||||
jei-api = "19.22.1.316"
|
||||
appleskin-api = "mc1.21-3.0.5"
|
||||
|
||||
# Graal
|
||||
graal = "22.3.0"
|
||||
@@ -34,7 +35,7 @@ mod-menu = "11.0.3"
|
||||
c2me-fabric = "0.3.0+alpha.0.320+1.21.1"
|
||||
|
||||
# NeoForge
|
||||
neoforge = "21.1.182"
|
||||
neoforge = "21.1.195"
|
||||
neo-kotlin-for-forge = "5.10.0"
|
||||
debugutils-forge = "1.21.1-1.0.9-neoforge"
|
||||
c2me-neoforge = "0.3.0+alpha.0.73+1.21.1"
|
||||
@@ -85,6 +86,7 @@ jei-fabric = { group = "mezz.jei", name = "jei-1.21.1-fabric", version.ref = "je
|
||||
fabric-debugutils = { group = "maven.modrinth", name = "debugutils", version.ref = "debugutils-fabric"}
|
||||
mod-menu = { group = "com.terraformersmc", name = "modmenu", version.ref = "mod-menu" }
|
||||
c2me-fabric = { group = "maven.modrinth", name = "c2me-fabric", version.ref = "c2me-fabric" }
|
||||
appleskin-api-fabric = { group = "squeek.appleskin", name = "appleskin-fabric", version.ref = "appleskin-api" }
|
||||
|
||||
# NeoForge
|
||||
neoforge-api = { group = "net.neoforged", name = "neoforge", version.ref = "neoforge" }
|
||||
@@ -92,6 +94,7 @@ neo-kotlin-forge = { group = "thedarkcolour", name = "kotlinforforge-neoforge",
|
||||
neoforge-debugutils = { group = "maven.modrinth", name = "debugutils", version.ref = "debugutils-forge"}
|
||||
jei-neoforge = { group = "mezz.jei", name = "jei-1.21.1-neoforge", version.ref = "jei-api"}
|
||||
c2me-neoforge = { group = "maven.modrinth", name = "c2me-neoforge", version.ref = "c2me-neoforge" }
|
||||
appleskin-api-neoforge = { group = "squeek.appleskin", name = "appleskin-neoforge", version.ref = "appleskin-api" }
|
||||
|
||||
# Data Storage
|
||||
mongo-driver-core = { group = "org.mongodb", name = "mongodb-driver-core", version.ref = "mongo" }
|
||||
|
||||
@@ -68,6 +68,9 @@ dependencies {
|
||||
bundle(it)
|
||||
}
|
||||
|
||||
// AppleSkin stores api under `api` classifier in their coordinates
|
||||
// Because of that, we cannot just add it to integrations bundle
|
||||
modCompileOnly(variantOf(libs.appleskin.api.neoforge) { classifier("api") })
|
||||
}
|
||||
|
||||
tasks {
|
||||
|
||||
@@ -34,5 +34,5 @@ object CobblemonEnumExtensions {
|
||||
Supplier<List<ItemStack>> { listOf(ItemStack(CobblemonItems.APRIJUICE_RED)) as List<ItemStack> })
|
||||
@JvmField
|
||||
val COOKING_POT_MISC = EnumProxy(RecipeBookCategories::class.java,
|
||||
Supplier<List<ItemStack>> { listOf(ItemStack(CobblemonItems.PROTEIN)) as List<ItemStack> })
|
||||
Supplier<List<ItemStack>> { listOf(ItemStack(CobblemonItems.HEALTH_CANDY)) as List<ItemStack> })
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import com.cobblemon.mod.common.item.group.CobblemonItemGroups
|
||||
import com.cobblemon.mod.common.loot.LootInjector
|
||||
import com.cobblemon.mod.common.particle.CobblemonParticles
|
||||
import com.cobblemon.mod.common.sherds.CobblemonSherds
|
||||
import com.cobblemon.mod.common.util.adapters.RegistryAccessResolver
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.didSleep
|
||||
import com.cobblemon.mod.common.world.CobblemonStructures
|
||||
@@ -39,7 +40,6 @@ import com.mojang.brigadier.arguments.ArgumentType
|
||||
import net.minecraft.commands.synchronization.ArgumentTypeInfo
|
||||
import net.minecraft.commands.synchronization.ArgumentTypeInfos
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.core.RegistryAccess
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
@@ -63,6 +63,8 @@ import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.GameRules
|
||||
import net.minecraft.world.level.ItemLike
|
||||
import net.minecraft.world.level.biome.Biome
|
||||
import net.minecraft.world.level.block.Blocks
|
||||
import net.minecraft.world.level.block.FlowerPotBlock
|
||||
import net.minecraft.world.level.levelgen.GenerationStep
|
||||
import net.minecraft.world.level.levelgen.placement.PlacedFeature
|
||||
import net.neoforged.api.distmarker.Dist
|
||||
@@ -286,7 +288,26 @@ class CobblemonNeoForge : CobblemonImplementation {
|
||||
override fun registerBlocks() {
|
||||
MOD_BUS.addListener<RegisterEvent> { event ->
|
||||
event.register(CobblemonBlocks.resourceKey) { helper ->
|
||||
CobblemonBlocks.register { identifier, block -> helper.register(identifier, block) }
|
||||
CobblemonBlocks.register { identifier, block ->
|
||||
if (block !is FlowerPotBlock) helper.register(identifier, block)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MOD_BUS.addListener<RegisterEvent>(EventPriority.LOW) { event ->
|
||||
// Register the pots after registering main blocks to solve race condition when pottable blocks are still not registered
|
||||
event.register(CobblemonBlocks.resourceKey) { helper ->
|
||||
CobblemonBlocks.register { identifier, block ->
|
||||
if (block is FlowerPotBlock) {
|
||||
helper.register(identifier, block)
|
||||
|
||||
val pottedIdentifier = RegistryAccessResolver.getAccess()
|
||||
.registryOrThrow(Registries.BLOCK)
|
||||
.getKeyOrNull(block.potted)!!
|
||||
|
||||
(Blocks.FLOWER_POT as FlowerPotBlock).addPlant(pottedIdentifier) { block }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.cobblemon.mod.common.item.PokedexItem
|
||||
import com.cobblemon.mod.common.particle.CobblemonParticles
|
||||
import com.cobblemon.mod.common.particle.SnowstormParticleType
|
||||
import com.cobblemon.mod.common.util.isUsingPokedex
|
||||
import com.cobblemon.mod.neoforge.client.integration.appleskin.AppleSkinClientEventHandler
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import java.util.function.Supplier
|
||||
import net.minecraft.client.Minecraft
|
||||
@@ -92,7 +93,9 @@ object CobblemonNeoForgeClient : CobblemonClientImplementation {
|
||||
event.enqueueWork {
|
||||
CobblemonClient.initialize(this)
|
||||
CobblemonModelPredicateRegistry.registerPredicates()
|
||||
this.attemptClientModCompat()
|
||||
}
|
||||
|
||||
NeoForgeClientPlatformEventHandler.register()
|
||||
|
||||
val modContainer = ModList.get().getModContainerById(Cobblemon.MODID).get()
|
||||
@@ -233,4 +236,10 @@ object CobblemonNeoForgeClient : CobblemonClientImplementation {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun attemptClientModCompat() {
|
||||
if (Cobblemon.implementation.isModInstalled("appleskin")) {
|
||||
AppleSkinClientEventHandler.register()
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
@@ -8,11 +8,13 @@
|
||||
|
||||
package com.cobblemon.mod.neoforge.client
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.platform.events.ClientEntityEvent
|
||||
import com.cobblemon.mod.common.platform.events.ClientPlayerEvent
|
||||
import com.cobblemon.mod.common.platform.events.ClientTickEvent
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import com.cobblemon.mod.common.platform.events.RenderEvent
|
||||
import com.cobblemon.mod.neoforge.client.integration.appleskin.AppleSkinClientEventHandler
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.multiplayer.ClientLevel
|
||||
import net.neoforged.api.distmarker.Dist
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.neoforge.client.integration.appleskin
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import net.neoforged.bus.api.SubscribeEvent
|
||||
import net.neoforged.neoforge.common.NeoForge
|
||||
import squeek.appleskin.api.event.HUDOverlayEvent
|
||||
|
||||
object AppleSkinClientEventHandler {
|
||||
fun register() {
|
||||
NeoForge.EVENT_BUS.register(this)
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
fun onHudLayerEvent(e: HUDOverlayEvent) {
|
||||
if (CobblemonClient.pokedexUsageContext.scanningGuiOpen) {
|
||||
e.isCanceled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
-3
@@ -24,7 +24,7 @@ import net.neoforged.neoforge.event.server.ServerAboutToStartEvent
|
||||
import net.neoforged.neoforge.event.server.ServerStartedEvent
|
||||
import net.neoforged.neoforge.event.server.ServerStoppedEvent
|
||||
import net.neoforged.neoforge.event.server.ServerStoppingEvent
|
||||
import net.neoforged.neoforge.event.tick.PlayerTickEvent
|
||||
import net.neoforged.neoforge.event.tick.EntityTickEvent
|
||||
|
||||
object NeoForgePlatformEventHandler {
|
||||
|
||||
@@ -53,14 +53,14 @@ object NeoForgePlatformEventHandler {
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
fun prePlayerTick(e: PlayerTickEvent.Pre) {
|
||||
fun prePlayerTick(e: EntityTickEvent.Pre) {
|
||||
if (e.entity is ServerPlayer) {
|
||||
PlatformEvents.SERVER_PLAYER_TICK_PRE.post(ServerPlayerTickEvent.Pre(e.entity as ServerPlayer))
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
fun postPlayerTick(e: PlayerTickEvent.Post) {
|
||||
fun postPlayerTick(e: EntityTickEvent.Post) {
|
||||
if (e.entity is ServerPlayer) {
|
||||
PlatformEvents.SERVER_PLAYER_TICK_POST.post(ServerPlayerTickEvent.Post(e.entity as ServerPlayer))
|
||||
}
|
||||
@@ -98,6 +98,12 @@ object NeoForgePlatformEventHandler {
|
||||
)
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
fun onRespawn(e: PlayerEvent.PlayerRespawnEvent) {
|
||||
val player = e.entity as? ServerPlayer ?: return
|
||||
PlatformEvents.PLAYER_RESPAWN.post(ServerPlayerEvent.Respawn(player))
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
fun onRightClickBlock(e: PlayerInteractEvent.RightClickBlock) {
|
||||
val player = e.entity as? ServerPlayer ?: return
|
||||
|
||||
Reference in New Issue
Block a user