Compare commits

..
Author SHA1 Message Date
Lily ee03e7b0de i are making cobbelmon lolcat! 2023-10-13 15:35:41 +00:00
1501 changed files with 11215 additions and 54410 deletions

No files matched your search

+71 -172
View File
@@ -1,123 +1,26 @@
# Changelog
## [1.4.1](#1-4-1)
### Changes
- Slightly lowered the volume of all cries
- Updated Pokeball animations and model.
- Turtwig can now be put on shoulder.
- Updated Zubat line model, texture, and animations.
- Added animations for Hitmontop, Tyrogue, and Mightyena.
- Tweaked animations for Dusknoir, Ratatta, Bewear, Exeggutor, and Alolan Exeggutor.
- Sized Kantonian Exeggutor down. Still big but not TOO BIG.
- Tweaked cries for Pikachu, Raichu and Alolan Raichu.
- Pasture blocks will now also connect their bottom left and right sides to walls, iron bars, glass panes and any other modded block that follows the same connection rules.
- The config option `consumeHeldItems` has been removed, please see the Datapack & Resourcepack Creators for instructions on the updated method.
- Using Potions, Status Heals, Ethers, and Antidotes will now return a glass bottle
- Using a Remedy, Fine Remedy, or Superb Remedy will no longer lower friendship with a Pokémon
- The Healing Machine now has a more difficult recipe, placing it later game.
- Heal Powder can now be composted with a 75% chance of adding a layer
- Mental, Power, White, and Mirror Herbs can now be composted with a 100% chance of adding a layer.
- Added emissive to Hoothoot.
- Mining Evolution Stone Ores with a Fortune pickaxe will now increase the amount of items recieved
- Black Augurite can now be used to craft stone axes and obsidian.
- Using Experience Candies brings up the Party Pokémon Select screen when not targeting a Pokémon.
- Added tab completion for statuses to commands
## [1.4.0](#1-4-0)
### Additions
- Added battle spectating, can disable in config
- Cobblemon now has compatibility with [Adorn](https://modrinth.com/mod/adorn) allowing you to craft Apricorn wood furniture.
- Berries can now be used in recipes from [Farmer's Delight](https://modrinth.com/mod/farmers-delight) and [Farmer's Delight (Fabric)](https://modrinth.com/mod/farmers-delight-fabric), as well as any other mods using the same berry tags.
- The nature of cobblemon will now be displayed italicized when a mint has been applied. Hovering over the nature will display the mint that was applied. This is the intended behaviour, because the original nature and taste of the Cobblemon does not change when a mint is applied.
- Giving Pokémon items now plays a sound
- A boat, sign and hanging sign is now craftable with Apricorn wood. The recipes are the same shape as Minecraft's equivalent with Apricorn planks as replacements.
- Added the [Cleanse Tag](https://wiki.cobblemon.com/index.php/Cleanse_Tag) and [Fairy Feather](https://wiki.cobblemon.com/index.php/Fairy_Feather)
- Added Fairy Feather drops to some pokemon
- Added the Inferno, Void, and Forsaken patterns for Vivillon. These can be obtained by evolving a Spewpa in the Nether, End, or Deep Dark respectively.
- Added the Litwick line.
- Bees can now be fed using Pep-Up Flowers.
- Mooshtank can now be milked with a bowl for Mushroom Stew.
- Added cries to Beldum, Metang and Metagross.
### Fixes
- Fixed various stone related blocks not being valid for Big Roots to spread on the Fabric version.
- Updated the registration of compostable items to improve compatibility with Fabric forks such as Quilt. Please note this does not mean we officially support Quilt, this change was only done since it was possible by correcting the registration to use the new intended way in the Fabric API.
- Fixed Dispensers being unable to shear grown Apricorns.
- Fixed Bowl not being given back to player after using Berry Juice
- Added context for -fail and -block handlers for battle text and added 16 related battle texts for them
- Fixed Battle text for Disable, Laser Focus, Foresight, Fire Spin, Telekinesis, Curse, Recharge and Encore
- Fixed missing text for snowy weather in battles
- Fixed missing text for attempting to catch an uncatchable Pokémon
- Fixed Moonphases for Clefairy line
- Fixed issue where Potions, Super Potions, and Hyper Potions did not work during battle
- Fixed the compatibility patch with the Forge version of [Carry On](https://modrinth.com/mod/carry-on) due to a bug on the mod, the Fabric version was unchanged and is still compatible.
- Added the ability to place Berries on modded Farmland blocks.
- Shouldered Pokémon now hop off when selected in team and r is pressed. This also is in effect in battles leading to shouldered Pokémon jumping of the shoulder of the trainer when it is their turn.
- Made more items compostable and changed the process for making items compostable.
- Added the ability for Hoppers to fill Brewing Stands with Medicinal Brews and Potions.
- Apricorn blocks are now flammable.
- The default pose for Pokémon being passengers is now "standing".
- Fixed issue where some IVs were changing every player relog.
- Fixed cursed battle message
- Fixed mistakes in pokemon spawning JSONs
- Fixed advancement crash from bad datapack evolution data.
- Fixed global influences being applied to TickingSpawners twice.
- Reverted the default SpawningSelector back to FlatContextWeightedSelector. This fixes multiple weight related issues, including weights with SpawningInfluences.
- Apricorn Planting advancement should work again.
- Advancement "Patterned Wings" should now allow High Plains and Icy Snow Vivillon to register.
- Fixed the last battle critical hits evolution requirement not working.
- Fixed the damage taken evolution requirement not saving progress.
- Fixed the defeated Pokémon evolution requirement not saving progress.
- Fixed potion brewing recipes not showing up JEI and similar mods on the Forge version.
- Fixed an exploit that could convert a single piece of Blaze Powder into an extra Medicinal Brew on the Forge version.
- Fixed an issue where health percentages would show incorrectly after healing
- Fixed the move Revival Blessing not allowing you to select from fainted party members.
- Fixed Exeggcute faint.
- Fixed Raticate, Onix, Unfezant, Bergmite, Avalugg, Boltund and Revavroom cries not playing.
- Fixed Alolan Ratticate animations causing a crash.
- Fixed Quaxwell not doing its cry.
- Fixed Shroomish not using its idle.
- Fixed a possible visual duplication of sent out Pokémon.
### Developer
- Fixed the `SpawnEvent` not respecting usage of `Cancelable#cancel`.
- Added the `EvolutionTestedEvent`, this allows listening and overriding the final result of evolution requirement tests.
- The `HeldItemManager` has a new method `shouldConsumeItem`, this will return false by default to prevent breaking changes, see the documentation and update your implementations as needed.
### Datapack & Resourcepack Creators
- Added 3 new item tags: `cobblemon:held/consumed_in_npc_battle`, `cobblemon:held/consumed_in_pvp_battle` & `cobblemon:held/consumed_in_wild_battle` these will determine which items get consumed in the implied battle types by Cobblemon, keep in mind the controller for this behaviour can be overriden by 3rd party.
## [1.4.0 - The Friends and Farms Update (October 13th, 2023)](#1-4-0)
### Additions
- Added pasture blocks, used to let your PC Pokémon roam around an area.
- Added nicknaming from the summary menu of a Pokémon (click their name).
- Added trading between players. Press R while looking at another player and you'll figure the rest out.
- Added mints for changing Pokémon stats. These are most commonly found at high altitudes.
- Added [Revival Herbs](https://wiki.cobblemon.com/index.php/Revival_Herb), with pep-up flowers when fully grown, growing in lush caves.
- Added [Medicinal Leeks](https://wiki.cobblemon.com/index.php/Medicinal_Leek), growing on the surface of rivers and ponds. It is a potion ingredient and can be cooked as food!.
- Added [Big Roots](https://wiki.cobblemon.com/index.php/Big_Root), generating from cave ceiling dirt which sometimes spread as energy roots.
- Added [69 Berry Trees](https://wiki.cobblemon.com/index.php/Berry_Tree) and [Berries](https://wiki.cobblemon.com/index.php/Berry). Some are found in village farms, some from planting different berries close to each other.
- Added mulches: Mulch Base, Growth Mulch, Surprise Mulch, Coarse Mulch, Humid Mulch, Rich Mulch, Loamy Mulch, Peat Mulch, and Sandy Mulch
- Added [Vivichokes](https://wiki.cobblemon.com/index.php/Vivichoke), obtainable from wandering villager trades and some loot chests.
- Added nicknaming.
- Added mints, found on mountains.
- Added revival herbs, with pep-up flowers if fully grown, growing in lush caves.
- Added medicinal leeks, growing on the surface of rivers and ponds. It is a potion ingredient!
- Added big roots, generating from cave ceiling dirt and sometimes spreading into energy roots.
- Added trading between players. Press R while looking at another player, you'll figure it out.
- Added pasture blocks, used to let your PC Pokémon roam around your base.
- Added 69 berry trees. Some are found in village farms, some from planting different berries close to each other.
- Added medicine brewing using medicinal leeks and berries in brewing stands.
- Added Pokémon cries when in battles and being sent out.
- Added medicinal items: Berry Juice, Heal Powder, Remedy, Fine Remedy, Superb Remedy, Revive, Max Revive, Potion, Super Potion, Hyper Potion, Max Potion, Full Restore, Full Heal, Antidote, Awakening, Burn Heal, Ice Heal, and Paralyze Heal.
- Added battle items: X Attack, X Defence, X Sp.Atk, X Sp.Def, X Speed, Dire Hit, and Guard Spec.
- Added EV items: Power Anklet, Power Band, Power Belt, Power Bracelet, Power Lens, Power Weight.
- Added food items: Roasted Leek, Leek and Potato Stew, Braised Vivichoke, and Vivichoke Dip
- Added evolution items: Auspicious Armor and Malicious Armor, which can be used to evolve Charcadet into Armarouge or Ceruledge respectively.
- Added (mostly brewing) recipes for HP Up, Protein, Iron, Calcium, Zinc, Carbos, PP Up, PP Max, and Medicinal Leek to Magenta Dye.
- Added held items: Bright Powder, Destiny Knot
- Added AI for Nosepass to point towards world spawn when idle. We just think it's neat.
- Added shoulder mounting for Mimikyu.
- Added support for scale in animations.
- Added support for jump keyframes (i.e. pre and post keyframes)
- Added AI for Nosepass to point towards world spawn when idle.
- Added structure spawn conditions
- Added recipes for Berry Juice, Heal Powder, Remedy, Fine Remedy, Superb Remedy, Revive, Max Revive, HP Up, Protein, Iron, Calcium, Zinc, Carbos, PP Up, PP Max, Pasture, Medicinal Leek to Magenta Dye, Roasted Leek, Leek and Potato Stew, Braised Vivichoke, Vivichoke Dip, Mulch Base, Growth Mulch, Surprise Mulch, Coarse Mulch, Humid Mulch, Rich Mulch, Loamy Mulch, Peat Mulch, Sandy Mulch, X Attack, X Defense, X Special Attack, X Special Defense, X Speed, X Accuracy, Dire Hit, Guard Spec, Power Anklet, Power Band, Power Belt, Power Bracelet, Power Lens, Power Weight, Bright Powder, Destiny Knot
- Added a shoulder mount for Mimikyu
- Added Advancement trigger for defeating Pokémon and collecting varieties of Pokémon.
- Added sleep animations to Arcanine, Jigglypuff, Wigglytuff, Vulpix and Ninetales.
- Added flying placeholder animations to Pidgey, Pidgeotto, Pidgeot, Golbat, Crobat, Scyther, Scizor, Zapdos, Moltres, Articuno, Dragonite, Rowlet, Dartrix, and Decidueye.
- Added loot to various vanilla chest loot tables (Link Cable in Ancient Cities, Woodland Mansions, End Cities, and Igloos, Vivichoke Seeds in Jungle Temples, Dungeons, and Plains, Savanna, Snowy, and Taiga Villages, and all 7 Apricorn Sprouts in Desert, Plains, Savanna, Snowy, and Taiga Villages, as well as the Bonus Chest, which can also have 5 of the basic Poké Ball types)
- Added a `doShinyStarters` gamerule to make it quick and easy to be offered shiny starters.
- Added a `doPokemonLoot` gamerule to toggle Pokémon dropping items/exp on death.
- Added ability activation announcement when in battle.
- Added animations for Wailord and made it BIGGER.
- Added Cherry Torterra variant.
- Added 2 new face spots for Spinda. The number of unique Spindas increases...
- Added Forretress Shulker variant.
- Added the `/teststore <player> <store> <properties>` command allowing command block/mcfunction users to query a party, PC or both for Pokémon matching specific properties and returning the match count, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.teststore` if a permission mod is present.
- Added the `/querylearnset <player> <slot> <move>` command allowing command block/mcfunction users to query a party slot and check if the Pokémon can learn a specific move returning a 1 if yes otherwise 0, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.querylearnset` if a permission mod is present.
- Added the `/testpcslot <player> <slot> <properties>` command allowing command block/mcfunction users to query a pc slot and check if the Pokémon matches specific properties returning a 1 if yes otherwise 0, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.testpcslot` if a permission mod is present.
@@ -125,6 +28,18 @@
- Added the `/clearparty <player>` command for emptying a player's party.
- Added the `/clearpc <player>` command for emptying a player's PC.
- Added the `/pokemonrestart <reset_starters>` and the `/pokemonrestartother <player> <reset_starters>` command allowing command block/mcfunction users to reset a players Pokémon data.
- Added support for "isBattle" and "isTouchingWater" properties on resource pack Pokémon poses. This allows your custom Pokémon to be posed differently when in battle.
- Added support for "isVisible" on a transformed part on resource pack Pokémon poses. This allows your custom Pokémon to have bones disappear in specific poses, such as hiding Greninja's throwing star when not in a battle pose.
- Added a "doShinyStarters" gamerule
- Added the `doPokemonLoot` gamerule to toggle Pokémon dropping items/exp on death.
- Added support for battle music. Sounds can be added to the ``battle.pvp.default`` and ``battle.pvw.default`` sound events.
- Added ability activation announcement when in battle.
- Added Auspicious Armor and Malicious Armor, which can be used to evolve Charcadet into Armarouge or Ceruledge respectively.
- Added animations for Wailord.
- Added Cherry Torterra variant.
- Added 2 new face spots for Spinda.
- Added Forretress Shulker variant.
- Added 'enabled' optional property on model layers, allowing later variations to disable previously-defined layers. See [this issue](https://gitlab.com/cable-mc/cobblemon/-/issues/335) for how this looks.
### Pokémon Added
#### Gen 2
@@ -342,36 +257,39 @@
- Clodsire
### Changes
- Removed the existing shoulder effects from Pokémon until we have more balanced versions of them (they're too powerful!)
- Updated models and textures of Weedle, Dwebble and Crustle, Spiritomb, Koffing and Weezing, Kadabra and Alakazam, Emolga, Oshawott, Doduo and Dodrio, Dratini and Dragonair and Dragonite, Sneasel and Weavile, Gyarados, Hitmonlee and Hitmonchan, Chesnaught, Spinda, Mamoswine, Steelix, Misdreavus and Mismagius, Buneary and Lopunny, Golduck, Meowth and Persian, Fennekin and Braixen and Delphox, Snivy and Servine and Serperior, Ratatta and Raticate, Nidorina and Nidoqueen, Nidoran Male and Nidoking, Riolu and Lucario, Haunter and Gengar, Mankey and Primeape, Mew and Mewtwo, Arcanine, Magnemite and Magneton and Magnezone, Exeggcute and Exeggutor, Elekid and Electabuzz and Electivire, Pichu and Pikachu and Raichu, Wooper, Drowzee and Hypno, Aerodactyl, Spearow and Fearow, Lickitung and Lickilicky, Pidgey and Pidgeotto and Pidgeot, Scyther and Scizor and Kleavor, Popplio and Brionne and Primarina, Torchic and Combusken and Blaziken, Happiny and Chansey and Blissey.
- Updated animations for Steelix, Turtwig and Grotle and Torterra, Ponyta and Rapidash, Piplup and Prinplup and Empoleon, Drowzee and Hypno, Farfetch'd, Exeggcute and Exeggutor, Bidoof, Chimecho, Lickitung and Lickilicky, Popplio and Brionne, Luvdisc, Chimchar and Monferno and Infernape, Sobble and Drizzile and Inteleon, Greninja, Heatmor, Aerodactyl, Ditto, Lotad and Lombre and Ludicolo, Pumpkaboo and Gourgeist.
- Updated model and textures of Spiritomb, Koffing, Weezing, Kadabra, Alakazam, Emolga, Oshawott, Doduo, Dodrio, Dratini, Dragonair, Dragonite, Sneasel, Weavile, Gyarados, Hitmonlee, Hitmonchan, Chesnaught, Spinda, Mamoswine, Steelix, Midreavus, Mismagius, Buneary, Lopunny, Golduck, Meowth, Persian, Fennekin, Braixen, Delphox, Snivy, Servine, Serperior, Ratatta, Raticate, Nidorina, Nidoqueen, NidoranM, Nidoking, Riolu, Lucario, Haunter, Mankey, Primeape, Mew, Mewtwo, Arcanine, Magnemite, Magneton, Magnezone, Exeggcute, Exeggutor, Elekid, Electabuzz, Electivire, Pichu, Pikachu, Raichu, Gengar, Wooper, Drowzee, Hypno, Aerodactyl, Spearow, Fearow, Lickitung, Pidgey, Pidgeotto, Pidgeot, Scyther, Scizor, Kleavor, Popplio, Brionne, Primarina, Torchic, Combusken, Blaziken, Aerodacyl, Scyther, Scizor, Kleavor, Lickitung, Lickilicky, Happiny, Chansey and Blissey.
- Updated animations for Steelix, Turtwig, Grotle, Torterra, Ponyta, Rapidash, Piplup, Prinplup, Empoleon, Drowzee, Hypno, Farfetch'd, Exeggcute, Exeggutor, Bidoof, Chimecho, Lickytung, Lickilicky, Popplio, Brionne, Luvdisc, Chimchar, Monferno, Infernape, Sobble, Drizzile, Inteleon, Greninja, Heatmor, Aerodactyl, Ditto, Lotad, Lombre, Ludicolo, Pumpkaboo, Gourgeist.
- Updated sprites for EV medicines, the rare candy, and the apricorn door item.
- Updated textures for apricorn doors and all the evolution stone ores.
- Ponyta and Rapidash now have animated textures; they look insane.
- Updated Apricorn Leaves color.
- Wild Pokémon now heal if you are defeated by them or flee from them.
- Doubled the default time between ambient Pokémon cries (they have cries if you're using a resource pack to add them)
- Moved spawn attempts per tick to a config option (ticksBetweenSpawnAttempts)
- PCs can now be waterlogged
- Starter selection prompt now appears as a tutorial-esque toast instead of plain text
- Cobblemon items can now all have their own tooltips via resourcepacks, to add a tooltip simply add a lang entry like "item.cobblemon.{item_id}.tooltip", if you want to add multiple tooltip lines you can do so with "item.cobblemon.{item_id}.tooltip_1" and upwards.
- Updated texture of Weedle.
- Updated shiny texture of Dwebble and Crustle.
- Reorganised the advancements recipes folder
- Pokéedit command now supports IVs and EVs.
- Reorganised creative categories
- Pokémon can now wander into non-solid blocks such as foliage
- Thrown Poké Balls now despawn after 30 seconds so that they don't fly forever.
- Pokéballs now despawn after 30 seconds
- Dive Balls will now have the same motion speed underwater as if they were thrown in the air.
- Hardcoded potion shoulder effects have been removed. You can now use any potion vanilla or otherwise with the parameters you'd like, for more information see the [Datapack & Resourcepack Creators](#datapack-&-resourcepack-creators) section.
- Clicking categories of the Stat subsection or the party reorder button in the Summary screen will now produce a click sound.
- Hardcoded potion shoulder effects have been removed, you can now use any potion vanilla or otherwise with the parameters you'd like, for more information see the [Datapack & Resourcepack Creators](#datapack-&-resourcepack-creators) section.
- Clicking categories of the Stat sub-section or the party reorder button in the Summary screen will now produce a click sound.
- Updated PC Recipe.
- Improved Pokémon AI and movement.
- Friendship will slowly increase when Pokémon are shoulder-mounted.
- Master Balls are now unable to be burned when dropped into fire/lava. They're made from stronger stuff.
- Master balls are now unable to be burned when dropped into fire/lava.
- Pokémon will appear red when hurt, like regular entities, except when they're fainting.
- Ponyta and Rapidash now have animated textures.
- Pokémon's air meter no longer depletes while battling underwater.
- Sleeping partially restores PP of Pokémon
- Item interaction evolutions and held item requirements now support NBT by creating an object JSON containing the key ``item`` for what used to be the existing condition support and a ``nbt`` key for the NBT format, this is the string [format](https://minecraft.fandom.com/wiki/NBT_format) expected in commands. Existing data does not need to be updated.
- Shoulder mounts now match the shoulder position a bit more accurately when sneaking.
- Poison Heal will now cause poisoned Pokémon to heal outside of battle.
- Updated Poké Ball, PC, UI, evolution and Healing Machine sounds.
- Updated Pokéball, PC, UI, evolution and Healing Machine sounds.
### Added cries to the following Pokémon:
- All starters and their evolutions
@@ -441,48 +359,48 @@
- Tatsugiri
### Fixes
- Fixed spawning moon phase dependent Pokémon only when the moon phase is wrong (that's a funny woopsy)
- Fixed spawning moon phase dependent Pokémon only when the moon phase is wrong
- Fixed large Pokémon spawning partially inside walls where they suffocate.
- Fixed custom Pokémon in your party or PC not being removed when the addon is removed, causing major issues.
- Fixed messages for entry hazards, screens, weather, damage, healing, Tailwind, Perish Song, Destiny Bond, Shed Skin, Uproar, Forewarn, Disguise, Arena Trap, Yawn, Curse, Clamp, Whirlpool, Liquid Ooze, Miracle Eye, Safeguard, Magic Bounce, Lock On, Focus Energy, Confusion, and more.
- Fixed Porygon not evolving with an Upgrade.
- Fixed super sized Pumpkaboo not having any moves.
- Fixed Infernape look animation.
- Fixed Garchomp T-posing while swimming which was very funny.
- Fixed a bug that caused sleeping Pokémon to stay asleep. Forever. The years passing them by as they dream of a world without hate...
- Fixed a bug that would freeze a battle when a Pokémon gets trapped by an ability, making the trap abilities even scarier and trap-like than they were before.
- Fixed Garchomp t-posing while swimming.
- Fixed a bug that caused sleeping Pokémon to stay asleep.
- Fixed a bug that would freeze a battle when a Pokémon gets trapped due to an ability.
- Fixed the Poké Ball close animation canceling whenever colliding with a block.
- Fixed faint animations not working properly in add-ons.
- Fixed lighting and Pokémon label issues when a Pokémon item frame is nearby.
- Fixed Pokémon being able to spawn outside the world border as a tease.
- Fixed deepslate water stone ore items looking like deepslate fire stone ores. Huh?
- Fixed a bunch of client-side logging errors when Pokémon are shoulder mounted. You didn't notice? Good.
- Fixed deepslate water stone ore items looking like deepslate fire stone ores.
- Fixed a bunch of client-side logging errors when Pokémon are shoulder mounted.
- Fixed a crash when wild Pokémon have to struggle under specific circumstances.
- Fixed uncolored pixels on Yanma's shiny texture.
- Fixed apricorn tree leaves looking gross on the Fast graphics mode.
- Fixed apricorn tree leaves looking gross on Fast graphics mode.
- Fixed hoes not breaking apricorn tree leaves any faster.
- Fixed Shiftry's PC model position.
- Fixed the /pc command not playing the opening sound.
- Fixed Shedinja not being able to recover naturally.
- Fixed different forms of Pokémon not being able to appear as different sizes.
- Fixed the Healing Machine soft locking you from using others when removed by non-players.
- Fixed animations being sped up when using the Replay Mod.
- Fixed particle animations not running when a Pokémon is off-screen.
- Fixed Pokémon variants and layers not rendering correctly when shouldered and playing on a dedicated server, existing shoulders affected will need to be retrieved and shouldered again.
- Fixed shoulder effects not staying applied through situations that remove potion effects such as drinking milk.
- Fixed Shedinja not being able to recover naturally.
- Fixed Shedinja evolving to use the consumed Poké Ball and removed the held item to prevent dupes.
- Fixed Shedinja healing above 1 HP.
- Fixed Shedinja, basically.
- Shoulder effects will now stay applied through situations that remove potion effects such as drinking milk.
- Fixed Shedinja evolving to use the consumed PokéBall and removed the held item.
- Fixed non-existent species in spawn pool file causing random species to spawn.
- Fixed shearing Pokémon dropping 0-2 wool instead of 1-3.
- Fixed some alignment issues in the stat hexagon of the summary menu. OCD people rejoice.
- Fixed some alignment issues in the stat hexagon of the summary menu.
- Fixed capture calculations not applying ball bonuses entirely correctly.
- Fixed Shedinja healing above 1 HP.
- Fixed battles soft-locking when consecutive Pokémon faint on switch-in.
- Fixed timing and color of battle window messages.
- Fixed players being able to trade, battle and let out their Pokémon while in spectator mode.
- Fixed Galarian Yamask not being able to evolve and by proxy the ``damage_taken`` evolution requirement.
- Fixed Bisharp not being able to evolve and by proxy the ``defeat`` evolution requirement.
- Fixed White-Striped Basculin not being able to evolve because of a broken ``recoil`` evolution requirement.
- Fixed Primeape, Qwilfish and Stantler not being able to evolve because of a broken ``use_move`` evolution requirement.
- Fixed Bramblin, Pawmo, and Rellor not being able to evolve because of a broken ``blocks_traveled`` evolution requirement.
- Fixed White-Striped Basculin not being able to evolve and by proxy the ``recoil`` evolution requirement.
- Fixed Primeape, Qwilfish and Stantler not being able to evolve and by proxy the ``use_move`` evolution requirement.
- Fixed Bramblin, Pawmo, and Rellor not being able to evolve and by proxy the ``blocks_traveled`` evolution requirement.
- Fixed displayName property in spawn files not doing what it's meant to do.
- Fixed Pokémon not sleeping in the wild like we wanted them to.
@@ -493,14 +411,11 @@
- Species and FormData have had their evolutions, pre-evolution and labels properties exposed. It is still recommended to work using a Pokémon instance when possible.
- Added capture check to BattleVictoryEvent.
- The various hardcoded potion shoulder effects have been removed, make use of PotionBaseEffect.
- Added ContextManager for tracking causes and contexts of conditions created during a battle. See BattleContext for types of conditions that are tracked.
- Added ContextManager for tracking causes and contexts of conditions created during a battle. See BattleContext for types of conditions that are tracked.
- Added MongoDB support for storing Pokémon and Player data. Must be enabled in config, requires MongoDB core and sync drivers (4.10.0+).
- CobblemonShowdown updated to version 10.
- Generation of a battle can be set in BattleFormat.
- Pokémon now have ``teraType``, ``dmaxLevel``, and ``gmaxFactor`` properties. Gimmicks can be used during battle by adding the respective identifiers to ``keyItems`` in PlayerData: ``key_stone``, ``z_ring``, ``dynamax_band``, and ``tera_orb``. Dynamax is only supported in Gen 8 battles. Mega Evolution and Z-Power require custom held items to be added (e.g. an item with the path ``gengarite`` will allow Gengar to Mega Evolve). Currently custom Z-Crystals and Mega Stones are not supported.
### Datapack & Resourcepack Creators
- All potion related shoulder effects have had their IDs changed. They now all share the same type being `potion_effect` and use the vanilla Potion data [parameters](https://minecraft.fandom.com/wiki/Potion#Item_data). For example, here is the converted Pidgey asset:
- All potion related shoulder effects have had their IDs changed, they now all share the same type being `potion_effect` and use the vanilla Potion data [parameters](https://minecraft.fandom.com/wiki/Potion#Item_data), take for example the default Pidgey asset:
- ```json
{
"type": "potion_effect",
@@ -512,22 +427,6 @@
}
```
- Renamed the ``walked_steps`` evolution requirement to ``blocks_traveled``.
- Added support for scale in animations.
- Added support for jump keyframes (i.e. pre and post keyframes)
- Added structure spawning conditions
- Added Advancement trigger for defeating Pokémon and collecting varieties of Pokémon.
- Added support for "isBattle" and "isTouchingWater" properties on resource pack Pokémon poses. This allows your custom Pokémon to be posed differently when in battle.
- Added support for "isVisible" on a transformed part on resource pack Pokémon poses. This allows your custom Pokémon to have bones disappear in specific poses, such as hiding Greninja's throwing star when not in a battle pose.
- Added support for battle music. Sounds can be added to the ``battle.pvp.default`` and ``battle.pvw.default`` sound events.
- Added 'enabled' optional property on model layers, allowing later variations to disable previously-defined layers. See [this issue](https://gitlab.com/cable-mc/cobblemon/-/issues/335) for how this looks.
- Cobblemon items can now all have their own tooltips via resourcepacks. To add a tooltip, add a lang entry like "item.cobblemon.{item_id}.tooltip". If you want to add multiple tooltip lines you can do so with "item.cobblemon.{item_id}.tooltip_1" and upwards.
- Item interaction evolutions and held item requirements now support NBT by creating an object JSON containing the key ``item`` for what used to be the existing condition support and a ``nbt`` key for the NBT format, this is the string [format](https://minecraft.fandom.com/wiki/NBT_format) expected in commands. Existing data does not need to be updated.
- Fixed faint animations not working properly in add-ons.
- Fixed non-existent species in spawn pool files causing random species to spawn.
### Localization
- Added partial translations for Dutch, Polish, Swedish, Hungarian, Czech, Cyprus Greek, and even Esperanto.
- Updated translation for French and Canadian French, Simplified Chinese, Japanese, Korean, Spanish and Mexican Spanish, Pirate English, German, Thai, Turkish, Portuguese and Brazilian Portuguese, Ukrainian, and Russian.
## [1.3.1 (March 31st, 2023)](#1-3-1)
@@ -541,7 +440,7 @@
- Add lava surface spawn preset.
- Added an ``any`` evolution requirement allowing you to define ``possibilities`` of other evolution requirements, for example, this allows you to create an evolution that requires the Pokémon to be shiny or a female.
- Added the `/spawnpokemonfrompool [amount]` or `/forcespawn [amount]` command to spawn Pokémon(s) in the surrounding area using the natural spawn rates/pool of that area, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.spawnpokemon` if a permission mod is present. On a successful execution of the command, the amount of Pokémon spawned will be the output.
- Added the `/pokebox` and `/pokeboxall` commands to move Pokémon(s) to the PC from a Player's party, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.pokebox` if a permission mod is present. On a successful execution of the command the output will be the number of pokemon moved to the Player's PC.
- Added the `/pokebox` and `/pokeboxall` commands to move Pokemon(s) to the PC from a Player's party, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.pokebox` if a permission mod is present. On a successful execution of the command the output will be the number of pokemon moved to the Player's PC.
- Added the `/pc` command which opens up the PC UI the same way interacting with the block would, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.pc` if a permission mod is present.
### Changes
@@ -873,17 +772,17 @@
- Fixed spawning in several biome tag categories.
- Fixed resource pack support for Pokémon models and textures.
- **Model Fixes**
- Fixed Paras and Nidoqueen looking very weird.
- Fixed Hitmonchan asserting dominance with a T-pose as well as Grimer and Muk pointing their hands to the sky.
- Fixed specific Pokémon suddenly pausing their animation after staying still for a long time.
- Fixed Mankey's feet being buried in the ground.
- Updated the Substitute model and updated its shiny texture to be better for the red-green colorblind.
- Improved Horsea, Seadra, and Kingdra animations, especially on land.
- Fixed Paras and Nidoqueen looking very weird.
- Fixed Hitmonchan asserting dominance with a T-pose as well as Grimer and Muk pointing their hands to the sky.
- Fixed specific Pokémon suddenly pausing their animation after staying still for a long time.
- Fixed Mankey's feet being buried in the ground.
- Updated the Substitute model and updated its shiny texture to be better for the red-green colorblind.
- Improved Horsea, Seadra, and Kingdra animations, especially on land.
- **Battle Fixes**
- Fixed an issue with battles where Pokémon had a different max HP causing some desync issues with the health bars.
- Fixed Magnitude battle messages.
- Moves that are disabled or out of PP now show transparently in the battle GUI instead of being hidden completely.
- Statuses like sleep and frozen no longer last forever if it was carried over from a previous battle.
- Fixed an issue with battles where Pokémon had a different max HP causing some desync issues with the health bars.
- Fixed Magnitude battle messages.
- Moves that are disabled or out of PP now show transparently in the battle GUI instead of being hidden completely.
- Statuses like sleep and frozen no longer last forever if it was carried over from a previous battle.
### Localization
- Added species, ability, and move translations for `ko_ko`, `jp_jp`, `fr_fr`, `es_es`, `it_it`, and `zh_cn`.
+1 -3
View File
@@ -19,7 +19,6 @@ architectury {
repositories {
maven(url = "${rootProject.projectDir}/deps")
maven(url = "https://api.modrinth.com/maven")
mavenLocal()
}
@@ -29,10 +28,9 @@ dependencies {
modImplementation(libs.fabricLoader)
//Flywheel has no common dep so just pick one and don't use any platform specific code in common
// modCompileOnly(libs.flywheelFabric)
modCompileOnly(libs.flywheelFabric)
modApi(libs.molang)
compileOnlyApi(libs.jeiApi)
modCompileOnly(libs.adornFabric)
// For Showdown
modCompileOnly(libs.graal)
@@ -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.mixin;
import com.cobblemon.mod.common.CobblemonBlocks;
import com.cobblemon.mod.common.block.PastureBlock;
import net.minecraft.block.BlockState;
import net.minecraft.block.FenceBlock;
import net.minecraft.block.HorizontalFacingBlock;
import net.minecraft.util.math.Direction;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(value = FenceBlock.class)
public abstract class FenceBlockMixin {
// This could be done with a modify variable but it just doesn't seem to want to work, very crude unfinished explanation I had on Fabric discord was
// "boolean is a primitive, it isnt passed by reference but by value and you have your own object references anyway so assigning a new object to non-primitive references (variables) wont modify it after your mixin returns
//(you cant modify a random argument that mixin passes you that way, target the boolean not the FenceBlock)"
// However the issue is the only way to get all the params which we need is by passing in the entire method reference which enforces the return type.
@Redirect(method = "getStateForNeighborUpdate", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/FenceBlock;canConnect(Lnet/minecraft/block/BlockState;ZLnet/minecraft/util/math/Direction;)Z"))
private boolean cobblemon$getStateForNeighborUpdate(FenceBlock instance, BlockState state, boolean neighborIsFullSquare, Direction dir) {
return instance.canConnect(state, neighborIsFullSquare, dir) || this.cobblemon$canConnect(state, dir);
}
@Redirect(method = "getPlacementState", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/FenceBlock;canConnect(Lnet/minecraft/block/BlockState;ZLnet/minecraft/util/math/Direction;)Z"))
private boolean cobblemon$getPlacementState(FenceBlock instance, BlockState state, boolean neighborIsFullSquare, Direction dir) {
return instance.canConnect(state, neighborIsFullSquare, dir) || this.cobblemon$canConnect(state, dir);
}
private boolean cobblemon$canConnect(BlockState state, Direction dir) {
if (state.isOf(CobblemonBlocks.PASTURE) && state.get(PastureBlock.Companion.getPART()) == PastureBlock.PasturePart.BOTTOM) {
final Direction pastureFacing = state.get(HorizontalFacingBlock.FACING);
return dir == pastureFacing.rotateYClockwise() || dir == pastureFacing.rotateYCounterclockwise();
}
return false;
}
}
@@ -6,9 +6,9 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.fabric.mixin;
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.fabric.brewing.CobblemonFabricBreweryRegistry;
import com.cobblemon.mod.common.brewing.BrewingRecipes;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.BrewingStandScreenHandler;
import org.spongepowered.asm.mixin.Mixin;
@@ -18,14 +18,14 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(BrewingStandScreenHandler.PotionSlot.class)
public class PotionSlotMixin {
@Inject(method = "matches", at = @At("RETURN"), cancellable = true)
private static void cobblemon$matches(ItemStack stack, CallbackInfoReturnable<Boolean> cir) {
if (cir.getReturnValue()) {
return;
@Inject(
method = "matches",
at = @At(value = "HEAD"),
cancellable = true
)
private static void matchesBrewable(ItemStack stack, CallbackInfoReturnable<Boolean> cir) {
if (BrewingRecipes.brewableItems.contains(stack.getItem())) {
cir.setReturnValue(true);
}
cir.setReturnValue(CobblemonFabricBreweryRegistry.INSTANCE.isValidPotionSlot(stack));
}
}
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.api.spawning.mixins.CachedOnlyChunkAccessor;
import com.mojang.datafixers.util.Either;
import net.minecraft.server.world.ChunkHolder;
import net.minecraft.server.world.ServerChunkManager;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.ChunkManager;
import net.minecraft.world.chunk.ChunkStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.concurrent.CompletableFuture;
@Mixin(ServerChunkManager.class)
public abstract class ServerChunkManagerMixin extends ChunkManager implements CachedOnlyChunkAccessor {
@Shadow @Nullable protected abstract ChunkHolder getChunkHolder(long pos);
@Override
public Chunk cobblemon$request(int x, int z, @NotNull ChunkStatus status) {
long l = ChunkPos.toLong(x, z);
ChunkHolder holder = getChunkHolder(l);
if (holder != null) {
CompletableFuture<Either<Chunk, ChunkHolder.Unloaded>> future = holder.getFutureFor(status);
if (future.isDone()) {
return future.join().left().orElse(null);
}
}
return null;
}
}
@@ -1,20 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.invoker;
import net.minecraft.block.Block;
import org.spongepowered.asm.mixin.Mixin;
import net.minecraft.block.FireBlock;
import net.minecraft.block.Blocks;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(FireBlock.class)
public interface FireBlockInvoker {
@Invoker("registerFlammableBlock") void registerNewFlammableBlock(Block block, int burnChance, int spreadChance);
}
@@ -9,7 +9,6 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.advancement.CobblemonCriteria
import com.cobblemon.mod.common.advancement.criterion.EvolvePokemonContext
import com.cobblemon.mod.common.api.Priority
import com.cobblemon.mod.common.api.SeasonResolver
import com.cobblemon.mod.common.api.data.DataProvider
@@ -337,7 +336,7 @@ object Cobblemon {
// Ensure the config option is enabled and that the result was a ninjask and that shedinja exists
if (this.config.ninjaskCreatesShedinja && pokemon.species.resourceIdentifier == ninjaskIdentifier && PokemonSpecies.getByIdentifier(Pokemon.SHEDINJA) != null) {
val player = pokemon.getOwnerPlayer() ?: return@subscribe
if (player.isCreative || player.inventory.containsAny { it.item is PokeBallItem }) {
if (player.inventory.containsAny { it.item is PokeBallItem }) {
var pokeball = Items.AIR
player.inventory.combinedInventory.forEach {
it.forEach {
@@ -346,12 +345,7 @@ object Cobblemon {
}
}
}
if (!player.isCreative) {
player.inventory.removeAmountIf(1) { it.item is PokeBallItem }
}
if (pokeball == Items.AIR) {
pokeball = CobblemonItems.POKE_BALL
}
player.inventory.removeAmountIf(1) { it.item is PokeBallItem }
val properties = event.evolution.result.copy()
properties.species = Pokemon.SHEDINJA.toString()
val product = pokemon.clone()
@@ -359,7 +353,6 @@ object Cobblemon {
properties.apply(product)
product.caughtBall = (pokeball as PokeBallItem).pokeBall
pokemon.storeCoordinates.get()?.store?.add(product)
CobblemonCriteria.EVOLVE_POKEMON.trigger(player, EvolvePokemonContext(event.pokemon.preEvolution!!.species.resourceIdentifier, product.species.resourceIdentifier, playerData.get(player).advancementData.totalEvolvedCount))
}
}
}
@@ -8,7 +8,10 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.block.entity.*
import com.cobblemon.mod.common.block.entity.BerryBlockEntity
import com.cobblemon.mod.common.block.entity.HealingMachineBlockEntity
import com.cobblemon.mod.common.block.entity.PCBlockEntity
import com.cobblemon.mod.common.block.entity.PokemonPastureBlockEntity
import com.cobblemon.mod.common.platform.PlatformRegistry
import net.minecraft.block.entity.BlockEntityType
import net.minecraft.registry.Registries
@@ -28,9 +31,5 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
val BERRY = this.create("berry", BlockEntityType.Builder.create(::BerryBlockEntity, *CobblemonBlocks.berries().values.toTypedArray()).build(null))
@JvmField
val PASTURE: BlockEntityType<PokemonPastureBlockEntity> = this.create("pasture", BlockEntityType.Builder.create(::PokemonPastureBlockEntity, CobblemonBlocks.PASTURE).build(null))
@JvmField
val SIGN: BlockEntityType<CobblemonSignBlockEntity> = this.create("sign", BlockEntityType.Builder.create(::CobblemonSignBlockEntity, CobblemonBlocks.APRICORN_SIGN, CobblemonBlocks.APRICORN_WALL_SIGN).build(null))
@JvmField
val HANGING_SIGN: BlockEntityType<CobblemonHangingSignBlockEntity> = this.create("hanging_sign", BlockEntityType.Builder.create(::CobblemonHangingSignBlockEntity, CobblemonBlocks.APRICORN_HANGING_SIGN, CobblemonBlocks.APRICORN_WALL_HANGING_SIGN).build(null))
}
@@ -19,10 +19,6 @@ import com.cobblemon.mod.common.mixin.invoker.*
import com.cobblemon.mod.common.platform.PlatformRegistry
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.block.BerryBlock
import com.cobblemon.mod.common.block.sign.CobblemonHangingSignBlock
import com.cobblemon.mod.common.block.sign.CobblemonSignBlock
import com.cobblemon.mod.common.block.sign.CobblemonWallHangingSignBlock
import com.cobblemon.mod.common.block.sign.CobblemonWallSignBlock
import net.minecraft.block.*
import net.minecraft.block.piston.PistonBehavior
import net.minecraft.entity.effect.StatusEffects
@@ -37,8 +33,6 @@ import net.minecraft.util.math.intprovider.UniformIntProvider
@Suppress("SameParameterValue", "HasPlatformType", "MemberVisibilityCanBePrivate", "unused")
object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<Block>>, Block>() {
override val registry: Registry<Block> = Registries.BLOCK
override val registryKey: RegistryKey<Registry<Block>> = RegistryKeys.BLOCK
@@ -111,14 +105,9 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
val APRICORN_BUTTON = this.create("apricorn_button", BlocksInvoker.createWoodenButtonBlock(BlockSetType.OAK))
@JvmField
val APRICORN_PRESSURE_PLATE = this.create("apricorn_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(PressurePlateBlock.ActivationRule.EVERYTHING, AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).noCollision().strength(0.5f).sounds(BlockSoundGroup.WOOD), APRICORN_BLOCK_SET_TYPE))
@JvmField
val APRICORN_SIGN = this.create("apricorn_sign", CobblemonSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_SIGN), APRICORN_WOOD_TYPE))
@JvmField
val APRICORN_WALL_SIGN = this.create("apricorn_wall_sign", CobblemonWallSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_WALL_SIGN), APRICORN_WOOD_TYPE))
@JvmField
val APRICORN_HANGING_SIGN = this.create("apricorn_hanging_sign", CobblemonHangingSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_WALL_HANGING_SIGN), APRICORN_WOOD_TYPE))
@JvmField
val APRICORN_WALL_HANGING_SIGN = this.create("apricorn_wall_hanging_sign", CobblemonWallHangingSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_HANGING_SIGN), APRICORN_WOOD_TYPE))
// Tag was removed be sure to add it back when implemented
//val APRICORN_SIGN = queue("apricorn_sign") { StandingSignBlock(AbstractBlock.Settings.of(Material.WOOD).noCollission().strength(1.0f).sounds(BlockSoundGroup.WOOD), APRICORN_WOOD_TYPE) }
//val APRICORN_WALL_SIGN = queue("apricorn_wall_sign") { WallSignBlock(AbstractBlock.Settings.of(Material.WOOD).noCollission().strength(1.0f).sounds(BlockSoundGroup.WOOD).dropsLike(APRICORN_SIGN), APRICORN_WOOD_TYPE) }
@JvmField
val APRICORN_SLAB = this.create("apricorn_slab", SlabBlock(AbstractBlock.Settings.create().mapColor(MapColor.OAK_TAN).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
@JvmField
@@ -239,8 +228,6 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
APRICORN_LOG to STRIPPED_APRICORN_LOG
)
private fun apricornBlock(name: String, apricorn: Apricorn): ApricornBlock = this.create(name, ApricornBlock(AbstractBlock.Settings.create().mapColor(apricorn.mapColor()).ticksRandomly().strength(Blocks.OAK_LOG.hardness, Blocks.OAK_LOG.blastResistance).sounds(BlockSoundGroup.WOOD).nonOpaque(), apricorn))
private val berries = mutableMapOf<Identifier, BerryBlock>()
@@ -315,25 +302,6 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
val WIKI_BERRY = this.berryBlock("wiki")
val YACHE_BERRY = this.berryBlock("yache")
init {
/**
* Makes all blocks in array flammable by adding them to FireBlock's flammableRegistry.
* second value is burn chance and third value is spread chance
*/
arrayOf(
Triple(APRICORN_LOG, 5, 5),
Triple(STRIPPED_APRICORN_LOG, 5, 5),
Triple(APRICORN_WOOD, 5, 5),
Triple(STRIPPED_APRICORN_WOOD, 5, 5),
Triple(APRICORN_PLANKS, 5, 20),
Triple(APRICORN_LEAVES, 30, 60),
Triple(APRICORN_FENCE, 5, 20),
Triple(APRICORN_FENCE_GATE, 5, 20),
Triple(APRICORN_SLAB, 5, 20),
Triple(APRICORN_STAIRS, 5, 20)
).onEach{ data -> setFlammable(data.first, data.second, data.third) }
}
fun berries() = this.berries.toMap()
private fun berryBlock(name: String): BerryBlock {
@@ -344,28 +312,14 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
}
/**
* Calls helper method from Vanilla
* Helper method for creating logs
* copied over from Vanilla
*/
private fun log(name: String, arg: MapColor = MapColor.DIRT_BROWN, arg2: MapColor = MapColor.DIRT_BROWN): PillarBlock {
val block = BlocksInvoker.createLogBlock(arg, arg2)
return this.create(name, block)
}
/**
* Method uses generic E in order to keep the block as the same return type.
* If E is not a block then it will not be set as flammable.
* Calls Vanilla implementation of registering a flammable block.
* Mixins looks cursed but it is java's fault.
*/
private fun <E> setFlammable(block: E, burnChance: Int, spreadChance: Int): E {
if(block !is Block) return block
var fireBlock: FireBlock = Blocks.FIRE as FireBlock
//Cursed Mixin stuff
(fireBlock as FireBlockInvoker).registerNewFlammableBlock(block as Block, burnChance, spreadChance)
return block
}
private fun evolutionStoneOre(name: String) = this.create(name, ExperienceDroppingBlock(AbstractBlock.Settings.copy(Blocks.IRON_ORE), UniformIntProvider.create(1, 2)))
private fun deepslateEvolutionStoneOre(name: String) = this.create(name, ExperienceDroppingBlock(AbstractBlock.Settings.copy(Blocks.DEEPSLATE_IRON_ORE), UniformIntProvider.create(1, 2)))
@@ -8,6 +8,7 @@
package com.cobblemon.mod.common
import java.util.function.Supplier
import net.minecraft.block.Block
import net.minecraft.block.entity.BlockEntity
import net.minecraft.block.entity.BlockEntityType
@@ -18,14 +19,11 @@ import net.minecraft.client.particle.ParticleFactory
import net.minecraft.client.particle.SpriteProvider
import net.minecraft.client.render.RenderLayer
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory
import net.minecraft.client.render.entity.EntityRendererFactory
import net.minecraft.client.render.entity.model.EntityModelLayer
import net.minecraft.entity.Entity
import net.minecraft.entity.EntityType
import net.minecraft.item.Item
import net.minecraft.particle.ParticleEffect
import net.minecraft.particle.ParticleType
import java.util.function.Supplier
import net.minecraft.resource.SynchronousResourceReloader
interface CobblemonClientImplementation {
fun registerLayer(modelLayer: EntityModelLayer, supplier: Supplier<TexturedModelData>)
@@ -40,7 +38,5 @@ interface CobblemonClientImplementation {
fun registerBlockColors(provider: BlockColorProvider, vararg blocks: Block)
fun <T : BlockEntity> registerBlockEntityRenderer(type: BlockEntityType<out T>, factory: BlockEntityRendererFactory<T>)
fun <T : Entity> registerEntityRenderer(type: EntityType<out T>, factory: EntityRendererFactory<T>)
fun <T : BlockEntity> registerBlockEntityRenderer(type: BlockEntityType<T>, factory: BlockEntityRendererFactory<T>)
}
@@ -9,8 +9,6 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.entity.boat.CobblemonBoatEntity
import com.cobblemon.mod.common.entity.boat.CobblemonChestBoatEntity
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.platform.PlatformRegistry
@@ -47,24 +45,6 @@ object CobblemonEntities : PlatformRegistry<Registry<EntityType<*>>, RegistryKey
.build(EMPTY_POKEBALL_KEY.toString())
)
@JvmField
val BOAT_KEY = cobblemonResource("boat")
@JvmField
val BOAT: EntityType<CobblemonBoatEntity> = this.create(
BOAT_KEY.path,
EntityType.Builder.create(::CobblemonBoatEntity, SpawnGroup.MISC).setDimensions(1.375F, 0.5625F).maxTrackingRange(10)
.build(BOAT_KEY.toString())
)
@JvmField
val CHEST_BOAT_KEY = cobblemonResource("chest_boat")
@JvmField
val CHEST_BOAT: EntityType<CobblemonChestBoatEntity> = this.create(
CHEST_BOAT_KEY.path,
EntityType.Builder.create(::CobblemonChestBoatEntity, SpawnGroup.MISC).setDimensions(1.375F, 0.5625F).maxTrackingRange(10)
.build(CHEST_BOAT_KEY.toString())
)
fun registerAttributes(consumer: (EntityType<out LivingEntity>, DefaultAttributeContainer.Builder) -> Unit) {
consumer(POKEMON, PokemonEntity.createAttributes())
}
@@ -15,9 +15,7 @@ import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
import com.mojang.brigadier.arguments.ArgumentType
import kotlin.reflect.KClass
import net.minecraft.advancement.criterion.Criterion
import net.minecraft.block.ComposterBlock
import net.minecraft.command.argument.serialize.ArgumentSerializer
import net.minecraft.item.ItemConvertible
import net.minecraft.network.PacketByteBuf
import net.minecraft.network.listener.ClientPlayPacketListener
import net.minecraft.network.packet.Packet
@@ -28,7 +26,6 @@ import net.minecraft.resource.ResourceReloader
import net.minecraft.resource.ResourceType
import net.minecraft.server.MinecraftServer
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.text.Text
import net.minecraft.util.Identifier
import net.minecraft.world.GameRules
import net.minecraft.world.biome.Biome
@@ -172,44 +169,6 @@ interface CobblemonImplementation {
* @param manager The [ResourceManager] to reload from.
*/
fun <T> reloadJsonRegistry(registry: JsonDataRegistry<T>, manager: ResourceManager): HashMap<Identifier, T>
/**
* Registers an item to the [ComposterBlock].
*
* @param item The [ItemConvertible] being registered.
* @param chance The chance % of increasing the composter level, 0 to 1 expected.
*/
fun registerCompostable(item: ItemConvertible, chance: Float)
/**
* Registers a builtin resource pack.
*
* @param id The unique [Identifier] of this pack.
* @param title The title displayed in the resource pack GUI, the description is still a part of the pack metadata.
* @param activationBehaviour The [ResourcePackActivationBehaviour] for this pack.
*/
fun registerBuiltinResourcePack(id: Identifier, title: Text, activationBehaviour: ResourcePackActivationBehaviour)
}
enum class ResourcePackActivationBehaviour {
/**
* The resource pack will start disabled.
*/
NORMAL,
/**
* The resource pack will start enabled.
*/
DEFAULT_ENABLED,
/**
* The resource pack will always be enabled.
* The user can reorder it but cannot remove it.
*/
ALWAYS_ENABLED;
}
enum class ModAPI {
@@ -14,9 +14,7 @@ import com.cobblemon.mod.common.api.pokemon.Natures
import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.api.pokemon.status.Statuses
import com.cobblemon.mod.common.block.BerryBlock
import com.cobblemon.mod.common.block.MintBlock
import com.cobblemon.mod.common.block.MintBlock.MintType
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
import com.cobblemon.mod.common.item.*
import com.cobblemon.mod.common.item.battle.DireHitItem
import com.cobblemon.mod.common.item.battle.GuardSpecItem
@@ -34,6 +32,7 @@ import com.cobblemon.mod.common.pokeball.PokeBall
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.block.Block
import net.minecraft.block.ComposterBlock
import net.minecraft.entity.LivingEntity
import net.minecraft.entity.effect.StatusEffectInstance
import net.minecraft.entity.effect.StatusEffects
@@ -118,40 +117,40 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
val CHERISH_BALL = pokeBallItem(PokeBalls.CHERISH_BALL)
@JvmField
val VIVICHOKE = compostableItem("vivichoke")
val VIVICHOKE = create("vivichoke", Item(Item.Settings()))
@JvmField
val VIVICHOKE_SEEDS = compostableItem("vivichoke_seeds", VivichokeItem(CobblemonBlocks.VIVICHOKE_SEEDS))
val VIVICHOKE_SEEDS = create("vivichoke_seeds", VivichokeItem(CobblemonBlocks.VIVICHOKE_SEEDS))
@JvmField
val RED_APRICORN = apricornItem("red", ApricornItem(CobblemonBlocks.RED_APRICORN))
val RED_APRICORN = create("red_apricorn", ApricornItem(CobblemonBlocks.RED_APRICORN))
@JvmField
val YELLOW_APRICORN = apricornItem("yellow", ApricornItem(CobblemonBlocks.YELLOW_APRICORN))
val YELLOW_APRICORN = create("yellow_apricorn", ApricornItem(CobblemonBlocks.YELLOW_APRICORN))
@JvmField
val GREEN_APRICORN = apricornItem("green", ApricornItem(CobblemonBlocks.GREEN_APRICORN))
val GREEN_APRICORN = create("green_apricorn", ApricornItem(CobblemonBlocks.GREEN_APRICORN))
@JvmField
val BLUE_APRICORN = apricornItem("blue", ApricornItem(CobblemonBlocks.BLUE_APRICORN))
val BLUE_APRICORN = create("blue_apricorn", ApricornItem(CobblemonBlocks.BLUE_APRICORN))
@JvmField
val PINK_APRICORN = apricornItem("pink", ApricornItem(CobblemonBlocks.PINK_APRICORN))
val PINK_APRICORN = create("pink_apricorn", ApricornItem(CobblemonBlocks.PINK_APRICORN))
@JvmField
val BLACK_APRICORN = apricornItem("black", ApricornItem(CobblemonBlocks.BLACK_APRICORN))
val BLACK_APRICORN = create("black_apricorn", ApricornItem(CobblemonBlocks.BLACK_APRICORN))
@JvmField
val WHITE_APRICORN = apricornItem("white", ApricornItem(CobblemonBlocks.WHITE_APRICORN))
val WHITE_APRICORN = create("white_apricorn", ApricornItem(CobblemonBlocks.WHITE_APRICORN))
@JvmField
val RED_APRICORN_SEED = apricornSeedItem("red", ApricornSeedItem(CobblemonBlocks.RED_APRICORN_SAPLING))
val RED_APRICORN_SEED = create("red_apricorn_seed", ApricornSeedItem(CobblemonBlocks.RED_APRICORN_SAPLING))
@JvmField
val YELLOW_APRICORN_SEED = apricornSeedItem("yellow", ApricornSeedItem(CobblemonBlocks.YELLOW_APRICORN_SAPLING))
val YELLOW_APRICORN_SEED = create("yellow_apricorn_seed", ApricornSeedItem(CobblemonBlocks.YELLOW_APRICORN_SAPLING))
@JvmField
val GREEN_APRICORN_SEED = apricornSeedItem("green", ApricornSeedItem(CobblemonBlocks.GREEN_APRICORN_SAPLING))
val GREEN_APRICORN_SEED = create("green_apricorn_seed", ApricornSeedItem(CobblemonBlocks.GREEN_APRICORN_SAPLING))
@JvmField
val BLUE_APRICORN_SEED = apricornSeedItem("blue", ApricornSeedItem(CobblemonBlocks.BLUE_APRICORN_SAPLING))
val BLUE_APRICORN_SEED = create("blue_apricorn_seed", ApricornSeedItem(CobblemonBlocks.BLUE_APRICORN_SAPLING))
@JvmField
val PINK_APRICORN_SEED = apricornSeedItem("pink", ApricornSeedItem(CobblemonBlocks.PINK_APRICORN_SAPLING))
val PINK_APRICORN_SEED = create("pink_apricorn_seed", ApricornSeedItem(CobblemonBlocks.PINK_APRICORN_SAPLING))
@JvmField
val BLACK_APRICORN_SEED = apricornSeedItem("black", ApricornSeedItem(CobblemonBlocks.BLACK_APRICORN_SAPLING))
val BLACK_APRICORN_SEED = create("black_apricorn_seed", ApricornSeedItem(CobblemonBlocks.BLACK_APRICORN_SAPLING))
@JvmField
val WHITE_APRICORN_SEED = apricornSeedItem("white", ApricornSeedItem(CobblemonBlocks.WHITE_APRICORN_SAPLING))
val WHITE_APRICORN_SEED = create("white_apricorn_seed", ApricornSeedItem(CobblemonBlocks.WHITE_APRICORN_SAPLING))
@JvmField
val APRICORN_LOG = blockItem("apricorn_log", CobblemonBlocks.APRICORN_LOG)
@@ -164,11 +163,13 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
@JvmField
val APRICORN_PLANKS = blockItem("apricorn_planks", CobblemonBlocks.APRICORN_PLANKS)
@JvmField
val APRICORN_LEAVES = compostableBlockItem("apricorn_leaves", CobblemonBlocks.APRICORN_LEAVES)
@JvmField
val APRICORN_BOAT = create("apricorn_boat", CobblemonBoatItem(CobblemonBoatType.APRICORN, false, Item.Settings().maxCount(1)))
@JvmField
val APRICORN_CHEST_BOAT = create("apricorn_chest_boat", CobblemonBoatItem(CobblemonBoatType.APRICORN, true, Item.Settings().maxCount(1)))
val APRICORN_LEAVES = blockItem("apricorn_leaves", CobblemonBlocks.APRICORN_LEAVES).also {
val compostChance = ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE.getFloat(Items.OAK_LEAVES)
// Should always pass unless Mojang reworks leaves to no longer work in the Composter, in that case we already updated w.o doing anything
if (compostChance != ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE.defaultReturnValue()) {
ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE[it] = compostChance
}
}
@JvmField
val APRICORN_DOOR = blockItem("apricorn_door", CobblemonBlocks.APRICORN_DOOR)
@@ -182,14 +183,12 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
val APRICORN_BUTTON = blockItem("apricorn_button", CobblemonBlocks.APRICORN_BUTTON)
@JvmField
val APRICORN_PRESSURE_PLATE = blockItem("apricorn_pressure_plate", CobblemonBlocks.APRICORN_PRESSURE_PLATE)
//@JvmField
// val APRICORN_SIGN = create("apricorn_sign", SignItem(Item.Properties().stacksTo(16).tab(CreativeModeTab.TAB_DECORATIONS), CobblemonBlocks.APRICORN_SIGN, CobblemonBlocks.APRICORN_WALL_SIGN))
@JvmField
val APRICORN_SLAB = blockItem("apricorn_slab", CobblemonBlocks.APRICORN_SLAB)
@JvmField
val APRICORN_STAIRS = blockItem("apricorn_stairs", CobblemonBlocks.APRICORN_STAIRS)
@JvmField
val APRICORN_SIGN = this.create("apricorn_sign", SignItem(Item.Settings().maxCount(16), CobblemonBlocks.APRICORN_SIGN, CobblemonBlocks.APRICORN_WALL_SIGN))
@JvmField
val APRICORN_HANGING_SIGN = this.create("apricorn_hanging_sign", HangingSignItem(CobblemonBlocks.APRICORN_HANGING_SIGN, CobblemonBlocks.APRICORN_WALL_HANGING_SIGN, Item.Settings().maxCount(16)))
@JvmField
val HEALING_MACHINE = blockItem("healing_machine", CobblemonBlocks.HEALING_MACHINE)
@@ -354,11 +353,11 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
}
})
@JvmField
val ENERGY_ROOT = compostableItem("energy_root", EnergyRootItem(CobblemonBlocks.ENERGY_ROOT, Item.Settings().food(FoodComponent.Builder().hunger(1).snack().saturationModifier(0.2f).build())))
val ENERGY_ROOT = create("energy_root", EnergyRootItem(CobblemonBlocks.ENERGY_ROOT, Item.Settings().food(FoodComponent.Builder().hunger(1).snack().saturationModifier(0.2f).build())))
@JvmField
val REVIVAL_HERB = compostableItem("revival_herb", RevivalHerbItem(CobblemonBlocks.REVIVAL_HERB))
val REVIVAL_HERB = create("revival_herb", RevivalHerbItem(CobblemonBlocks.REVIVAL_HERB))
@JvmField
val PEP_UP_FLOWER = compostableBlockItem("pep_up_flower", CobblemonBlocks.PEP_UP_FLOWER)
val PEP_UP_FLOWER = blockItem("pep_up_flower", CobblemonBlocks.PEP_UP_FLOWER)
@JvmField
val MEDICINAL_BREW = create("medicinal_brew", Item(Item.Settings()))
@JvmField
@@ -393,74 +392,72 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
val PP_MAX = create("pp_max", PPUpItem(3))
@JvmField
val RED_MINT_SEEDS = mintSeed("red", MintType.RED.getCropBlock())
val RED_MINT_SEEDS = blockItem("red_mint_seeds", MintType.RED.getCropBlock())
@JvmField
val RED_MINT_LEAF = mintLeaf("red", MintLeafItem(MintType.RED))
val RED_MINT_LEAF = create("red_mint_leaf", MintLeafItem(MintType.RED))
@JvmField
val BLUE_MINT_SEEDS = mintSeed("blue", MintType.BLUE.getCropBlock())
val BLUE_MINT_SEEDS = blockItem("blue_mint_seeds", MintType.BLUE.getCropBlock())
@JvmField
val BLUE_MINT_LEAF = mintLeaf("blue", MintLeafItem(MintType.BLUE))
val BLUE_MINT_LEAF = create("blue_mint_leaf", MintLeafItem(MintType.BLUE))
@JvmField
val CYAN_MINT_SEEDS = mintSeed("cyan", MintType.CYAN.getCropBlock())
val CYAN_MINT_SEEDS = blockItem("cyan_mint_seeds", MintType.CYAN.getCropBlock())
@JvmField
val CYAN_MINT_LEAF = mintLeaf("cyan", MintLeafItem(MintType.CYAN))
val CYAN_MINT_LEAF = create("cyan_mint_leaf", MintLeafItem(MintType.CYAN))
@JvmField
val PINK_MINT_SEEDS = mintSeed("pink", MintType.PINK.getCropBlock())
val PINK_MINT_SEEDS = blockItem("pink_mint_seeds", MintType.PINK.getCropBlock())
@JvmField
val PINK_MINT_LEAF = mintLeaf("pink", MintLeafItem(MintType.PINK))
val PINK_MINT_LEAF = create("pink_mint_leaf", MintLeafItem(MintType.PINK))
@JvmField
val GREEN_MINT_SEEDS = mintSeed("green", MintType.GREEN.getCropBlock())
val GREEN_MINT_SEEDS = blockItem("green_mint_seeds", MintType.GREEN.getCropBlock())
@JvmField
val GREEN_MINT_LEAF = mintLeaf("green", MintLeafItem(MintType.GREEN))
val GREEN_MINT_LEAF = create("green_mint_leaf", MintLeafItem(MintType.GREEN))
@JvmField
val WHITE_MINT_SEEDS = mintSeed("white", MintType.WHITE.getCropBlock())
val WHITE_MINT_SEEDS = blockItem("white_mint_seeds", MintType.WHITE.getCropBlock())
@JvmField
val WHITE_MINT_LEAF = mintLeaf("white", MintLeafItem(MintType.WHITE))
val mints = mutableMapOf<String, MintItem>()
val WHITE_MINT_LEAF = create("white_mint_leaf", MintLeafItem(MintType.WHITE))
@JvmField
val LONELY_MINT = mintItem("lonely_mint", MintItem(Natures.LONELY))
val LONELY_MINT = create("lonely_mint", MintItem(Natures.LONELY))
@JvmField
val ADAMANT_MINT = mintItem("adamant_mint", MintItem(Natures.ADAMANT))
val ADAMANT_MINT = create("adamant_mint", MintItem(Natures.ADAMANT))
@JvmField
val NAUGHTY_MINT = mintItem("naughty_mint", MintItem(Natures.NAUGHTY))
val NAUGHTY_MINT = create("naughty_mint", MintItem(Natures.NAUGHTY))
@JvmField
val BRAVE_MINT = mintItem("brave_mint", MintItem(Natures.BRAVE))
val BRAVE_MINT = create("brave_mint", MintItem(Natures.BRAVE))
@JvmField
val BOLD_MINT = mintItem("bold_mint", MintItem(Natures.BOLD))
val BOLD_MINT = create("bold_mint", MintItem(Natures.BOLD))
@JvmField
val IMPISH_MINT = mintItem("impish_mint", MintItem(Natures.IMPISH))
val IMPISH_MINT = create("impish_mint", MintItem(Natures.IMPISH))
@JvmField
val LAX_MINT = mintItem("lax_mint", MintItem(Natures.LAX))
val LAX_MINT = create("lax_mint", MintItem(Natures.LAX))
@JvmField
val RELAXED_MINT = mintItem("relaxed_mint", MintItem(Natures.RELAXED))
val RELAXED_MINT = create("relaxed_mint", MintItem(Natures.RELAXED))
@JvmField
val MODEST_MINT = mintItem("modest_mint", MintItem(Natures.MODEST))
val MODEST_MINT = create("modest_mint", MintItem(Natures.MODEST))
@JvmField
val MILD_MINT = mintItem("mild_mint", MintItem(Natures.MILD))
val MILD_MINT = create("mild_mint", MintItem(Natures.MILD))
@JvmField
val RASH_MINT = mintItem("rash_mint", MintItem(Natures.RASH))
val RASH_MINT = create("rash_mint", MintItem(Natures.RASH))
@JvmField
val QUIET_MINT = mintItem("quiet_mint", MintItem(Natures.QUIET))
val QUIET_MINT = create("quiet_mint", MintItem(Natures.QUIET))
@JvmField
val CALM_MINT = mintItem("calm_mint", MintItem(Natures.CALM))
val CALM_MINT = create("calm_mint", MintItem(Natures.CALM))
@JvmField
val GENTLE_MINT = mintItem("gentle_mint", MintItem(Natures.GENTLE))
val GENTLE_MINT = create("gentle_mint", MintItem(Natures.GENTLE))
@JvmField
val CAREFUL_MINT = mintItem("careful_mint", MintItem(Natures.CAREFUL))
val CAREFUL_MINT = create("careful_mint", MintItem(Natures.CAREFUL))
@JvmField
val SASSY_MINT = mintItem("sassy_mint", MintItem(Natures.SASSY))
val SASSY_MINT = create("sassy_mint", MintItem(Natures.SASSY))
@JvmField
val TIMID_MINT = mintItem("timid_mint", MintItem(Natures.TIMID))
val TIMID_MINT = create("timid_mint", MintItem(Natures.TIMID))
@JvmField
val HASTY_MINT = mintItem("hasty_mint", MintItem(Natures.HASTY))
val HASTY_MINT = create("hasty_mint", MintItem(Natures.HASTY))
@JvmField
val JOLLY_MINT = mintItem("jolly_mint", MintItem(Natures.JOLLY))
val JOLLY_MINT = create("jolly_mint", MintItem(Natures.JOLLY))
@JvmField
val NAIVE_MINT = mintItem("naive_mint", MintItem(Natures.NAIVE))
val NAIVE_MINT = create("naive_mint", MintItem(Natures.NAIVE))
@JvmField
val SERIOUS_MINT = mintItem("serious_mint", MintItem(Natures.SERIOUS))
val SERIOUS_MINT = create("serious_mint", MintItem(Natures.SERIOUS))
@JvmField val X_ACCURACY = create("x_${Stats.ACCURACY.identifier.path}", XStatItem(Stats.ACCURACY))
@JvmField val X_ATTACK = create("x_${Stats.ATTACK.identifier.path}", XStatItem(Stats.ATTACK))
@@ -571,14 +568,10 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
@JvmField
val CHOICE_SPECS = heldItem("choice_specs")
@JvmField
val CLEANSE_TAG = heldItem("cleanse_tag")
@JvmField
val DRAGON_FANG = heldItem("dragon_fang")
@JvmField
val EXP_SHARE = heldItem("exp_share")
@JvmField
val FAIRY_FEATHER = heldItem("fairy_feather")
@JvmField
val FOCUS_BAND = heldItem("focus_band")
@JvmField
val HARD_STONE = heldItem("hard_stone")
@@ -623,20 +616,18 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
@JvmField
val WISE_GLASSES = heldItem("wise_glasses")
@JvmField
val MENTAL_HERB = compostableHeldItem("mental_herb", null, 1F)
val MENTAL_HERB = heldItem("mental_herb")
@JvmField
val MIRROR_HERB = compostableHeldItem("mirror_herb", null, 1F)
val MIRROR_HERB = heldItem("mirror_herb")
@JvmField
val POWER_HERB = compostableHeldItem("power_herb", null, 1F)
val POWER_HERB = heldItem("power_herb")
@JvmField
val WHITE_HERB = compostableHeldItem("white_herb", null, 1F)
val WHITE_HERB = heldItem("white_herb")
@JvmField
val BRIGHT_POWDER = heldItem("bright_powder")
@JvmField
val METAL_POWDER = heldItem("metal_powder")
@JvmField
val LIGHT_POWDER = heldItem("light_powder")
@JvmField
val QUICK_POWDER = heldItem("quick_powder")
@JvmField
val DESTINY_KNOT = heldItem("destiny_knot")
@@ -654,104 +645,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
val POWER_LENS = heldItem("power_lens")
@JvmField
val POWER_WEIGHT = heldItem("power_weight")
@JvmField
val ABSORB_BULB = heldItem("absorb_bulb")
@JvmField
val ELECTRIC_SEED = heldItem("electric_seed")
@JvmField
val GRASSY_SEED = heldItem("grassy_seed")
@JvmField
val MISTY_SEED = heldItem("misty_seed")
@JvmField
val PSYCHIC_SEED = heldItem("psychic_seed")
@JvmField
val FLOAT_STONE = heldItem("float_stone")
@JvmField
val GRIP_CLAW = heldItem("grip_claw")
@JvmField
val LIGHT_BALL = heldItem("light_ball")
@JvmField
val SHED_SHELL = heldItem("shed_shell")
@JvmField
val STICKY_BARB = heldItem("sticky_barb")
@JvmField
val ABILITY_SHIELD = heldItem("ability_shield")
@JvmField
val AIR_BALLOON = heldItem("air_balloon")
@JvmField
val AMULET_COIN = heldItem("amulet_coin")
@JvmField
val BINDING_BAND = heldItem("binding_band")
@JvmField
val BLUNDER_POLICY = heldItem("blunder_policy")
@JvmField
val CELL_BATTERY = heldItem("cell_battery")
@JvmField
val CLEAR_AMULET = heldItem("clear_amulet")
@JvmField
val COVERT_CLOAK = heldItem("covert_cloak")
@JvmField
val EJECT_BUTTON = heldItem("eject_button")
@JvmField
val EJECT_PACK = heldItem("eject_pack")
@JvmField
val EXPERT_BELT = heldItem("expert_belt")
@JvmField
val FLAME_ORB = heldItem("flame_orb")
@JvmField
val FOCUS_SASH = heldItem("focus_sash")
@JvmField
val LAGGING_TAIL = heldItem("lagging_tail")
@JvmField
val LIFE_ORB = heldItem("life_orb")
@JvmField
val LOADED_DICE = heldItem("loaded_dice")
@JvmField
val LUMINOUS_MOSS = heldItem("luminous_moss")
@JvmField
val METRONOME = heldItem("metronome")
@JvmField
val PROTECTIVE_PADS = heldItem("protective_pads")
@JvmField
val PUNCHING_GLOVE = heldItem("punching_glove")
@JvmField
val RED_CARD = heldItem("red_card")
@JvmField
val RING_TARGET = heldItem("ring_target")
@JvmField
val ROOM_SERVICE = heldItem("room_service")
@JvmField
val SCOPE_LENS = heldItem("scope_lens")
@JvmField
val SHELL_BELL = heldItem("shell_bell")
@JvmField
val SOOTHE_BELL = heldItem("soothe_bell")
@JvmField
val TERRAIN_EXTRUDER = heldItem("terrain_extruder")
@JvmField
val THROAT_SPRAY = heldItem("throat_spray")
@JvmField
val TOXIC_ORB = heldItem("toxic_orb")
@JvmField
val UTILITY_UMBRELLA = heldItem("utility_umbrella")
@JvmField
val WEAKNESS_POLICY = heldItem("weakness_policy")
@JvmField
val WIDE_LENS = heldItem("wide_lens")
@JvmField
val ZOOM_LENS = heldItem("zoom_lens")
@JvmField
val IRON_BALL = heldItem("iron_ball")
@JvmField
val SMOKE_BALL = heldItem("smoke_ball")
@JvmField
val HEAT_ROCK = heldItem("heat_rock")
@JvmField
val DAMP_ROCK = heldItem("damp_rock")
@JvmField
val SMOOTH_ROCK = heldItem("smooth_rock")
@JvmField
val ICY_ROCK = heldItem("icy_rock")
// Mulch
@JvmField
@@ -803,12 +696,9 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
}
)
private fun compostable(item: Item, increaseLevelChance: Float) = Cobblemon.implementation.registerCompostable(item, increaseLevelChance)
private fun berryItem(name: String, berryBlock: BerryBlock): BerryItem {
val finalName = "${name}_berry"
val item = this.create(finalName, BerryItem(berryBlock))
compostable(item, .65f)
this.berries[cobblemonResource(finalName)] = item
return item
}
@@ -816,62 +706,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
private fun berryItem(name: String, berryItem: BerryItem): BerryItem {
val finalName = "${name}_berry"
val item = this.create(finalName, berryItem)
compostable(item, .65f)
this.berries[cobblemonResource(finalName)] = item
return item
}
private fun mintItem(name: String, mintItem: MintItem): MintItem {
val item = this.create(name, mintItem)
mints[item.nature.displayName] = item
compostable(item, .65f)
return item
}
private fun apricornItem(name: String, apricornItem: ApricornItem): ApricornItem {
val finalName = "${name}_apricorn"
val item = this.create(finalName, apricornItem)
compostable(item, .65f)
return item
}
private fun apricornSeedItem(name: String, apricornSeedItem: ApricornSeedItem): ApricornSeedItem {
val finalName = "${name}_apricorn_seed"
val item = this.create(finalName, apricornSeedItem)
compostable(item, .65f)
return item
}
private fun mintSeed(name: String, mintBlock: MintBlock): Item {
val finalName = "${name}_mint_seeds"
val item = this.blockItem(finalName, mintBlock)
compostable(item, .65f)
return item
}
private fun mintLeaf(name: String, mintLeafItem: MintLeafItem): MintLeafItem {
val finalName = "${name}_mint_leaf"
val item = this.create(finalName, mintLeafItem)
compostable(item, .65f)
return item
}
private fun compostableItem(name: String, item: Item? = null, increaseLevelChance: Float = .65f): Item {
val createdItem = this.create(name, item ?: Item(Item.Settings()))
compostable(createdItem, increaseLevelChance)
return createdItem
}
private fun compostableHeldItem(name: String, remappedName: String? = null, increaseLevelChance: Float = .65f): CobblemonItem {
val createdItem = heldItem(name, remappedName)
compostable(createdItem, increaseLevelChance)
return createdItem
}
private fun compostableBlockItem(name: String, block: Block, increaseLevelChance: Float = .65f): Item {
val createdItem = this.blockItem(name, block)
compostable(createdItem, increaseLevelChance)
return createdItem
}
}
@@ -11,27 +11,8 @@ package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
import com.cobblemon.mod.common.client.net.PlayerInteractOptionsHandler
import com.cobblemon.mod.common.client.net.SetClientPlayerDataHandler
import com.cobblemon.mod.common.client.net.battle.BattleApplyPassResponseHandler
import com.cobblemon.mod.common.client.net.battle.BattleCaptureEndHandler
import com.cobblemon.mod.common.client.net.battle.BattleCaptureShakeHandler
import com.cobblemon.mod.common.client.net.battle.BattleCaptureStartHandler
import com.cobblemon.mod.common.client.net.battle.BattleChallengeExpiredHandler
import com.cobblemon.mod.common.client.net.battle.BattleChallengeNotificationHandler
import com.cobblemon.mod.common.client.net.battle.BattleEndHandler
import com.cobblemon.mod.common.client.net.battle.BattleFaintHandler
import com.cobblemon.mod.common.client.net.battle.BattleHealthChangeHandler
import com.cobblemon.mod.common.client.net.battle.BattleInitializeHandler
import com.cobblemon.mod.common.client.net.battle.BattleMadeInvalidChoiceHandler
import com.cobblemon.mod.common.client.net.battle.BattleMakeChoiceHandler
import com.cobblemon.mod.common.client.net.battle.BattleMessageHandler
import com.cobblemon.mod.common.client.net.battle.BattleMusicHandler
import com.cobblemon.mod.common.client.net.battle.BattlePersistentStatusHandler
import com.cobblemon.mod.common.client.net.battle.BattleQueueRequestHandler
import com.cobblemon.mod.common.client.net.battle.BattleSetTeamPokemonHandler
import com.cobblemon.mod.common.client.net.battle.BattleSwitchPokemonHandler
import com.cobblemon.mod.common.client.net.battle.BattleUpdateTeamPokemonHandler
import com.cobblemon.mod.common.client.net.battle.*
import com.cobblemon.mod.common.client.net.callback.move.OpenMoveCallbackHandler
import com.cobblemon.mod.common.client.net.callback.party.OpenPartyCallbackHandler
import com.cobblemon.mod.common.client.net.callback.partymove.OpenPartyMoveCallbackHandler
@@ -70,7 +51,6 @@ import com.cobblemon.mod.common.client.net.trade.TradeOfferExpiredHandler
import com.cobblemon.mod.common.client.net.trade.TradeOfferNotificationHandler
import com.cobblemon.mod.common.client.net.trade.TradeStartedHandler
import com.cobblemon.mod.common.client.net.trade.TradeUpdatedHandler
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
import com.cobblemon.mod.common.net.messages.client.battle.*
import com.cobblemon.mod.common.net.messages.client.callback.OpenMoveCallbackPacket
import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyCallbackPacket
@@ -119,10 +99,12 @@ import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
import com.cobblemon.mod.common.net.messages.server.*
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
import com.cobblemon.mod.common.net.messages.server.BenchMovePacket
import com.cobblemon.mod.common.net.messages.server.RequestMoveSwapPacket
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectCancelledPacket
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectedPacket
import com.cobblemon.mod.common.net.messages.server.callback.party.PartyPokemonSelectedPacket
@@ -152,10 +134,7 @@ import com.cobblemon.mod.common.net.messages.server.trade.ChangeTradeAcceptanceP
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket
import com.cobblemon.mod.common.net.serverhandling.ChallengeHandler
import com.cobblemon.mod.common.net.serverhandling.RequestInteractionsHandler
import com.cobblemon.mod.common.net.serverhandling.battle.BattleSelectActionsHandler
import com.cobblemon.mod.common.net.serverhandling.battle.RemoveSpectatorHandler
import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectCancelledHandler
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectedHandler
import com.cobblemon.mod.common.net.serverhandling.callback.party.PartyPokemonSelectedHandler
@@ -189,12 +168,12 @@ import com.cobblemon.mod.common.net.serverhandling.trade.ChangeTradeAcceptanceHa
import com.cobblemon.mod.common.net.serverhandling.trade.OfferTradeHandler
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler
import com.cobblemon.mod.common.util.server
import kotlin.reflect.KClass
import net.minecraft.network.PacketByteBuf
import net.minecraft.network.listener.ClientPlayPacketListener
import net.minecraft.network.packet.Packet
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
import kotlin.reflect.KClass
/**
* Registers Cobblemon network packets.
@@ -259,7 +238,6 @@ object CobblemonNetwork : NetworkManager {
// UI Packets
this.createClientBound(SummaryUIPacket.ID, SummaryUIPacket::decode, SummaryUIPacketHandler)
this.createClientBound(InteractPokemonUIPacket.ID, InteractPokemonUIPacket::decode, InteractPokemonUIPacketHandler)
this.createClientBound(PlayerInteractOptionsPacket.ID, PlayerInteractOptionsPacket::decode, PlayerInteractOptionsHandler)
// Starter packets
this.createClientBound(OpenStarterUIPacket.ID, OpenStarterUIPacket::decode, StarterUIPacketHandler)
@@ -345,7 +323,6 @@ object CobblemonNetwork : NetworkManager {
// Interaction Packets
this.createServerBound(InteractPokemonPacket.ID, InteractPokemonPacket::decode, InteractPokemonHandler)
this.createServerBound(RequestPlayerInteractionsPacket.ID, RequestPlayerInteractionsPacket::decode, RequestInteractionsHandler)
// Storage Packets
this.createServerBound(SendOutPokemonPacket.ID, SendOutPokemonPacket::decode, SendOutPokemonHandler)
@@ -373,8 +350,6 @@ object CobblemonNetwork : NetworkManager {
// Battle packets
this.createServerBound(BattleSelectActionsPacket.ID, BattleSelectActionsPacket::decode, BattleSelectActionsHandler)
this.createServerBound(SpectateBattlePacket.ID, SpectateBattlePacket::decode, SpectateBattleHandler)
this.createServerBound(RemoveSpectatorPacket.ID, RemoveSpectatorPacket::decode, RemoveSpectatorHandler)
// Trade
this.createServerBound(AcceptTradeRequestPacket.ID, AcceptTradeRequestPacket::decode, AcceptTradeRequestHandler)
@@ -40,7 +40,6 @@ import com.cobblemon.mod.common.net.messages.client.battle.BattleEndPacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleMessagePacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleMusicPacket
import com.cobblemon.mod.common.pokemon.evolution.progress.DefeatEvolutionProgress
import com.cobblemon.mod.common.pokemon.evolution.progress.LastBattleCriticalHitsEvolutionProgress
import com.cobblemon.mod.common.pokemon.evolution.requirements.DefeatRequirement
import com.cobblemon.mod.common.util.battleLang
import com.cobblemon.mod.common.util.getPlayer
@@ -56,7 +55,6 @@ import net.minecraft.text.Text
* @since January 16th, 2022
* @author Deltric, Hiroku
*/
@Suppress("unused", "MemberVisibilityCanBePrivate")
open class PokemonBattle(
val format: BattleFormat,
val side1: BattleSide,
@@ -70,9 +68,7 @@ open class PokemonBattle(
side2.battle = this
this.actors.forEach { actor ->
actor.pokemonList.forEach { battlePokemon ->
battlePokemon.effectedPokemon.evolutionProxy.current().progress()
.filterIsInstance<LastBattleCriticalHitsEvolutionProgress>()
.forEach { it.reset() }
battlePokemon.criticalHits = 0
}
}
}
@@ -86,13 +82,12 @@ open class PokemonBattle(
val playerUUIDs: Iterable<UUID>
get() = actors.flatMap { it.getPlayerUUIDs() }
val players = playerUUIDs.mapNotNull { it.getPlayer() }
val spectators = mutableSetOf<UUID>()
val spectators = mutableListOf<UUID>()
val battleId = UUID.randomUUID()
val showdownMessages = mutableListOf<String>()
val battleLog = mutableListOf<String>()
val chatLog = mutableListOf<Text>()
var started = false
var ended = false
// TEMP battle showcase stuff
@@ -180,8 +175,11 @@ open class PokemonBattle(
}
fun broadcastChatMessage(component: Text) {
chatLog.add(component)
sendSpectatorUpdate(BattleMessagePacket(component))
spectators.forEach { spectatorId ->
spectatorId.getPlayer()?.let {
CobblemonNetwork.sendPacketToPlayer(it, BattleMessagePacket(component))
}
}
return actors.forEach { it.sendMessage(component) }
}
@@ -26,20 +26,13 @@ abstract class AIBattleActor(
super.sendUpdate(packet)
if (packet is BattleMakeChoicePacket) {
this.onChoiceRequested()
}
}
/**
* Called when the AI is requested to make a choice.
*/
open fun onChoiceRequested() {
try {
setActionResponses(request!!.iterate(this.activePokemon, battleAI::choose))
} catch (exception: IllegalActionChoiceException) {
LOGGER.error("AI was unable to choose a move, we're going to need to pass!")
exception.printStackTrace()
setActionResponses(request!!.iterate(this.activePokemon) { _, _, _ -> PassActionResponse })
try {
setActionResponses(request!!.iterate(this.activePokemon, battleAI::choose))
} catch (exception: IllegalActionChoiceException) {
LOGGER.error("AI was unable to choose a move, we're going to need to pass!")
exception.printStackTrace()
setActionResponses(request!!.iterate(this.activePokemon) { _, _, _ -> PassActionResponse })
}
}
}
}
@@ -10,11 +10,11 @@ package com.cobblemon.mod.common.api.drop
import com.cobblemon.mod.common.api.events.CobblemonEvents.LOOT_DROPPED
import com.cobblemon.mod.common.api.events.drops.LootDroppedEvent
import kotlin.random.Random
import net.minecraft.entity.LivingEntity
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.math.Vec3d
import kotlin.random.Random
/**
* A table of drops that can produce a list of [DropEntry]. You can produce a drop list from [getDrops] to
@@ -31,7 +31,6 @@ import com.cobblemon.mod.common.api.events.pokemon.*
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionAcceptedEvent
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEvent
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionDisplayEvent
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionTestedEvent
import com.cobblemon.mod.common.api.events.pokemon.interaction.ExperienceCandyUseEvent
import com.cobblemon.mod.common.api.events.starter.StarterChosenEvent
import com.cobblemon.mod.common.api.events.storage.ReleasePokemonEvent
@@ -44,7 +43,6 @@ import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import net.minecraft.server.network.ServerPlayerEntity
@Suppress("unused")
object CobblemonEvents {
@JvmField
@@ -60,8 +58,6 @@ object CobblemonEvents {
@JvmField
val EVOLUTION_DISPLAY = EventObservable<EvolutionDisplayEvent>()
@JvmField
val EVOLUTION_TESTED = EventObservable<EvolutionTestedEvent>()
@JvmField
val EVOLUTION_COMPLETE = EventObservable<EvolutionCompleteEvent>()
@JvmField
val POKEMON_NICKNAMED = CancelableObservable<PokemonNicknamedEvent>()
@@ -113,10 +109,7 @@ object CobblemonEvents {
val POKEMON_ENTITY_SPAWN = ENTITY_SPAWN
.pipe(
filter { it.entity is PokemonEntity },
map {
@Suppress("UNCHECKED_CAST")
it as SpawnEvent<PokemonEntity>
}
map { it as SpawnEvent<PokemonEntity> }
)
@JvmField
@@ -23,6 +23,6 @@ import com.cobblemon.mod.common.pokemon.Pokemon
* @since April 28th, 2022
*/
data class EvolutionAcceptedEvent(
override val pokemon: Pokemon,
override val evolution: Evolution
) : Cancelable(), EvolutionEvent
val pokemon: Pokemon,
val evolution: Evolution
) : Cancelable()
@@ -21,6 +21,6 @@ import com.cobblemon.mod.common.pokemon.Pokemon
* @since October 2nd, 2022
*/
data class EvolutionCompleteEvent(
override val pokemon: Pokemon,
override val evolution: Evolution
) : EvolutionEvent
val pokemon: Pokemon,
val evolution: Evolution
)
@@ -25,7 +25,7 @@ import com.cobblemon.mod.common.pokemon.Pokemon
* @since May 3rd, 2022
*/
data class EvolutionDisplayEvent(
override val pokemon: Pokemon,
val pokemon: Pokemon,
var display: EvolutionDisplay,
override val evolution: Evolution
) : EvolutionEvent
val evolution: Evolution
)
@@ -1,29 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.pokemon.evolution
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.pokemon.Pokemon
/**
* The root of the various evolution related events.
*/
interface EvolutionEvent {
/**
* The Pokémon impacted in this event.
*/
val pokemon: Pokemon
/**
* The evolution triggering this event.
*/
val evolution: Evolution
}
@@ -1,28 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.pokemon.evolution
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.pokemon.Pokemon
/**
* An event fired when [Evolution.test] has been performed.
* The final state [result] will be the return value of the test function.
*
* @property pokemon The [Pokemon] being tested against.
* @property evolution The [Evolution] instance performing the test.
* @property originalResult The base result from the Cobblemon implementation.
* @property result The final value returned by [Evolution.test].
*/
data class EvolutionTestedEvent(
override val pokemon: Pokemon,
override val evolution: Evolution,
val originalResult: Boolean,
var result: Boolean
) : EvolutionEvent
@@ -122,27 +122,16 @@ fun drawText(
y: Number,
centered: Boolean = false,
colour: Int,
shadow: Boolean = true,
pMouseX: Number? = null,
pMouseY: Number? = null
): Boolean {
shadow: Boolean = true
) {
val comp = if (font == null) text else text.setStyle(text.style.withFont(font))
val textRenderer = MinecraftClient.getInstance().textRenderer
var x = x
val width = textRenderer.getWidth(comp)
if (centered) {
val width = textRenderer.getWidth(comp)
x = x.toDouble() - width / 2
}
context.drawText(textRenderer, comp, x.toInt(), y.toInt(), colour, shadow)
var isHovered = false
if (pMouseY != null && pMouseX != null) {
if (pMouseX.toInt() >= x.toInt() && pMouseX.toInt() <= x.toInt() + width &&
pMouseY.toInt() >= y.toInt() && pMouseY.toInt() <= y.toInt() + textRenderer.fontHeight
) {
isHovered = true
}
}
return isHovered
}
fun drawText(
@@ -66,15 +66,7 @@ interface PokemonSelectingItem {
return if (entity != null) {
val pokemon = entity.pokemon
if (entity.ownerUuid == player.uuid) {
val typedActionResult = applyToPokemon(player, stack, pokemon)
if (typedActionResult != null)
{
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(pokemon.species.resourceIdentifier, Registries.ITEM.getId(stack.item)))
typedActionResult
}
else {
TypedActionResult.pass(stack)
}
applyToPokemon(player, stack, pokemon) ?: TypedActionResult.pass(stack)
} else {
TypedActionResult.fail(stack)
}
@@ -156,7 +156,7 @@ open class PokemonProperties {
}
private fun parseSpeciesIdentifier(keyPairs: MutableList<Pair<String, String?>>): String? {
fun cleanSpeciesName(string: String) = string.lowercase().replace("[^a-z0-9_:]".toRegex(), "")
fun cleanSpeciesName(string: String) = string.lowercase().replace("[^a-z0-9:]".toRegex(), "")
val matched = getMatchedKeyPair(keyPairs, listOf("species"))
if (matched != null) {
val value = matched.second?.let(::cleanSpeciesName) ?: return null
@@ -486,6 +486,7 @@ open class PokemonProperties {
fun roll(pokemon: Pokemon) {
val baseTypes = pokemon.species.types.toList()
if (this.shiny == null) pokemon.shiny = Cobblemon.config.shinyRate.checkRate()
if (this.gmaxFactor == null) pokemon.gmaxFactor = Cobblemon.config.gigantamaxFactorRate.checkRate()
if (this.teraType == null) pokemon.teraType =
if (Cobblemon.config.teraTypeRate.checkRate()) ElementalTypes.all().filter { !baseTypes.contains(it) }.random()
else baseTypes.random()
@@ -9,9 +9,9 @@
package com.cobblemon.mod.common.api.pokemon.evolution
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.abilities.AbilityPool
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEvent
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionTestedEvent
import com.cobblemon.mod.common.api.moves.BenchedMove
import com.cobblemon.mod.common.api.moves.MoveTemplate
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
@@ -67,12 +67,7 @@ interface Evolution : EvolutionLike {
* @param pokemon The [Pokemon] being queried.
* @return If the [Evolution] can start.
*/
fun test(pokemon: Pokemon): Boolean {
val result = this.requirements.all { requirement -> requirement.check(pokemon) }
val event = EvolutionTestedEvent(pokemon, this, result, result)
CobblemonEvents.EVOLUTION_TESTED.post(event)
return event.result
}
fun test(pokemon: Pokemon) = this.requirements.all { requirement -> requirement.check(pokemon) }
/**
* Starts this evolution or queues it if [optional] is true.
@@ -8,16 +8,14 @@
package com.cobblemon.mod.common.api.pokemon.evolution.progress
import com.cobblemon.mod.common.pokemon.evolution.progress.*
import com.cobblemon.mod.common.pokemon.evolution.progress.RecoilEvolutionProgress
import com.cobblemon.mod.common.pokemon.evolution.progress.UseMoveEvolutionProgress
object EvolutionProgressFactory {
private val variants = hashMapOf<String, () -> EvolutionProgress<*>>()
init {
registerVariant(DamageTakenEvolutionProgress.ID.toString()) { DamageTakenEvolutionProgress() }
registerVariant(DefeatEvolutionProgress.ID.toString()) { DefeatEvolutionProgress() }
registerVariant(LastBattleCriticalHitsEvolutionProgress.ID.toString()) { LastBattleCriticalHitsEvolutionProgress() }
registerVariant(RecoilEvolutionProgress.ID.toString()) { RecoilEvolutionProgress() }
registerVariant(UseMoveEvolutionProgress.ID.toString()) { UseMoveEvolutionProgress() }
}
@@ -79,16 +79,6 @@ interface HeldItemManager {
*/
fun take(pokemon: BattlePokemon, showdownId: String)
/**
* Tests if the given [BattlePokemon] should have their item consumed.
* This method is expected to be used in each implementation when needed.
*
* @param pokemon The [BattlePokemon] being tested.
* @param battle The [PokemonBattle] the [pokemon] is participating in.
* @param showdownId The literal ID of the held item on Showdown.
*/
fun shouldConsumeItem(pokemon: BattlePokemon, battle: PokemonBattle, showdownId: String): Boolean = false
companion object {
/**
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common.api.pokemon.status
import com.cobblemon.mod.common.pokemon.status.PersistentStatus
import com.cobblemon.mod.common.pokemon.status.statuses.BurnStatus
import com.cobblemon.mod.common.pokemon.status.statuses.FrozenStatus
import com.cobblemon.mod.common.pokemon.status.statuses.ParalysisStatus
@@ -40,5 +39,4 @@ object Statuses {
fun getStatus(name: Identifier) = allStatuses.find { status -> status.name == name }
fun getStatus(showdownName: String) = allStatuses.find { it.showdownName == showdownName }
fun getPersistentStatuses() = allStatuses.filterIsInstance<PersistentStatus>()
}
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.api.spawning
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.Cobblemon.config
import com.cobblemon.mod.common.api.spawning.mixins.CachedOnlyChunkAccessor
import com.cobblemon.mod.common.api.spawning.prospecting.SpawningProspector
import com.cobblemon.mod.common.api.spawning.spawner.Spawner
import com.cobblemon.mod.common.api.spawning.spawner.SpawningArea
@@ -80,7 +81,8 @@ object CobblemonSpawningProspector : SpawningProspector {
for (x in area.baseX until area.baseX + area.length) {
for (z in area.baseZ until area.baseZ + area.width) {
val query = chunks.computeIfAbsent(Pair(getSectionCoord(x), getSectionCoord(z))) {
world.getChunk(it.first, it.second, ChunkStatus.FULL, false)
val manager = world.chunkManager as CachedOnlyChunkAccessor
manager.`cobblemon$request`(it.first, it.second, ChunkStatus.FULL)
} ?: continue
var canSeeSky = world.isSkyVisibleAllowingSea(pos.set(x, yRange.first, z))
@@ -31,16 +31,12 @@ open class SpawnerManager {
open fun registerSpawner(spawner: Spawner) {
spawners.add(spawner)
if (spawner !is TickingSpawner) {
spawner.influences.addAll(influences)
}
spawner.influences.addAll(influences)
}
open fun unregisterSpawner(spawner: Spawner) {
spawners.remove(spawner)
if (spawner !is TickingSpawner) {
spawner.influences.removeAll(influences)
}
spawner.influences.removeAll(influences)
}
open fun onServerStarted() {
@@ -28,12 +28,13 @@ abstract class SpawnAction<T : Entity>(
) {
abstract fun createEntity(): T?
open fun run() {
fun run() {
ctx.influences.forEach { it.affectAction(this) }
val e = createEntity() ?: return
e.setPosition(ctx.position.toVec3d().add(0.5, 1.0, 0.5))
entity.emit(e)
CobblemonEvents.ENTITY_SPAWN.postThen(SpawnEvent(e, ctx), ifSucceeded = { ctx.world.spawnEntity(e) })
CobblemonEvents.ENTITY_SPAWN.post(SpawnEvent(e, ctx))
ctx.world.spawnEntity(e)
}
/**
@@ -46,4 +47,4 @@ abstract class SpawnAction<T : Entity>(
val entity: SimpleObservable<T> = SimpleObservable<T>().apply {
subscribe { entity -> ctx.afterSpawn(entity) }
}
}
}
@@ -0,0 +1,18 @@
/*
* 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.spawning.mixins
import net.minecraft.world.chunk.Chunk
import net.minecraft.world.chunk.ChunkStatus
interface CachedOnlyChunkAccessor {
fun `cobblemon$request`(x: Int, z: Int, status: ChunkStatus): Chunk?
}
@@ -17,9 +17,9 @@ import com.cobblemon.mod.common.api.spawning.context.calculators.AreaSpawningCon
import com.cobblemon.mod.common.api.spawning.context.calculators.SpawningContextCalculator.Companion.prioritizedAreaCalculators
import com.cobblemon.mod.common.api.spawning.detail.SpawnDetail
import com.cobblemon.mod.common.api.spawning.detail.SpawnPool
import com.cobblemon.mod.common.api.spawning.mixins.CachedOnlyChunkAccessor
import com.cobblemon.mod.common.api.spawning.prospecting.SpawningProspector
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.isBoxLoaded
import com.cobblemon.mod.common.util.squeezeWithinBounds
import com.cobblemon.mod.common.util.toVec3f
import net.minecraft.entity.ai.pathing.NavigationType
@@ -31,7 +31,6 @@ import net.minecraft.world.World
import net.minecraft.world.chunk.Chunk
import net.minecraft.world.chunk.ChunkStatus
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules.DO_POKEMON_SPAWNING
import net.minecraft.util.math.ChunkPos
/**
* A type of [TickingSpawner] that operates within some area. When this spawner type
@@ -60,7 +59,6 @@ abstract class AreaSpawner(
var resolver: AreaContextResolver = Cobblemon.areaContextResolver
var contextCalculators: List<AreaSpawningContextCalculator<*>> = prioritizedAreaCalculators
override fun run(cause: SpawnCause): Pair<SpawningContext, SpawnDetail>? {
val area = getArea(cause)
if (area?.world?.gameRules?.getBoolean(DO_POKEMON_SPAWNING) == false) {
@@ -68,15 +66,9 @@ abstract class AreaSpawner(
}
val constrainedArea = if (area != null) constrainArea(area) else null
if (constrainedArea != null) {
val areaBox = Box.of(Vec3d(constrainedArea.getCenter().toVec3f()), CHUNK_REACH * 16.0 * 2, 1000.0, CHUNK_REACH * 16.0 * 2)
if (!constrainedArea.world.isBoxLoaded(areaBox)) {
return null
}
val numberNearby = constrainedArea.world.getEntitiesByClass(
PokemonEntity::class.java,
areaBox
Box.of(Vec3d(constrainedArea.getCenter().toVec3f()), CHUNK_REACH * 16.0 * 2, 1000.0, CHUNK_REACH * 16.0 * 2)
) { true }.size
val chunksCovered = CHUNK_REACH * CHUNK_REACH
@@ -125,11 +117,7 @@ abstract class AreaSpawner(
val originalY = area.baseY
val (chunkX, chunkZ) = Pair(ChunkSectionPos.getSectionCoord(area.baseX), ChunkSectionPos.getSectionCoord(area.baseZ))
// if the chunk isn't loaded, we don't want to go further & we don't want the getChunk function below to load/create the chunk.
if (!area.world.isChunkLoaded(ChunkPos.toLong(chunkX, chunkZ))) return null
val chunk = area.world.getChunk(chunkX, chunkZ, ChunkStatus.FULL) ?: return null
val chunk = (area.world.chunkManager as CachedOnlyChunkAccessor).`cobblemon$request`(chunkX, chunkZ, ChunkStatus.FULL) ?: return null
var valid = isValidStartPoint(area.world, chunk, basePos)
@@ -15,7 +15,7 @@ import com.cobblemon.mod.common.api.spawning.detail.SpawnAction
import com.cobblemon.mod.common.api.spawning.detail.SpawnDetail
import com.cobblemon.mod.common.api.spawning.detail.SpawnPool
import com.cobblemon.mod.common.api.spawning.influence.SpawningInfluence
import com.cobblemon.mod.common.api.spawning.selection.FlatContextWeightedSelector
import com.cobblemon.mod.common.api.spawning.selection.FlatSelector
import com.cobblemon.mod.common.api.spawning.selection.SpawningSelector
import net.minecraft.entity.Entity
@@ -32,7 +32,7 @@ abstract class TickingSpawner(
var spawns: SpawnPool,
val manager: SpawnerManager
) : Spawner {
private var selector: SpawningSelector = FlatContextWeightedSelector()
private var selector: SpawningSelector = FlatSelector()
override val influences = mutableListOf<SpawningInfluence>()
override fun canSpawn() = active
@@ -32,19 +32,29 @@ import java.util.UUID
* @author Pebbles
* @since August 23rd, 2023
*/
@Suppress("MemberVisibilityCanBePrivate")
open class MongoDBStoreAdapter(
protected val mongoClient: MongoClient,
protected val databaseName: String,
private val mongoClient: MongoClient,
private val databaseName: String,
) : CobblemonAdapterParent<JsonObject>(), FileStoreAdapter<JsonObject> {
private fun getCollection(storeClass: Class<out PokemonStore<*>>): MongoCollection<Document> {
val collectionName = when (storeClass) {
PlayerPartyStore::class.java -> "PlayerPartyCollection"
PCStore::class.java -> "PCCollection"
else -> "OtherCollection"
}
return mongoClient.getDatabase(databaseName).getCollection(collectionName)
}
protected val gson: Gson = this.createGson()
private val gson: Gson = Gson()
override fun <E : StorePosition, T : PokemonStore<E>> serialize(store: T): JsonObject = store.saveToJSON(JsonObject())
override fun <E : StorePosition, T : PokemonStore<E>> serialize(store: T): JsonObject {
return store.saveToJSON(JsonObject())
}
override fun save(storeClass: Class<out PokemonStore<*>>, uuid: UUID, serialized: JsonObject) {
val document = Document.parse(this.gson.toJson(serialized))
document["uuid"] = uuid.toString()
val document = Document.parse(gson.toJson(serialized))
document.put("uuid", uuid.toString())
val collection = getCollection(storeClass)
val filter = Document("uuid", uuid.toString())
collection.replaceOne(filter, document, ReplaceOptions().upsert(true))
@@ -66,7 +76,7 @@ open class MongoDBStoreAdapter(
val document = collection.find(filter).first()
if (document != null) {
val json = this.gson.fromJson(document.toJson(), JsonObject::class.java)
val json = gson.fromJson(document.toJson(), JsonObject::class.java)
val store = storeClass.getConstructor(UUID::class.java).newInstance(uuid)
store.loadFromJSON(json)
return store
@@ -88,15 +98,4 @@ open class MongoDBStoreAdapter(
return null
}
protected open fun createGson(): Gson = Gson()
protected open fun getCollection(storeClass: Class<out PokemonStore<*>>): MongoCollection<Document> {
val collectionName = when (storeClass) {
PlayerPartyStore::class.java -> "PlayerPartyCollection"
PCStore::class.java -> "PCCollection"
else -> "OtherCollection"
}
return this.mongoClient.getDatabase(this.databaseName).getCollection(collectionName)
}
}
@@ -48,11 +48,7 @@ open class JSONStoreAdapter(
val br = BufferedReader(FileReader(file))
val json = gson.fromJson<JsonObject>(br)
br.close()
val store = try {
storeClass.getConstructor(UUID::class.java, UUID::class.java).newInstance(uuid, uuid)
} catch (exception: NoSuchMethodException) {
storeClass.getConstructor(UUID::class.java).newInstance(uuid)
}
val store = storeClass.getConstructor(UUID::class.java).newInstance(uuid)
store.loadFromJSON(json)
store
} catch (e: Exception) {
@@ -31,12 +31,7 @@ open class NBTStoreAdapter(
override fun <E : StorePosition, T : PokemonStore<E>> serialize(store: T) = store.saveToNBT(NbtCompound())
override fun save(file: File, serialized: NbtCompound) = NbtIo.writeCompressed(serialized, file)
override fun <E, T : PokemonStore<E>> load(file: File, storeClass: Class<out T>, uuid: UUID): T? {
val store = try {
storeClass.getConstructor(UUID::class.java, UUID::class.java).newInstance(uuid, uuid)
} catch (exception: NoSuchMethodException) {
storeClass.getConstructor(UUID::class.java).newInstance(uuid)
}
val store = storeClass.getConstructor(UUID::class.java).newInstance(uuid)
return try {
val nbt = NbtIo.readCompressed(file)
store.loadFromNBT(nbt)
@@ -38,10 +38,8 @@ import kotlin.random.Random
*/
open class PlayerPartyStore(
/** The UUID of the player this store is for. */
val playerUUID: UUID,
/** The UUID of the store. This is the same as [playerUUID] by default, but can be changed to allow for multiple parties. */
storageUUID: UUID = playerUUID
) : PartyStore(storageUUID) {
val playerUUID: UUID
) : PartyStore(playerUUID) {
private var secondsSinceFriendshipUpdate = 0
@@ -22,8 +22,6 @@ import net.minecraft.registry.tag.TagKey
@Suppress("HasPlatformType", "unused")
object CobblemonBlockTags {
@JvmField val ALL_HANGING_SIGNS = createTag("all_hanging_signs")
@JvmField val ALL_SIGNS = createTag("all_signs")
@JvmField val APRICORN_LEAVES = createTag("apricorn_leaves")
@JvmField val APRICORN_LOGS = createTag("apricorn_logs")
@JvmField val APRICORN_SAPLINGS = createTag("apricorn_saplings")
@@ -31,7 +29,6 @@ object CobblemonBlockTags {
@JvmField val BERRY_WILD_SOIL = createTag("berry_wild_soil")
@JvmField val BERRY_SOIL = createTag("berry_soil")
@JvmField val BERRY_REPLACEABLE = createTag("berry_replaceable")
@JvmField val CEILING_HANGING_SIGNS = createTag("ceiling_hanging_signs")
@JvmField val CROPS = createTag("crops")
@JvmField val DRIPSTONE_GROWABLE = createTag("dripstone_growable")
@JvmField val DRIPSTONE_REPLACEABLES = createTag("dripstone_replaceables")
@@ -39,15 +36,10 @@ object CobblemonBlockTags {
@JvmField val MEDICINAL_LEEK_PLANTABLE = createTag("medicinal_leek_plantable")
@JvmField val MINTS = createTag("mints")
@JvmField val ROOTS_SPREADABLE = createTag("roots_spreadable")
@JvmField val SIGNS = createTag("signs")
@JvmField val SMALL_FLOWERS = createTag("small_flowers")
@JvmField val SEES_SKY = createTag("sees_sky")
@JvmField val SNOW_BLOCK = createTag("snow_block")
@JvmField val ROOTS = createTag("roots")
@JvmField val STANDING_SIGNS = createTag("standing_signs")
@JvmField val WALL_HANGING_SIGNS = createTag("wall_hanging_signs")
@JvmField val WALL_SIGNS = createTag("wall_signs")
private fun createTag(name: String) = TagKey.of(RegistryKeys.BLOCK, cobblemonResource(name))
}
@@ -9,17 +9,15 @@
package com.cobblemon.mod.common.api.tags
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.registry.Registries
import net.minecraft.registry.RegistryKeys
import net.minecraft.registry.tag.TagKey
/**
* A collection of the Cobblemon [TagKey]s related to the [Registries.ENTITY_TYPE].
* A collection of the Cobblemon [TagKey]s related to the [Registry.ENTITY_TYPE].
*
* @author Licious
* @since March 6th, 2023
*/
@Suppress("HasPlatformType", "unused")
object CobblemonEntityTypeTags {
@@ -29,9 +27,6 @@ object CobblemonEntityTypeTags {
@JvmField
val CANNOT_HAVE_NAME_TAG = create("cannot_have_name_tag")
@JvmField
val BOATS = create("boats")
private fun create(path: String) = TagKey.of(RegistryKeys.ENTITY_TYPE, cobblemonResource(path))
}
@@ -9,17 +9,16 @@
package com.cobblemon.mod.common.api.tags
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.registry.Registries
import net.minecraft.registry.Registry
import net.minecraft.registry.RegistryKeys
import net.minecraft.registry.tag.TagKey
/**
* A collection of the Cobblemon [TagKey]s related to the [Registries.ITEM].
* A collection of the Cobblemon [TagKey]s related to the [Registry.ITEM].
*
* @author Licious
* @since January 8th, 2023
*/
@Suppress("unused", "HasPlatformType")
object CobblemonItemTags {
@JvmField
@@ -28,47 +27,11 @@ object CobblemonItemTags {
val APRICORN_SEEDS = create("apricorn_seeds")
@JvmField
val APRICORNS = create("apricorns")
/**
* This tag is only used for a Torterra aspect based easter egg evolution at the moment.
* It simply includes the 'minecraft:azalea' and 'minecraft:flowering_azalea' items by default.
*/
@JvmField
val AZALEA_TREE = create("azalea_tree")
@JvmField
val BERRIES = create("berries")
@JvmField
val BOATS = create("boats")
@JvmField
val COBBLEMON_SEEDS = create("cobblemon_seeds")
@JvmField
val EVOLUTION_ITEMS = create("evolution_items")
@JvmField
val EVOLUTION_STONES = create("evolution_stones")
@JvmField
val EXPERIENCE_CANDIES = create("experience_candies")
@JvmField
val HANGING_SIGNS = create("hanging_signs")
@JvmField
val HERBS = create("herbs")
@JvmField
val MINT_LEAF = create("mint_leaf")
@JvmField
val MINTS = create("mints")
@JvmField
val MUTATED_BERRIES = create("mutated_berries")
@JvmField
val PLANTS = create("plants")
@JvmField
val POKEBALLS = create("poke_balls")
@JvmField
val PROTEIN_INGREDIENTS = create("protein_ingredients")
@JvmField
val SEEDS = create("seeds")
@JvmField
val SIGNS = create("signs")
@JvmField
val ZINC_INGREDIENTS = create("zinc_ingredients")
@JvmField
val ANY_HELD_ITEM = create("held/is_held_item")
@JvmField
val EXPERIENCE_SHARE = create("held/experience_share")
@@ -91,11 +54,19 @@ object CobblemonItemTags {
@JvmField
val POWER_WEIGHT = create("held/power_weight")
@JvmField
val CONSUMED_IN_NPC_BATTLE = create("held/consumed_in_npc_battle")
val EVOLUTION_STONES = create("evolution_stones")
@JvmField
val CONSUMED_IN_PVP_BATTLE = create("held/consumed_in_pvp_battle")
val EVOLUTION_ITEMS = create("evolution_items")
@JvmField
val CONSUMED_IN_WILD_BATTLE = create("held/consumed_in_wild_battle")
val MINTS = create("mints")
@JvmField
val MINT_LEAVES = create("mint_leaves")
/**
* This tag is only used for a Torterra aspect based easter egg evolution at the moment.
* It simply includes the 'minecraft:azalea' and 'minecraft:flowering_azalea' items by default.
*/
val AZALEA_TREE = create("azalea_tree")
private fun create(path: String) = TagKey.of(RegistryKeys.ITEM, cobblemonResource(path))
@@ -158,7 +158,6 @@ fun String.stripCodes(): String = this.replace("[&§][A-Ea-e0-9K-Ok-oRr]".toRege
fun MutableText.onClick(consumed: AtomicBoolean, action: (p: ServerPlayerEntity) -> Unit) = also { it.style = it.style.withClickEvent(click(consumed, action)) }
fun MutableText.onClick(onlyOnce: Boolean = false, action: (p: ServerPlayerEntity) -> Unit) = also { it.style = it.style.withClickEvent(click(onlyOnce, action)) }
fun MutableText.onHover(string: String) = also { it.style = it.style.withHoverEvent(hover(string)) }
fun MutableText.onHover(text: Text) = also { it.style = it.style.withHoverEvent(hover(text)) }
fun MutableText.onHover(text: MutableText) = also { it.style = it.style.withHoverEvent(hover(text)) }
fun MutableText.underline() = also { it.style = it.style.withUnderline(true) }
fun MutableText.bold() = also { it.style = it.style.withBold(true) }
@@ -221,10 +221,6 @@ object BattleRegistry {
return battleMap.values.find { it.getActor(serverPlayerEntity) != null }
}
fun getBattleByParticipatingPlayerId(playerId: UUID): PokemonBattle? {
return battleMap.values.find { playerId in it.playerUUIDs }
}
fun tick() {
battleMap.forEachValue(Long.MAX_VALUE) { it.tick() }
}
@@ -206,7 +206,7 @@ data class SwitchActionResponse(var newPokemonId: UUID) : ShowdownActionResponse
val pokemon = activeBattlePokemon.actor.pokemonList.find { it.uuid == newPokemonId }
return when {
pokemon == null -> false // No such Pokémon
(!activeBattlePokemon.actor.request?.side?.pokemon?.get(0)?.reviving!! && pokemon.health <= 0) -> false // Checks if the active Pokémon is reviving, if so ignore this check. If not, return false if dead
pokemon.health <= 0 -> false // Pokémon is dead
showdownMoveSet != null && showdownMoveSet.trapped -> false // You're not allowed to switch
activeBattlePokemon.actor.getSide().activePokemon.any { it.battlePokemon?.uuid == newPokemonId } -> false // Pokémon is already sent out
else -> true
@@ -12,7 +12,6 @@ import com.cobblemon.mod.common.Cobblemon.LOGGER
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.battles.interpreter.*
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
import com.cobblemon.mod.common.api.battles.model.actor.EntityBackedBattleActor
import com.cobblemon.mod.common.api.data.ShowdownIdentifiable
@@ -25,7 +24,6 @@ import com.cobblemon.mod.common.api.pokemon.status.Statuses
import com.cobblemon.mod.common.api.scheduling.after
import com.cobblemon.mod.common.api.text.*
import com.cobblemon.mod.common.api.types.ElementalTypes
import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
import com.cobblemon.mod.common.battles.dispatch.BattleDispatch
import com.cobblemon.mod.common.battles.dispatch.DispatchResult
import com.cobblemon.mod.common.battles.dispatch.GO
@@ -35,7 +33,6 @@ import com.cobblemon.mod.common.battles.interpreter.ContextManager
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.net.messages.client.battle.*
import com.cobblemon.mod.common.pokemon.evolution.progress.DamageTakenEvolutionProgress
import com.cobblemon.mod.common.pokemon.evolution.progress.LastBattleCriticalHitsEvolutionProgress
import com.cobblemon.mod.common.pokemon.evolution.progress.RecoilEvolutionProgress
import com.cobblemon.mod.common.pokemon.evolution.progress.UseMoveEvolutionProgress
import com.cobblemon.mod.common.pokemon.status.PersistentStatus
@@ -48,7 +45,6 @@ import net.minecraft.server.world.ServerWorld
import net.minecraft.text.MutableText
import net.minecraft.text.Text
@Suppress("KotlinPlaceholderCountMatchesArgumentCount", "UNUSED_PARAMETER")
object ShowdownInterpreter {
private val updateInstructions = mutableMapOf<String, (PokemonBattle, BattleMessage, MutableList<String>) -> Unit>()
private val sideUpdateInstructions = mutableMapOf<String, (PokemonBattle, BattleActor, BattleMessage) -> Unit>()
@@ -83,7 +79,6 @@ object ShowdownInterpreter {
updateInstructions["|-mustrecharge|"] = this::handleRechargeInstructions
updateInstructions["|-fail|"] = this::handleFailInstruction
updateInstructions["|-start|"] = this::handleStartInstructions
updateInstructions["|-block|"] = this::handleBlockInstructions
updateInstructions["|-activate|"] = this::handleActivateInstructions
updateInstructions["|-curestatus|"] = this::handleCureStatusInstruction
updateInstructions["|-fieldstart|"] = this::handleFieldStartInstructions
@@ -584,17 +579,6 @@ object ShowdownInterpreter {
battle.end()
val wasCaught = battle.showdownMessages.any { "capture" in it }
// If the battle was a PvW battle, we need to set the killer of the wild Pokémon to the player
if (battle.isPvW) {
val nonPlayerActor = battle.actors.first { it.type == ActorType.WILD }
val wildPokemon: BattlePokemon = nonPlayerActor.pokemonList.first()
if (!wasCaught && losers.any { it.uuid == wildPokemon.uuid }) {
wildPokemon.effectedPokemon.entity?.killer = (battle.actors.firstOrNull { it.type == ActorType.PLAYER } as? PlayerBattleActor)?.entity
}
}
CobblemonEvents.BATTLE_VICTORY.post(BattleVictoryEvent(battle, winners, losers, wasCaught))
this.lastCauser.remove(battle.battleId)
@@ -782,10 +766,7 @@ object ShowdownInterpreter {
battle.broadcastChatMessage(battleLang("crit").yellow())
this.lastCauser[battle.battleId]?.let { message ->
val battlePokemon = message.getBattlePokemon(0, battle) ?: return@let
if (LastBattleCriticalHitsEvolutionProgress.supports(battlePokemon.effectedPokemon)) {
val progress = battlePokemon.effectedPokemon.evolutionProxy.current().progressFirstOrCreate({ it is LastBattleCriticalHitsEvolutionProgress }) { LastBattleCriticalHitsEvolutionProgress() }
progress.updateProgress(LastBattleCriticalHitsEvolutionProgress.Progress(progress.currentProgress().amount + 1))
}
battlePokemon.criticalHits++
}
battle.minorBattleActions[pokemon.uuid] = message
}
@@ -828,19 +809,10 @@ object ShowdownInterpreter {
*
* The specified ACTION has failed against the POKEMON targetted.
*/
private fun handleFailInstruction(battle: PokemonBattle, message: BattleMessage, remainingLines: MutableList<String>) {
private fun handleFailInstruction(battle: PokemonBattle, message: BattleMessage, remainingLines: MutableList<String>){
battle.dispatchWaiting(1.5F){
val pokemon = message.getBattlePokemon(0, battle) ?: return@dispatchWaiting
val pokemonName = pokemon.getName()
val effectID = message.effectAt(1)?.id ?: return@dispatchWaiting
val lang = when (effectID) {
"shedtail" -> battleLang("fail.substitute", pokemonName)
"hyperspacefury" -> battleLang("fail.darkvoid", pokemonName)
"corrosivegas" -> battleLang("fail.healblock", pokemonName)
else -> battleLang("fail.$effectID", pokemonName)
}
battle.broadcastChatMessage(lang.red())
battle.broadcastChatMessage(battleLang("fail").red())
battle.minorBattleActions[pokemon.uuid] = message
}
}
@@ -916,8 +888,6 @@ object ShowdownInterpreter {
"confusion", "perish3" -> return@dispatch GO // Skip
"perish2", "perish1", "perish0" -> battleLang("start.perish", pokemon.getName(), effectID.last().digitToInt())
"dynamax" -> battleLang("start.${message.effectAt(2)?.id ?: effectID}", pokemon.getName()).yellow()
"curse" -> battleLang("start.curse", message.getSourceBattlePokemon(battle)!!.getName(), pokemon.getName())
"disable" -> battleLang("start.disable", pokemon.getName(), message.effectAt(2)!!.rawData)
else -> battleLang("start.$effectID", pokemon.getName())
}
battle.broadcastChatMessage(lang)
@@ -961,27 +931,6 @@ object ShowdownInterpreter {
}
}
/**
* Format:
* |-block|POKEMON|EFFECT|MOVE|ATTACKER
*
* An effect targeted at POKEMON was blocked by EFFECT. This may optionally specify that the effect was a MOVE from ATTACKER. [of]SOURCE will note the owner of the EFFECT, in the case that it's not EFFECT (for instance, an ally with Aroma Veil.)
*/
private fun handleBlockInstructions(battle: PokemonBattle, message: BattleMessage, remainingLines: MutableList<String>) {
battle.dispatchWaiting(1.5F) {
val pokemon = message.getBattlePokemon(0, battle) ?: return@dispatchWaiting
val pokemonName = pokemon.getName()
val effectID = message.effectAt(1)?.id ?: return@dispatchWaiting
val lang = when (effectID) {
"matblock" -> battleLang("block.matblock", message.effectAt(2)!!.rawData)
else -> battleLang("block.$effectID", pokemonName)
}
battle.broadcastChatMessage(lang)
battle.minorBattleActions[pokemon.uuid] = message
}
}
/**
* Format:
* |-activate|POKEMON|EFFECT
@@ -1006,7 +955,6 @@ object ShowdownInterpreter {
"spite" -> battleLang("activate.spite", pokemonName, message.argumentAt(2)!!, message.argumentAt(3)!!)
// Don't need additional lang, announced elsewhere
"toxicdebris", "shedskin" -> return@dispatch GO
"matblock" -> battleLang("activate.matblock", message.effectAt(2)!!.rawData)
// Add activation to each Pokemon's history
"destinybond" -> {
battle.activePokemon.mapNotNull { it.battlePokemon?.uuid }.forEach { battle.minorBattleActions[it] = message }
@@ -1019,7 +967,6 @@ object ShowdownInterpreter {
}
"focussash", "focusband" -> battleLang("activate.focusband", pokemonName, message.effectAt(1)!!.typelessData)
"maxguard", "protect" -> battleLang("activate.protect", pokemonName)
"shadowforce", "hyperspacefury", "hyperspacehole" -> battleLang("activate.phantomforce", pokemonName)
else -> battleLang("activate.${effect.id}", pokemonName, sourceName)
}
battle.broadcastChatMessage(lang)
@@ -1086,7 +1033,7 @@ object ShowdownInterpreter {
/**
* Format:
* |-ability|POKEMON|ABILITY|&#91from&#93EFFECT
* |-ability|POKEMON|ABILITY|[from]EFFECT
*
* The ABILITY of the POKEMON has been changed due to a move/ability EFFECT.
*
@@ -1154,8 +1101,6 @@ object ShowdownInterpreter {
}
}
/**
* Format:
* |-swapboost|SOURCE|TARGET|STATS
@@ -1453,8 +1398,6 @@ object ShowdownInterpreter {
lang("status.$status.hurt", pokemonName)
}
"aftermath" -> battleLang("damage.generic", pokemonName)
"chloroblast", "steelbeam" -> battleLang("damage.mindblown", pokemonName)
"jumpkick" -> battleLang("damage.highjumpkick", pokemonName)
else -> battleLang("damage.${effect.id}", pokemonName, sourceName)
}
battle.broadcastChatMessage(lang.red())
@@ -1485,9 +1428,7 @@ object ShowdownInterpreter {
GO
}
}
privateMessage.pnxAndUuid(0)?.let { (pnx, _) -> {
battle.sendSidedUpdate(actor, BattleHealthChangePacket(pnx, remainingHealth.toFloat()), BattleHealthChangePacket(pnx, newHealthRatio))
}}
privateMessage.pnxAndUuid(0)?.let { (pnx, _) -> battle.sendSidedUpdate(actor, BattleHealthChangePacket(pnx, remainingHealth.toFloat()), BattleHealthChangePacket(pnx, newHealthRatio)) }
battle.minorBattleActions[battlePokemon.uuid] = privateMessage
WaitDispatch(1F)
@@ -1547,7 +1488,7 @@ object ShowdownInterpreter {
/**
* Format:
* |-item|POKEMON|ITEM|&#91from&#93EFFECT
* |-item|POKEMON|ITEM|[from]EFFECT
*
* The ITEM held by the POKEMON has been changed or revealed due to a move or ability EFFECT.
*
@@ -1570,7 +1511,7 @@ object ShowdownInterpreter {
/**
* Format:
* |-enditem|POKEMON|ITEM|&#91from&#93EFFECT
* |-enditem|POKEMON|ITEM|[from]EFFECT
*
* The ITEM held by POKEMON has been destroyed by a move or ability, and it now holds no item.
*
@@ -1604,7 +1545,7 @@ object ShowdownInterpreter {
val rawHpAndStatus = privateMessage.argumentAt(1)?.split(" ") ?: return
val rawHpRatio = rawHpAndStatus.getOrNull(0) ?: return
val newHealth = rawHpRatio.split("/").map { it.toFloatOrNull() ?: return }
val newHealthRatio = rawHpRatio.split("/").map { it.toFloatOrNull()?.div(newHealth[1]) ?: return }
val newHealthRatio = rawHpRatio.split("/").map { it.toFloatOrNull()?.div(100) ?: return }
val effect = privateMessage.effect()
val pokemonName = battlePokemon.getName()
broadcastOptionalAbility(battle, effect, pokemonName)
@@ -64,6 +64,11 @@ open class BattlePokemon(
/** A set of all the BattlePokemon that they faced during the battle (for exp purposes) */
val facedOpponents = mutableSetOf<BattlePokemon>()
/**
* A counter of critical hits during this battle, this is used for an evolution requirement.
*/
var criticalHits: Int = 0
/**
* The [HeldItemManager] backing this [BattlePokemon].
*/
@@ -84,12 +89,7 @@ open class BattlePokemon(
}
fun isSentOut() = actor.battle.activePokemon.any { it.battlePokemon == this }
fun canBeSentOut() =
if (actor.request?.side?.pokemon?.get(0)?.reviving == true) {
!isSentOut() && !willBeSwitchedIn && health <= 0
} else {
!isSentOut() && !willBeSwitchedIn && health > 0
}
fun canBeSentOut() = !isSentOut() && !willBeSwitchedIn && health > 0
fun writeVariables(struct: VariableStruct) {
effectedPokemon.writeVariables(struct)
@@ -166,7 +166,7 @@ class ApricornBlock(settings: Settings, val apricorn: Apricorn) : HorizontalFaci
}
override fun attemptShear(world: World, state: BlockState, pos: BlockPos, successCallback: () -> Unit): Boolean {
if (state.get(AGE) != MAX_AGE) {
if (state.get(AGE) == MAX_AGE) {
return false
}
world.playSound(null, pos, SoundEvents.ENTITY_SHEEP_SHEAR, SoundCategory.BLOCKS, 1F, 1F)
@@ -24,7 +24,6 @@ import net.minecraft.block.BlockRenderType
import net.minecraft.block.BlockState
import net.minecraft.block.BlockWithEntity
import net.minecraft.block.Blocks
import net.minecraft.block.FarmlandBlock
import net.minecraft.block.Fertilizable
import net.minecraft.block.ShapeContext
import net.minecraft.block.entity.BlockEntity
@@ -68,14 +67,6 @@ class BerryBlock(private val berryIdentifier: Identifier, settings: Settings) :
*/
fun berry(): Berry? = Berries.getByIdentifier(this.berryIdentifier)
override fun onBreak(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity) {
if (!player.isCreative && state.get(AGE) == FRUIT_AGE) {
val treeEntity = world.getBlockEntity(pos) as BerryBlockEntity
treeEntity.harvest(world, state, pos, player).forEach { drop -> Block.dropStack(world, pos, drop) }
}
super.onBreak(world, pos, state, player)
}
override fun createBlockEntity(pos: BlockPos, state: BlockState) = BerryBlockEntity(pos, state, berryIdentifier)
override fun isFertilizable(world: WorldView, pos: BlockPos, state: BlockState, isClient: Boolean) = !this.isMaxAge(state)
@@ -187,9 +178,7 @@ class BerryBlock(private val berryIdentifier: Identifier, settings: Settings) :
@Deprecated("Deprecated in Java")
override fun canPlaceAt(state: BlockState, world: WorldView, pos: BlockPos): Boolean {
val below = world.getBlockState(pos.down())
return (state.get(WAS_GENERATED) && below.isIn(CobblemonBlockTags.BERRY_WILD_SOIL))
|| below.isIn(CobblemonBlockTags.BERRY_SOIL)
|| below.block is FarmlandBlock
return (state.get(WAS_GENERATED) && below.isIn(CobblemonBlockTags.BERRY_WILD_SOIL)) || below.isIn(CobblemonBlockTags.BERRY_SOIL)
}
@Deprecated("Deprecated in Java")
@@ -114,10 +114,7 @@ class PastureBlock(properties: Settings): BlockWithEntity(properties), Waterlogg
voxelShape(0.1875, 0.25, 0.25, 0.1875, 0.4375, 0.875, direction),
voxelShape(0.8125, 0.25, 0.25, 0.8125, 0.4375, 0.875, direction),
voxelShape(0.1875, 0.3125, 0.3125, 0.8125, 0.5, 0.3125, direction),
voxelShape(0.25, 0.75, 0.3125, 0.75, 1.0, 0.8125, direction),
// I'm lazy and this gets optimized in union anyway
voxelShape(0.0, 0.0, 0.0, 0.0625, 1.0, 1.0, direction),
voxelShape(0.9375, 0.0, 0.0, 1.0, 1.0, 1.0, direction),
voxelShape(0.25, 0.75, 0.3125, 0.75, 1.0, 0.8125, direction)
)
}
}
@@ -1,21 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.block.entity
import com.cobblemon.mod.common.CobblemonBlockEntities
import net.minecraft.block.BlockState
import net.minecraft.block.entity.BlockEntityType
import net.minecraft.block.entity.HangingSignBlockEntity
import net.minecraft.util.math.BlockPos
class CobblemonHangingSignBlockEntity(pos: BlockPos, state: BlockState) : HangingSignBlockEntity(pos, state) {
override fun getType(): BlockEntityType<*> = CobblemonBlockEntities.HANGING_SIGN
}
@@ -1,21 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.block.entity
import com.cobblemon.mod.common.CobblemonBlockEntities
import net.minecraft.block.BlockState
import net.minecraft.block.entity.BlockEntityType
import net.minecraft.block.entity.SignBlockEntity
import net.minecraft.util.math.BlockPos
class CobblemonSignBlockEntity(pos: BlockPos, state: BlockState) : SignBlockEntity(pos, state) {
override fun getType(): BlockEntityType<*> = CobblemonBlockEntities.SIGN
}
@@ -1,22 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.block.sign
import com.cobblemon.mod.common.block.entity.CobblemonHangingSignBlockEntity
import net.minecraft.block.BlockState
import net.minecraft.block.HangingSignBlock
import net.minecraft.block.WoodType
import net.minecraft.block.entity.BlockEntity
import net.minecraft.util.math.BlockPos
class CobblemonHangingSignBlock(settings: Settings, woodType: WoodType) : HangingSignBlock(settings, woodType) {
override fun createBlockEntity(pos: BlockPos, state: BlockState): BlockEntity = CobblemonHangingSignBlockEntity(pos, state)
}
@@ -1,22 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.block.sign
import com.cobblemon.mod.common.block.entity.CobblemonSignBlockEntity
import net.minecraft.block.BlockState
import net.minecraft.block.SignBlock
import net.minecraft.block.WoodType
import net.minecraft.block.entity.BlockEntity
import net.minecraft.util.math.BlockPos
class CobblemonSignBlock(settings: Settings, woodType: WoodType) : SignBlock(settings, woodType) {
override fun createBlockEntity(pos: BlockPos, state: BlockState): BlockEntity = CobblemonSignBlockEntity(pos, state)
}
@@ -1,22 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.block.sign
import com.cobblemon.mod.common.block.entity.CobblemonHangingSignBlockEntity
import net.minecraft.block.BlockState
import net.minecraft.block.WallHangingSignBlock
import net.minecraft.block.WoodType
import net.minecraft.block.entity.BlockEntity
import net.minecraft.util.math.BlockPos
class CobblemonWallHangingSignBlock(settings: Settings, woodType: WoodType) : WallHangingSignBlock(settings, woodType) {
override fun createBlockEntity(pos: BlockPos, state: BlockState): BlockEntity = CobblemonHangingSignBlockEntity(pos, state)
}
@@ -1,22 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.block.sign
import com.cobblemon.mod.common.block.entity.CobblemonSignBlockEntity
import net.minecraft.block.BlockState
import net.minecraft.block.WallSignBlock
import net.minecraft.block.WoodType
import net.minecraft.block.entity.BlockEntity
import net.minecraft.util.math.BlockPos
class CobblemonWallSignBlock(settings: Settings, woodType: WoodType) : WallSignBlock(settings, woodType) {
override fun createBlockEntity(pos: BlockPos, state: BlockState): BlockEntity = CobblemonSignBlockEntity(pos, state)
}
@@ -9,47 +9,74 @@
package com.cobblemon.mod.common.brewing
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.brewing.ingredient.CobblemonIngredient
import com.cobblemon.mod.common.brewing.ingredient.CobblemonItemIngredient
import com.cobblemon.mod.common.brewing.ingredient.CobblemonPotionIngredient
import net.minecraft.item.Item
import net.minecraft.potion.Potion
import net.minecraft.potion.Potions
import net.minecraft.recipe.BrewingRecipeRegistry
import net.minecraft.recipe.Ingredient
object BrewingRecipes {
// Put things here if you want them to be add-able to the bottom of the brewing stand (like where potions go)
@JvmField
val brewableItems = mutableListOf(
CobblemonItems.MEDICINAL_BREW,
CobblemonItems.POTION,
CobblemonItems.SUPER_POTION,
CobblemonItems.HYPER_POTION,
CobblemonItems.MAX_POTION,
CobblemonItems.FULL_RESTORE,
CobblemonItems.FULL_HEAL,
CobblemonItems.ANTIDOTE,
CobblemonItems.AWAKENING,
CobblemonItems.BURN_HEAL,
CobblemonItems.ICE_HEAL,
CobblemonItems.PARALYZE_HEAL,
CobblemonItems.ETHER,
CobblemonItems.MAX_ETHER,
CobblemonItems.ELIXIR,
CobblemonItems.MAX_ELIXIR
)
val recipes: List<Triple<CobblemonIngredient, CobblemonIngredient, Item>> by lazy {
listOf(
Triple(CobblemonPotionIngredient(Potions.WATER), CobblemonItemIngredient(CobblemonItems.MEDICINAL_LEEK), CobblemonItems.MEDICINAL_BREW),
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.LEPPA_BERRY, CobblemonItems.ETHER),
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.HOPO_BERRY, CobblemonItems.ELIXIR),
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.ORAN_BERRY, CobblemonItems.POTION),
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.SITRUS_BERRY, CobblemonItems.HYPER_POTION),
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.LUM_BERRY, CobblemonItems.FULL_HEAL),
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.PECHA_BERRY, CobblemonItems.ANTIDOTE),
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.CHESTO_BERRY, CobblemonItems.AWAKENING),
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.RAWST_BERRY, CobblemonItems.BURN_HEAL),
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.ASPEAR_BERRY, CobblemonItems.ICE_HEAL),
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.CHERI_BERRY, CobblemonItems.PARALYZE_HEAL),
convert(CobblemonItems.BURN_HEAL, CobblemonItems.LUM_BERRY, CobblemonItems.FULL_HEAL),
convert(CobblemonItems.ANTIDOTE, CobblemonItems.LUM_BERRY, CobblemonItems.FULL_HEAL),
convert(CobblemonItems.AWAKENING, CobblemonItems.LUM_BERRY, CobblemonItems.FULL_HEAL),
convert(CobblemonItems.ICE_HEAL, CobblemonItems.LUM_BERRY, CobblemonItems.FULL_HEAL),
convert(CobblemonItems.PARALYZE_HEAL, CobblemonItems.LUM_BERRY, CobblemonItems.FULL_HEAL),
convert(CobblemonItems.ETHER, CobblemonItems.PEP_UP_FLOWER, CobblemonItems.MAX_ETHER),
convert(CobblemonItems.ELIXIR, CobblemonItems.PEP_UP_FLOWER, CobblemonItems.MAX_ELIXIR),
convert(CobblemonItems.POTION, CobblemonItems.ENERGY_ROOT, CobblemonItems.SUPER_POTION),
convert(CobblemonItems.SUPER_POTION, CobblemonItems.FIGY_BERRY, CobblemonItems.HYPER_POTION),
convert(CobblemonItems.SUPER_POTION, CobblemonItems.WIKI_BERRY, CobblemonItems.HYPER_POTION),
convert(CobblemonItems.SUPER_POTION, CobblemonItems.MAGO_BERRY, CobblemonItems.HYPER_POTION),
convert(CobblemonItems.SUPER_POTION, CobblemonItems.AGUAV_BERRY, CobblemonItems.HYPER_POTION),
convert(CobblemonItems.SUPER_POTION, CobblemonItems.IAPAPA_BERRY, CobblemonItems.HYPER_POTION),
convert(CobblemonItems.HYPER_POTION, CobblemonItems.VIVICHOKE, CobblemonItems.MAX_POTION),
convert(CobblemonItems.MAX_POTION, CobblemonItems.LUM_BERRY, CobblemonItems.FULL_RESTORE)
fun registerPotionTypes() {
brewableItems.forEach { item ->
BrewingRecipeRegistry.POTION_TYPES.add(Ingredient.ofItems(item))
}
}
fun getPotionRecipes(): List<Triple<Potion, Ingredient, Potion>> {
return listOf(
Triple(Potions.WATER, Ingredient.ofItems(CobblemonItems.MEDICINAL_LEEK), Potions.WATER), // This one is Mixin'd to result in brew rather than water
)
}
private fun convert(input: Item, ingredient: Item, output: Item): Triple<CobblemonIngredient, CobblemonIngredient, Item> {
return Triple(CobblemonItemIngredient(input), CobblemonItemIngredient(ingredient), output)
}
fun getItemRecipes(): List<Triple<Item, Ingredient, Item>> {
// This is where the majority of our recipes go. First arg is thing down the bottom, second is thing up the top, third is results.
return listOf(
Triple(CobblemonItems.MEDICINAL_BREW, Ingredient.ofItems(CobblemonItems.LEPPA_BERRY), CobblemonItems.ETHER),
Triple(CobblemonItems.MEDICINAL_BREW, Ingredient.ofItems(CobblemonItems.HOPO_BERRY), CobblemonItems.ELIXIR),
Triple(CobblemonItems.MEDICINAL_BREW, Ingredient.ofItems(CobblemonItems.ORAN_BERRY), CobblemonItems.POTION),
Triple(CobblemonItems.MEDICINAL_BREW, Ingredient.ofItems(CobblemonItems.SITRUS_BERRY), CobblemonItems.HYPER_POTION),
Triple(CobblemonItems.MEDICINAL_BREW, Ingredient.ofItems(CobblemonItems.LUM_BERRY), CobblemonItems.FULL_HEAL),
Triple(CobblemonItems.MEDICINAL_BREW, Ingredient.ofItems(CobblemonItems.PECHA_BERRY), CobblemonItems.ANTIDOTE),
Triple(CobblemonItems.MEDICINAL_BREW, Ingredient.ofItems(CobblemonItems.CHESTO_BERRY), CobblemonItems.AWAKENING),
Triple(CobblemonItems.MEDICINAL_BREW, Ingredient.ofItems(CobblemonItems.RAWST_BERRY), CobblemonItems.BURN_HEAL),
Triple(CobblemonItems.MEDICINAL_BREW, Ingredient.ofItems(CobblemonItems.ASPEAR_BERRY), CobblemonItems.ICE_HEAL),
Triple(CobblemonItems.MEDICINAL_BREW, Ingredient.ofItems(CobblemonItems.CHERI_BERRY), CobblemonItems.PARALYZE_HEAL),
Triple(CobblemonItems.BURN_HEAL, Ingredient.ofItems(CobblemonItems.LUM_BERRY), CobblemonItems.FULL_HEAL),
Triple(CobblemonItems.ANTIDOTE, Ingredient.ofItems(CobblemonItems.LUM_BERRY), CobblemonItems.FULL_HEAL),
Triple(CobblemonItems.AWAKENING, Ingredient.ofItems(CobblemonItems.LUM_BERRY), CobblemonItems.FULL_HEAL),
Triple(CobblemonItems.ICE_HEAL, Ingredient.ofItems(CobblemonItems.LUM_BERRY), CobblemonItems.FULL_HEAL),
Triple(CobblemonItems.PARALYZE_HEAL, Ingredient.ofItems(CobblemonItems.LUM_BERRY), CobblemonItems.FULL_HEAL),
Triple(CobblemonItems.ETHER, Ingredient.ofItems(CobblemonItems.PEP_UP_FLOWER), CobblemonItems.MAX_ETHER),
Triple(CobblemonItems.ELIXIR, Ingredient.ofItems(CobblemonItems.PEP_UP_FLOWER), CobblemonItems.MAX_ELIXIR),
Triple(CobblemonItems.POTION, Ingredient.ofItems(CobblemonItems.ENERGY_ROOT), CobblemonItems.SUPER_POTION),
Triple(CobblemonItems.SUPER_POTION, Ingredient.ofItems(CobblemonItems.FIGY_BERRY), CobblemonItems.HYPER_POTION),
Triple(CobblemonItems.SUPER_POTION, Ingredient.ofItems(CobblemonItems.WIKI_BERRY), CobblemonItems.HYPER_POTION),
Triple(CobblemonItems.SUPER_POTION, Ingredient.ofItems(CobblemonItems.MAGO_BERRY), CobblemonItems.HYPER_POTION),
Triple(CobblemonItems.SUPER_POTION, Ingredient.ofItems(CobblemonItems.AGUAV_BERRY), CobblemonItems.HYPER_POTION),
Triple(CobblemonItems.SUPER_POTION, Ingredient.ofItems(CobblemonItems.IAPAPA_BERRY), CobblemonItems.HYPER_POTION),
Triple(CobblemonItems.HYPER_POTION, Ingredient.ofItems(CobblemonItems.VIVICHOKE), CobblemonItems.MAX_POTION),
Triple(CobblemonItems.MAX_POTION, Ingredient.ofItems(CobblemonItems.LUM_BERRY), CobblemonItems.FULL_RESTORE)
)
}
}
@@ -1,36 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.brewing.ingredient
import net.minecraft.item.ItemStack
import org.jetbrains.annotations.ApiStatus
/**
* The Cobblemon representation of a brewing ingredient.
* This is done to abstract platform specific requirements for a more custom solution to brewing.
*/
@ApiStatus.Internal
sealed interface CobblemonIngredient {
/**
* Tests if a given [stack] is valid for this ingredient.
*
* @param stack The [ItemStack] being tested.
* @return If the given [stack] is valid for this ingredient.
*/
fun matches(stack: ItemStack): Boolean
/**
* Resolves list of [ItemStack]s that is used by the vanilla Ingredient implementation when a platform requires wrapping.
*
* @return A list of [ItemStack]s
*/
fun matchingStacks(): List<ItemStack>
}
@@ -1,22 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.brewing.ingredient
import net.minecraft.item.Item
import net.minecraft.item.ItemStack
import org.jetbrains.annotations.ApiStatus
@ApiStatus.Internal
class CobblemonItemIngredient(val item: Item) : CobblemonIngredient {
override fun matches(stack: ItemStack): Boolean = stack.isOf(this.item)
override fun matchingStacks(): List<ItemStack> = listOf(this.item.defaultStack)
}
@@ -1,33 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.brewing.ingredient
import net.minecraft.item.ItemStack
import net.minecraft.item.Items
import net.minecraft.potion.Potion
import net.minecraft.potion.PotionUtil
import org.jetbrains.annotations.ApiStatus
@ApiStatus.Internal
class CobblemonPotionIngredient(val potion: Potion) : CobblemonIngredient {
override fun matches(stack: ItemStack): Boolean {
val potion = PotionUtil.getPotion(stack)
return potion == this.potion
}
override fun matchingStacks(): List<ItemStack> {
val list = arrayListOf<ItemStack>()
list += PotionUtil.setPotion(Items.POTION.defaultStack, this.potion)
list += PotionUtil.setPotion(Items.SPLASH_POTION.defaultStack, this.potion)
list += PotionUtil.setPotion(Items.LINGERING_POTION.defaultStack, this.potion)
return list
}
}
@@ -17,13 +17,12 @@ import com.cobblemon.mod.common.client.gui.PartyOverlay
import com.cobblemon.mod.common.client.gui.battle.BattleOverlay
import com.cobblemon.mod.common.client.particle.BedrockParticleEffectRepository
import com.cobblemon.mod.common.client.render.block.BerryBlockRenderer
import com.cobblemon.mod.common.client.render.block.BerryEntityInstance
import com.cobblemon.mod.common.client.render.block.HealingMachineRenderer
import com.cobblemon.mod.common.client.render.boat.CobblemonBoatRenderer
import com.cobblemon.mod.common.client.render.item.CobblemonBuiltinItemRendererRegistry
import com.cobblemon.mod.common.client.render.item.PokemonItemRenderer
import com.cobblemon.mod.common.client.render.layer.PokemonOnShoulderRenderer
import com.cobblemon.mod.common.client.render.models.blockbench.bedrock.animation.BedrockAnimationRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.BerryModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokeBallModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
import com.cobblemon.mod.common.client.render.pokeball.PokeBallRenderer
@@ -32,19 +31,19 @@ import com.cobblemon.mod.common.client.starter.ClientPlayerData
import com.cobblemon.mod.common.client.storage.ClientStorageManager
import com.cobblemon.mod.common.client.trade.ClientTrade
import com.cobblemon.mod.common.data.CobblemonDataProvider
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
import com.cobblemon.mod.common.item.PokeBallItem
import com.cobblemon.mod.common.client.render.models.blockbench.repository.BerryModelRepository
import com.cobblemon.mod.common.platform.events.PlatformEvents
import com.cobblemon.mod.common.util.DataKeys
import com.cobblemon.mod.common.util.asTranslated
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry
import net.minecraft.client.color.block.BlockColorProvider
import net.minecraft.client.color.item.ItemColorProvider
import net.minecraft.client.gui.DrawContext
import net.minecraft.client.render.RenderLayer
import net.minecraft.client.render.block.entity.HangingSignBlockEntityRenderer
import net.minecraft.client.render.block.entity.SignBlockEntityRenderer
import net.minecraft.client.render.entity.EntityRenderer
import net.minecraft.client.render.entity.EntityRendererFactory
import net.minecraft.client.render.entity.LivingEntityRenderer
import net.minecraft.client.render.entity.model.BoatEntityModel
import net.minecraft.client.render.entity.model.ChestBoatEntityModel
import net.minecraft.client.render.entity.model.PlayerEntityModel
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
@@ -88,11 +87,12 @@ object CobblemonClient {
PlatformEvents.CLIENT_PLAYER_LOGIN.subscribe { onLogin() }
PlatformEvents.CLIENT_PLAYER_LOGOUT.subscribe { onLogout() }
this.registerBlockEntityRenderers()
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.HEALING_MACHINE, ::HealingMachineRenderer)
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.BERRY, ::BerryBlockRenderer)
registerBlockRenderTypes()
//registerColors()
registerFlywheelRenderers()
this.registerEntityRenderers()
LOGGER.info("Registering custom BuiltinItemRenderers")
CobblemonBuiltinItemRendererRegistry.register(CobblemonItems.POKEMON_MODEL, PokemonItemRenderer())
@@ -121,11 +121,11 @@ object CobblemonClient {
}
fun registerFlywheelRenderers() {
// InstancedRenderRegistry
// .configure(CobblemonBlockEntities.BERRY)
// .alwaysSkipRender()
// .factory(::BerryEntityInstance)
// .apply()
InstancedRenderRegistry
.configure(CobblemonBlockEntities.BERRY)
.alwaysSkipRender()
.factory(::BerryEntityInstance)
.apply()
}
/*
@@ -147,10 +147,6 @@ object CobblemonClient {
RenderLayer.getCutout(),
CobblemonBlocks.APRICORN_DOOR,
CobblemonBlocks.APRICORN_TRAPDOOR,
CobblemonBlocks.APRICORN_SIGN,
CobblemonBlocks.APRICORN_WALL_SIGN,
CobblemonBlocks.APRICORN_HANGING_SIGN,
CobblemonBlocks.APRICORN_WALL_HANGING_SIGN,
CobblemonBlocks.BLACK_APRICORN_SAPLING,
CobblemonBlocks.BLUE_APRICORN_SAPLING,
CobblemonBlocks.GREEN_APRICORN_SAPLING,
@@ -184,8 +180,6 @@ object CobblemonClient {
CobblemonBlocks.REVIVAL_HERB,
*CobblemonBlocks.berries().values.toTypedArray()
)
this.createBoatModelLayers()
}
fun beforeChatRender(context: DrawContext, partialDeltaTicks: Float) {
@@ -204,22 +198,14 @@ object CobblemonClient {
renderer?.addFeature(PokemonOnShoulderRenderer(renderer))
}
private fun registerBlockEntityRenderers() {
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.HEALING_MACHINE, ::HealingMachineRenderer)
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.BERRY, ::BerryBlockRenderer)
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.SIGN, ::SignBlockEntityRenderer)
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.HANGING_SIGN, ::HangingSignBlockEntityRenderer)
fun registerPokemonRenderer(context: EntityRendererFactory.Context): PokemonRenderer {
LOGGER.info("Registering Pokémon renderer")
return PokemonRenderer(context)
}
private fun registerEntityRenderers() {
LOGGER.info("Registering Pokémon renderer")
this.implementation.registerEntityRenderer(CobblemonEntities.POKEMON, ::PokemonRenderer)
fun registerPokeBallRenderer(context: EntityRendererFactory.Context): PokeBallRenderer {
LOGGER.info("Registering PokéBall renderer")
this.implementation.registerEntityRenderer(CobblemonEntities.EMPTY_POKEBALL, ::PokeBallRenderer)
LOGGER.info("Registering Boat renderer")
this.implementation.registerEntityRenderer(CobblemonEntities.BOAT) { ctx -> CobblemonBoatRenderer(ctx, false) }
LOGGER.info("Registering Boat with Chest renderer")
this.implementation.registerEntityRenderer(CobblemonEntities.CHEST_BOAT) { ctx -> CobblemonBoatRenderer(ctx, true) }
return PokeBallRenderer(context)
}
fun reloadCodedAssets(resourceManager: ResourceManager) {
@@ -233,6 +219,7 @@ object CobblemonClient {
PokeBallModelRepository.reload(resourceManager)
BerryModelRepository.reload(resourceManager)
LOGGER.info("Loaded assets")
// PokeBallModelRepository.reload(resourceManager)
}
fun endBattle() {
@@ -247,11 +234,4 @@ object CobblemonClient {
return "${stack.translationKey}.tooltip"
}
private fun createBoatModelLayers() {
CobblemonBoatType.values().forEach { type ->
this.implementation.registerLayer(CobblemonBoatRenderer.createBoatModelLayer(type, false), BoatEntityModel::getTexturedModelData)
this.implementation.registerLayer(CobblemonBoatRenderer.createBoatModelLayer(type, true), ChestBoatEntityModel::getTexturedModelData)
}
}
}
@@ -13,14 +13,12 @@ import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.battle.ClientBattleActor
import com.cobblemon.mod.common.client.battle.SingleActionRequest
import com.cobblemon.mod.common.client.gui.battle.subscreen.BattleActionSelection
import com.cobblemon.mod.common.client.gui.battle.subscreen.BattleBackButton
import com.cobblemon.mod.common.client.gui.battle.subscreen.BattleGeneralActionSelection
import com.cobblemon.mod.common.client.gui.battle.subscreen.BattleSwitchPokemonSelection
import com.cobblemon.mod.common.client.gui.battle.widgets.BattleMessagePane
import com.cobblemon.mod.common.client.keybind.boundKey
import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
import com.cobblemon.mod.common.util.battleLang
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.client.MinecraftClient
@@ -43,7 +41,6 @@ class BattleGUI : Screen(battleLang("gui.title")) {
private lateinit var messagePane: BattleMessagePane
var opacity = 0F
val actor = CobblemonClient.battle?.side1?.actors?.find { it.uuid == MinecraftClient.getInstance().player?.uuid }
val specBackButton = BattleBackButton(12f, MinecraftClient.getInstance().window.scaledHeight - 32f)
var queuedActions = mutableListOf<() -> Unit>()
@@ -109,10 +106,6 @@ class BattleGUI : Screen(battleLang("gui.title")) {
}
}
if (battle.spectating) {
specBackButton.render(context.matrices, mouseX, mouseY, delta)
}
val currentSelection = getCurrentActionSelection()
if (currentSelection == null || currentSelection is BattleGeneralActionSelection ) {
drawScaledText(
@@ -160,13 +153,4 @@ class BattleGUI : Screen(battleLang("gui.title")) {
}
return super.charTyped(chr, modifiers)
}
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
val battle = CobblemonClient.battle
if (battle?.spectating == true && specBackButton.isHovered(mouseX, mouseY)) {
RemoveSpectatorPacket(battle.battleId).sendToServer()
CobblemonClient.endBattle()
}
return super.mouseClicked(mouseX, mouseY, button)
}
}
@@ -9,7 +9,8 @@
package com.cobblemon.mod.common.client.gui.battle.subscreen
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.battles.*
import com.cobblemon.mod.common.battles.ShowdownPokemon
import com.cobblemon.mod.common.battles.SwitchActionResponse
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.battle.SingleActionRequest
import com.cobblemon.mod.common.client.gui.battle.BattleGUI
@@ -23,7 +24,6 @@ import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder
import net.minecraft.client.sound.PositionedSoundInstance
import net.minecraft.client.sound.SoundManager
import net.minecraft.client.util.math.MatrixStack
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.math.MathHelper.ceil
class BattleSwitchPokemonSelection(
battleGUI: BattleGUI,
@@ -83,6 +83,7 @@ class BattleSwitchPokemonSelection(
partialTicks = deltaTicks
)
} catch (exception: Exception) {
println(showdownPokemon.condition)
throw exception
}
}
@@ -97,15 +98,9 @@ class BattleSwitchPokemonSelection(
.find { it.uuid == showdownPokemon.uuid }
?.let { showdownPokemon to it }
}
.filter {
if (request.side.pokemon[0].reviving) {
"fnt" in it.first.condition
} else {
"fnt" !in it.first.condition
}
}
.filter { it.second.uuid !in battleGUI.actor!!.activePokemon.map { it.battlePokemon?.uuid } }
.filter { it.second.uuid !in switchingInPokemon }
.filter { "fnt" !in it.first.condition || it.first.reviving }
showdownPokemonToPokemon.forEachIndexed { index, (showdownPokemon, pokemon) ->
val row = index / 2
@@ -10,9 +10,7 @@ package com.cobblemon.mod.common.client.gui.interact.wheel
import com.cobblemon.mod.common.CobblemonNetwork
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
import com.cobblemon.mod.common.net.messages.server.pokemon.interact.InteractPokemonPacket
import com.cobblemon.mod.common.net.messages.server.trade.AcceptTradeRequestPacket
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
@@ -50,14 +48,14 @@ fun createPokemonInteractGui(pokemonID: UUID, canMountShoulder: Boolean): Intera
return InteractWheelGUI(options, Text.translatable("cobblemon.ui.interact.pokemon"))
}
fun createPlayerInteractGui(optionsPacket: PlayerInteractOptionsPacket): InteractWheelGUI {
fun createPlayerInteractGui(targetPlayer: PlayerEntity, pokemon: Pokemon): InteractWheelGUI {
val trade = InteractWheelOption(
iconResource = cobblemonResource("textures/gui/interact/icon_trade.png"),
colour = { if (CobblemonClient.requests.tradeOffers.any { it.traderId == optionsPacket.targetId }) Vector3f(0F, 0.6F, 0F) else null },
colour = { if (CobblemonClient.requests.tradeOffers.any { it.traderId == targetPlayer.uuid }) Vector3f(0F, 0.6F, 0F) else null },
onPress = {
val tradeOffer = CobblemonClient.requests.tradeOffers.find { it.traderId == optionsPacket.targetId }
val tradeOffer = CobblemonClient.requests.tradeOffers.find { it.traderId == targetPlayer.uuid }
if (tradeOffer == null) {
CobblemonNetwork.sendToServer(OfferTradePacket(optionsPacket.targetId))
CobblemonNetwork.sendToServer(OfferTradePacket(targetPlayer.uuid))
} else {
CobblemonClient.requests.tradeOffers -= tradeOffer
CobblemonNetwork.sendToServer(AcceptTradeRequestPacket(tradeOffer.tradeOfferId))
@@ -67,35 +65,18 @@ fun createPlayerInteractGui(optionsPacket: PlayerInteractOptionsPacket): Interac
)
val battle = InteractWheelOption(
iconResource = cobblemonResource("textures/gui/interact/icon_battle.png"),
colour = { if (CobblemonClient.requests.battleChallenges.any { it.challengerId == optionsPacket.targetId }) Vector3f(0F, 0.6F, 0F) else null },
colour = { if (CobblemonClient.requests.battleChallenges.any { it.challengerId == targetPlayer.uuid }) Vector3f(0F, 0.6F, 0F) else null },
onPress = {
val battleRequest = CobblemonClient.requests.battleChallenges.find { it.challengerId == optionsPacket.targetId }
val battleRequest = CobblemonClient.requests.battleChallenges.find { it.challengerId == targetPlayer.uuid }
// This can be improved in future with more detailed battle challenge data.
BattleChallengePacket(optionsPacket.numericTargetId, optionsPacket.selectedPokemonId).sendToServer()
BattleChallengePacket(targetPlayer.id, pokemon.uuid).sendToServer()
closeGUI()
}
)
val spectate = InteractWheelOption(
iconResource = cobblemonResource("textures/gui/interact/icon_spectate_battle.png"),
colour = { if (CobblemonClient.requests.battleChallenges.any { it.challengerId == optionsPacket.targetId }) Vector3f(0F, 0.6F, 0F) else null },
onPress = {
SpectateBattlePacket(optionsPacket.targetId).sendToServer()
closeGUI()
}
val options = mutableMapOf(
Orientation.TOP_LEFT to trade,
Orientation.TOP_RIGHT to battle
)
val options = mutableMapOf<Orientation, InteractWheelOption>()
//The way things are positioned should probably be more thought out if more options are added
optionsPacket.options.map {
if (it.equals(PlayerInteractOptionsPacket.Options.TRADE)) {
options[Orientation.TOP_LEFT] = trade
}
if (it.equals(PlayerInteractOptionsPacket.Options.BATTLE)) {
options[Orientation.TOP_RIGHT] = battle
}
if (it.equals(PlayerInteractOptionsPacket.Options.SPECTATE_BATTLE)) {
options[Orientation.TOP_RIGHT] = spectate
}
}
return InteractWheelGUI(options, Text.translatable("cobblemon.ui.interact.player"))
}
@@ -17,7 +17,6 @@ import com.cobblemon.mod.common.client.gui.ExitButton
import com.cobblemon.mod.common.client.gui.TypeIcon
import com.cobblemon.mod.common.client.gui.summary.Summary
import com.cobblemon.mod.common.client.gui.summary.widgets.ModelWidget
import com.cobblemon.mod.common.client.gui.summary.widgets.common.reformatNatureTextIfMinted
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.client.storage.ClientPC
import com.cobblemon.mod.common.client.storage.ClientParty
@@ -32,6 +31,7 @@ import net.minecraft.client.gui.DrawContext
import net.minecraft.client.gui.screen.Screen
import net.minecraft.client.sound.PositionedSoundInstance
import net.minecraft.client.util.InputUtil
import net.minecraft.client.util.math.MatrixStack
import net.minecraft.sound.SoundEvent
import net.minecraft.text.Text
@@ -309,18 +309,14 @@ class PCGUI(
).render(context)
// Nature
val natureText = reformatNatureTextIfMinted(pokemon)
drawScaledText(
context = context,
text = natureText,
text = pokemon.nature.displayName.asTranslated(),
x = x + 39,
y = y + 137,
centered = true,
shadow = true,
scale = SCALE,
colour = 0x32CBFF,
pMouseX = mouseX,
pMouseY = mouseY
scale = SCALE
)
// Ability
@@ -406,14 +402,8 @@ class PCGUI(
if (pokemon != null && !pokemon.heldItemNoCopy().isEmpty) {
val itemX = x + 3
val itemY = y + 98
val itemHovered =
mouseX.toFloat() in (itemX.toFloat()..(itemX.toFloat() + 16)) && mouseY.toFloat() in (itemY.toFloat()..(itemY.toFloat() + 16))
if (itemHovered) context.drawItemTooltip(
MinecraftClient.getInstance().textRenderer,
pokemon.heldItemNoCopy(),
mouseX,
mouseY
)
val itemHovered = mouseX.toFloat() in (itemX.toFloat()..(itemX.toFloat() + 16)) && mouseY.toFloat() in (itemY.toFloat()..(itemY.toFloat() + 16))
if (itemHovered) context.drawItemTooltip(MinecraftClient.getInstance().textRenderer, pokemon.heldItemNoCopy(), mouseX, mouseY)
}
}
@@ -426,22 +416,12 @@ class PCGUI(
}
override fun mouseScrolled(mouseX: Double, mouseY: Double, amount: Double): Boolean {
if (storageWidget.pastureWidget != null) storageWidget.pastureWidget!!.pastureScrollList.mouseScrolled(
mouseX,
mouseY,
amount
)
if (storageWidget.pastureWidget != null) storageWidget.pastureWidget!!.pastureScrollList.mouseScrolled(mouseX, mouseY, amount)
return children().any { it.mouseScrolled(mouseX, mouseY, amount) }
}
override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean {
if (storageWidget.pastureWidget != null) storageWidget.pastureWidget!!.pastureScrollList.mouseDragged(
mouseX,
mouseY,
button,
deltaX,
deltaY
)
if (storageWidget.pastureWidget != null) storageWidget.pastureWidget!!.pastureScrollList.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
}
@@ -451,12 +431,10 @@ class PCGUI(
playSound(CobblemonSounds.PC_OFF)
UnlinkPlayerFromPCPacket().sendToServer()
}
InputUtil.GLFW_KEY_RIGHT -> {
playSound(CobblemonSounds.PC_CLICK)
this.storageWidget.box += 1
}
InputUtil.GLFW_KEY_LEFT -> {
playSound(CobblemonSounds.PC_CLICK)
this.storageWidget.box -= 1
@@ -476,7 +454,7 @@ class PCGUI(
ticksElapsed++
// Calculate select pointer offset
val delayFactor = 3
var delayFactor = 3
if (ticksElapsed % (2 * delayFactor) == 0) selectPointerOffsetIncrement = !selectPointerOffsetIncrement
if (ticksElapsed % delayFactor == 0) selectPointerOffsetY += if (selectPointerOffsetIncrement) 1 else -1
}
@@ -502,8 +480,8 @@ class PCGUI(
offsetY = -10.0
)
} else {
previewPokemon = null
modelWidget = null
previewPokemon = null;
modelWidget = null;
}
}
}
@@ -1,30 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.gui.summary.widgets.common
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.api.text.italicise
import com.cobblemon.mod.common.api.text.onHover
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.asTranslated
import net.minecraft.text.MutableText
/**
* Italicizes the nature text and makes it include the name of the MintItem used to mint the Pokémon's nature
*/
fun reformatNatureTextIfMinted(pokemon: Pokemon): MutableText {
var natureText = pokemon.nature.displayName.asTranslated()
if (pokemon.mintedNature != null) {
CobblemonItems.mints[pokemon.mintedNature!!.displayName]?.let { mint ->
natureText = natureText.italicise().onHover(mint.name)
}
}
return natureText
}
@@ -1,44 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.gui.summary.widgets.screens.info
import com.cobblemon.mod.common.api.text.*
import com.cobblemon.mod.common.client.gui.summary.widgets.SoundlessWidget
import com.cobblemon.mod.common.client.render.drawScaledText
import net.minecraft.client.gui.DrawContext
import net.minecraft.text.MutableText
import net.minecraft.text.Text
import net.minecraft.util.Identifier
class InfoBlockWidget(
pX: Int,
pY: Int,
blockWidth: Int,
blockHeight: Int,
private val text: MutableText,
private val withinRowVerticalTextOffset: Int,
private val font: Identifier,
) : SoundlessWidget(pX, pY, blockWidth, blockHeight, Text.literal("InfoBlockWidget")) {
override fun renderButton(context: DrawContext, pMouseX: Int, pMouseY: Int, pPartialTicks: Float) {
drawScaledText(
context = context,
font = font,
text = text.bold(),
x = x,
y = y + withinRowVerticalTextOffset,
shadow = true,
pMouseX = pMouseX,
pMouseY = pMouseY
)
}
}
@@ -1,62 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.gui.summary.widgets.screens.info
import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.gui.summary.widgets.SoundlessWidget
import net.minecraft.client.MinecraftClient
import net.minecraft.client.gui.DrawContext
import net.minecraft.text.MutableText
import net.minecraft.text.Text
class InfoOneLineWidget(
pX: Int,
pY: Int,
width: Int,
height: Int = ROW_HEIGHT,
private val label: MutableText,
private val value: MutableText,
) : SoundlessWidget(pX, pY, width, height, Text.literal("InfoOneLineWidget")) {
companion object {
private val FONT = CobblemonResources.DEFAULT_LARGE
private const val ROW_HEIGHT = 15
private const val WITHIN_ROW_VERTICAL_OFFSET = 6
private const val LABEL_HORIZONTAL_OFFSET = 8
private const val VALUE_HORIZONTAL_OFFSET = 53
}
override fun renderButton(context: DrawContext, pMouseX: Int, pMouseY: Int, pPartialTicks: Float) {
// Label
val label = InfoBlockWidget(
pX = x + LABEL_HORIZONTAL_OFFSET,
pY = y,
blockWidth = MinecraftClient.getInstance().textRenderer.getWidth(label),
blockHeight = height,
text = label,
font = FONT,
withinRowVerticalTextOffset = WITHIN_ROW_VERTICAL_OFFSET
)
label.render(context, pMouseX, pMouseY, pPartialTicks)
// Value
val value = InfoBlockWidget(
pX = x + VALUE_HORIZONTAL_OFFSET,
pY = y,
blockWidth = MinecraftClient.getInstance().textRenderer.getWidth(value),
blockHeight = height,
text = value,
font = FONT,
withinRowVerticalTextOffset = WITHIN_ROW_VERTICAL_OFFSET
)
value.render(context, pMouseX, pMouseY, pPartialTicks)
}
}
@@ -11,10 +11,11 @@ package com.cobblemon.mod.common.client.gui.summary.widgets.screens.info
import com.cobblemon.mod.common.api.gui.ColourLibrary
import com.cobblemon.mod.common.api.gui.MultiLineLabelK
import com.cobblemon.mod.common.api.gui.blitk
import com.cobblemon.mod.common.api.text.*
import com.cobblemon.mod.common.api.text.bold
import com.cobblemon.mod.common.api.text.plus
import com.cobblemon.mod.common.api.text.text
import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.gui.summary.widgets.SoundlessWidget
import com.cobblemon.mod.common.client.gui.summary.widgets.common.reformatNatureTextIfMinted
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.asTranslated
@@ -22,21 +23,17 @@ import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.lang
import net.minecraft.client.MinecraftClient
import net.minecraft.client.gui.DrawContext
import net.minecraft.text.MutableText
import net.minecraft.text.Text
import net.minecraft.text.TextContent
class InfoWidget(
pX: Int,
pY: Int,
private val pokemon: Pokemon
) : SoundlessWidget(pX, pY, WIDTH, HEIGHT, Text.literal("InfoWidget")) {
): SoundlessWidget(pX, pY, WIDTH, HEIGHT, Text.literal("InfoWidget")) {
companion object {
private const val WIDTH = 134
private const val HEIGHT = 148
private val infoBaseResource = cobblemonResource("textures/gui/summary/summary_info_base.png")
private const val ROW_HEIGHT = 15
}
override fun renderButton(context: DrawContext, pMouseX: Int, pMouseY: Int, pPartialTicks: Float) {
@@ -45,89 +42,137 @@ class InfoWidget(
blitk(
matrixStack = matrices,
texture = infoBaseResource,
x = x,
x= x,
y = y,
width = width,
height = height
)
// Pokédex Number
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = lang("ui.info.pokedex_number").bold(),
x = x + 8,
y = y + 6,
shadow = true
)
// Add preceding zeroes if Pokédex number is less than 3 digits
var dexNo = pokemon.species.nationalPokedexNumber.toString()
while (dexNo.length < 3) {
dexNo = "0$dexNo"
while(dexNo.length < 3) {
dexNo = "0$dexNo";
}
val pokedexNumberWidget = InfoOneLineWidget(
pX = x,
pY = y,
width = width,
label = lang("ui.info.pokedex_number"),
value = dexNo.text()
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = dexNo.text().bold(),
x = x + 53,
y = y + 6,
shadow = true
)
pokedexNumberWidget.render(context, pMouseX, pMouseY, pPartialTicks)
// Species
val speciesWidget = InfoOneLineWidget(
pX = x,
pY = y + ROW_HEIGHT,
width = width,
label = lang("ui.info.species"),
value = pokemon.species.translatedName
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = lang("ui.info.species").bold(),
x = x + 8,
y = y + 21,
shadow = true
)
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = pokemon.species.translatedName.bold(),
x = x + 53,
y = y + 21,
shadow = true
)
speciesWidget.render(context, pMouseX, pMouseY, pPartialTicks)
// Type
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = lang("ui.info.type").bold(),
x = x + 8,
y = y + 36,
shadow = true
)
val type = pokemon.types.map { it.displayName.copy() }.reduce { acc, next -> acc.plus("/").plus(next) }
val typeWidget = InfoOneLineWidget(
pX = x,
pY = y + 2 * ROW_HEIGHT,
width = width,
label = lang("ui.info.type"),
value = type
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = type.bold(),
x = x + 53,
y = y + 36,
shadow = true
)
typeWidget.render(context, pMouseX, pMouseY, pPartialTicks)
// OT
var displayName: MutableText = MutableText.of(TextContent.EMPTY)
if (pokemon.isPlayerOwned() && pokemon.getOwnerPlayer() != null) {
displayName = pokemon.getOwnerPlayer()!!.displayName.copy()
}
val otWidget = InfoOneLineWidget(
pX = x,
pY = y + 3 * ROW_HEIGHT,
width = width,
label = lang("ui.info.original_trainer"),
value = displayName // You'll need to provide the value for the Original Trainer
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = lang("ui.info.original_trainer").bold(),
x = x + 8,
y = y + 51,
shadow = true
)
otWidget.render(context, pMouseX, pMouseY, pPartialTicks)
if (pokemon.isPlayerOwned() && pokemon.getOwnerPlayer() != null) {
pokemon.getOwnerPlayer()?.displayName?.copy()?.let {
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = it.bold(),
x = x + 53,
y = y + 51,
shadow = true
)
}
}
// Nature
// Get the name of the MintItem used to mint the Pokémon's nature
val natureText = reformatNatureTextIfMinted(pokemon)
val natureWidget = InfoOneLineWidget(
pX = x,
pY = y + 4 * ROW_HEIGHT,
width = width,
label = lang("ui.info.nature"),
value = natureText,
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = lang("ui.info.nature").bold(),
x = x + 8,
y = y + 66,
shadow = true
)
natureWidget.render(context, pMouseX, pMouseY, pPartialTicks)
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = pokemon.nature.displayName.asTranslated().bold(),
x = x + 53,
y = y + 66,
shadow = true
)
// Ability
val abilityWidget = InfoOneLineWidget(
pX = x,
pY = y + 5 * ROW_HEIGHT,
width = width,
label = lang("ui.info.ability").bold(),
value = pokemon.ability.displayName.asTranslated().bold()
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = lang("ui.info.ability").bold(),
x = x + 8,
y = y + 81,
shadow = true
)
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = pokemon.ability.displayName.asTranslated().bold(),
x = x + 53,
y = y + 81,
shadow = true
)
abilityWidget.render(context, pMouseX, pMouseY, pPartialTicks)
val smallTextScale = 0.5F
@@ -167,10 +212,8 @@ class InfoWidget(
val mcFont = MinecraftClient.getInstance().textRenderer
val experience = pokemon.experience.toString().text()
val experienceForThisLevel =
pokemon.experience - if (pokemon.level == 1) 0 else pokemon.experienceGroup.getExperience(pokemon.level)
val experienceToNext =
pokemon.experienceGroup.getExperience(pokemon.level + 1) - pokemon.experienceGroup.getExperience(pokemon.level)
val experienceForThisLevel = pokemon.experience - if (pokemon.level == 1) 0 else pokemon.experienceGroup.getExperience(pokemon.level)
val experienceToNext = pokemon.experienceGroup.getExperience(pokemon.level + 1) - pokemon.experienceGroup.getExperience(pokemon.level)
drawScaledText(
context = context,
@@ -19,7 +19,6 @@ import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.gui.ExitButton
import com.cobblemon.mod.common.client.gui.TypeIcon
import com.cobblemon.mod.common.client.gui.summary.Summary
import com.cobblemon.mod.common.client.gui.summary.widgets.common.reformatNatureTextIfMinted
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.client.trade.ClientTrade
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket.TradeablePokemon
@@ -37,6 +36,7 @@ import net.minecraft.client.gui.DrawContext
import net.minecraft.client.gui.screen.Screen
import net.minecraft.client.sound.PositionedSoundInstance
import net.minecraft.client.util.InputUtil
import net.minecraft.client.util.math.MatrixStack
import net.minecraft.sound.SoundEvent
import net.minecraft.text.MutableText
@@ -266,8 +266,8 @@ class TradeGUI(
renderInfoLabels(context, x, y)
renderPokemonInfo(offeredPokemon, false, context, x, y, mouseX, mouseY)
renderPokemonInfo(opposingOfferedPokemon, true, context, x, y, mouseX, mouseY)
renderPokemonInfo(offeredPokemon, false, context, x, y)
renderPokemonInfo(opposingOfferedPokemon, true, context, x, y)
if (trade.acceptedOppositeOffer) {
blitk(
@@ -373,7 +373,7 @@ class TradeGUI(
}
// Calculate select pointer offset
val delayFactor = 3
var delayFactor = 3
if (ticksElapsed % (2 * delayFactor) == 0) selectPointerOffsetIncrement = !selectPointerOffsetIncrement
if (ticksElapsed % delayFactor == 0) selectPointerOffsetY += if (selectPointerOffsetIncrement) 1 else -1
@@ -422,7 +422,7 @@ class TradeGUI(
MinecraftClient.getInstance().soundManager.play(PositionedSoundInstance.master(soundEvent, 1.0F))
}
private fun renderPokemonInfo(pokemon: Pokemon?, isOpposing: Boolean, context: DrawContext, x: Int, y: Int, mouseX: Int, mouseY: Int) {
private fun renderPokemonInfo(pokemon: Pokemon?, isOpposing: Boolean, context: DrawContext, x: Int, y: Int) {
if (pokemon != null) {
val matrices = context.matrices
// Level
@@ -530,17 +530,14 @@ class TradeGUI(
val labelXOffset = if (isOpposing) 77 else 0
// Nature
val natureText = reformatNatureTextIfMinted(pokemon)
drawScaledText(
context = context,
text = natureText,
text = pokemon.nature.displayName.asTranslated(),
x = x + 108 + labelXOffset,
y = y + 146.5,
centered = true,
shadow = true,
scale = SCALE,
pMouseX = mouseX,
pMouseY = mouseY
scale = SCALE
)
// Ability
@@ -15,7 +15,7 @@ import net.minecraft.client.util.InputUtil
object HidePartyBinding : CobblemonKeyBinding(
"key.cobblemon.hideparty",
InputUtil.Type.KEYSYM,
InputUtil.GLFW_KEY_O,
InputUtil.GLFW_KEY_P,
KeybindCategories.COBBLEMON_CATEGORY
) {
var shouldHide = false
@@ -11,14 +11,15 @@ package com.cobblemon.mod.common.client.keybind.keybinds
import com.cobblemon.mod.common.CobblemonNetwork.sendPacketToServer
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.gui.battle.BattleGUI
import com.cobblemon.mod.common.client.gui.interact.wheel.createPlayerInteractGui
import com.cobblemon.mod.common.client.keybind.CobblemonBlockingKeyBinding
import com.cobblemon.mod.common.client.keybind.KeybindCategories
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
import com.cobblemon.mod.common.net.messages.server.RequestPlayerInteractionsPacket
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.traceFirstEntityCollision
import javax.swing.plaf.basic.BasicSliderUI.ScrollListener
import net.minecraft.client.MinecraftClient
import net.minecraft.client.network.ClientPlayerEntity
import net.minecraft.client.util.InputUtil
@@ -89,9 +90,7 @@ object PartySendBinding : CobblemonBlockingKeyBinding(
private fun processEntityTarget(player: ClientPlayerEntity, pokemon: Pokemon, entity: LivingEntity) {
when (entity) {
is PlayerEntity -> {
//This sends a packet to the server with the id of the player
//The server sends a packet back that opens the player interaction menu with the proper options
sendPacketToServer(RequestPlayerInteractionsPacket(entity.uuid, entity.id, pokemon.uuid))
MinecraftClient.getInstance().setScreen(createPlayerInteractGui(entity, pokemon))
}
is PokemonEntity -> {
if (!entity.canBattle(player)) return
@@ -1,21 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.net
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.client.gui.interact.wheel.createPlayerInteractGui
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
import net.minecraft.client.MinecraftClient
object PlayerInteractOptionsHandler : ClientNetworkPacketHandler<PlayerInteractOptionsPacket> {
override fun handle(packet: PlayerInteractOptionsPacket, client: MinecraftClient) {
MinecraftClient.getInstance().setScreen(createPlayerInteractGui(packet))
}
}
@@ -32,10 +32,10 @@ object BattleInitializeHandler : ClientNetworkPacketHandler<BattleInitializePack
}
val otherSide = if (mySide == packet.side1) packet.side2 else packet.side1
val sides = listOf(packet.side1, packet.side2)
spectating = !sides.any { it.actors.any { it.uuid == MinecraftClient.getInstance().player?.uuid } }
side1.actors.addAll(mySide.actors.map{ actorFromDTO(it, !spectating) })
side1.actors.addAll(mySide.actors.map{ actorFromDTO(it, true) })
side2.actors.addAll(otherSide.actors.map{ actorFromDTO(it, false) })
spectating = sides.any { it.actors.any { it.uuid == MinecraftClient.getInstance().player?.uuid } }
for (side in listOf(side1, side2)) {
side.battle = this
for (actor in side.actors) {
@@ -115,7 +115,6 @@ fun getDepletableRedGreen(
return r.toFloat() to g.toFloat()
}
fun drawScaledText(
context: DrawContext,
font: Identifier? = null,
@@ -127,9 +126,7 @@ fun drawScaledText(
maxCharacterWidth: Int = Int.MAX_VALUE,
colour: Int = 0x00FFFFFF + ((opacity.toFloat() * 255).toInt() shl 24),
centered: Boolean = false,
shadow: Boolean = false,
pMouseX: Int? = null,
pMouseY: Int? = null
shadow: Boolean = false
) {
if (opacity.toFloat() < 0.05F) {
return
@@ -141,7 +138,7 @@ fun drawScaledText(
val matrices = context.matrices
matrices.push()
matrices.scale(scale * extraScale, scale * extraScale, 1F)
val isHovered = drawText(
drawText(
context = context,
font = font,
text = text,
@@ -149,15 +146,9 @@ fun drawScaledText(
y = y.toFloat() / (scale * extraScale) + (1 - extraScale) * fontHeight * scale,
centered = centered,
colour = colour,
shadow = shadow,
pMouseX = pMouseX?.toFloat()?.div((scale * extraScale)),
pMouseY = pMouseY?.toFloat()?.div(scale * extraScale)?.plus((1 - extraScale) * fontHeight * scale)
shadow = shadow
)
matrices.pop()
// Draw tooltip that was created with onHover and is attached to the MutableText
if (isHovered) {
context.drawHoverEvent(MinecraftClient.getInstance().textRenderer, text.style, pMouseX!!, pMouseY!!)
}
}
fun drawScaledText(
@@ -7,54 +7,55 @@
*/
package com.cobblemon.mod.common.client.render.block
//import com.cobblemon.mod.common.block.BerryBlock
//import com.cobblemon.mod.common.block.entity.BerryBlockEntity
//import com.cobblemon.mod.common.client.render.layer.CobblemonRenderLayers
//import com.cobblemon.mod.common.client.render.models.blockbench.repository.BerryModelRepository
//import com.cobblemon.mod.common.util.cobblemonResource
//import com.jozufozu.flywheel.api.MaterialManager
//import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance
//import com.jozufozu.flywheel.core.Materials
//import com.jozufozu.flywheel.core.materials.model.ModelData
//
//class BerryEntityInstance(val materialManager: MaterialManager, val entity: BerryBlockEntity) : BlockEntityInstance<BerryBlockEntity>(materialManager, entity) {
// val models: MutableList<ModelData> = mutableListOf()
// override fun init() {
// super.init()
// val age = entity.cachedState.get(BerryBlock.AGE)
// if (age < BerryBlock.FLOWER_AGE) {
// return
// }
// entity.berryAndGrowthPoint().forEach {
// val newModel = if (age == BerryBlock.FLOWER_AGE) BerryModelRepository.flywheelModelOf(
// cobblemonResource("flower.geo")
// ) else BerryModelRepository.flywheelModelOf(it.first.fruitModelIdentifier)
// if (newModel != null) {
// val instancedModel = materialManager
// .cutout(CobblemonRenderLayers.BERRY_LAYER)
// .material(Materials.TRANSFORMED)
// .model(newModel.name()) { newModel }
// .createInstance()
// models.add(instancedModel)
// val identity = instancedModel.loadIdentity()
// identity.translate(instancePosition)
// identity.translate(it.second.position.multiply(1.0/16.0))
// identity.rotateZ(it.second.rotation.z)
// identity.rotateY(it.second.rotation.y + 180)
// identity.rotateX(-it.second.rotation.x)
// }
//
// }
// }
//
// override fun updateLight() {
// relight(worldPosition, models.stream())
// }
//
// override fun remove() {
// models.forEach {
// it.delete()
// }
// }
//
//}
import com.cobblemon.mod.common.block.BerryBlock
import com.cobblemon.mod.common.block.entity.BerryBlockEntity
import com.cobblemon.mod.common.client.render.layer.CobblemonRenderLayers
import com.cobblemon.mod.common.client.render.models.blockbench.repository.BerryModelRepository
import com.cobblemon.mod.common.util.cobblemonResource
import com.jozufozu.flywheel.api.MaterialManager
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance
import com.jozufozu.flywheel.core.Materials
import com.jozufozu.flywheel.core.materials.model.ModelData
class BerryEntityInstance(val materialManager: MaterialManager, val entity: BerryBlockEntity) : BlockEntityInstance<BerryBlockEntity>(materialManager, entity) {
val models: MutableList<ModelData> = mutableListOf()
override fun init() {
super.init()
val age = entity.cachedState.get(BerryBlock.AGE)
if (age < BerryBlock.FLOWER_AGE) {
return
}
entity.berryAndGrowthPoint().forEach {
val newModel = if (age == BerryBlock.FLOWER_AGE) BerryModelRepository.flywheelModelOf(
cobblemonResource("flower")
) else BerryModelRepository.flywheelModelOf(it.first.fruitModelIdentifier)
if (newModel != null) {
val instancedModel = materialManager
.cutout(CobblemonRenderLayers.BERRY_LAYER)
.material(Materials.TRANSFORMED)
.model(newModel.name()) { newModel }
.createInstance()
models.add(instancedModel)
val identity = instancedModel.loadIdentity()
identity.translate(instancePosition)
identity.translate(it.second.position.multiply(1.0/16.0))
identity.rotateZ(it.second.rotation.z)
identity.rotateY(it.second.rotation.y + 180)
identity.rotateX(-it.second.rotation.x)
}
}
}
override fun updateLight() {
relight(worldPosition, models.stream())
}
override fun remove() {
models.forEach {
it.delete()
}
}
}
@@ -1,90 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.render.boat
import com.cobblemon.mod.common.entity.boat.CobblemonBoatEntity
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.client.render.OverlayTexture
import net.minecraft.client.render.RenderLayer
import net.minecraft.client.render.VertexConsumerProvider
import net.minecraft.client.render.entity.EntityRenderer
import net.minecraft.client.render.entity.EntityRendererFactory
import net.minecraft.client.render.entity.model.BoatEntityModel
import net.minecraft.client.render.entity.model.ChestBoatEntityModel
import net.minecraft.client.render.entity.model.EntityModelLayer
import net.minecraft.client.util.math.MatrixStack
import net.minecraft.util.Identifier
import net.minecraft.util.math.MathHelper
import net.minecraft.util.math.RotationAxis
import org.joml.Quaternionf
class CobblemonBoatRenderer(ctx: EntityRendererFactory.Context, private val hasChest: Boolean) : EntityRenderer<CobblemonBoatEntity>(ctx) {
private val boatModels = hashMapOf<CobblemonBoatType, Pair<Identifier, BoatEntityModel>>()
init {
this.shadowRadius = 0.8F
CobblemonBoatType.values().forEach { type ->
this.boatModels[type] = generateTextureIdentifier(type, this.hasChest) to generateBoatModel(ctx, type, this.hasChest)
}
}
override fun getTexture(entity: CobblemonBoatEntity): Identifier = this.boatModels[entity.boatType]!!.first
override fun render(entity: CobblemonBoatEntity, yaw: Float, tickDelta: Float, matrices: MatrixStack, vertexConsumers: VertexConsumerProvider, light: Int) {
matrices.push()
matrices.translate(0F, 0.375F, 0F)
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180F - yaw))
val h = entity.damageWobbleTicks - tickDelta
val j = (entity.damageWobbleStrength - tickDelta).coerceAtLeast(0F)
if (h > 0F) {
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(MathHelper.sin(h) * h * j / 10F * entity.damageWobbleSide))
}
val k = entity.interpolateBubbleWobble(tickDelta)
if (!MathHelper.approximatelyEquals(k, 0F)) {
matrices.multiply(Quaternionf().setAngleAxis(entity.interpolateBubbleWobble(tickDelta) * 0.017453292F, 1F, 0F, 1F))
}
val (identifier, entityModel) = this.boatModels[entity.boatType]!!
matrices.scale(-1F, -1F, 1F)
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(90F))
entityModel.setAngles(entity, tickDelta, 0F, -0.1F, 0F, 0F)
val vertexConsumer = vertexConsumers.getBuffer(entityModel.getLayer(identifier))
entityModel.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV, 1F, 1F, 1F, 1F)
if (!entity.isSubmergedInWater) {
val vertexConsumer2 = vertexConsumers.getBuffer(RenderLayer.getWaterMask())
entityModel.waterPatch.render(matrices, vertexConsumer2, light, OverlayTexture.DEFAULT_UV)
}
matrices.pop()
super.render(entity, yaw, tickDelta, matrices, vertexConsumers, light)
}
companion object {
private fun generateTextureIdentifier(type: CobblemonBoatType, hasChest: Boolean): Identifier {
val boatSubPath = if (hasChest) "chest_boat" else "boat"
val path = "textures/entity/$boatSubPath/${type.name.lowercase()}.png"
return cobblemonResource(path)
}
private fun generateBoatModel(ctx: EntityRendererFactory.Context, type: CobblemonBoatType, hasChest: Boolean): BoatEntityModel {
val modelLayer = this.createBoatModelLayer(type, hasChest)
val modelPart = ctx.getPart(modelLayer)
return if (hasChest) ChestBoatEntityModel(modelPart) else BoatEntityModel(modelPart)
}
internal fun createBoatModelLayer(type: CobblemonBoatType, hasChest: Boolean): EntityModelLayer {
val boatSubPath = if (hasChest) "chest_boat" else "boat"
val path = "$boatSubPath/${type.name.lowercase()}"
return EntityModelLayer(cobblemonResource(path), "main")
}
}
}
@@ -13,6 +13,8 @@ import com.cobblemon.mod.common.util.math.fromEulerXYZ
import com.cobblemon.mod.common.util.math.geometry.toRadians
import com.google.gson.GsonBuilder
import com.google.gson.annotations.SerializedName
import com.jozufozu.flywheel.core.hardcoded.PartBuilder
import com.jozufozu.flywheel.core.model.Model
import net.minecraft.client.model.Dilation
import net.minecraft.client.model.ModelData
import net.minecraft.client.model.ModelPartBuilder
@@ -69,88 +71,88 @@ class TexturedModel {
*
* - Hiro & Apion
*/
// fun createFlywheelModel(atlas: SpriteAtlasHolder, textureName: Identifier, name: String): Model {
// val texture = atlas.getSprite(textureName)
// val width = ((texture.maxU * atlas.atlas.width.toFloat()) - (texture.minU * atlas.atlas.width)).toInt()
// val height =( (texture.maxV * atlas.atlas.height.toFloat()) - (texture.minV * atlas.atlas.height)).toInt()
//
// val modelBuilder = PartBuilder(name, width, height)
// modelBuilder.sprite(texture)
// val boneMap = mutableMapOf<String, ModelBone>()
// geometry?.forEach { it.bones?.forEach { boneMap[it.name] = it } }
//
// geometry?.forEach {
// it.bones?.forEach { bone ->
// // This is meant to prepare the rotation stack so that the rotation around a cube's pivot point is respecting
// // all of the parent bone rotations. It's not meant to influence the POSITION of the cubes further down
// // the chain, only the location of the joints. It doesn't sum the pivot points either; the child bones
// // are only affected by the parent bones because of the rotations.
// //
// // This probably doesn't work but haven't tested it on models with joints so.
// val stack = MatrixStack()
// for (bone in resolveParentsFromRoot(mutableMapOf(), bone)) {
// val rotation = bone.rotation?.takeIf { it[0] != 0F || it[1] != 0F || it[2] != 0F } ?: continue
// stack.translate(-bone.pivot[0], bone.pivot[1], -bone.pivot[2])
// stack.multiply(Quaternionf().rotationXYZ(rotation[0].toRadians(), rotation[1].toRadians(), rotation[2].toRadians()))
// stack.translate(bone.pivot[0], -bone.pivot[1], bone.pivot[2])
// }
//
// bone.cubes?.forEach { cube ->
// val size = cube.size?.let { Vector3f(it[0], it[1], it[2]) } ?: Vector3f()
// val rotation = cube.rotation?.let { Vector3f(it[0], it[1], it[2]) } ?: Vector3f()
// val inflation = (cube.inflate ?: 0F) / 2
// val uvs = cube.uv?.let { Vector2i(it[0], it[1]) } ?: Vector2i()
//
// /*
// * The origin has the X and Z flipped, and that also means counting from the opposite side of the
// * cube (second line is accomplishing that part). The reason for this is because Minecraft Java Edition
// * is a "right hand" coordinate system (finger guns time!!) whereas Bedrock presumably is left-hand.
// *
// * Pivots are also inverted fyi.
// *
// * - Hiro
// */
// val origin = cube.origin?.let { Vector3f(-it[0], it[1], -it[2]) } ?: Vector3f()
// origin.sub(size.get(Vector3f()).mul(1F, 0F, 1F))
// val pivot = cube.pivot?.let { Vector3f(-it[0], it[1], -it[2]) } ?: Vector3f()
//
// // Apply translate, rotate, then translate back because the pivots don't actually directly translate
// // to shifted positions in Bedrock.
// stack.push()
// stack.translate(pivot.x, pivot.y, pivot.z)
// stack.multiply(Quaternionf().rotationXYZ(rotation.x.toRadians(), rotation.y.toRadians(), rotation.z.toRadians()))
// stack.translate(-pivot.x, -pivot.y, -pivot.z)
// val rotationMatrix = stack.peek().positionMatrix
// stack.pop()
//
// // Finds where Bedrock put the start of the cube. The matrix does the rotation correctly because we
// // are chasing rotations around very specific points.
// val desiredPoint = rotationMatrix.transformPosition(origin.get(Vector3f()))
//
// // The rotation in Euler angles (which are about 0,0,0), that's what Flywheel likes to eat.
// // It will orient it correctly, but a limitation of Euler angles is that it can't get the thing
// // to rotate around a specific point, only ever the origin. We'll fix that.
// val eulerRotation = rotationMatrix.getEulerAnglesXYZ(Vector3f())
// // The reversed form of the rotation Flywheel is about to apply.
// val reversedRotation = Quaternionf().fromEulerXYZ(-eulerRotation.x, -eulerRotation.y, -eulerRotation.z)
// // Figure out the start point such that Flywheel applying the eulerRotation will put it at the desired point.
// val correctStart = reversedRotation.transform(desiredPoint.get(Vector3f()))
//
// // Now just put it all together. Inflation is a slight tweak to size and start position.
// // Invert YZ is something I don't understand but is necessary.
// modelBuilder.cuboid()
// .sprite(texture)
// .start(correctStart.x - inflation, correctStart.y - inflation, correctStart.z - inflation)
// .invertYZ()
// .size(size.x + 2 * inflation, size.y + 2 * inflation, size.z + 2 * inflation)
// .rotate(eulerRotation.x, eulerRotation.y, eulerRotation.z)
// .textureOffset(uvs.x, uvs.y)
// .endCuboid()
// }
// }
// }
// return modelBuilder.build()
// }
fun createFlywheelModel(atlas: SpriteAtlasHolder, textureName: Identifier, name: String): Model {
val texture = atlas.getSprite(textureName)
val width = ((texture.maxU * atlas.atlas.width.toFloat()) - (texture.minU * atlas.atlas.width)).toInt()
val height =( (texture.maxV * atlas.atlas.height.toFloat()) - (texture.minV * atlas.atlas.height)).toInt()
val modelBuilder = PartBuilder(name, width, height)
modelBuilder.sprite(texture)
val boneMap = mutableMapOf<String, ModelBone>()
geometry?.forEach { it.bones?.forEach { boneMap[it.name] = it } }
geometry?.forEach {
it.bones?.forEach { bone ->
// This is meant to prepare the rotation stack so that the rotation around a cube's pivot point is respecting
// all of the parent bone rotations. It's not meant to influence the POSITION of the cubes further down
// the chain, only the location of the joints. It doesn't sum the pivot points either; the child bones
// are only affected by the parent bones because of the rotations.
//
// This probably doesn't work but haven't tested it on models with joints so.
val stack = MatrixStack()
for (bone in resolveParentsFromRoot(mutableMapOf(), bone)) {
val rotation = bone.rotation?.takeIf { it[0] != 0F || it[1] != 0F || it[2] != 0F } ?: continue
stack.translate(-bone.pivot[0], bone.pivot[1], -bone.pivot[2])
stack.multiply(Quaternionf().rotationXYZ(rotation[0].toRadians(), rotation[1].toRadians(), rotation[2].toRadians()))
stack.translate(bone.pivot[0], -bone.pivot[1], bone.pivot[2])
}
bone.cubes?.forEach { cube ->
val size = cube.size?.let { Vector3f(it[0], it[1], it[2]) } ?: Vector3f()
val rotation = cube.rotation?.let { Vector3f(it[0], it[1], it[2]) } ?: Vector3f()
val inflation = (cube.inflate ?: 0F) / 2
val uvs = cube.uv?.let { Vector2i(it[0], it[1]) } ?: Vector2i()
/*
* The origin has the X and Z flipped, and that also means counting from the opposite side of the
* cube (second line is accomplishing that part). The reason for this is because Minecraft Java Edition
* is a "right hand" coordinate system (finger guns time!!) whereas Bedrock presumably is left-hand.
*
* Pivots are also inverted fyi.
*
* - Hiro
*/
val origin = cube.origin?.let { Vector3f(-it[0], it[1], -it[2]) } ?: Vector3f()
origin.sub(size.get(Vector3f()).mul(1F, 0F, 1F))
val pivot = cube.pivot?.let { Vector3f(-it[0], it[1], -it[2]) } ?: Vector3f()
// Apply translate, rotate, then translate back because the pivots don't actually directly translate
// to shifted positions in Bedrock.
stack.push()
stack.translate(pivot.x, pivot.y, pivot.z)
stack.multiply(Quaternionf().rotationXYZ(rotation.x.toRadians(), rotation.y.toRadians(), rotation.z.toRadians()))
stack.translate(-pivot.x, -pivot.y, -pivot.z)
val rotationMatrix = stack.peek().positionMatrix
stack.pop()
// Finds where Bedrock put the start of the cube. The matrix does the rotation correctly because we
// are chasing rotations around very specific points.
val desiredPoint = rotationMatrix.transformPosition(origin.get(Vector3f()))
// The rotation in Euler angles (which are about 0,0,0), that's what Flywheel likes to eat.
// It will orient it correctly, but a limitation of Euler angles is that it can't get the thing
// to rotate around a specific point, only ever the origin. We'll fix that.
val eulerRotation = rotationMatrix.getEulerAnglesXYZ(Vector3f())
// The reversed form of the rotation Flywheel is about to apply.
val reversedRotation = Quaternionf().fromEulerXYZ(-eulerRotation.x, -eulerRotation.y, -eulerRotation.z)
// Figure out the start point such that Flywheel applying the eulerRotation will put it at the desired point.
val correctStart = reversedRotation.transform(desiredPoint.get(Vector3f()))
// Now just put it all together. Inflation is a slight tweak to size and start position.
// Invert YZ is something I don't understand but is necessary.
modelBuilder.cuboid()
.sprite(texture)
.start(correctStart.x - inflation, correctStart.y - inflation, correctStart.z - inflation)
.invertYZ()
.size(size.x + 2 * inflation, size.y + 2 * inflation, size.z + 2 * inflation)
.rotate(eulerRotation.x, eulerRotation.y, eulerRotation.z)
.textureOffset(uvs.x, uvs.y)
.endCuboid()
}
}
}
return modelBuilder.build()
}
fun createWithUvOverride(isForLivingEntityRenderer: Boolean, u: Int, v: Int, textureWidth: Int?, textureHeight: Int?) : TexturedModelData {
val modelData = ModelData()
@@ -19,7 +19,7 @@ import net.minecraft.client.model.ModelPart
class PokeBallModel(root: ModelPart) : PoseableEntityModel<EmptyPokeBallEntity>(), PokeBallFrame {
override val rootPart = root.registerChildWithAllChildren("poke_ball")
override val base = getPart("bottom")
override val base = getPart("base")
override val lid = getPart("lid")
override val isForLivingEntityRenderer = false
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen1
import com.cobblemon.mod.common.client.render.models.blockbench.animation.WingFlapIdleAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.asTransformed
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BiWingedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.TransformedModelPart
@@ -24,50 +23,44 @@ import com.cobblemon.mod.common.util.math.geometry.toRadians
import net.minecraft.client.model.ModelPart
import net.minecraft.util.math.Vec3d
class GolbatModel(root: ModelPart) : PokemonPoseableModel() {
class GolbatModel(root: ModelPart) : PokemonPoseableModel(), BiWingedFrame {
override val rootPart = root.registerChildWithAllChildren("golbat")
override val leftWing = getPart("leftwing")
override val rightWing = getPart("rightwing")
override val portraitScale = 1.55F
override val portraitTranslation = Vec3d(-0.1, -0.1, 0.0)
override val portraitTranslation = Vec3d(0.0, -0.55, 0.0)
override val profileScale = 0.7F
override val profileTranslation = Vec3d(0.0, 0.7, 0.0)
override val profileScale = 0.9F
override val profileTranslation = Vec3d(0.0, 0.4, 0.0)
lateinit var sleep: PokemonPose
lateinit var standing: PokemonPose
lateinit var walk: PokemonPose
lateinit var hover: PokemonPose
lateinit var fly: PokemonPose
lateinit var battleidle: PokemonPose
// override val cryAnimation = CryProvider { _, _ -> bedrockStateful("golbat", "cry").setPreventsIdle(false) }
override fun registerPoses() {
val blink = quirk("blink") { bedrockStateful("golbat", "blink").setPreventsIdle(false) }
standing = registerPose(
poseName = "standing",
poseTypes = STATIONARY_POSES + UI_POSES - PoseType.HOVER,
transformTicks = 10,
idleAnimations = arrayOf(
//bedrock("golbat", "ground_idle")
)
)
sleep = registerPose(
poseType = PoseType.SLEEP,
idleAnimations = arrayOf(bedrock("golbat", "sleep"))
)
standing = registerPose(
poseName = "standing",
poseTypes = STATIONARY_POSES + UI_POSES - PoseType.HOVER,
transformTicks = 10,
quirks = arrayOf(blink),
condition = { !it.isBattling },
idleAnimations = arrayOf(
bedrock("golbat", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = MOVING_POSES - PoseType.FLY,
transformTicks = 10,
quirks = arrayOf(blink),
idleAnimations = arrayOf(
bedrock("golbat", "ground_walk")
//bedrock("golbat", "ground_walk")
)
)
@@ -75,9 +68,12 @@ class GolbatModel(root: ModelPart) : PokemonPoseableModel() {
poseName = "hover",
poseType = PoseType.HOVER,
transformTicks = 10,
quirks = arrayOf(blink),
idleAnimations = arrayOf(
bedrock("golbat", "air_idle")
WingFlapIdleAnimation(this,
flapFunction = sineFunction(verticalShift = -10F.toRadians(), period = 0.9F, amplitude = 0.6F),
timeVariable = { state, _, _ -> state?.animationSeconds ?: 0F },
axis = TransformedModelPart.Y_AXIS
)
)
)
@@ -85,20 +81,12 @@ class GolbatModel(root: ModelPart) : PokemonPoseableModel() {
poseName = "fly",
poseType = PoseType.FLY,
transformTicks = 10,
quirks = arrayOf(blink),
idleAnimations = arrayOf(
bedrock("golbat", "air_fly")
)
)
battleidle = registerPose(
poseName = "battle_idle",
poseTypes = PoseType.STATIONARY_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
condition = { it.isBattling },
idleAnimations = arrayOf(
bedrock("golbat", "battle_idle")
WingFlapIdleAnimation(this,
flapFunction = sineFunction(verticalShift = -14F.toRadians(), period = 0.9F, amplitude = 0.9F),
timeVariable = { state, _, _ -> state?.animationSeconds ?: 0F },
axis = TransformedModelPart.Y_AXIS
)
)
)
}
@@ -37,6 +37,7 @@ class KadabraModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Biped
override val profileScale = 0.75F
override val profileTranslation = Vec3d(0.0, 0.6, 0.0)
lateinit var sleep: PokemonPose
lateinit var standing: PokemonPose
lateinit var walk: PokemonPose
lateinit var battleidle: PokemonPose
@@ -10,14 +10,11 @@ package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen1
import com.cobblemon.mod.common.client.render.models.blockbench.EarJoint
import com.cobblemon.mod.common.client.render.models.blockbench.RangeOfMotion
import com.cobblemon.mod.common.client.render.models.blockbench.animation.WingFlapIdleAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.asTransformed
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BiWingedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.frame.EaredFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.TransformedModelPart
import com.cobblemon.mod.common.client.render.models.blockbench.pose.TransformedModelPart.Companion.X_AXIS
import com.cobblemon.mod.common.client.render.models.blockbench.pose.TransformedModelPart.Companion.Y_AXIS
import com.cobblemon.mod.common.client.render.models.blockbench.pose.TransformedModelPart.Companion.Z_AXIS
@@ -30,121 +27,81 @@ import net.minecraft.client.model.ModelPart
import net.minecraft.util.math.MathConstants.PI
import net.minecraft.util.math.Vec3d
class ZubatModel(root: ModelPart) : PokemonPoseableModel() {
class ZubatModel(root: ModelPart) : PokemonPoseableModel(), BiWingedFrame, EaredFrame {
override val rootPart = root.registerChildWithAllChildren("zubat")
val wings_folded = getPart("wings_folded")
val wings_open = getPart("wings_open")
override val leftWing = getPart("leftwing")
override val rightWing = getPart("rightwing")
override val portraitScale = 1.7F
override val portraitTranslation = Vec3d(0.0, 0.0, 0.0)
private val leftEar = getPart("leftear")
private val rightEar = getPart("rightear")
override val leftEarJoint = EarJoint(leftEar, Z_AXIS, RangeOfMotion(70F.toRadians(), 40F.toRadians()))
override val rightEarJoint = EarJoint(rightEar, Z_AXIS, RangeOfMotion((-70F).toRadians(), (-40F).toRadians()))
override val profileScale = 0.7F
override val profileTranslation = Vec3d(0.0, 0.7, 0.0)
override val portraitScale = 2.3F
override val portraitTranslation = Vec3d(0.0, -0.5, 0.0)
override val profileScale = 1.0F
override val profileTranslation = Vec3d(0.0, 0.36, 0.0)
lateinit var sleep: PokemonPose
lateinit var standing: PokemonPose
lateinit var walk: PokemonPose
lateinit var hover: PokemonPose
lateinit var fly: PokemonPose
lateinit var shoulderLeft: PokemonPose
lateinit var shoulderRight: PokemonPose
val shoulderOffset = 0
override val cryAnimation = CryProvider { _, _ -> bedrockStateful("zubat", "cry").setPreventsIdle(false) }
override fun registerPoses() {
val twitch = quirk("twitch") { bedrockStateful("zubat", "eartwitch").setPreventsIdle(false) }
sleep = registerPose(
poseType = PoseType.SLEEP,
transformedParts = arrayOf(
wings_folded.asTransformed().withVisibility(visibility = false),
wings_open.asTransformed().withVisibility(visibility = true),
),
quirks = arrayOf(twitch),
idleAnimations = arrayOf(bedrock("zubat", "sleep"))
)
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES - PoseType.HOVER,
transformedParts = arrayOf(
wings_folded.asTransformed().withVisibility(visibility = false),
wings_open.asTransformed().withVisibility(visibility = true),
),
transformTicks = 10,
quirks = arrayOf(twitch),
registerPose(
poseName = "hover",
poseTypes = ALL_POSES - SHOULDER_POSES - PoseType.FLY - PoseType.SLEEP,
idleAnimations = arrayOf(
bedrock("zubat", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES - PoseType.FLY,
transformedParts = arrayOf(
wings_folded.asTransformed().withVisibility(visibility = false),
wings_open.asTransformed().withVisibility(visibility = true),
),
transformTicks = 10,
quirks = arrayOf(twitch),
registerPose(
poseName = "fly",
poseType = PoseType.FLY,
idleAnimations = arrayOf(
bedrock("zubat", "ground_walk")
)
)
hover = registerPose(
poseName = "hover",
poseType = PoseType.HOVER,
transformedParts = arrayOf(
wings_folded.asTransformed().withVisibility(visibility = false),
wings_open.asTransformed().withVisibility(visibility = true),
),
transformTicks = 10,
quirks = arrayOf(twitch),
idleAnimations = arrayOf(
bedrock("zubat", "air_idle")
)
)
fly = registerPose(
poseName = "fly",
poseType = PoseType.FLY,
transformedParts = arrayOf(
wings_folded.asTransformed().withVisibility(visibility = false),
wings_open.asTransformed().withVisibility(visibility = true),
),
quirks = arrayOf(twitch),
transformTicks = 10,
idleAnimations = arrayOf(
bedrock("zubat", "air_fly")
)
)
shoulderLeft = registerPose(
registerPose(
poseType = PoseType.SHOULDER_LEFT,
idleAnimations = arrayOf(
bedrock("zubat", "shoulder_left")
leftWing.rotation(
function = sineFunction(
amplitude = PI / 3,
period = 1F
),
axis = Z_AXIS,
timeVariable = { _, _, ageInTicks -> ageInTicks / 20 },
)
),
transformedParts = arrayOf(
rootPart.asTransformed().addPosition(TransformedModelPart.X_AXIS, shoulderOffset)
rootPart.asTransformed().addRotation(X_AXIS, PI / 9).addPosition(Y_AXIS, 4F).addPosition(Z_AXIS, 3F),
leftWing.asTransformed().addRotation(X_AXIS, PI / 3),
rightWing.asTransformed().addRotation(X_AXIS, PI / 3).addRotation(Z_AXIS, -PI / 2)
)
)
shoulderRight = registerPose(
registerPose(
poseType = PoseType.SHOULDER_RIGHT,
idleAnimations = arrayOf(
bedrock("zubat", "shoulder_right")
rightWing.rotation(
function = sineFunction(
amplitude = PI / 3,
period = 1F
),
axis = Z_AXIS,
timeVariable = { _, _, ageInTicks -> ageInTicks / 20 },
)
),
transformedParts = arrayOf(
rootPart.asTransformed().addPosition(TransformedModelPart.X_AXIS, -shoulderOffset)
rootPart.asTransformed().addRotation(X_AXIS, PI / 9).addPosition(Y_AXIS, 4F).addPosition(Z_AXIS, 3F),
leftWing.asTransformed().addRotation(X_AXIS, PI / 3).addRotation(Z_AXIS, PI / 2),
rightWing.asTransformed().addRotation(X_AXIS, PI / 3)
)
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PoseableEntityState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("zubat", "faint") else null
}
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen2
import com.cobblemon.mod.common.client.render.models.blockbench.animation.WingFlapIdleAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BiWingedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.TransformedModelPart
@@ -20,37 +19,26 @@ import com.cobblemon.mod.common.util.math.geometry.toRadians
import net.minecraft.client.model.ModelPart
import net.minecraft.util.math.Vec3d
class CrobatModel(root: ModelPart) : PokemonPoseableModel() {
class CrobatModel(root: ModelPart) : PokemonPoseableModel(), BiWingedFrame {
override val rootPart = root.registerChildWithAllChildren("crobat")
override val leftWing = getPart("leftwings")
override val rightWing = getPart("rightwings")
override val portraitScale = 1.2F
override val portraitTranslation = Vec3d(-0.1, 1.8, 0.0)
override val portraitScale = 1.8F
override val portraitTranslation = Vec3d(-0.11, -0.77, 0.0)
override val profileScale = 0.5F
override val profileTranslation = Vec3d(0.0, 1.2, 0.0)
override val profileScale = 0.9F
override val profileTranslation = Vec3d(0.0, 0.35, 0.0)
lateinit var sleep: PokemonPose
lateinit var standing: PokemonPose
lateinit var walk: PokemonPose
lateinit var hover: PokemonPose
lateinit var fly: PokemonPose
lateinit var battleidle: PokemonPose
override val cryAnimation = CryProvider { _, _ -> bedrockStateful("crobat", "cry").setPreventsIdle(false) }
lateinit var walk: PokemonPose
override fun registerPoses() {
val blink = quirk("blink") { bedrockStateful("crobat", "blink").setPreventsIdle(false) }
sleep = registerPose(
poseType = PoseType.SLEEP,
idleAnimations = arrayOf(bedrock("crobat", "sleep"))
)
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES - PoseType.HOVER,
condition = { !it.isBattling },
transformTicks = 10,
poseType = PoseType.STAND,
idleAnimations = arrayOf(
bedrock("crobat", "ground_idle")
)
@@ -69,9 +57,13 @@ class CrobatModel(root: ModelPart) : PokemonPoseableModel() {
poseName = "hover",
poseType = PoseType.HOVER,
transformTicks = 10,
quirks = arrayOf(blink),
idleAnimations = arrayOf(
bedrock("crobat", "air_idle")
bedrock("crobat", "ground_idle"),
WingFlapIdleAnimation(this,
flapFunction = sineFunction(verticalShift = -10F.toRadians(), period = 0.9F, amplitude = 0.6F),
timeVariable = { state, _, _ -> state?.animationSeconds ?: 0F },
axis = TransformedModelPart.Y_AXIS
)
)
)
@@ -79,20 +71,13 @@ class CrobatModel(root: ModelPart) : PokemonPoseableModel() {
poseName = "fly",
poseType = PoseType.FLY,
transformTicks = 10,
quirks = arrayOf(blink),
idleAnimations = arrayOf(
bedrock("crobat", "air_fly")
)
)
battleidle = registerPose(
poseName = "battle_idle",
poseTypes = PoseType.STATIONARY_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
condition = { it.isBattling },
idleAnimations = arrayOf(
bedrock("crobat", "battle_idle")
bedrock("crobat", "ground_walk"),
WingFlapIdleAnimation(this,
flapFunction = sineFunction(verticalShift = -14F.toRadians(), period = 0.9F, amplitude = 0.9F),
timeVariable = { state, _, _ -> state?.animationSeconds ?: 0F },
axis = TransformedModelPart.Y_AXIS
)
)
)
}
@@ -8,53 +8,42 @@
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen2
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BimanualSwingAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BipedWalkAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.asTransformed
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BimanualFrame
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.TransformedModelPart
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import net.minecraft.client.model.ModelPart
import net.minecraft.util.math.Vec3d
class HitmontopModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
class HitmontopModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, BipedFrame, BimanualFrame {
override val rootPart = root.registerChildWithAllChildren("hitmontop")
override val head = getPart("head")
override val leftArm = getPart("arm_left")
override val rightArm = getPart("arm_right")
override val leftLeg = getPart("leg_left")
override val rightLeg = getPart("leg_right")
override val portraitScale = 2.6F
override val portraitTranslation = Vec3d(-0.26, -0.5, 0.0)
override val profileScale = 0.91F
override val profileTranslation = Vec3d(0.0, 0.4, 0.0)
lateinit var sleep: PokemonPose
lateinit var standing: PokemonPose
lateinit var walk: PokemonPose
lateinit var battleidle: PokemonPose
// override val cryAnimation = CryProvider { _, _ -> bedrockStateful("hitmontop", "cry").setPreventsIdle(false) }
override fun registerPoses() {
val blink = quirk("blink") { bedrockStateful("hitmontop", "blink").setPreventsIdle(false) }
sleep = registerPose(
poseType = PoseType.SLEEP,
idleAnimations = arrayOf(bedrock("hitmontop", "sleep"))
)
val blink = quirk("blink") { bedrockStateful("hitmontop", "blink").setPreventsIdle(false)}
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
transformTicks = 10,
condition = { !it.isBattling },
poseTypes = STATIONARY_POSES + UI_POSES,
quirks = arrayOf(blink),
idleAnimations = arrayOf(
singleBoneLook(),
@@ -64,29 +53,19 @@ class HitmontopModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES,
transformTicks = 10,
poseTypes = MOVING_POSES,
quirks = arrayOf(blink),
idleAnimations = arrayOf(
singleBoneLook(),
bedrock("hitmontop", "ground_walk")
)
)
battleidle = registerPose(
poseName = "battle_idle",
poseTypes = PoseType.STATIONARY_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
condition = { it.isBattling },
idleAnimations = arrayOf(
singleBoneLook(),
bedrock("hitmontop", "battle_idle")
bedrock("hitmontop", "ground_idle"),
BipedWalkAnimation(this, periodMultiplier = 0.6F, amplitudeMultiplier = 0.9F),
BimanualSwingAnimation(this, swingPeriodMultiplier = 0.6F, amplitudeMultiplier = 0.9F)
)
)
}
override fun getFaintAnimation(
pokemonEntity: PokemonEntity,
state: PoseableEntityState<PokemonEntity>
) = bedrockStateful("hitmontop", "faint")
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PoseableEntityState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("hitmontop", "faint") else null
}
@@ -8,59 +8,42 @@
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen2
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BimanualSwingAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BipedWalkAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.asTransformed
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BimanualFrame
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.frame.QuadrupedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.TransformedModelPart
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import net.minecraft.client.model.ModelPart
import net.minecraft.util.math.Vec3d
class TyrogueModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
class TyrogueModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, BipedFrame, BimanualFrame {
override val rootPart = root.registerChildWithAllChildren("tyrogue")
override val head = getPart("head")
override val leftArm = getPart("arm_left")
override val rightArm = getPart("arm_right")
override val leftLeg = getPart("leg_left")
override val rightLeg = getPart("leg_right")
override val portraitScale = 2.56F
override val portraitTranslation = Vec3d(-0.24, 0.1, 0.0)
override val profileScale = 0.73F
override val profileTranslation = Vec3d(-0.03, 0.7, 0.0)
lateinit var sleep: PokemonPose
lateinit var standing: PokemonPose
lateinit var walk: PokemonPose
lateinit var shoulderLeft: PokemonPose
lateinit var shoulderRight: PokemonPose
lateinit var battleidle: PokemonPose
val shoulderOffset = 3
// override val cryAnimation = CryProvider { _, _ -> bedrockStateful("tyrogue", "cry").setPreventsIdle(false) }
override fun registerPoses() {
val blink = quirk("blink") { bedrockStateful("tyrogue", "blink").setPreventsIdle(false) }
sleep = registerPose(
poseType = PoseType.SLEEP,
idleAnimations = arrayOf(bedrock("tyrogue", "sleep"))
)
val blink = quirk("blink") { bedrockStateful("tyrogue", "blink").setPreventsIdle(false)}
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
transformTicks = 10,
condition = { !it.isBattling },
poseTypes = STATIONARY_POSES + UI_POSES,
quirks = arrayOf(blink),
idleAnimations = arrayOf(
singleBoneLook(),
@@ -70,55 +53,19 @@ class TyrogueModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES,
transformTicks = 10,
poseTypes = MOVING_POSES,
quirks = arrayOf(blink),
idleAnimations = arrayOf(
singleBoneLook(),
bedrock("tyrogue", "ground_walk")
)
)
battleidle = registerPose(
poseName = "battle_idle",
poseTypes = PoseType.STATIONARY_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
condition = { it.isBattling },
idleAnimations = arrayOf(
singleBoneLook(),
bedrock("tyrogue", "battle_idle")
)
)
shoulderLeft = registerPose(
poseType = PoseType.SHOULDER_LEFT,
quirks = arrayOf(blink),
condition = { !it.isBattling },
idleAnimations = arrayOf(
singleBoneLook(),
bedrock("tyrogue", "shoulder_left")
),
transformedParts = arrayOf(
rootPart.asTransformed().addPosition(TransformedModelPart.X_AXIS, shoulderOffset)
)
)
shoulderRight = registerPose(
poseType = PoseType.SHOULDER_RIGHT,
quirks = arrayOf(blink),
condition = { !it.isBattling },
idleAnimations = arrayOf(
singleBoneLook(),
bedrock("tyrogue", "shoulder_right")
),
transformedParts = arrayOf(
rootPart.asTransformed().addPosition(TransformedModelPart.X_AXIS, -shoulderOffset)
bedrock("tyrogue", "ground_idle"),
BipedWalkAnimation(this, periodMultiplier = 0.6F, amplitudeMultiplier = 0.9F),
BimanualSwingAnimation(this, swingPeriodMultiplier = 0.6F, amplitudeMultiplier = 0.9F)
)
)
}
override fun getFaintAnimation(
pokemonEntity: PokemonEntity,
state: PoseableEntityState<PokemonEntity>
) = if (state.isPosedIn(standing, walk, battleidle, sleep)) bedrockStateful("tyrogue", "faint") else null
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PoseableEntityState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("tyrogue", "faint") else null
}
@@ -13,7 +13,6 @@ import com.cobblemon.mod.common.client.render.models.blockbench.animation.BipedW
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BimanualFrame
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
import com.cobblemon.mod.common.entity.PoseType
@@ -36,8 +35,6 @@ class BeldumModel (root: ModelPart) : PokemonPoseableModel() {
lateinit var sleep: PokemonPose
lateinit var battleidle: PokemonPose
override val cryAnimation = CryProvider { _, _ -> bedrockStateful("beldum", "cry").setPreventsIdle(false) }
override fun registerPoses() {
val blink = quirk("blink") { bedrockStateful("beldum", "blink").setPreventsIdle(false)}
val quirk = quirk("quirk") { bedrockStateful("beldum", "quirk_spin").setPreventsIdle(false)}
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen3
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
import com.cobblemon.mod.common.entity.PoseType
@@ -31,8 +30,6 @@ class MetagrossModel (root: ModelPart) : PokemonPoseableModel() {
lateinit var sleep: PokemonPose
lateinit var battleidle: PokemonPose
override val cryAnimation = CryProvider { _, _ -> bedrockStateful("metagross", "cry").setPreventsIdle(false) }
override fun registerPoses() {
val blink = quirk("blink") { bedrockStateful("metagross", "blink").setPreventsIdle(false)}
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen3
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
import com.cobblemon.mod.common.entity.PoseType
@@ -31,8 +30,6 @@ class MetangModel (root: ModelPart) : PokemonPoseableModel() {
lateinit var sleep: PokemonPose
lateinit var battleidle: PokemonPose
override val cryAnimation = CryProvider { _, _ -> bedrockStateful("metang", "cry").setPreventsIdle(false) }
override fun registerPoses() {
val blink = quirk("blink") { bedrockStateful("metang", "blink").setPreventsIdle(false)}
@@ -8,87 +8,64 @@
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen3
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
import com.cobblemon.mod.common.client.render.models.blockbench.animation.QuadrupedWalkAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.frame.QuadrupedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import net.minecraft.client.model.ModelPart
import net.minecraft.util.math.Vec3d
class MightyenaModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
class MightyenaModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, QuadrupedFrame {
override val rootPart = root.registerChildWithAllChildren("mightyena")
override val head = getPart("head")
override val hindLeftLeg = getPart("leg_left")
override val hindRightLeg = getPart("leg_right")
override val foreLeftLeg = getPart("arm_left")
override val foreRightLeg = getPart("arm_right")
override val portraitScale = 2.2F
override val portraitTranslation = Vec3d(-0.8, 0.6, 0.0)
override val profileScale = 0.6F
override val profileTranslation = Vec3d(0.0, 0.8, 0.0)
lateinit var sleep: PokemonPose
lateinit var standing: PokemonPose
lateinit var walk: PokemonPose
lateinit var battleidle: PokemonPose
override val cryAnimation = CryProvider { _, _ -> bedrockStateful("mightyena", "cry").setPreventsIdle(false) }
override fun registerPoses() {
val blink = quirk("blink") { bedrockStateful("mightyena", "blink").setPreventsIdle(false) }
val laugh_out_battle = quirk("laugh_out_battle", secondsBetweenOccurrences = 120F to 240F) { bedrockStateful("mightyena", "quirk").setPreventsIdle(false) }
val laugh_in_battle = quirk("laugh_in_battle", secondsBetweenOccurrences = 30F to 60F) { bedrockStateful("mightyena", "quirk").setPreventsIdle(false) }
val sleep_quirk = quirk("sleep_quirk", secondsBetweenOccurrences = 30F to 60F) { bedrockStateful("mightyena", "sleep_quirk").setPreventsIdle(false) }
sleep = registerPose(
poseType = PoseType.SLEEP,
quirks = arrayOf(sleep_quirk),
idleAnimations = arrayOf(bedrock("mightyena", "sleep"))
)
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
transformTicks = 10,
condition = { !it.isBattling },
quirks = arrayOf(blink,laugh_out_battle),
poseTypes = UI_POSES + STATIONARY_POSES,
quirks = arrayOf(blink),
idleAnimations = arrayOf(
singleBoneLook(),
bedrock("mightyena", "ground_idle")
bedrock("mightyena","ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES,
transformTicks = 10,
poseTypes = MOVING_POSES,
quirks = arrayOf(blink),
idleAnimations = arrayOf(
singleBoneLook(),
bedrock("mightyena", "ground_walk")
)
)
battleidle = registerPose(
poseName = "battle_idle",
poseTypes = PoseType.STATIONARY_POSES,
transformTicks = 10,
quirks = arrayOf(blink,laugh_in_battle),
condition = { it.isBattling },
idleAnimations = arrayOf(
singleBoneLook(),
bedrock("mightyena", "battle_idle")
QuadrupedWalkAnimation(this, periodMultiplier = 0.8F, amplitudeMultiplier = 0.8F),
bedrock("mightyena","ground_idle")
)
)
}
override fun getFaintAnimation(
pokemonEntity: PokemonEntity,
state: PoseableEntityState<PokemonEntity>
) = bedrockStateful("mightyena", "faint")
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PoseableEntityState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("mightyena", "faint") else null
}
@@ -49,7 +49,7 @@ class ShroomishModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bip
poseName = "standing",
poseTypes = STATIONARY_POSES + UI_POSES,
quirks = arrayOf(blink),
condition = { !it.isBattling },
condition = { it.isBattling },
idleAnimations = arrayOf(
singleBoneLook(),
bedrock("shroomish", "ground_idle")
@@ -68,6 +68,7 @@ class VolbeatModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bipe
poseTypes = setOf(PoseType.HOVER, PoseType.FLOAT),
transformTicks = 10,
quirks = arrayOf(blink),
condition = { it.isTouchingWater },
idleAnimations = arrayOf(
singleBoneLook(),
bedrock("volbeat", "air_idle")
@@ -79,6 +80,7 @@ class VolbeatModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bipe
poseTypes = setOf(PoseType.FLY, PoseType.SWIM),
transformTicks = 10,
quirks = arrayOf(blink),
condition = { it.isTouchingWater },
idleAnimations = arrayOf(
singleBoneLook(),
bedrock("volbeat", "air_fly")
@@ -8,16 +8,12 @@
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen4
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
import com.cobblemon.mod.common.client.render.models.blockbench.asTransformed
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.frame.QuadrupedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.TransformedModelPart
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import net.minecraft.client.model.ModelPart
import net.minecraft.util.math.Vec3d
@@ -38,10 +34,6 @@ class TurtwigModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Quad
lateinit var sleep: PokemonPose
lateinit var standing: PokemonPose
lateinit var walk: PokemonPose
lateinit var shoulderLeft: PokemonPose
lateinit var shoulderRight: PokemonPose
val shoulderOffset = 3
override val cryAnimation = CryProvider { _, _ -> bedrockStateful("turtwig", "cry").setPreventsIdle(false) }
@@ -73,33 +65,5 @@ class TurtwigModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Quad
bedrock("turtwig", "ground_walk")
)
)
shoulderLeft = registerPose(
poseType = PoseType.SHOULDER_LEFT,
quirks = arrayOf(blink),
idleAnimations = arrayOf(
singleBoneLook(),
bedrock("turtwig", "shoulder_left")
),
transformedParts = arrayOf(
rootPart.asTransformed().addPosition(TransformedModelPart.X_AXIS, shoulderOffset)
)
)
shoulderRight = registerPose(
poseType = PoseType.SHOULDER_RIGHT,
quirks = arrayOf(blink),
idleAnimations = arrayOf(
singleBoneLook(),
bedrock("turtwig", "shoulder_right")
),
transformedParts = arrayOf(
rootPart.asTransformed().addPosition(TransformedModelPart.X_AXIS, -shoulderOffset)
)
)
}
override fun getFaintAnimation(
pokemonEntity: PokemonEntity,
state: PoseableEntityState<PokemonEntity>
) = bedrockStateful("turtwig", "faint")
}
@@ -1,57 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen5
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
import com.cobblemon.mod.common.entity.PoseType
import net.minecraft.client.model.ModelPart
import net.minecraft.util.math.Vec3d
class ChandelureModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
override val rootPart = root.registerChildWithAllChildren("chandelure")
override val head = getPart("head")
override val portraitScale = 2.0F
override val portraitTranslation = Vec3d(-0.3, -1.2, 0.0)
override val profileScale = 0.8F
override val profileTranslation = Vec3d(0.0, 0.5, 0.0)
lateinit var standing: PokemonPose
lateinit var walk: PokemonPose
override fun registerPoses() {
// val blink = quirk("blink") { bedrockStateful("chandelure", "blink").setPreventsIdle(false) }
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
// quirks = arrayOf(blink),
idleAnimations = arrayOf(
bedrock("chandelure", "idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES,
// quirks = arrayOf(blink),
idleAnimations = arrayOf(
bedrock("chandelure", "idle")
)
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PoseableEntityState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("chandelure", "faint") else null
}
@@ -1,57 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen5
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
import com.cobblemon.mod.common.entity.PoseType
import net.minecraft.client.model.ModelPart
import net.minecraft.util.math.Vec3d
class LampentModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
override val rootPart = root.registerChildWithAllChildren("lampent")
override val head = getPart("head")
override val portraitScale = 2.0F
override val portraitTranslation = Vec3d(-0.3, -1.2, 0.0)
override val profileScale = 0.8F
override val profileTranslation = Vec3d(0.0, 0.5, 0.0)
lateinit var standing: PokemonPose
lateinit var walk: PokemonPose
override fun registerPoses() {
val blink = quirk("blink") { bedrockStateful("lampent", "blink").setPreventsIdle(false) }
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
quirks = arrayOf(blink),
idleAnimations = arrayOf(
bedrock("lampent", "idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES,
quirks = arrayOf(blink),
idleAnimations = arrayOf(
bedrock("lampent", "idle")
)
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PoseableEntityState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("lampent", "faint") else null
}
@@ -1,57 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen5
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
import com.cobblemon.mod.common.entity.PoseType
import net.minecraft.client.model.ModelPart
import net.minecraft.util.math.Vec3d
class LitwickModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
override val rootPart = root.registerChildWithAllChildren("litwick")
override val head = getPart("head")
override val portraitScale = 2.0F
override val portraitTranslation = Vec3d(-0.3, -1.2, 0.0)
override val profileScale = 0.8F
override val profileTranslation = Vec3d(0.0, 0.5, 0.0)
lateinit var standing: PokemonPose
lateinit var walk: PokemonPose
override fun registerPoses() {
val blink = quirk("blink") { bedrockStateful("litwick", "blink").setPreventsIdle(false) }
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
quirks = arrayOf(blink),
idleAnimations = arrayOf(
bedrock("litwick", "idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES,
quirks = arrayOf(blink),
idleAnimations = arrayOf(
bedrock("litwick", "idle")
)
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PoseableEntityState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("litwick", "faint") else null
}
@@ -41,10 +41,9 @@ class TrevenantModel (root: ModelPart) : PokemonPoseableModel() {
poseType = PoseType.SLEEP,
idleAnimations = arrayOf(bedrock("trevenant", "sleep"))
)
standing = registerPose(
poseName = "stand",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
poseTypes = PoseType.STATIONARY_POSES - PoseType.HOVER - PoseType.FLOAT + PoseType.UI_POSES,
condition = { !it.isBattling },
transformTicks = 10,
quirks = arrayOf(blink),
@@ -54,7 +53,7 @@ class TrevenantModel (root: ModelPart) : PokemonPoseableModel() {
)
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES,
poseTypes = PoseType.MOVING_POSES - PoseType.FLY - PoseType.SWIM,
transformTicks = 5,
quirks = arrayOf(blink),
idleAnimations = arrayOf(
@@ -25,6 +25,7 @@ class KomalaModel (root: ModelPart) : PokemonPoseableModel() {
override val profileScale = 0.8F
override val profileTranslation = Vec3d(0.0, 0.5, 0.0)
lateinit var sleep: PokemonPose
lateinit var standing: PokemonPose
// override val cryAnimation = CryProvider { _, _ -> bedrockStateful("komala", "cry").setPreventsIdle(false) }
@@ -18,8 +18,8 @@ import net.minecraft.util.math.Vec3d
class WishiwashiSchoolingModel (root: ModelPart) : PokemonPoseableModel(){
override val rootPart = root.registerChildWithAllChildren("wishiwashi_school")
override val portraitScale = 0.5F
override val portraitTranslation = Vec3d(-0.4, 0.8, 0.0)
override val portraitScale = 0.55F
override val portraitTranslation = Vec3d(-1.21, 0.4, 0.0)
override val profileScale = 0.2F
override val profileTranslation = Vec3d(0.0, 1.0, 0.0)
@@ -40,7 +40,7 @@ class WishiwashiSchoolingModel (root: ModelPart) : PokemonPoseableModel(){
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STANDING_POSES - PoseType.FLOAT + PoseType.UI_POSES,
poseTypes = PoseType.STANDING_POSES - PoseType.FLOAT,
idleAnimations = arrayOf(
bedrock("wishiwashi_school", "water_idle")
),
@@ -62,7 +62,7 @@ class WishiwashiSchoolingModel (root: ModelPart) : PokemonPoseableModel(){
floating = registerPose(
poseName = "floating",
poseType = PoseType.FLOAT,
poseTypes = PoseType.UI_POSES + PoseType.FLOAT,
idleAnimations = arrayOf(
bedrock("wishiwashi_school", "water_idle")
)
@@ -62,5 +62,5 @@ class EiscueModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
override fun getFaintAnimation(
pokemonEntity: PokemonEntity,
state: PoseableEntityState<PokemonEntity>
) = bedrockStateful("eiscue_ice", "faint")
) = if (state.isPosedIn(standing, walk, sleep)) bedrockStateful("eiscue_ice", "faint") else null
}
Loaded 100 of 1501 files, more files were not shown because too many files have changed in this diff. Show more