Compare commits

...
Author SHA1 Message Date
Plastered_Crab 86d48df9fe Render Rotom drone camera to start orbiting around + try to avoid collisions using raycast point cloud 2025-02-28 16:59:03 -08:00
Flarkinater 3401ba9cbb Fix drone animation 2025-02-15 21:48:29 -05:00
Flarkinater dac9ccb461 Revert debug change 2025-02-15 21:47:59 -05:00
Flarkinater 191a62f693 Attempt to debug the animation issue 2025-02-15 16:50:52 -05:00
Flarkinater d8d410e539 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into stadium-block 2025-02-15 15:37:37 -05:00
Flarkinater b7c6e1ea77 Attempt to make the drone animated (WIP) 2025-02-15 15:35:48 -05:00
Hiroku 0af4588a14 README change [skip-ci] 2025-02-15 20:26:29 +00:00
Flarkinater 186812d6fd Refactor - move most drone assets into bedrock/drone 2025-02-14 12:23:27 -05:00
Polymeta df9dc8c029 Merge branch 'feat/capture-qol-feature-parity' into 'main'
Critical capture feature parity

See merge request cable-mc/cobblemon!1516
2025-02-14 16:35:16 +00:00
Ina 51dc606246 Critical capture feature parity 2025-02-14 16:35:15 +00:00
Polymeta 790f8347f8 Merge branch 'flying_shoulder_mons' into 'main'
Fix flying shoulder mons

See merge request cable-mc/cobblemon!1530
2025-02-13 14:55:01 +00:00
JPAK 09de901b35 Fix flying shoulder mons 2025-02-13 08:14:46 -06:00
Flarkinater 1c0bdc766a Fix upside-down drone 2025-02-12 14:55:41 -05:00
Flarkinater c697bcd2e9 Render the drone in-game 2025-02-12 01:17:42 -05:00
Polymeta dcf321da8f Merge branch 'pokemon-follow-mouse' into 'main'
Add functionality for Pokémon to follow the mouse cursor

Closes #282

See merge request cable-mc/cobblemon!1361
2025-02-11 13:46:48 +00:00
lion c32bd4d014 Add functionality for Pokémon to follow the mouse cursor 2025-02-11 13:46:47 +00:00
Polymeta ab4e2f2540 Merge branch 'test/shoulder_caching' into 'main'
Touch up shoulder rendering cache management

Closes #1367

See merge request cable-mc/cobblemon!1499
2025-02-11 11:37:21 +00:00
aeroeng15 741bfb3316 Touch up shoulder rendering cache management 2025-02-11 11:37:20 +00:00
Flarkinater 9d6ff01d80 Add Rotom drone model/texture/animation placeholders 2025-02-10 20:20:24 -05:00
Flarkinater 1691853a19 Remove placeholder model, we'll just use some "dev art" for now 2025-02-10 20:20:12 -05:00
Flarkinater 4e9a4e1e5a Update deprecated methods, imports, and formatting 2025-02-10 20:20:03 -05:00
Flarkinater 6450255a0b Rebase old stadium camera test branch 2025-02-10 20:19:13 -05:00
Polymeta ce5df762f6 Merge branch 'blacklisted-items-to-hold' into 'main'
Add 'blacklisted_items_to_hold' and 'whitelisted_items_to_hold' tags

Closes #914

See merge request cable-mc/cobblemon!1526
2025-02-10 22:27:35 +00:00
lion c5543cbd64 Add 'blacklisted_items_to_hold' and 'whitelisted_items_to_hold' tags 2025-02-10 22:27:35 +00:00
Polymeta 4929a4a567 Merge branch 'feature/evolution-crashes' into 'main'
small fixes to evolution S2C sync

Closes #1391

See merge request cable-mc/cobblemon!1519
2025-02-10 16:57:22 +00:00
Polymeta e4591825c3 Merge branch 'fix-fling-check-remaps' into 'main'
CobblemonHeldItemManager nameof function changes to account remaps

See merge request cable-mc/cobblemon!1524
2025-02-10 16:55:53 +00:00
Polymeta 6d847e4b7d Merge branch 'feature/packet-checkup' into 'main'
tidying up network packets

See merge request cable-mc/cobblemon!1515
2025-02-09 21:11:10 +00:00
Polymeta ac9d4f49d9 tidying up network packets 2025-02-09 21:11:10 +00:00
Polymeta 26e1145562 Merge branch 'replacing-fossil-anylizer-fix' into 'main'
Fixed Breaking and Replacing Fossil Analyzer crashing the game

See merge request cable-mc/cobblemon!1509
2025-02-09 20:21:10 +00:00
BuildTools 8417be3b89 Switched to using safecast instead 2025-02-09 11:43:18 +02:00
BuildTools 53a7282c31 Fix for HeldItemManager not accounting for remaps and such causing fling battlelog to not display correct name 2025-02-09 11:23:08 +02:00
Polymeta 6349f12d8e Merge branch 'feature/pc-additions' into 'main'
PC Search, Custom Box Names, Wallpapers, & Sorting

See merge request cable-mc/cobblemon!1304
2025-02-09 00:30:03 +00:00
JustAHuman-xD 052b01ff00 PC Search, Custom Box Names, Wallpapers, & Sorting 2025-02-09 00:30:03 +00:00
Polymeta 36f4e4fe1b Merge branch '1431-item-rarity-implementation' into 'main'
Updated rarities for various items. Wasn't able to update the Automaton Armor...

Closes #1431

See merge request cable-mc/cobblemon!1520
2025-02-08 23:50:29 +00:00
Josh 06fe7568a5 Updated rarities for various items. Wasn't able to update the Automaton Armor... 2025-02-08 23:50:28 +00:00
Paul dc03f26b20 Changelog [skip-ci] 2025-02-08 18:05:49 +10:00
Paul b30ad68975 Added /changejointscale for debugging joint scales (a surprise tool we'll use later) 2025-02-08 18:02:55 +10:00
Paul cc1f40a165 Added modelpart transformations to root posable models that stack with pose modelpart transformations 2025-02-07 09:41:40 +10:00
Polymeta c1ce5491f1 Ensure EVBerries make sound on consumption as intended
Closes #1390

Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-02-06 21:15:32 +00:00
Polymeta 588a5d4ce1 Ensure EV berries actually reduce the stat instead of raising it
Closes #1434

Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-02-05 21:13:47 +00:00
Polymeta 58bd15b3b2 Merge branch '1403-creative-tab-lang-changes' into 'main'
Added 'Cobblemon: ' to creative tabs for clarity.  Closes #1403

Closes #1403

See merge request cable-mc/cobblemon!1518
2025-02-05 00:23:44 +00:00
Josh 88769ec1f2 Added 'Cobblemon: ' to creative tabs for clarity. Closes #1403 2025-02-05 00:23:44 +00:00
Hiroku aa790d0511 Merge branch 'shared-model-repository' into 'main'
Refactored VaryingModelRepository to simplify and support NPCs using Pokémon models and anims etc

See merge request cable-mc/cobblemon!1507
2025-02-04 21:02:00 +00:00
Polymeta bd0b1bca3d pass HA prio along to ensure it's not being incorrectly set as forced
Closes #1401

Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-02-04 15:00:23 +00:00
Paul 2fa0204a20 Remove redundant comments 2025-02-04 20:34:21 +10:00
Polymeta d2d50a4c71 more consumption of held item back into its original place
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-02-04 00:44:14 +00:00
Polymeta e07a5ca019 fix evolutions both crashing clients and being sometimes forgotten by pokemon after passing requirements initially
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-02-04 00:20:37 +00:00
Polymeta 7bcd398438 whops missed a file to fix pipeline
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-02-03 14:29:02 +00:00
Polymeta 830d30e0de fix pipeline build
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-02-03 14:24:05 +00:00
Hiroku 21e279224d Merge branch 'fix/modern-item-conditions' into 'main'
Remove legacy NbtItemPredicate, replace with vanilla ItemCondition

See merge request cable-mc/cobblemon!1513
2025-02-03 03:25:45 +00:00
Ina 6b6d9d9ecf All my homies hate fandom 2025-02-01 22:07:12 +00:00
Ina 5f01e1a5d8 Remove legacy NbtItemPredicate, replace with vanilla ItemCondition 2025-02-01 15:47:44 +00:00
BuildTools c43e6aba4a Fixed Breaking and Replacing Fossil Analyzer crashing the game in a complete multi-structure 2025-01-31 19:27:55 +02:00
Paul 26ef75fba7 Teeny cleanup things 2025-01-31 14:06:36 +10:00
Paul dabc0ae859 Conflicto destructo 2025-01-31 14:01:22 +10:00
Paul 6184bd850e Merge branch 'main' into shared-model-repository
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/client/CobblemonClient.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/gui/PokemonGuiUtils.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/gui/npc/widgets/NPCRenderWidget.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/layer/PokemonOnShoulderRenderer.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/models/blockbench/repository/PokemonModelRepository.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/models/blockbench/repository/VaryingModelRepository.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/npc/NPCRenderer.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/pokemon/PokemonRenderer.kt
2025-01-31 11:43:47 +10:00
Paul 01d2bcdfcf Squashed all of the VaryingModelRepositories down into one, allowing NPCs to use Pokemon models etc 2024-09-28 17:25:52 +10:00
Paul 8d5e2f5773 Remove dead code from fossil model repo 2024-09-28 10:34:01 +10:00
Paul 73029800e4 Significantly cleaned handling of living entity renderer offsets 2024-09-28 10:33:12 +10:00
223 changed files with 4188 additions and 1543 deletions

No files matched your search

+16
View File
@@ -0,0 +1,16 @@
### Additions
- Added ability to rename PC Boxes by clicking on the name of a box
- Added ability to set wallpapers per PC Box by clicking the button right to the box name
- Added sorting by Name, Level and type by clicking the button left of the box name (shift reverses order)
- Added filtering/search functionality in PC UI, which also supports pokemon properties (e.g. shiny=yes shows all shinies)
- Added /changewallpaper <player> <boxNumber> <wallpaper> command to change a wallpaper through commands
- Added /renamebox <player> <boxNumber> <name> command to rename a PC box through commands
### Developer
- Added RenamePCBoxEvent.Pre/Post events to prevent players from renaming a box or change their input
- Added ChangePCBoxWallpaperEvent.Pre/Post to prevent players from changing to a wallpaper or change their selection
- Added WallpaperCollectionEvent which gets called when clients connect to a server, allowing the server which of the clients found wallpapers it's allowed to move (collected wallpapers can be removed for example to make it "vanish" client-side)
- Wallpapers are loaded from `assets/<namespace>/textures/gui/pc/wallpaper/` and all wallpapers in this folder are available to the client to choose by default
- Renamed `SetPCBoxPokemonPacket` and the respective handler to `SetPCBoxPacket`
+10
View File
@@ -0,0 +1,10 @@
### Additions
- Added support for NPCs to use Pokémon models and vice versa. This will require changes in addons that add fossil types due to naming conflicts between fossils and the Pokémon species.
- Added `/changejointscale` command to change the scale of a joint in a model. Unbelievably funny.
### Developer
- Removed all VaryingModelRepository subclasses into the parent class.
### Addons
- Added `transformedParts` to the root of poser JSONs so it now exists in both poses and the model overall.
+20 -2
View File
@@ -4,6 +4,8 @@
### Additions
- Added an in-game configuration screen, allowing all settings from `main.json` to be edited directly in-game.
- Added `/cobblemonconfig reload` command to reload `main.json` configuration. **Note:** Some settings require a server restart to take effect; use this command cautiously.
- Added `blacklisted_items_to_hold` and `whitelisted_items_to_hold` tags to allow for controlling which items players can give to their Pokémon. If the whitelist is empty, it will consider all item as allowed (unless they are in the blacklist).
- Pokémon now follow the mouse cursor on the Summary screen, with an option to disable this in the settings.
### Changes
- Renamed `chargeGainedPerTick` config to `secondsToChargeHealingMachine`.
@@ -11,6 +13,14 @@
### Fixes
- Fixed Particles sometimes facing the wrong direction (looking at you, Swords Dance)
- Fixed PCs always opening at box 2 instead of box 1.
- Fixed not being able to do complex item requirements aside from just NBT with evolution conditions, requirements and fossil items.
- Fixed the usage `hiddenability` in `pokegive` or other spawn commands resulting in a forced hidden ability
- Fixed the consumption of friendship berries (or EV berries) not making any noise
- Fixed Instantly breaking and replacing a fossil analyzer with any block entity crashing the game in a complete multi-structure
- Fixed players getting disconnected when sidemods update a Pokémon's teratype
- Fixed fling not using Item Names for minecraft held items that substitute Pokémon items
- Fixed evolutions sometimes preventing players from logging in to servers
- Fixed rendering of shoulder-mounted Pokémon desyncing between clients
### Developer
- A finished battle now has winners and losers set inside of `PokemonBattle` instead of them always being empty.
@@ -18,9 +28,17 @@
- Dialogues with variably-set initial pages now properly start timeout tracking.
- Added `EvGainedEvent.Pre` and `EvGainedEvent.Post`.
- Deprecated `EVs#add(Stat, Int)`, you will not be able to compile against this code please migrate to the `EVs#add(Stat, Int, EvSource)` you most likely want to use `SidemodEvSource` but please check other implementations or make your own.
- Removed the NbtItemPredicate class, all the mod usages now use the vanilla item predicate solution, this causes breaking changes on Fossil, HeldItemRequirement & ItemInteractionEvolution
- Renamed Cobblemon's creative tabs to start with "Cobblemon: " to distinguish Cobblemon's tabs from tabs for other mods.
- Various items now have a rarity value.
### Additions
- Added `/cobblemonconfig reload` command to reload `main.json` configuration. **Note:** Some settings require a server restart to take effect; use this command cautiously.
### Changes
- When using the `cobblemon` or `generation_9` capture calculators a critical capture with a single shake will always play for successful captures when you've already registered the Pokémon as caught in your Pokédex.
### MoLang & Datapacks
- The following usages for item predicates can now use item conditions like advancements do, you can learn about them in the [Minecraft wiki](https://minecraft.wiki/w/Advancement_definition#minecraft:filled_bucket)
- The `requiredContext` for an item interaction evolution
- The `itemCondition` for a held item evolution requirement
- The `fossils` for a fossil entry
## [1.6.1 (January 26th, 2025)](#1-6-1)
+1 -1
View File
@@ -1,6 +1,6 @@
# Cobblemon
An open-source Pokémon mod for Minecraft Java Edition, written in Kotlin for Fabric and Forge.
An open-source Pokémon mod for Minecraft Java Edition, written in Kotlin for Fabric and NeoForge.
## Getting started
@@ -100,6 +100,7 @@ import com.mongodb.client.MongoClients
import net.minecraft.client.Minecraft
import net.minecraft.commands.synchronization.SingletonArgumentInfo
import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType
import net.minecraft.world.item.NameTagItem
@@ -150,6 +151,7 @@ object Cobblemon {
var permissionValidator: PermissionValidator by Delegates.observable(LaxPermissionValidator().also { it.initialize() }) { _, _, newValue -> newValue.initialize() }
var statProvider: StatProvider = CobblemonStatProvider
var seasonResolver: SeasonResolver = TagSeasonResolver
var wallpapers = mapOf<UUID, List<ResourceLocation>>()
@JvmStatic
val builtinPacks = listOf<CobblemonPack>(
@@ -206,6 +208,7 @@ object Cobblemon {
storage.onPlayerDataSync(it)
playerDataManager.syncAllToPlayer(it)
starterHandler.handleJoin(it)
it.requestWallpapers()
sendServerSettingsPacketToPlayer(it)
}
PlatformEvents.SERVER_PLAYER_LOGOUT.subscribe {
@@ -36,6 +36,9 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
@JvmField
val PC: BlockEntityType<PCBlockEntity> = this.create("pc", BlockEntityType.Builder.of(::PCBlockEntity, CobblemonBlocks.PC).build(null))
@JvmField
val STADIUM: BlockEntityType<StadiumBlockEntity> = this.create("stadium_terminal", BlockEntityType.Builder.of(::StadiumBlockEntity, CobblemonBlocks.STADIUM).build(null))
@JvmField
val LECTERN: BlockEntityType<LecternBlockEntity> = this.create("lectern", BlockEntityType.Builder.of(::LecternBlockEntity, CobblemonBlocks.LECTERN).build(null))
@@ -354,6 +354,9 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
@JvmField
val PC = create("pc", PCBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F).noOcclusion().lightLevel { if ((it.getValue(PCBlock.ON) as Boolean) && (it.getValue(PCBlock.PART) == PCBlock.PCPart.TOP)) 10 else 0 }))
@JvmField
val STADIUM = create("stadium_terminal", StadiumBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F)))
@JvmField
val LECTERN = create("lectern", LecternBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).sound(SoundType.WOOD).strength(2.5F).ignitedByLava()))
@@ -23,6 +23,7 @@ object CobblemonCommands {
ChangeEyeHeight.register(dispatcher)
ChangeScaleAndSize.register(dispatcher)
ChangeWalkSpeed.register(dispatcher)
ChangeJointScaleCommand.register(dispatcher)
TestCommand.register(dispatcher)
ReloadShowdownCommand.register(dispatcher)
ClickTextCommand.register(dispatcher)
@@ -56,6 +57,8 @@ object CobblemonCommands {
AbandonMultiTeam.register(dispatcher)
FreezePokemonCommand.register(dispatcher)
ApplyPlayerTextureCommand.register(dispatcher)
RenameBoxCommand.register(dispatcher)
ChangeBoxWallpaperCommand.register(dispatcher)
RunMolangScriptCommand.register(dispatcher)
CobblemonConfigCommand.register(dispatcher)
@@ -35,7 +35,6 @@ 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.core.Registry
import net.minecraft.core.component.DataComponents
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.core.registries.Registries
import net.minecraft.network.chat.Component
@@ -269,10 +268,12 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val MONITOR = blockItem("monitor", CobblemonBlocks.MONITOR)
@JvmField
val HEALING_MACHINE = blockItem("healing_machine", CobblemonBlocks.HEALING_MACHINE)
val HEALING_MACHINE = blockItem("healing_machine", CobblemonBlocks.HEALING_MACHINE, Rarity.UNCOMMON)
@JvmField
val PC = blockItem("pc", CobblemonBlocks.PC)
@JvmField
val STADIUM = blockItem("stadium_terminal", CobblemonBlocks.STADIUM)
@JvmField
val PASTURE = blockItem("pasture", CobblemonBlocks.PASTURE)
@JvmField
val DISPLAY_CASE = blockItem("display_case", CobblemonBlocks.DISPLAY_CASE)
@@ -398,7 +399,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
// Medicine
@JvmField
val RARE_CANDY = candyItem("rare_candy") { _, pokemon -> pokemon.getExperienceToNextLevel() }
val RARE_CANDY = candyItem("rare_candy", Rarity.RARE) { _, pokemon -> pokemon.getExperienceToNextLevel() }
@JvmField
val EXPERIENCE_CANDY_XS = candyItem("exp_candy_xs") { _, _ -> CandyItem.DEFAULT_XS_CANDY_YIELD }
@JvmField
@@ -883,48 +884,48 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
// Archaeology
@JvmField
val ARMOR_FOSSIL = noSettingsItem("armor_fossil")
val ARMOR_FOSSIL = itemWithRarity("armor_fossil", Rarity.UNCOMMON)
@JvmField
val FOSSILIZED_BIRD = noSettingsItem("fossilized_bird")
val FOSSILIZED_BIRD = itemWithRarity("fossilized_bird", Rarity.UNCOMMON)
@JvmField
val CLAW_FOSSIL = noSettingsItem("claw_fossil")
val CLAW_FOSSIL = itemWithRarity("claw_fossil", Rarity.UNCOMMON)
@JvmField
val COVER_FOSSIL = noSettingsItem("cover_fossil")
val COVER_FOSSIL = itemWithRarity("cover_fossil", Rarity.UNCOMMON)
@JvmField
val FOSSILIZED_DINO = noSettingsItem("fossilized_dino")
val FOSSILIZED_DINO = itemWithRarity("fossilized_dino", Rarity.UNCOMMON)
@JvmField
val DOME_FOSSIL = noSettingsItem("dome_fossil")
val DOME_FOSSIL = itemWithRarity("dome_fossil", Rarity.UNCOMMON)
@JvmField
val FOSSILIZED_DRAKE = noSettingsItem("fossilized_drake")
val FOSSILIZED_DRAKE = itemWithRarity("fossilized_drake", Rarity.UNCOMMON)
@JvmField
val FOSSILIZED_FISH = noSettingsItem("fossilized_fish")
val FOSSILIZED_FISH = itemWithRarity("fossilized_fish", Rarity.UNCOMMON)
@JvmField
val HELIX_FOSSIL = noSettingsItem("helix_fossil")
val HELIX_FOSSIL = itemWithRarity("helix_fossil", Rarity.UNCOMMON)
@JvmField
val JAW_FOSSIL = noSettingsItem("jaw_fossil")
val JAW_FOSSIL = itemWithRarity("jaw_fossil", Rarity.UNCOMMON)
@JvmField
val OLD_AMBER_FOSSIL = noSettingsItem("old_amber_fossil")
val OLD_AMBER_FOSSIL = itemWithRarity("old_amber_fossil", Rarity.UNCOMMON)
@JvmField
val PLUME_FOSSIL = noSettingsItem("plume_fossil")
val PLUME_FOSSIL = itemWithRarity("plume_fossil", Rarity.UNCOMMON)
@JvmField
val ROOT_FOSSIL = noSettingsItem("root_fossil")
val ROOT_FOSSIL = itemWithRarity("root_fossil", Rarity.UNCOMMON)
@JvmField
val SAIL_FOSSIL = noSettingsItem("sail_fossil")
val SAIL_FOSSIL = itemWithRarity("sail_fossil", Rarity.UNCOMMON)
@JvmField
val SKULL_FOSSIL = noSettingsItem("skull_fossil")
val SKULL_FOSSIL = itemWithRarity("skull_fossil", Rarity.UNCOMMON)
@JvmField
val BYGONE_SHERD = noSettingsItem("bygone_sherd")
val BYGONE_SHERD = itemWithRarity("bygone_sherd", Rarity.UNCOMMON)
@JvmField
val CAPTURE_SHERD = noSettingsItem("capture_sherd")
val CAPTURE_SHERD = itemWithRarity("capture_sherd",Rarity.UNCOMMON)
@JvmField
val DOME_SHERD = noSettingsItem("dome_sherd")
val DOME_SHERD = itemWithRarity("dome_sherd", Rarity.UNCOMMON)
@JvmField
val HELIX_SHERD = noSettingsItem("helix_sherd")
val HELIX_SHERD = itemWithRarity("helix_sherd", Rarity.UNCOMMON)
@JvmField
val NOSTALGIC_SHERD = noSettingsItem("nostalgic_sherd")
val NOSTALGIC_SHERD = itemWithRarity("nostalgic_sherd",Rarity.UNCOMMON)
@JvmField
val SUSPICIOUS_SHERD = noSettingsItem("suspicious_sherd")
val SUSPICIOUS_SHERD = itemWithRarity("suspicious_sherd", Rarity.UNCOMMON)
@JvmField
val TUMBLESTONE = this.create("tumblestone", TumblestoneItem(Item.Properties(), CobblemonBlocks.SMALL_BUDDING_TUMBLESTONE))
@@ -1144,11 +1145,11 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val DREAM_ROD = pokerodItem(cobblemonResource("dream_rod"))
@JvmField
val BEAST_ROD = pokerodItem(cobblemonResource("beast_rod"))
val BEAST_ROD = pokerodItem(cobblemonResource("beast_rod"), Rarity.RARE)
@JvmField
val MASTER_ROD = pokerodItem(cobblemonResource("master_rod"))
val MASTER_ROD = pokerodItem(cobblemonResource("master_rod"), Rarity.EPIC)
@JvmField
val CHERISH_ROD = pokerodItem(cobblemonResource("cherish_rod"))
val CHERISH_ROD = pokerodItem(cobblemonResource("cherish_rod"), Rarity.EPIC)
@JvmField
val ANCIENT_POKE_ROD = pokerodItem(cobblemonResource("ancient_poke_rod"))
@JvmField
@@ -1180,7 +1181,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val ANCIENT_GIGATON_ROD = pokerodItem(cobblemonResource("ancient_gigaton_rod"))
@JvmField
val ANCIENT_ORIGIN_ROD = pokerodItem(cobblemonResource("ancient_origin_rod"))
val ANCIENT_ORIGIN_ROD = pokerodItem(cobblemonResource("ancient_origin_rod"), Rarity.EPIC)
// Misc
@JvmField
@@ -1232,10 +1233,12 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
//@JvmField
//val BINDING_SOIL = blockItem("binding_soil", CobblemonBlocks.BINDING_SOIL)
private fun blockItem(name: String, block: Block): BlockItem = this.create(name, BlockItem(block, Item.Properties()))
private fun blockItem(name: String, block: Block, rarity: Rarity = Rarity.COMMON): BlockItem = this.create(name, BlockItem(block, Item.Properties().rarity(rarity)))
private fun noSettingsItem(name: String): CobblemonItem = this.create(name, CobblemonItem(Item.Properties()))
private fun itemWithRarity(name: String, rarity: Rarity): CobblemonItem = this.create(name, CobblemonItem(Item.Properties().rarity(rarity)))
fun berries() = this.berries.toMap()
private fun mulchItem(name: String, mulchVariant: MulchVariant): MulchItem = this.create(name, MulchItem(mulchVariant))
@@ -1247,10 +1250,10 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
return item
}
private fun candyItem(name: String, calculator: CandyItem.Calculator): CandyItem = this.create(name, CandyItem(calculator))
private fun candyItem(name: String, rarity: Rarity = Rarity.COMMON, calculator: CandyItem.Calculator): CandyItem = this.create(name, CandyItem(rarity, calculator))
private fun pokerodItem(pokeRodId: ResourceLocation): PokerodItem {
val settings = Item.Properties().stacksTo(1).durability(256)
private fun pokerodItem(pokeRodId: ResourceLocation, rarity: Rarity = Rarity.COMMON): PokerodItem {
val settings = Item.Properties().stacksTo(1).durability(256).rarity(rarity)
val item = create(pokeRodId.path, PokerodItem(pokeRodId, settings))
pokeRods.add(item)
return item
@@ -45,12 +45,7 @@ import com.cobblemon.mod.common.client.net.storage.party.InitializePartyHandler
import com.cobblemon.mod.common.client.net.storage.party.MoveClientPartyPokemonHandler
import com.cobblemon.mod.common.client.net.storage.party.SetPartyPokemonHandler
import com.cobblemon.mod.common.client.net.storage.party.SetPartyReferenceHandler
import com.cobblemon.mod.common.client.net.storage.pc.ClosePCHandler
import com.cobblemon.mod.common.client.net.storage.pc.InitializePCHandler
import com.cobblemon.mod.common.client.net.storage.pc.MoveClientPCPokemonHandler
import com.cobblemon.mod.common.client.net.storage.pc.OpenPCHandler
import com.cobblemon.mod.common.client.net.storage.pc.SetPCBoxPokemonHandler
import com.cobblemon.mod.common.client.net.storage.pc.SetPCPokemonHandler
import com.cobblemon.mod.common.client.net.storage.pc.*
import com.cobblemon.mod.common.client.net.toast.ToastPacketHandler
import com.cobblemon.mod.common.client.net.trade.*
import com.cobblemon.mod.common.net.PacketRegisterInfo
@@ -67,9 +62,6 @@ import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueOpenedPacke
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
import com.cobblemon.mod.common.net.messages.client.fishing.FishingBaitRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.fossil.FossilRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.fossil.NaturalMaterialRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.npc.CloseNPCEditorPacket
import com.cobblemon.mod.common.net.messages.client.npc.OpenNPCEditorPacket
import com.cobblemon.mod.common.net.messages.client.pasture.ClosePasturePacket
@@ -96,6 +88,9 @@ import com.cobblemon.mod.common.net.messages.client.storage.party.MoveClientPart
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyReferencePacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.*
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.ChangePCBoxWallpaperPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.RequestPCBoxWallpapersPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.SetPCBoxWallpapersPacket
import com.cobblemon.mod.common.net.messages.client.toast.ToastPacket
import com.cobblemon.mod.common.net.messages.client.trade.*
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
@@ -129,7 +124,11 @@ import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokem
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePCPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePCPokemonToPartyPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePartyPokemonToPCPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.PCBoxWallpapersPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.ReleasePCPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.RequestChangePCBoxWallpaperPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.RequestRenamePCBoxPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.SortPCBoxPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.SwapPCPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.UnlinkPlayerFromPCPacket
import com.cobblemon.mod.common.net.messages.server.trade.*
@@ -162,12 +161,7 @@ import com.cobblemon.mod.common.net.serverhandling.storage.SwapPCPartyPokemonHan
import com.cobblemon.mod.common.net.serverhandling.storage.party.MovePartyPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.party.ReleasePCPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.party.SwapPartyPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.pc.MovePCPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.pc.MovePCPokemonToPartyHandler
import com.cobblemon.mod.common.net.serverhandling.storage.pc.MovePartyPokemonToPCHandler
import com.cobblemon.mod.common.net.serverhandling.storage.pc.ReleasePartyPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.pc.SwapPCPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.pc.UnlinkPlayerFromPCHandler
import com.cobblemon.mod.common.net.serverhandling.storage.pc.*
import com.cobblemon.mod.common.net.serverhandling.trade.*
import com.cobblemon.mod.common.util.server
import net.minecraft.server.level.ServerPlayer
@@ -223,6 +217,9 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(SpeciesFeatureUpdatePacket.ID, SpeciesFeatureUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(OriginalTrainerUpdatePacket.ID, OriginalTrainerUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(FormUpdatePacket.ID, FormUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(TeraTypeUpdatePacket.ID, TeraTypeUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(DmaxLevelUpdatePacket.ID, DmaxLevelUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(GmaxFactorUpdatePacket.ID, GmaxFactorUpdatePacket::decode, PokemonUpdatePacketHandler()))
// Evolution start
list.add(PacketRegisterInfo(AddEvolutionPacket.ID, AddEvolutionPacket::decode, PokemonUpdatePacketHandler()))
@@ -237,13 +234,18 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(SetPartyReferencePacket.ID, SetPartyReferencePacket::decode, SetPartyReferenceHandler))
list.add(PacketRegisterInfo(InitializePCPacket.ID, InitializePCPacket::decode, InitializePCHandler))
list.add(PacketRegisterInfo(MoveClientPCPokemonPacket.ID, MoveClientPCPokemonPacket::decode, MoveClientPCPokemonHandler))
list.add(PacketRegisterInfo(SetPCBoxPokemonPacket.ID, SetPCBoxPokemonPacket::decode, SetPCBoxPokemonHandler))
list.add(PacketRegisterInfo(SetPCBoxPacket.ID, SetPCBoxPacket::decode, SetPCBoxHandler))
list.add(PacketRegisterInfo(SetPCPokemonPacket.ID, SetPCPokemonPacket::decode, SetPCPokemonHandler))
list.add(PacketRegisterInfo(OpenPCPacket.ID, OpenPCPacket::decode, OpenPCHandler))
list.add(PacketRegisterInfo(ClosePCPacket.ID, ClosePCPacket::decode, ClosePCHandler))
list.add(PacketRegisterInfo(SwapClientPokemonPacket.ID, SwapClientPokemonPacket::decode, SwapClientPokemonHandler))
list.add(PacketRegisterInfo(RemoveClientPokemonPacket.ID, RemoveClientPokemonPacket::decode, RemoveClientPokemonHandler))
list.add(PacketRegisterInfo(RenamePCBoxPacket.ID, RenamePCBoxPacket::decode, RenamePCBoxHandler))
list.add(PacketRegisterInfo(RequestPCBoxWallpapersPacket.ID, RequestPCBoxWallpapersPacket::decode, RequestPCBoxWallpapersHandler))
list.add(PacketRegisterInfo(SetPCBoxWallpapersPacket.ID, SetPCBoxWallpapersPacket::decode, SetPCBoxWallpapersHandler))
list.add(PacketRegisterInfo(ChangePCBoxWallpaperPacket.ID, ChangePCBoxWallpaperPacket::decode, ChangePCBoxWallpaperHandler))
// UI Packets
list.add(PacketRegisterInfo(SummaryUIPacket.ID, SummaryUIPacket::decode, SummaryUIPacketHandler))
list.add(PacketRegisterInfo(InteractPokemonUIPacket.ID, InteractPokemonUIPacket::decode, InteractPokemonUIPacketHandler))
@@ -281,6 +283,7 @@ object CobblemonNetwork {
// MultiBattleTeam Packets
list.add(PacketRegisterInfo(TeamRequestNotificationPacket.ID, TeamRequestNotificationPacket::decode, TeamRequestNotificationHandler))
list.add(PacketRegisterInfo(TeamRequestExpiredPacket.ID, TeamRequestExpiredPacket::decode, TeamRequestExpiredHandler))
list.add(PacketRegisterInfo(TeamMemberAddNotificationPacket.ID, TeamMemberAddNotificationPacket::decode, TeamMemberAddNotificationHandler))
list.add(PacketRegisterInfo(TeamMemberRemoveNotificationPacket.ID, TeamMemberRemoveNotificationPacket::decode, TeamMemberRemoveNotificationHandler))
list.add(PacketRegisterInfo(TeamJoinNotificationPacket.ID, TeamJoinNotificationPacket::decode, TeamJoinNotificationHandler))
@@ -390,6 +393,10 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(ReleasePCPokemonPacket.ID, ReleasePCPokemonPacket::decode, ReleasePCPokemonHandler))
list.add(PacketRegisterInfo(UnlinkPlayerFromPCPacket.ID, UnlinkPlayerFromPCPacket::decode, UnlinkPlayerFromPCHandler))
list.add(PacketRegisterInfo(RequestRenamePCBoxPacket.Companion.ID, RequestRenamePCBoxPacket.Companion::decode, RequestRenamePCBoxHandler))
list.add(PacketRegisterInfo(PCBoxWallpapersPacket.ID, PCBoxWallpapersPacket::decode, PCBoxWallpapersHandler))
list.add(PacketRegisterInfo(RequestChangePCBoxWallpaperPacket.ID, RequestChangePCBoxWallpaperPacket::decode, RequestChangePCBoxWallpaperHandler))
// Starter packets
list.add(PacketRegisterInfo(SelectStarterPacket.ID, SelectStarterPacket::decode, SelectStarterPacketHandler))
list.add(PacketRegisterInfo(RequestStarterScreenPacket.ID, RequestStarterScreenPacket::decode, RequestStarterScreenHandler))
@@ -402,6 +409,8 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(SwapPCPartyPokemonPacket.ID, SwapPCPartyPokemonPacket::decode, SwapPCPartyPokemonHandler))
list.add(PacketRegisterInfo(SortPCBoxPacket.ID, SortPCBoxPacket::decode, SortPCBoxHandler))
// Battle packets
list.add(PacketRegisterInfo(BattleSelectActionsPacket.ID, BattleSelectActionsPacket::decode, BattleSelectActionsHandler))
list.add(PacketRegisterInfo(SpectateBattlePacket.ID, SpectateBattlePacket::decode, SpectateBattleHandler))
@@ -42,7 +42,10 @@ import com.cobblemon.mod.common.api.events.pokemon.healing.PokemonHealedEvent
import com.cobblemon.mod.common.api.events.pokemon.interaction.ExperienceCandyUseEvent
import com.cobblemon.mod.common.api.events.pokemon.interaction.PokemonInteractionGUICreationEvent
import com.cobblemon.mod.common.api.events.starter.StarterChosenEvent
import com.cobblemon.mod.common.api.events.storage.ChangePCBoxWallpaperEvent
import com.cobblemon.mod.common.api.events.storage.ReleasePokemonEvent
import com.cobblemon.mod.common.api.events.storage.RenamePCBoxEvent
import com.cobblemon.mod.common.api.events.storage.WallpaperCollectionEvent
import com.cobblemon.mod.common.api.events.world.BigRootPropagatedEvent
import com.cobblemon.mod.common.api.reactive.CancelableObservable
import com.cobblemon.mod.common.api.reactive.EventObservable
@@ -168,6 +171,19 @@ object CobblemonEvents {
@JvmField
val POKEMON_RELEASED_EVENT_POST = EventObservable<ReleasePokemonEvent.Post>()
@JvmField
val RENAME_PC_BOX_EVENT_PRE = CancelableObservable<RenamePCBoxEvent.Pre>()
@JvmField
val RENAME_PC_BOX_EVENT_POST = EventObservable<RenamePCBoxEvent.Post>()
@JvmField
val WALLPAPER_COLLECTION_EVENT = EventObservable<WallpaperCollectionEvent>()
@JvmField
val CHANGE_PC_BOX_WALLPAPER_EVENT_PRE = CancelableObservable<ChangePCBoxWallpaperEvent.Pre>()
@JvmField
val CHANGE_PC_BOX_WALLPAPER_EVENT_POST = EventObservable<ChangePCBoxWallpaperEvent.Post>()
@JvmField
val LOOT_DROPPED = CancelableObservable<LootDroppedEvent>()
@JvmField
@@ -1,8 +1,17 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.pokemon
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.pokemon.stats.EvSource
import com.cobblemon.mod.common.api.pokemon.stats.Stat
import com.cobblemon.mod.common.pokemon.Pokemon
/**
* Fired during EV mutation.
@@ -17,6 +26,11 @@ interface EvGainedEvent {
*/
val stat: Stat
/**
* @see EvSource.pokemon
*/
val pokemon: Pokemon get() = this.source.pokemon
/**
* The [EvSource] that fired this event.
*/
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.storage
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.storage.pc.PCBox
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
/**
* Events fired whenever a player changes their PC Wallpaper.
* Has a cancelable [Pre] event and a [Post] which gets fired after the change.
*
* @author JustAHuman-xD
* @since February 14th, 2025
*/
interface ChangePCBoxWallpaperEvent {
/**
* The [ServerPlayer] who is changing their wallpaper
*/
val player: ServerPlayer
/**
* The [PCBox] whose wallpaper is being changed
*/
val box: PCBox
/**
* The location of the wallpaper that is being changed to. Can be modified in the [Pre] event.
* NOTE: Changing this to a wallpaper that does not exist on the client, will result in a purple/black fallback texture being displayed.
*/
val wallpaper: ResourceLocation
class Pre(
override val player: ServerPlayer,
override val box: PCBox,
override var wallpaper: ResourceLocation
) : ChangePCBoxWallpaperEvent, Cancelable()
class Post(
override val player: ServerPlayer,
override val box: PCBox,
override val wallpaper: ResourceLocation
) : ChangePCBoxWallpaperEvent
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.storage
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.storage.pc.PCBox
import net.minecraft.server.level.ServerPlayer
/**
* Events fired whenever a player renames one of their PC boxes.
* Has a cancelable [Pre] event and a [Post] which gets fired after the change.
*
* @author JustAHuman-xD
* @since February 14th, 2025
*/
interface RenamePCBoxEvent {
/**
* The [ServerPlayer] who is changing their wallpaper
*/
val player: ServerPlayer
/**
* The [PCBox] whose wallpaper is being changed
*/
val box: PCBox
/**
* The new box name being used. This can be modified in the [Pre] event.
*/
val name: String
class Pre(
override val player: ServerPlayer,
override val box: PCBox,
override var name: String
) : RenamePCBoxEvent, Cancelable()
class Post(
override val player: ServerPlayer,
override val box: PCBox,
override val name: String
) : RenamePCBoxEvent
}
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.storage
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
/**
* Event being fired whenever the client connects to a server and "requests" what wallpapers are available for it to choose from.
* Mods can listen to this event and remove available options from the client when they connect, essentially causing them to not exist client-side
*
* NOTE: Adding wallpapers here that do not exist on the client, will result in the purple/black fallback texture being displayed client-side.
*
* @author JustAHuman-xD
* @since February 14th, 2025
*/
data class WallpaperCollectionEvent(
val player: ServerPlayer,
val wallpapers: MutableList<ResourceLocation>
)
@@ -11,7 +11,7 @@ package com.cobblemon.mod.common.api.fishing
import com.cobblemon.mod.common.CobblemonItemComponents
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.net.messages.client.fishing.FishingBaitRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.FishingBaitRegistrySyncPacket
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.Gson
@@ -9,7 +9,7 @@
package com.cobblemon.mod.common.api.fossil
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.pokemon.evolution.predicate.NbtItemPredicate
import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.MutableComponent
import net.minecraft.resources.ResourceLocation
@@ -19,7 +19,7 @@ import net.minecraft.world.item.ItemStack
class Fossil(
identifier: ResourceLocation,
val result: PokemonProperties,
val fossils: List<NbtItemPredicate>
val fossils: List<ItemPredicate>
): StringRepresentable {
@Transient
@@ -13,15 +13,15 @@ import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.net.messages.client.fossil.FossilRegistrySyncPacket
import com.cobblemon.mod.common.pokemon.evolution.adapters.NbtItemPredicateAdapter
import com.cobblemon.mod.common.pokemon.evolution.predicate.NbtItemPredicate
import com.cobblemon.mod.common.net.messages.client.data.FossilRegistrySyncPacket
import com.cobblemon.mod.common.pokemon.evolution.adapters.LegacyItemConditionWrapperAdapter
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.adapters.ItemLikeConditionAdapter
import com.cobblemon.mod.common.util.adapters.pokemonPropertiesShortAdapter
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType
@@ -40,7 +40,7 @@ object Fossils: JsonDataRegistry<Fossil> {
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
.registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
.registerTypeAdapter(NbtItemPredicate::class.java, NbtItemPredicateAdapter)
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter)
.create()
override val typeToken: TypeToken<Fossil> = TypeToken.get(Fossil::class.java)
@@ -10,7 +10,7 @@ package com.cobblemon.mod.common.api.fossil
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.net.messages.client.fossil.NaturalMaterialRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.NaturalMaterialRegistrySyncPacket
import com.cobblemon.mod.common.registry.ItemTagCondition
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.adapters.ItemLikeConditionAdapter
@@ -12,12 +12,10 @@ import com.cobblemon.mod.common.api.text.font
import com.cobblemon.mod.common.client.gui.battle.BattleOverlay.Companion.PORTRAIT_DIAMETER
import com.cobblemon.mod.common.client.render.SpriteType
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.util.toHex
import com.mojang.authlib.minecraft.client.MinecraftClient
import com.mojang.blaze3d.platform.GlStateManager
import com.mojang.blaze3d.platform.Lighting
import com.mojang.blaze3d.systems.RenderSystem
@@ -209,7 +207,6 @@ fun drawPosablePortrait(
contextScale: Float = 1F,
reversed: Boolean = false,
state: PosableState,
repository: VaryingModelRepository<*>,
partialTicks: Float,
limbSwing: Float = 0F,
limbSwingAmount: Float = 0F,
@@ -227,16 +224,16 @@ fun drawPosablePortrait(
matrixStack.scale(scale, scale, -scale)
matrixStack.translate(0.0, -PORTRAIT_DIAMETER / 18.0, 0.0)
val sprite = repository.getSprite(identifier, state, SpriteType.PORTRAIT);
val sprite = VaryingModelRepository.getSprite(identifier, state, SpriteType.PORTRAIT);
if (sprite == null) {
val model = repository.getPoser(identifier, state)
val model = VaryingModelRepository.getPoser(identifier, state)
state.currentModel = model
val texture = repository.getTexture(identifier, state)
val texture = VaryingModelRepository.getTexture(identifier, state)
val context = RenderContext()
model.context = context
repository.getTextureNoSubstitute(identifier, state).let { context.put(RenderContext.TEXTURE, it) }
VaryingModelRepository.getTextureNoSubstitute(identifier, state).let { context.put(RenderContext.TEXTURE, it) }
context.put(RenderContext.SCALE, contextScale)
context.put(RenderContext.SPECIES, identifier)
context.put(RenderContext.ASPECTS, state.currentAspects)
@@ -255,7 +252,7 @@ fun drawPosablePortrait(
matrixStack.translate(
model.portraitTranslation.x * if (reversed) -1F else 1F,
model.portraitTranslation.y,
model.portraitTranslation.y + 1.5 * model.portraitScale,
model.portraitTranslation.z - 4
)
matrixStack.scale(model.portraitScale, model.portraitScale, 1 / model.portraitScale)
@@ -272,7 +269,7 @@ fun drawPosablePortrait(
val packedLight = LightTexture.pack(11, 7)
val colour = toHex(r, g, b, a)
model.withLayerContext(immediate, state, repository.getLayers(identifier, state)) {
model.withLayerContext(immediate, state, VaryingModelRepository.getLayers(identifier, state)) {
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, colour)
immediate.endBatch()
}
@@ -288,7 +285,6 @@ fun drawPosablePortrait(
}
fun drawProfile(
repository: VaryingModelRepository<*>,
resourceIdentifier: ResourceLocation,
matrixStack: PoseStack,
state: PosableState,
@@ -298,16 +294,16 @@ fun drawProfile(
RenderSystem.applyModelViewMatrix()
matrixStack.scale(scale, scale, -scale)
val sprite = repository.getSprite(resourceIdentifier, state, SpriteType.PROFILE)
val sprite = VaryingModelRepository.getSprite(resourceIdentifier, state, SpriteType.PROFILE)
if (sprite == null) {
val model = repository.getPoser(resourceIdentifier, state)
val texture = repository.getTexture(resourceIdentifier, state)
val model = VaryingModelRepository.getPoser(resourceIdentifier, state)
val texture = VaryingModelRepository.getTexture(resourceIdentifier, state)
val context = RenderContext()
model.context = context
repository.getTextureNoSubstitute(resourceIdentifier, state).let { context.put(RenderContext.TEXTURE, it) }
VaryingModelRepository.getTextureNoSubstitute(resourceIdentifier, state).let { context.put(RenderContext.TEXTURE, it) }
context.put(RenderContext.SCALE, 1F)
context.put(RenderContext.SPECIES, resourceIdentifier)
context.put(RenderContext.ASPECTS, state.currentAspects)
@@ -319,7 +315,11 @@ fun drawProfile(
state.setPoseToFirstSuitable(PoseType.PORTRAIT)
state.updatePartialTicks(partialTicks)
model.applyAnimations(null, state, 0F, 0F, 0F, 0F, 0F)
matrixStack.translate(model.profileTranslation.x, model.profileTranslation.y, model.profileTranslation.z - 4.0)
matrixStack.translate(
model.profileTranslation.x,
model.profileTranslation.y + 1.5 * model.profileScale,
model.profileTranslation.z - 4.0
)
matrixStack.scale(model.profileScale, model.profileScale, 1 / model.profileScale)
// matrixStack.multiply(rotation)
val quaternion1 = Axis.YP.rotationDegrees(-32F * if (false) -1F else 1F)
@@ -337,7 +337,7 @@ fun drawProfile(
RenderSystem.setShaderLights(light1, light2)
val packedLight = LightTexture.pack(11, 7)
model.withLayerContext(bufferSource, state, repository.getLayers(resourceIdentifier, state)) {
model.withLayerContext(bufferSource, state, VaryingModelRepository.getLayers(resourceIdentifier, state)) {
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
bufferSource.endBatch()
}
@@ -16,6 +16,7 @@ object CobblemonPermissions {
val CHANGE_EYE_HEIGHT = this.create("${COMMAND_PREFIX}changeeyeheight", PermissionLevel.ALL_COMMANDS)
val CHANGE_SCALE_AND_SIZE = this.create("${COMMAND_PREFIX}changescaleandsize", PermissionLevel.ALL_COMMANDS)
val CHANGE_WALK_SPEED = this.create("${COMMAND_PREFIX}changewalkspeed", PermissionLevel.ALL_COMMANDS)
val CHANGE_JOINT_SCALE = this.create("${COMMAND_PREFIX}changejointscale", PermissionLevel.ALL_COMMANDS)
val CHECKSPAWNS = this.create("${COMMAND_PREFIX}checkspawns", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
val GET_NBT = this.create("${COMMAND_PREFIX}getnbt", PermissionLevel.ALL_COMMANDS)
@@ -62,6 +63,9 @@ object CobblemonPermissions {
val POKEBOX = this.create("${COMMAND_PREFIX}pokebox", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
val RENAMEBOX = this.create("${COMMAND_PREFIX}renamebox", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
val CHANGE_WALLPAPER = this.create("${COMMAND_PREFIX}changewallpaper", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
val TEST_STORE = this.create("${COMMAND_PREFIX}teststore", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
val QUERY_LEARNSET = this.create("${COMMAND_PREFIX}querylearnset", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
@@ -0,0 +1,53 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokeball.catching.calculators
import com.cobblemon.mod.common.api.pokeball.catching.CaptureContext
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.pokedex
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.LivingEntity
/**
* An influencer on capture results based on Pokedex data.
*/
interface PokedexStatusCaptureInfluencer {
/**
* Attempts to influence the [context] of a capture.
*
* @param thrower The [LivingEntity] that threw the Pokeball
* @param target The [PokemonEntity] attempting to capture.
* @param context The calculated [CaptureContext].
* @return The final [CaptureContext].
*/
fun influence(thrower: LivingEntity, target: PokemonEntity, context: CaptureContext): CaptureContext {
if (!context.isSuccessfulCapture) {
return context
}
val player = thrower as? ServerPlayer ?: return context
val pokedex = player.pokedex()
val speciesId = target.pokemon.species.resourceIdentifier
val formName = target.pokemon.form.name
val hasCaughtStatus = pokedex.getOrCreateSpeciesRecord(speciesId)
.getOrCreateFormRecord(formName)
.knowledge == PokedexEntryProgress.CAUGHT
// In modern games when the catch is a success and the Pokémon has already been registered to the Pokédex
// the catch becomes a critical capture and only requires one shake
return if (hasCaughtStatus) {
CaptureContext(
numberOfShakes = 1,
isSuccessfulCapture = true,
isCriticalCapture = true
)
} else context
}
}
@@ -0,0 +1,22 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokemon
import com.cobblemon.mod.common.pokemon.Pokemon
enum class PokemonSortMode(val comparator: Comparator<Pokemon?>, val reverseComparator: Comparator<Pokemon?>) {
NAME( { it?.getDisplayName()?.string } ),
LEVEL( { it?.level } ),
TYPE( { it?.primaryType?.name } );
constructor(mapper: (Pokemon?) -> Comparable<*>?) : this(compareBy({ it == null }, mapper),
compareBy<Pokemon?> { it == null }.thenComparing(compareBy(mapper).reversed()))
fun comparator(descending: Boolean) = if (descending) reverseComparator else comparator
}
@@ -42,8 +42,7 @@ import com.cobblemon.mod.common.pokemon.SpeciesAdditions
import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonEvolutionAdapter
import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonPreEvolutionAdapter
import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonRequirementAdapter
import com.cobblemon.mod.common.pokemon.evolution.adapters.NbtItemPredicateAdapter
import com.cobblemon.mod.common.pokemon.evolution.predicate.NbtItemPredicate
import com.cobblemon.mod.common.pokemon.evolution.adapters.LegacyItemConditionWrapperAdapter
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
import com.cobblemon.mod.common.util.adapters.*
import com.cobblemon.mod.common.util.cobblemonResource
@@ -51,6 +50,7 @@ import com.google.common.collect.HashBasedTable
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.nbt.CompoundTag
import net.minecraft.resources.ResourceLocation
@@ -99,7 +99,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Structure::class.java).type, StructureLikeConditionAdapter)
.registerTypeAdapter(EggGroup::class.java, EggGroupAdapter)
.registerTypeAdapter(MobEffect::class.java, RegistryElementAdapter<MobEffect>(BuiltInRegistries::MOB_EFFECT))
.registerTypeAdapter(NbtItemPredicate::class.java, NbtItemPredicateAdapter)
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter)
.disableHtmlEscaping()
.enableComplexMapKeySerialization()
.create()
@@ -105,6 +105,9 @@ interface Evolution : EvolutionLike {
* @param pokemon The [Pokemon] being evolved.
*/
fun evolve(pokemon: Pokemon): Boolean {
if (this.consumeHeldItem) {
pokemon.swapHeldItem(ItemStack.EMPTY)
}
if (this.optional) {
// All the networking is handled under the hood, see EvolutionController.
return pokemon.evolutionProxy.server().add(this)
@@ -220,10 +223,6 @@ interface Evolution : EvolutionLike {
this.shed(pokemon)
if (this.consumeHeldItem) {
pokemon.swapHeldItem(ItemStack.EMPTY)
}
val ownerPlayer = pokemon.getOwnerPlayer()
if (ownerPlayer != null && ownerPlayer.level().gameRules.getBoolean(CobblemonGameRules.DO_POKEMON_LOOT)) {
drops.drop(
@@ -1,3 +1,11 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokemon.stats
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
@@ -45,4 +45,15 @@ open class CancelableObservable<T : Cancelable> : EventObservable<T>() {
}
}
}
inline fun postThenFinally(event: T, ifCanceled: (T) -> Unit = {}, finally: (T) -> Unit = {},ifSucceeded: (T) -> Unit) {
post(event) {
if (it.isCanceled) {
ifCanceled(it)
} else {
ifSucceeded(it)
}
finally(it)
}
}
}
@@ -167,10 +167,10 @@ open class PlayerPartyStore(
}
// Shoulder validation code
if (player.shoulderEntityLeft.isPokemonEntity() && !validateShoulder(player.shoulderEntityLeft, true)) {
if (player.shoulderEntityLeft.isPokemonEntity() && !validateShoulder(player, true)) {
player.respawnEntityOnShoulder(player.shoulderEntityLeft)
}
if (player.shoulderEntityRight.isPokemonEntity() && !validateShoulder(player.shoulderEntityRight, false)) {
if (player.shoulderEntityRight.isPokemonEntity() && !validateShoulder(player, false)) {
player.respawnEntityOnShoulder(player.shoulderEntityRight)
}
@@ -182,11 +182,14 @@ open class PlayerPartyStore(
}
}
fun validateShoulder(shoulderEntity: CompoundTag, isLeft: Boolean): Boolean {
private fun validateShoulder(player: ServerPlayer, isLeft: Boolean): Boolean {
val shoulderEntity = if(isLeft) player.shoulderEntityLeft else player.shoulderEntityRight
val pokemon = find { it.uuid == shoulderEntity.getCompound("Pokemon").getUUID(DataKeys.POKEMON_UUID) }
if (pokemon == null || (pokemon.state as? ShoulderedState)?.isLeftShoulder != isLeft) {
// No longer valid if (in order): not in party, not the correct shoulder, no longer shoulder mountable
if (pokemon == null || (pokemon.state as? ShoulderedState)?.isLeftShoulder != isLeft || !pokemon.form.shoulderMountable) {
return false
}
player.updateShoulderNbt(pokemon)
return true
}
@@ -8,16 +8,19 @@
package com.cobblemon.mod.common.api.storage.pc
import com.cobblemon.mod.common.api.pokemon.PokemonSortMode
import com.cobblemon.mod.common.api.reactive.Observable.Companion.stopAfter
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.api.storage.InvalidSpeciesException
import com.cobblemon.mod.common.api.storage.StoreCoordinates
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPacket
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.DataKeys
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.JsonObject
import net.minecraft.core.RegistryAccess
import net.minecraft.nbt.CompoundTag
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
/**
@@ -34,6 +37,18 @@ open class PCBox(val pc: PCStore) : Iterable<Pokemon> {
protected var emit = true
var name : String? = null
set(value) {
field = value
if (emit) boxChangeEmitter.emit(Unit)
}
var wallpaper : ResourceLocation = cobblemonResource("textures/gui/pc/pc_screen_overlay.png")
set(value) {
field = value
if (emit) boxChangeEmitter.emit(Unit)
}
protected val pokemon = Array<Pokemon?>(POKEMON_PER_BOX) { null }
open operator fun get(index: Int): Pokemon? {
@@ -88,6 +103,13 @@ open class PCBox(val pc: PCStore) : Iterable<Pokemon> {
boxChangeEmitter.subscribe { pc.pcChangeObservable.emit(Unit) }
}
fun sort(sortMode: PokemonSortMode, descending: Boolean) {
pokemon.sortWith(sortMode.comparator(descending))
pokemon.forEachIndexed { slot, pokemon ->
pokemon?.storeCoordinates?.set(StoreCoordinates(pc, PCPosition(boxNumber, slot)))
}
}
fun trackPokemon(pokemon: Pokemon) {
pokemon.getChangeObservable()
.pipe(
@@ -100,10 +122,14 @@ open class PCBox(val pc: PCStore) : Iterable<Pokemon> {
}
fun sendTo(player: ServerPlayer) {
SetPCBoxPokemonPacket(this).sendToPlayer(player)
SetPCBoxPacket(this).sendToPlayer(player)
}
open fun saveToNBT(nbt: CompoundTag, registryAccess: RegistryAccess): CompoundTag {
name?.let {
nbt.putString(DataKeys.STORE_BOX_NAME, it)
}
nbt.putString(DataKeys.STORE_BOX_WALLPAPER, wallpaper.toString())
for (slot in 0 until POKEMON_PER_BOX) {
val pokemon = pokemon[slot] ?: continue
nbt.put(DataKeys.STORE_SLOT + slot, pokemon.saveToNBT(registryAccess))
@@ -112,6 +138,10 @@ open class PCBox(val pc: PCStore) : Iterable<Pokemon> {
}
open fun saveToJSON(json: JsonObject, registryAccess: RegistryAccess): JsonObject {
name?.let {
json.addProperty(DataKeys.STORE_BOX_NAME, it)
}
json.addProperty(DataKeys.STORE_BOX_WALLPAPER, wallpaper.toString())
for (slot in 0 until POKEMON_PER_BOX) {
val pokemon = pokemon[slot] ?: continue
json.add(DataKeys.STORE_SLOT + slot, pokemon.saveToJSON(registryAccess))
@@ -119,7 +149,16 @@ open class PCBox(val pc: PCStore) : Iterable<Pokemon> {
return json
}
open fun loadFromJSON(json: JsonObject, registryAccess: RegistryAccess): PCBox {
if (json.has(DataKeys.STORE_BOX_NAME)) {
name = json.getAsJsonPrimitive(DataKeys.STORE_BOX_NAME).asString
}
if (json.has(DataKeys.STORE_BOX_WALLPAPER)) {
wallpaper = ResourceLocation.parse(json.getAsJsonPrimitive(DataKeys.STORE_BOX_WALLPAPER).asString)
}
for (slot in 0 until POKEMON_PER_BOX) {
if (json.has(DataKeys.STORE_SLOT + slot)) {
val pokemonJson = json.getAsJsonObject(DataKeys.STORE_SLOT + slot)
@@ -134,6 +173,14 @@ open class PCBox(val pc: PCStore) : Iterable<Pokemon> {
}
open fun loadFromNBT(nbt: CompoundTag, registryAccess: RegistryAccess): PCBox {
if (nbt.contains(DataKeys.STORE_BOX_NAME)) {
name = nbt.getString(DataKeys.STORE_BOX_NAME)
}
if (nbt.contains(DataKeys.STORE_BOX_WALLPAPER)) {
wallpaper = ResourceLocation.parse(nbt.getString(DataKeys.STORE_BOX_WALLPAPER))
}
for (slot in 0 until POKEMON_PER_BOX) {
if (nbt.contains(DataKeys.STORE_SLOT + slot)) {
val pokemonNBT = nbt.getCompound(DataKeys.STORE_SLOT + slot)
@@ -0,0 +1,22 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.storage.pc.search
import com.cobblemon.mod.common.pokemon.Pokemon
/**
* Functional interface used in [Search]es
*/
fun interface PokemonFilter {
fun test(pokemon: Pokemon): Boolean
fun inverted(): PokemonFilter {
return PokemonFilter { pokemon -> !this.test(pokemon) }
}
}
@@ -0,0 +1,71 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.storage.pc.search
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.pokemon.Pokemon
import java.util.HashSet
import java.util.Locale
import java.util.UUID
/**
* Client-side class containing currently applied filters, and cached results of which Pokémon pass or fail those filters.
* Used in [com.cobblemon.mod.common.client.gui.pc.PCGUI]
*/
class Search(
private val filters: Set<PokemonFilter>,
private val passed: MutableSet<UUID> = HashSet(),
private val failed: MutableSet<UUID> = HashSet()
) {
companion object {
val DEFAULT = Search(setOf())
fun of(search: String): Search {
if (search.isBlank()) return DEFAULT
val split = search.lowercase(Locale.ROOT).trim().split(" ")
val filters = HashSet<PokemonFilter>()
for (piece in split) {
var filter = piece
val inverted = filter.startsWith("!")
if (inverted) {
filter = filter.substring(1)
}
val pokemonFilter: PokemonFilter = when (filter) {
"holding" -> PokemonFilter { pokemon -> !pokemon.heldItem().isEmpty }
"fainted" -> PokemonFilter { pokemon -> pokemon.isFainted() }
"legendary" -> PokemonFilter { pokemon -> pokemon.isLegendary() }
"mythical" -> PokemonFilter { pokemon -> pokemon.isMythical() }
"ultrabeast", "ultra_beast" -> PokemonFilter { pokemon -> pokemon.isUltraBeast() }
else -> PokemonFilter { pokemon -> PokemonProperties.parse(filter).matches(pokemon) }
}
if (inverted) {
filters.add(pokemonFilter.inverted())
} else {
filters.add(pokemonFilter)
}
}
return Search(filters)
}
}
fun passes(pokemon: Pokemon?): Boolean {
if (pokemon == null) return false
val uuid = pokemon.uuid
if (passed.contains(uuid)) return true
if (failed.contains(uuid)) return false
val passes = filters.all { it.test(pokemon) }
val set = if (passes) passed else failed
set.add(uuid)
return passes
}
}
@@ -111,6 +111,9 @@ object CobblemonItemTags {
@JvmField val EXPERIENCE_SHARE = create("held/experience_share")
@JvmField val IS_FRIENDSHIP_BOOSTER = create("is_friendship_booster")
@JvmField val ANY_HELD_ITEM = create("held/is_held_item")
@JvmField val BLACKLISTED_ITEMS_TO_HOLD = create("held/blacklisted_items_to_hold")
@JvmField val WHITELISTED_ITEMS_TO_HOLD = create("held/whitelisted_items_to_hold")
/** Tag that flags items as being able to "create" [CobblemonItems.LEFTOVERS]. */
@JvmField val LEAVES_LEFTOVERS = create("held/leaves_leftovers")
@JvmField val LUCKY_EGG = create("held/lucky_egg")
@@ -0,0 +1,113 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.block
import com.cobblemon.mod.common.api.text.red
import com.cobblemon.mod.common.api.text.text
import com.cobblemon.mod.common.block.entity.StadiumBlockEntity
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.InteractionResult
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.context.BlockPlaceContext
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.BaseEntityBlock
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.HorizontalDirectionalBlock
import net.minecraft.world.level.block.Mirror
import net.minecraft.world.level.block.RenderShape
import net.minecraft.world.level.block.Rotation
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.block.state.StateDefinition
import net.minecraft.world.phys.BlockHitResult
class StadiumBlock(properties: Properties): BaseEntityBlock(properties) {
companion object {
val CODEC = simpleCodec(::StadiumBlock)
}
init {
registerDefaultState(stateDefinition.any().setValue(HorizontalDirectionalBlock.FACING, Direction.NORTH))
}
override fun codec() = CODEC
override fun newBlockEntity(pos: BlockPos, state: BlockState): BlockEntity {
return StadiumBlockEntity(pos, state)
}
override fun getStateForPlacement(blockPlaceContext: BlockPlaceContext): BlockState {
return this.defaultBlockState().setValue(HorizontalDirectionalBlock.FACING, blockPlaceContext.horizontalDirection)
}
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
builder.add(HorizontalDirectionalBlock.FACING)
}
override fun rotate(blockState: BlockState, rotation: Rotation): BlockState {
return blockState.setValue(
HorizontalDirectionalBlock.FACING, rotation.rotate(blockState.getValue(
HorizontalDirectionalBlock.FACING)))
}
override fun mirror(blockState: BlockState, mirror: Mirror): BlockState {
return blockState.rotate(mirror.getRotation(blockState.getValue(HorizontalDirectionalBlock.FACING)))
}
override fun onRemove(state: BlockState, world: Level, pos: BlockPos, newState: BlockState, moved: Boolean) {
if (!state.`is`(newState.block)) super.onRemove(state, world, pos, newState, moved)
}
//TODO: override getTicker
override fun getRenderShape(state: BlockState) = RenderShape.MODEL
override fun useWithoutItem(
blockState: BlockState,
world: Level,
blockPos: BlockPos,
player: Player,
blockHitResult: BlockHitResult
): InteractionResult {
if (player !is ServerPlayer) return InteractionResult.SUCCESS
val blockEntity = world.getBlockEntity(blockPos)
if (blockEntity !is StadiumBlockEntity) return InteractionResult.SUCCESS
// Toggle isInUse state
blockEntity.isInUse = !blockEntity.isInUse
// debug
val activateMessage = if (blockEntity.isInUse) "Stadium Activated!" else "Stadium Deactivated!"
player.sendSystemMessage(text(activateMessage).red())
if (blockEntity.isInUse) {
// Generate flight path when activated
blockEntity.generateFlightPath(world, radiusX = 5.0, radiusZ = 3.0, height = 10.0, steps = 20)
} else {
// Clear path when deactivated
blockEntity.pathPoints.clear()
}
val message = "Stadium Pos: " + blockEntity.blockPos +
"\nPlayer 1 Pos: " + blockEntity.getPlayer1Pos() +
"\nPoke 1 Pos: " + blockEntity.getPoke1Pos() +
"\nPlayer 2 Pos: " + blockEntity.getPlayer2Pos() +
"\nPoke 2 Pos: " + blockEntity.getPoke2Pos()
player.sendSystemMessage(text(message).red())
blockEntity.setChanged()
world.sendBlockUpdated(blockPos, blockState, blockState, Block.UPDATE_CLIENTS)
return InteractionResult.SUCCESS
}
}
@@ -42,7 +42,7 @@ open class FossilMultiblockEntity(
if(masterBlockPos != null && masterBlockPos != blockPos) {
val chunkPos = ChunkPos(masterBlockPos)
if (level?.chunkSource?.hasChunk(chunkPos.x, chunkPos.z) == true) {
val entity: FossilMultiblockEntity? = level?.getBlockEntity(masterBlockPos) as FossilMultiblockEntity?
val entity: FossilMultiblockEntity? = level?.getBlockEntity(masterBlockPos) as? FossilMultiblockEntity?
field = entity?.multiblockStructure
}
}
@@ -0,0 +1,132 @@
package com.cobblemon.mod.common.block.entity
import com.cobblemon.mod.common.CobblemonBlockEntities
import com.cobblemon.mod.common.client.render.models.blockbench.drone.DroneState
import net.minecraft.core.BlockPos
import net.minecraft.core.HolderLookup
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag
import net.minecraft.network.protocol.Packet
import net.minecraft.network.protocol.game.ClientGamePacketListener
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket
import net.minecraft.network.protocol.game.ClientboundPlayerLookAtPacket
import net.minecraft.network.protocol.game.ClientboundSetCarriedItemPacket
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.phys.Vec3
class StadiumBlockEntity(
pos: BlockPos,
blockState: BlockState
): BlockEntity(
CobblemonBlockEntities.STADIUM,
pos,
blockState
) {
var isInUse = false
val droneState = DroneState()
val pathPoints: MutableList<Vec3> = mutableListOf()
fun generateFlightPath(world: Level, radiusX: Double, radiusZ: Double, height: Double, steps: Int) {
pathPoints.clear()
for (i in 0 until steps) {
val angle = (i.toDouble() / steps) * Math.PI * 2
val xOffset = radiusX * Math.cos(angle)
val zOffset = radiusZ * Math.sin(angle)
val basePos = Vec3(blockPos.x + xOffset, blockPos.y + height, blockPos.z + zOffset)
val adjustedPos = getValidPoint(world, basePos)
pathPoints.add(adjustedPos)
}
}
private fun getValidPoint(world: Level, start: Vec3): Vec3 {
val maxHeight = 40 // Max height for drone path
val stepHeight = 1.0 // Step size for raycast
var adjustedHeight = start.y
for (h in 0..maxHeight step stepHeight.toInt()) {
val checkPos = BlockPos(start.x.toInt(), start.y.toInt() - h, start.z.toInt()) // Convert to BlockPos
if (!world.getBlockState(checkPos).isAir) { // Check if block is solid
return Vec3(start.x, start.y - h - 1, start.z) // Adjust position
}
}
return start // No obstruction found
}
fun getPlayer1Pos(): BlockPos {
return blockPos.north(10)
}
fun getPlayer2Pos(): BlockPos {
return blockPos.south(10)
}
fun getPoke1Pos(): BlockPos {
return blockPos.north(5)
}
fun getPoke2Pos(): BlockPos {
return blockPos.south(5)
}
/**
* Saves data to NBT.
*/
override fun saveAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
super.saveAdditional(tag, registries)
// Save the isInUse state
tag.putBoolean("IsInUse", isInUse)
// Save path points
val pathTag = ListTag()
for (point in pathPoints) {
val pointTag = CompoundTag()
pointTag.putDouble("x", point.x)
pointTag.putDouble("y", point.y)
pointTag.putDouble("z", point.z)
pathTag.add(pointTag)
}
tag.put("PathPoints", pathTag)
}
/**
* Loads data from NBT.
*/
override fun loadAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
super.loadAdditional(tag, registries)
// Load the isInUse state
isInUse = tag.getBoolean("IsInUse")
// Load path points
pathPoints.clear()
val pathTag = tag.getList("PathPoints", 10) // 10 is the ID for CompoundTag
for (i in 0 until pathTag.size) {
val pointTag = pathTag.getCompound(i)
val point = Vec3(pointTag.getDouble("x"), pointTag.getDouble("y"), pointTag.getDouble("z"))
pathPoints.add(point)
}
}
override fun getUpdatePacket(): Packet<ClientGamePacketListener>? {
//println("getUpdatePacket called for NestBlockEntity at $blockPos with egg: $eggComponent")
return ClientboundBlockEntityDataPacket.create(this)
}
override fun getUpdateTag(registryLookup: HolderLookup.Provider): CompoundTag {
val tag = saveWithoutMetadata(registryLookup)
//println("getUpdateTag called for NestBlockEntity at $blockPos with tag: $tag")
return tag
}
}
@@ -25,13 +25,7 @@ import com.cobblemon.mod.common.client.gui.battle.BattleOverlay
import com.cobblemon.mod.common.client.particle.BedrockParticleOptionsRepository
import com.cobblemon.mod.common.client.render.ClientPlayerIcon
import com.cobblemon.mod.common.client.render.DeferredRenderer
import com.cobblemon.mod.common.client.render.block.BerryBlockRenderer
import com.cobblemon.mod.common.client.render.block.DisplayCaseRenderer
import com.cobblemon.mod.common.client.render.block.FossilAnalyzerRenderer
import com.cobblemon.mod.common.client.render.block.GildedChestBlockRenderer
import com.cobblemon.mod.common.client.render.block.HealingMachineRenderer
import com.cobblemon.mod.common.client.render.block.LecternBlockEntityRenderer
import com.cobblemon.mod.common.client.render.block.RestorationTankRenderer
import com.cobblemon.mod.common.client.render.block.*
import com.cobblemon.mod.common.client.render.boat.CobblemonBoatRenderer
import com.cobblemon.mod.common.client.render.entity.PokeBobberEntityRenderer
import com.cobblemon.mod.common.client.render.generic.GenericBedrockRenderer
@@ -40,13 +34,8 @@ 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.BlockEntityModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.FossilModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.GenericBedrockEntityModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.MiscModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.NPCModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokeBallModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.client.render.npc.NPCRenderer
import com.cobblemon.mod.common.client.render.pokeball.PokeBallRenderer
import com.cobblemon.mod.common.client.render.pokemon.PokemonRenderer
@@ -77,10 +66,12 @@ import net.minecraft.client.renderer.blockentity.SignRenderer
import net.minecraft.client.renderer.entity.EntityRenderer
import net.minecraft.client.renderer.entity.LivingEntityRenderer
import net.minecraft.client.resources.PlayerSkin
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.packs.resources.ResourceManager
import net.minecraft.world.InteractionHand
import net.minecraft.world.entity.player.Player
import net.minecraft.world.phys.AABB
import java.util.UUID
object CobblemonClient {
@@ -94,15 +85,6 @@ object CobblemonClient {
var checkedStarterScreen = false
var requests = ClientPlayerActionRequests()
var teamData = ClientPlayerTeamData()
var posableModelRepositories = listOf(
PokemonModelRepository,
PokeBallModelRepository,
NPCModelRepository,
FossilModelRepository,
BlockEntityModelRepository,
GenericBedrockEntityModelRepository
)
val overlay: PartyOverlay by lazy { PartyOverlay() }
val battleOverlay: BattleOverlay by lazy { BattleOverlay() }
val pokedexUsageContext: PokedexUsageContext by lazy { PokedexUsageContext() }
@@ -268,7 +250,8 @@ object CobblemonClient {
CobblemonBlocks.SKY_TUMBLESTONE_CLUSTER,
CobblemonBlocks.GIMMIGHOUL_CHEST,
CobblemonBlocks.DISPLAY_CASE,
CobblemonBlocks.LECTERN
CobblemonBlocks.LECTERN,
CobblemonBlocks.STADIUM
)
this.createBoatModelLayers()
@@ -302,6 +285,7 @@ object CobblemonClient {
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.GILDED_CHEST, ::GildedChestBlockRenderer)
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.DISPLAY_CASE, ::DisplayCaseRenderer)
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.LECTERN, ::LecternBlockEntityRenderer)
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.STADIUM, ::StadiumBlockRenderer)
}
private fun registerEntityRenderers() {
@@ -330,9 +314,9 @@ object CobblemonClient {
// Animations come next because models need them.
BedrockAnimationRepository.loadAnimations(
resourceManager = resourceManager,
directories = posableModelRepositories.flatMap { it.animationDirectories }
directories = VaryingModelRepository.animationDirectories
)
posableModelRepositories.forEach { it.reload(resourceManager) }
VaryingModelRepository.reload(resourceManager)
BerryModelRepository.reload(resourceManager)
MiscModelRepository.reload(resourceManager)
@@ -10,8 +10,7 @@ package com.cobblemon.mod.common.client.entity
import com.cobblemon.mod.common.api.entity.EntitySideDelegate
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.repository.GenericBedrockEntityModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.entity.generic.GenericBedrockEntity
class GenericBedrockClientDelegate : EntitySideDelegate<GenericBedrockEntity>, PosableState() {
@@ -24,7 +23,7 @@ class GenericBedrockClientDelegate : EntitySideDelegate<GenericBedrockEntity>, P
super.initialize(entity)
this.currentEntity = entity
this.age = entity.tickCount
this.currentModel = GenericBedrockEntityModelRepository.getPoser(entity.category, entity.delegate as GenericBedrockClientDelegate)
this.currentModel = VaryingModelRepository.getPoser(entity.category, entity.delegate as GenericBedrockClientDelegate)
currentModel!!.updateLocators(entity, this)
updateLocatorPosition(entity.position())
@@ -29,7 +29,7 @@ import com.cobblemon.mod.common.client.render.MatrixWrapper
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.animation.ActiveAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.animation.PrimaryAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.client.render.pokemon.PokemonRenderer.Companion.ease
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.pokemon.Pokemon
@@ -99,7 +99,7 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
currentPose = null
currentEntity.pokemon.species = PokemonSpecies.getByIdentifier(identifier)!! // TODO exception handling
// force a model update - handles edge case where the PosableState's tracked PosableModel isn't updated until the LivingEntityRenderer render is run
currentModel = PokemonModelRepository.getPoser(identifier, this)
currentModel = VaryingModelRepository.getPoser(identifier, this)
} else if (data == PokemonEntity.ASPECTS) {
currentAspects = currentEntity.entityData.get(PokemonEntity.ASPECTS)
currentEntity.pokemon.shiny = currentAspects.contains("shiny")
@@ -24,7 +24,6 @@ import com.cobblemon.mod.common.client.keybind.keybinds.SummaryBinding
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.client.render.getDepletableRedGreen
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
import com.cobblemon.mod.common.client.render.renderScaledGuiItemIcon
import com.cobblemon.mod.common.pokemon.Gender
import com.cobblemon.mod.common.util.cobblemonResource
@@ -161,7 +160,6 @@ class PartyOverlay : Gui(Minecraft.getInstance()) {
matrixStack = matrices,
partialTicks = 0F, // partialDeltaTicks, //Before you get any funny ideas about party animated pokemon, make sure they each get their own state instead of sharing.
contextScale = pokemon.form.baseScale,
repository = PokemonModelRepository,
state = state
)
matrices.popPose()
@@ -12,10 +12,11 @@ import com.cobblemon.mod.common.api.gui.renderSprite
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
import com.cobblemon.mod.common.client.render.SpriteType
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.pokemon.RenderablePokemon
import com.cobblemon.mod.common.util.math.toEulerXYZDegrees
import com.cobblemon.mod.common.util.toHex
import com.mojang.blaze3d.platform.Lighting
import com.mojang.blaze3d.systems.RenderSystem
@@ -25,8 +26,10 @@ import net.minecraft.client.renderer.LightTexture
import net.minecraft.client.renderer.RenderType
import net.minecraft.client.renderer.texture.OverlayTexture
import net.minecraft.resources.ResourceLocation
import net.minecraft.util.Mth
import org.joml.Quaternionf
import org.joml.Vector3f
import kotlin.math.atan
fun drawProfilePokemon(
renderablePokemon: RenderablePokemon,
@@ -41,7 +44,9 @@ fun drawProfilePokemon(
r: Float = 1F,
g: Float = 1F,
b: Float = 1F,
a: Float = 1F
a: Float = 1F,
headYaw: Float = 0f,
headPitch: Float = 0f,
) = drawProfilePokemon(
species = renderablePokemon.species.resourceIdentifier,
matrixStack = matrixStack,
@@ -56,6 +61,8 @@ fun drawProfilePokemon(
g = g,
b = b,
a = a,
headYaw = headYaw,
headPitch = headPitch,
)
fun drawProfilePokemon(
@@ -71,21 +78,23 @@ fun drawProfilePokemon(
r: Float = 1F,
g: Float = 1F,
b: Float = 1F,
a: Float = 1F
a: Float = 1F,
headYaw: Float = 0f,
headPitch: Float = 0f,
) {
RenderSystem.applyModelViewMatrix()
matrixStack.scale(scale, scale, -scale)
val sprite = PokemonModelRepository.getSprite(species, state, SpriteType.PROFILE)
val sprite = VaryingModelRepository.getSprite(species, state, SpriteType.PROFILE)
if (sprite == null) {
val model = PokemonModelRepository.getPoser(species, state)
val texture = PokemonModelRepository.getTexture(species, state)
val model = VaryingModelRepository.getPoser(species, state)
val texture = VaryingModelRepository.getTexture(species, state)
val context = RenderContext()
model.context = context
PokemonModelRepository.getTextureNoSubstitute(species, state).let { context.put(RenderContext.TEXTURE, it) }
VaryingModelRepository.getTextureNoSubstitute(species, state).let { context.put(RenderContext.TEXTURE, it) }
val baseScale = PokemonSpecies.getByIdentifier(species)!!.getForm(state.currentAspects).baseScale
context.put(RenderContext.SCALE, baseScale)
context.put(RenderContext.SPECIES, species)
@@ -100,9 +109,13 @@ fun drawProfilePokemon(
state.setPoseToFirstSuitable(poseType)
state.updatePartialTicks(partialTicks)
model.applyAnimations(null, state, 0F, 0F, 0F, 0F, 0F)
if (applyProfileTransform) {
matrixStack.translate(model.profileTranslation.x, model.profileTranslation.y, model.profileTranslation.z - 4.0)
matrixStack.translate(
model.profileTranslation.x,
model.profileTranslation.y + 1.5 * model.profileScale,
model.profileTranslation.z - 4.0
)
matrixStack.scale(model.profileScale, model.profileScale, 1 / model.profileScale)} else {
matrixStack.translate(0F, 0F, -4.0F)
if (applyBaseScale) {
@@ -110,6 +123,9 @@ fun drawProfilePokemon(
}
}
matrixStack.mulPose(rotation)
model.applyAnimations(null, state, 0F, 0F, 0F, headYaw, headPitch)
Lighting.setupForEntityInInventory()
val entityRenderDispatcher = Minecraft.getInstance().entityRenderDispatcher
rotation.conjugate()
@@ -124,7 +140,7 @@ fun drawProfilePokemon(
val packedLight = LightTexture.pack(11, 7)
val colour = toHex(r, g, b, a)
model.withLayerContext(bufferSource, state, PokemonModelRepository.getLayers(species, state)) {
model.withLayerContext(bufferSource, state, VaryingModelRepository.getLayers(species, state)) {
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, colour)
bufferSource.endBatch()
}
@@ -136,3 +152,29 @@ fun drawProfilePokemon(
}
}
const val HEAD_YAW_FACTOR = 40f
const val HEAD_PITCH_FACTOR = 20f
const val SMOOTHING_FACTOR = 0.05f
fun calculateHeadYawAndPitch(
xCoordinate: Float,
yCoordinate: Float,
rotation: Quaternionf,
mouseX: Int,
mouseY: Int,
currentYaw: Float,
currentPitch: Float,
resetToCenter: Boolean,
): Pair<Float, Float> {
val horizontalAngle = atan(((xCoordinate - mouseX) / 40.0f).toDouble()).toFloat()
val verticalAngle = atan(((yCoordinate - mouseY) / 40.0f).toDouble()).toFloat()
val eulerXYZRotationDegrees = rotation.toEulerXYZDegrees()
val targetYaw = if (!resetToCenter) horizontalAngle * HEAD_YAW_FACTOR - eulerXYZRotationDegrees.y else 0f
val targetPitch = if (!resetToCenter) -verticalAngle * HEAD_PITCH_FACTOR - eulerXYZRotationDegrees.x else 0f
val newYaw = Mth.rotLerp(SMOOTHING_FACTOR, currentYaw, targetYaw)
val newPitch = Mth.rotLerp(SMOOTHING_FACTOR, currentPitch, targetPitch)
return Pair(newYaw, newPitch)
}
@@ -26,9 +26,8 @@ import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.client.render.drawScaledTextJustifiedRight
import com.cobblemon.mod.common.client.render.getDepletableRedGreen
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokeBallModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.sineFunction
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
@@ -321,7 +320,6 @@ class BattleOverlay : Gui(Minecraft.getInstance()), Schedulable {
matrixStack = matrixStack,
scale = 18F * (ballState?.scale ?: 1F) * if (isCompact) 0.65F else 1.0f,
contextScale = species.getForm(state.currentAspects).baseScale,
repository = PokemonModelRepository,
reversed = reversed,
state = state,
partialTicks = partialTicks
@@ -490,8 +488,8 @@ class BattleOverlay : Gui(Minecraft.getInstance()), Schedulable {
reversed: Boolean = false
) {
val context = RenderContext()
val model = PokeBallModelRepository.getPoser(state.pokeBall.name, state)
val texture = PokeBallModelRepository.getTexture(state.pokeBall.name, state)
val model = VaryingModelRepository.getPoser(state.pokeBall.name, state)
val texture = VaryingModelRepository.getTexture(state.pokeBall.name, state)
val renderType = RenderType.entityCutout(texture)//model.getLayer(texture)
RenderSystem.applyModelViewMatrix()
@@ -15,8 +15,6 @@ import com.cobblemon.mod.common.client.entity.NPCClientDelegate
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.repository.NPCModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
import com.cobblemon.mod.common.entity.PosableEntity
import com.cobblemon.mod.common.entity.npc.NPCEntity
import java.util.UUID
@@ -82,7 +80,6 @@ class ReferenceRenderableFace(val entity: PosableEntity, override val isLeftSide
state.currentAspects = state.currentEntity.pokemon.aspects
drawPosablePortrait(
identifier = state.currentEntity.pokemon.species.resourceIdentifier,
repository = PokemonModelRepository,
contextScale = state.currentEntity.pokemon.form.baseScale,
matrixStack = GuiGraphics.pose(),
state = state,
@@ -96,7 +93,6 @@ class ReferenceRenderableFace(val entity: PosableEntity, override val isLeftSide
val limbSwingAmount = entity.walkAnimation.speed(partialTicks)
drawPosablePortrait(
identifier = state.npcEntity.npc.resourceIdentifier,
repository = NPCModelRepository,
matrixStack = GuiGraphics.pose(),
state = state,
reversed = !isLeftSide,
@@ -131,7 +127,6 @@ class ArtificialRenderableFace(
contextScale = species.getForm(aspects).baseScale,
state = state,
reversed = !isLeftSide,
repository = PokemonModelRepository,
partialTicks = partialTicks
)
} else if (modelType == "npc") {
@@ -140,7 +135,6 @@ class ArtificialRenderableFace(
matrixStack = GuiGraphics.pose(),
state = state,
reversed = !isLeftSide,
repository = NPCModelRepository,
partialTicks = partialTicks
)
}
@@ -11,9 +11,7 @@ package com.cobblemon.mod.common.client.gui.npc.widgets
import com.cobblemon.mod.common.api.gui.drawProfile
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
import com.cobblemon.mod.common.client.render.models.blockbench.repository.NPCModelRepository
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.gui.components.Renderable
import net.minecraft.client.gui.components.events.GuiEventListener
import net.minecraft.resources.ResourceLocation
@@ -47,7 +45,6 @@ class NPCRenderWidget(
context.pose().translate(x + (WIDTH / 2F), y + HEIGHT + (HEIGHT / 4F), -500F)
drawProfile(
repository = NPCModelRepository,
resourceIdentifier = identifier,
matrixStack = context.pose(),
partialTicks = delta,
@@ -0,0 +1,81 @@
/*
* 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.pc
import com.cobblemon.mod.common.api.text.bold
import com.cobblemon.mod.common.api.text.font
import com.cobblemon.mod.common.api.text.text
import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.client.storage.ClientBox
import com.cobblemon.mod.common.net.messages.server.storage.pc.RequestRenamePCBoxPacket
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.gui.components.EditBox
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.MutableComponent
class BoxNameWidget(
private val pX: Int,
pY: Int,
text: Component = "BoxNameWidget".text(),
private val pcGui: PCGUI,
private val storageWidget: StorageWidget,
): EditBox(Minecraft.getInstance().font, pX, pY, 0, HEIGHT, text) {
companion object {
const val HEIGHT = 14
}
init {
setMaxLength(21)
update()
setResponder { update() }
}
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
if (cursorPosition != value.length) moveCursorToEnd(false)
drawScaledText(
context = context,
text = text(),
x = x,
y = y
)
}
override fun setFocused(focused: Boolean) {
super.setFocused(focused)
update()
if (!focused) {
RequestRenamePCBoxPacket(pcGui.pc.uuid, storageWidget.box, value).sendToServer()
pcGui.pc.boxes[storageWidget.box].name = if (value.isBlank()) null else Component.literal(value).bold()
value = ""
}
}
private fun text(): MutableComponent {
return (if (isFocused) {
"${value}_".text()
} else if (value.isEmpty()) {
getBox().name?: Component.translatable("cobblemon.ui.pc.box.title", storageWidget.box + 1)
} else {
value.text()
}).bold().font(CobblemonResources.DEFAULT_LARGE)
}
fun getBox(): ClientBox {
return pcGui.pc.boxes[storageWidget.box]
}
fun update() {
width = Minecraft.getInstance().font.width(text())
x = pX - width / 2
}
}
@@ -25,6 +25,8 @@ class BoxStorageSlot(
}
override fun shouldRender(): Boolean {
if (!super.shouldRender()) return false
val grabbedSlot = parent.grabbedSlot
return if (grabbedSlot == null) {
true
@@ -30,4 +30,6 @@ class GrabbedStorageSlot(
override fun getPokemon() = pokemon
override fun isHoveredOrFocused() = true
override fun shouldRender() = true
}
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.client.gui.pc
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.gui.blitk
import com.cobblemon.mod.common.api.storage.pc.search.Search
import com.cobblemon.mod.common.api.text.bold
import com.cobblemon.mod.common.api.text.text
import com.cobblemon.mod.common.client.CobblemonResources
@@ -22,6 +23,7 @@ import com.cobblemon.mod.common.client.gui.summary.widgets.common.reformatNature
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.client.storage.ClientPC
import com.cobblemon.mod.common.client.storage.ClientParty
import com.cobblemon.mod.common.net.messages.server.storage.pc.SortPCBoxPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.UnlinkPlayerFromPCPacket
import com.cobblemon.mod.common.pokemon.Gender
import com.cobblemon.mod.common.pokemon.Pokemon
@@ -36,6 +38,7 @@ import net.minecraft.client.gui.screens.Screen
import net.minecraft.client.resources.sounds.SimpleSoundInstance
import net.minecraft.network.chat.Component
import net.minecraft.sounds.SoundEvent
import kotlin.isInitialized
class PCGUI(
val pc: ClientPC,
@@ -67,9 +70,13 @@ class PCGUI(
}
private lateinit var storageWidget: StorageWidget
private lateinit var boxNameWidget: BoxNameWidget
private lateinit var searchWidget: SearchWidget
private lateinit var wallpaperWidget: WallpapersScrollingWidget
private var modelWidget: ModelWidget? = null
internal var previewPokemon: Pokemon? = null
var search: Search = Search.DEFAULT
var ticksElapsed = 0
var selectPointerOffsetY = 0
var selectPointerOffsetIncrement = false
@@ -91,7 +98,9 @@ class PCGUI(
pX = x + 221,
pY = y + 17,
forward = true
) { storageWidget.box += 1 }
) {
storageWidget.box += 1
}
)
// Add Backwards Button
@@ -100,7 +109,20 @@ class PCGUI(
pX = x + 119,
pY = y + 17,
forward = false
) { storageWidget.box -= 1 }
) {
storageWidget.box -= 1
}
)
// Add Sort Button
addRenderableWidget(
SortButton(
pX = x + 85,
pY = y + 12,
onPress = { it as SortButton
SortPCBoxPacket(pc.uuid, storageWidget.box, it.sortMode, hasShiftDown()).sendToServer()
}
)
)
// Add Storage
@@ -113,8 +135,47 @@ class PCGUI(
)
this.storageWidget.box = openOnBox
// Add Box Name
this.boxNameWidget = BoxNameWidget(
pX = x + 172,
pY = y + 15,
pcGui = this,
storageWidget = storageWidget
)
// Add Search Widget
this.searchWidget = SearchWidget(
pX = x + 117,
pY = y + 183,
update = { search = Search.of(searchWidget.value) }
)
// Add Wallpaper Button
this.addRenderableWidget(
WallpaperButton(
pX = x + 235,
pY = y + 12,
onPress = {
configuration.showParty = wallpaperWidget.visible
wallpaperWidget.visible = !wallpaperWidget.visible
},
pcGui = this
)
)
// Add Wallpaper Widget
this.wallpaperWidget = WallpapersScrollingWidget(
pX = x + 275,
pY = y + 30,
pcGui = this,
storageWidget = storageWidget
)
this.setPreviewPokemon(null)
this.addRenderableWidget(storageWidget)
this.addRenderableWidget(boxNameWidget)
this.addRenderableWidget(searchWidget)
this.addRenderableWidget(wallpaperWidget)
super.init()
}
@@ -136,7 +197,9 @@ class PCGUI(
)
// Render Model Portrait
modelWidget?.render(context, mouseX, mouseY, delta)
if (search.passes(previewPokemon)) {
modelWidget?.render(context, mouseX, mouseY, delta)
}
// Render Base Resource
blitk(
@@ -177,7 +240,7 @@ class PCGUI(
// Render Pokemon Info
val pokemon = previewPokemon
if (pokemon != null) {
if (pokemon != null && search.passes(pokemon)) {
// Status
val status = pokemon.status?.status
if (pokemon.isFainted() || status != null) {
@@ -367,16 +430,6 @@ class PCGUI(
)
}
// Box Label
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = Component.translatable("cobblemon.ui.pc.box.title", (this.storageWidget.box + 1).toString()).bold(),
x = x + 172,
y = y + 15,
centered = true
)
blitk(
matrixStack = matrices,
texture = topSpacerResource,
@@ -454,27 +507,36 @@ class PCGUI(
}
override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
if (isInventoryKeyPressed(minecraft, keyCode, scanCode)) {
val boxNameSelected = this::boxNameWidget.isInitialized && boxNameWidget.isFocused
val searchSelected = this::searchWidget.isInitialized && searchWidget.isFocused
if (isInventoryKeyPressed(minecraft, keyCode, scanCode) && !boxNameSelected && !searchSelected) {
playSound(CobblemonSounds.PC_OFF)
UnlinkPlayerFromPCPacket().sendToServer()
Minecraft.getInstance().setScreen(null)
return true
}
if ((keyCode == InputConstants.KEY_RETURN || keyCode == InputConstants.KEY_NUMPADENTER)
&& (boxNameSelected || searchSelected)) {
this.focused = null
}
when (keyCode) {
InputConstants.KEY_ESCAPE -> {
playSound(CobblemonSounds.PC_OFF)
UnlinkPlayerFromPCPacket().sendToServer()
onClose()
return true
}
InputConstants.KEY_RIGHT -> {
playSound(CobblemonSounds.PC_CLICK)
this.storageWidget.box += 1
return true
}
InputConstants.KEY_LEFT -> {
playSound(CobblemonSounds.PC_CLICK)
this.storageWidget.box -= 1
return true
}
}
return super.keyPressed(keyCode, scanCode, modifiers)
@@ -483,9 +545,7 @@ class PCGUI(
/**
* Whether this Screen should pause the Game in SinglePlayer
*/
override fun isPauseScreen(): Boolean {
return false
}
override fun isPauseScreen() = false
override fun tick() {
ticksElapsed++
@@ -521,4 +581,10 @@ class PCGUI(
modelWidget = null
}
}
fun updateBoxName() {
if (this::boxNameWidget.isInitialized) {
boxNameWidget.update()
}
}
}
@@ -14,6 +14,6 @@ import com.cobblemon.mod.common.pokemon.Pokemon
open class PCGUIConfiguration(
val exitFunction: (PCGUI) -> Unit = { it.closeNormally(unlink = true) },
val selectOverride: ((PCGUI, StorePosition, Pokemon?) -> Unit)? = null,
val showParty: Boolean = true,
var showParty: Boolean = true,
val canSelect: (Pokemon) -> Boolean = { true }
)
@@ -25,6 +25,8 @@ class PartyStorageSlot(
}
override fun shouldRender(): Boolean {
if (!super.shouldRender()) return false
val grabbedSlot = parent.grabbedSlot
return if (grabbedSlot == null) {
true
@@ -32,4 +34,8 @@ class PartyStorageSlot(
grabbedSlot.getPokemon() != getPokemon()
}
}
override fun clickable(): Boolean {
return parent.pcGui.configuration.showParty && super.clickable()
}
}
@@ -0,0 +1,66 @@
/*
* 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.pc
import com.cobblemon.mod.common.api.gui.blitk
import com.cobblemon.mod.common.api.text.bold
import com.cobblemon.mod.common.api.text.text
import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.gui.components.EditBox
import net.minecraft.network.chat.Component
class SearchWidget(
private var pX: Int,
private var pY: Int,
text: Component = "SearchWidget".text(),
update: () -> (Unit)
): EditBox(Minecraft.getInstance().font, pX, pY, WIDTH, HEIGHT, text) {
companion object {
const val WIDTH = 110
const val HEIGHT = 14
const val HINT_COLOUR = 0x8D8D8D
private val hint = Component.translatable("cobblemon.ui.pc.search")
private val searchIcon = cobblemonResource("textures/gui/pc/pc_search_icon.png")
}
init {
setMaxLength(21)
setResponder { update() }
}
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
if (cursorPosition != value.length) moveCursorToEnd(false)
val input = if (isFocused) "${value}_".text() else value.text()
val useHint = !isFocused && value.isEmpty()
blitk(
matrixStack = context.pose(),
texture = searchIcon,
x = pX + 1,
y = pY + 3,
width = 8,
height = 8
)
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = if (useHint) hint.bold() else input.bold(),
x = pX + if (useHint) 55 else 14,
y = pY + 2,
colour = if (useHint) HINT_COLOUR else 0xFFFFFF,
centered = useHint
)
}
}
@@ -0,0 +1,78 @@
/*
* 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.pc
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.gui.blitk
import com.cobblemon.mod.common.api.pokemon.PokemonSortMode
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.client.gui.components.Button
import net.minecraft.client.resources.sounds.SimpleSoundInstance
import net.minecraft.client.sounds.SoundManager
import net.minecraft.network.chat.Component
import kotlin.math.abs
class SortButton(
pX: Int, pY: Int,
onPress: OnPress,
) : Button(pX, pY, WIDTH, HEIGHT, Component.literal("SortButton"), onPress, DEFAULT_NARRATION) {
var sortMode = PokemonSortMode.NAME
companion object {
const val WIDTH = 24
const val HEIGHT = 11
private val modeResources = PokemonSortMode.entries.map { cobblemonResource("textures/gui/pc/pc_sort_${it.name.lowercase()}.png") }
private val buttonResource = cobblemonResource("textures/gui/pc/pc_sort_button.png")
}
override fun renderWidget(context: net.minecraft.client.gui.GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
blitk(
matrixStack = context.pose(),
texture = buttonResource,
x = x,
y = y,
width = WIDTH,
height = HEIGHT,
vOffset = if (isHovered()) HEIGHT else 0,
textureHeight = HEIGHT * 2
)
blitk(
matrixStack = context.pose(),
texture = modeResources[sortMode.ordinal],
x = x,
y = y,
width = WIDTH,
height = HEIGHT
)
}
override fun mouseScrolled(
mouseX: Double,
mouseY: Double,
scrollX: Double,
scrollY: Double
): Boolean {
if (abs(scrollY) >= .5 && isMouseOver(mouseX, mouseY)) {
val modes = PokemonSortMode.entries
var mode = sortMode.ordinal + if (scrollY > 0) 1 else -1
if (mode < 0) mode = modes.size - 1
if (mode >= modes.size) mode = 0
sortMode = modes[mode]
return true
}
return false
}
override fun playDownSound(soundManager: SoundManager) {
soundManager.play(SimpleSoundInstance.forUI(CobblemonSounds.PC_CLICK, 1.0F))
}
}
@@ -212,7 +212,15 @@ open class StorageSlot(
}
open fun shouldRender(): Boolean {
return true
return parent.pcGui.search.passes(getPokemon())
}
open fun clickable(): Boolean {
return getPokemon() == null || parent.pcGui.search.passes(getPokemon())
}
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
return if (clickable()) super.mouseClicked(mouseX, mouseY, button) else false
}
fun isHovered(mouseX: Int, mouseY: Int) = mouseX.toFloat() in (x.toFloat()..(x.toFloat() + SIZE)) && mouseY.toFloat() in (y.toFloat()..(y.toFloat() + SIZE))
@@ -57,7 +57,6 @@ class StorageWidget(
const val PARTY_SLOT_PADDING = 6
private val partyPanelResource = cobblemonResource("textures/gui/pc/party_panel.png")
private val screenOverlayResource = cobblemonResource("textures/gui/pc/pc_screen_overlay.png")
}
private val partySlots = arrayListOf<PartyStorageSlot>()
@@ -82,6 +81,7 @@ class StorageWidget(
// Else it's greater than max, wrap around to start
else 0
this.setupStorageSlots()
this.pcGui.updateBoxName()
}
init {
@@ -255,7 +255,7 @@ class StorageWidget(
// Screen Overlay
blitk(
matrixStack = matrices,
texture = screenOverlayResource,
texture = pc.boxes[box].wallpaper,
x = x - 17,
y = y - 17,
width = 208,
@@ -348,7 +348,7 @@ class StorageWidget(
}
if (grabbedSlot == null) {
if (clickedPokemon != null) {
if (clickedPokemon != null && pcGui.search.passes(clickedPokemon)) {
val shiftClicked = Screen.hasShiftDown()
if (shiftClicked) {
if (clickedPosition is PCPosition) {
@@ -0,0 +1,48 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.gui.pc
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.gui.blitk
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.client.gui.components.Button
import net.minecraft.client.resources.sounds.SimpleSoundInstance
import net.minecraft.client.sounds.SoundManager
import net.minecraft.network.chat.Component
class WallpaperButton(
pX: Int, pY: Int,
onPress: OnPress,
private val pcGui: PCGUI
) : Button(pX, pY, WIDTH, HEIGHT, Component.literal("WallpaperButton"), onPress, DEFAULT_NARRATION) {
companion object {
const val WIDTH = 24
const val HEIGHT = 11
private val buttonResource = cobblemonResource("textures/gui/pc/pc_wallpaper_button.png")
}
override fun renderWidget(context: net.minecraft.client.gui.GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
blitk(
matrixStack = context.pose(),
texture = buttonResource,
x = x,
y = y,
width = WIDTH,
height = HEIGHT,
vOffset = if (isHovered() || !pcGui.configuration.showParty) HEIGHT else 0,
textureHeight = HEIGHT * 2
)
}
override fun playDownSound(soundManager: SoundManager) {
soundManager.play(SimpleSoundInstance.forUI(CobblemonSounds.PC_CLICK, 1.0F))
}
}
@@ -0,0 +1,153 @@
/*
* 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.pc
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.gui.blitk
import com.cobblemon.mod.common.api.text.bold
import com.cobblemon.mod.common.api.text.text
import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.gui.ScrollingWidget
import com.cobblemon.mod.common.client.gui.pc.WallpapersScrollingWidget.WallpaperEntry
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.client.render.gui.PCBoxWallpaperRepository
import com.cobblemon.mod.common.net.messages.server.storage.pc.RequestChangePCBoxWallpaperPacket
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.lang
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.resources.sounds.SimpleSoundInstance
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
class WallpapersScrollingWidget(
pX: Int, val pY: Int,
val pcGui: PCGUI,
val storageWidget: StorageWidget
) : ScrollingWidget<WallpaperEntry>(
width = WIDTH,
height = HEIGHT,
left = pX,
top = 0,
slotHeight = SLOT_HEIGHT + SLOT_PADDING,
scrollBarWidth = SCROLL_BAR_WIDTH
) {
companion object {
const val WIDTH = 67
const val HEIGHT = 147
const val SLOT_WIDTH = 58
const val SLOT_HEIGHT = 53
const val SLOT_PADDING = 3
const val SCROLL_BAR_WIDTH = 3
val ENTRY_HOVERED = cobblemonResource("textures/gui/pc/wallpaper_entry_hover.png")
val BACKGROUND = cobblemonResource("textures/gui/pc/wallpaper_widget_background.png")
}
init {
this.visible = false
this.y = pY
createEntries()
}
override fun renderWidget(
context: GuiGraphics,
mouseX: Int,
mouseY: Int,
delta: Float
) {
blitk(
matrixStack = context.pose(),
texture = BACKGROUND,
x = x - 1,
y = y - 1,
width = width + 1,
height = height + 2
)
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = lang("ui.wallpapers").bold(),
x = x + 23,
y = y - 18.5,
centered = true,
shadow = true
)
super.renderWidget(context, mouseX, mouseY, delta)
}
private fun createEntries() {
clearEntries()
for (wallpaper in PCBoxWallpaperRepository.wallpapers) {
addEntry(WallpaperEntry(wallpaper))
}
}
override fun getRowLeft(): Int {
return this.left + SLOT_PADDING
}
override fun getRowWidth(): Int {
return SLOT_WIDTH
}
override fun getRowRight(): Int {
return this.rowLeft + SLOT_WIDTH
}
inner class WallpaperEntry(val wallpaper: ResourceLocation) : Slot<WallpaperEntry>() {
override fun render(
guiGraphics: GuiGraphics,
index: Int,
top: Int,
left: Int,
width: Int,
height: Int,
mouseX: Int,
mouseY: Int,
hovering: Boolean,
partialTick: Float
) {
val matrices = guiGraphics.pose()
blitk(
matrixStack = matrices,
texture = wallpaper,
x = left,
y = top,
width = width,
height = height,
)
if (hovering) {
blitk(
matrixStack = matrices,
texture = ENTRY_HOVERED,
x = left,
y = top,
width = width,
height = height
)
}
}
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
if (this@WallpapersScrollingWidget.visible && isMouseOver(mouseX, mouseY)) {
RequestChangePCBoxWallpaperPacket(pcGui.pc.uuid, storageWidget.box, wallpaper).sendToServer()
pcGui.pc.boxes[storageWidget.box].wallpaper = wallpaper
minecraft.soundManager.play(SimpleSoundInstance.forUI(CobblemonSounds.PC_CLICK, 1.0F))
return true
}
return false
}
override fun getNarration(): Component? {
return wallpaper.toString().text()
}
}
}
@@ -38,7 +38,7 @@ import com.cobblemon.mod.common.client.gui.summary.widgets.SoundlessWidget
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.client.render.drawScaledTextJustifiedRight
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.pokemon.FormData
import com.cobblemon.mod.common.pokemon.Gender
@@ -655,7 +655,7 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
fun recalculatePoses(renderablePokemon: RenderablePokemon) {
val state = FloatingState()
state.currentAspects = renderablePokemon.aspects
val poser = PokemonModelRepository.getPoser(renderablePokemon.species.resourceIdentifier, state)
val poser = VaryingModelRepository.getPoser(renderablePokemon.species.resourceIdentifier, state)
state.currentModel = poser
this.poseList = poser.poses
.map { it.value.poseTypes.minBy { it.ordinal } }
@@ -80,7 +80,7 @@ class SizeWidget(val pX: Int, val pY: Int) : SoundlessWidget(
matrices.pushPose()
matrices.translate(
pX.toDouble() + 50,
pY.toDouble() + (POKEMON_DESCRIPTION_HEIGHT / 2) + 18.5 - baseScale * modelScale * 1.5,
pY.toDouble() + (POKEMON_DESCRIPTION_HEIGHT / 2) + 18.5,
0.0
)
drawProfilePokemon(
@@ -161,7 +161,7 @@ class StarterSelectionScreen(private val categories: List<RenderableStarterCateg
pX = x + 119, pY = height / 2 + 84,
pWidth = StarterRoundabout.MODEL_WIDTH, pHeight = StarterRoundabout.MODEL_HEIGHT,
pokemon = currentPokemon,
rotationVector = this.modelWidget.rotVec
rotationVector = this.modelWidget.rotationVector
)
starterRoundaboutLeft = StarterRoundabout(
@@ -169,7 +169,7 @@ class StarterSelectionScreen(private val categories: List<RenderableStarterCateg
pWidth = StarterRoundabout.MODEL_WIDTH, pHeight = StarterRoundabout.MODEL_HEIGHT,
pokemon = currentCategory.pokemon[leftOfCurrentSelection()],
clickAction = { _, _ -> this.left() },
rotationVector = this.modelWidget.rotVec
rotationVector = this.modelWidget.rotationVector
)
starterRoundaboutRight = StarterRoundabout(
@@ -177,7 +177,7 @@ class StarterSelectionScreen(private val categories: List<RenderableStarterCateg
pWidth = StarterRoundabout.MODEL_WIDTH, pHeight = StarterRoundabout.MODEL_HEIGHT,
pokemon = currentCategory.pokemon[rightOfCurrentSelection()],
clickAction = { _, _ -> this.right() },
rotationVector = this.modelWidget.rotVec
rotationVector = this.modelWidget.rotationVector
)
addRenderableWidget(starterRoundaboutLeft)
@@ -35,7 +35,7 @@ import com.cobblemon.mod.common.client.gui.summary.widgets.screens.moves.MoveSwa
import com.cobblemon.mod.common.client.gui.summary.widgets.screens.moves.MovesWidget
import com.cobblemon.mod.common.client.gui.summary.widgets.screens.stats.StatWidget
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokemonPacket
import com.cobblemon.mod.common.pokemon.Gender
@@ -235,7 +235,8 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
pokemon = selectedPokemon.asRenderablePokemon(),
baseScale = 2F,
rotationY = 325F,
offsetY = -10.0
offsetY = -10.0,
shouldFollowCursor = true,
)
addRenderableOnly(this.modelWidget)
}
@@ -274,9 +275,11 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
listenToMoveSet()
displayMainScreen(mainScreenIndex)
children().find { it is EvolutionSelectScreen }?.let(this::removeWidget)
if (this::modelWidget.isInitialized) {
this.modelWidget.pokemon = selectedPokemon.asRenderablePokemon()
if (::modelWidget.isInitialized) {
modelWidget.pokemon = selectedPokemon.asRenderablePokemon()
}
if (this::nicknameEntryWidget.isInitialized) {
this.nicknameEntryWidget.setSelectedPokemon(selectedPokemon)
}
@@ -592,12 +595,6 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
return children().any { it.mouseScrolled(mouseX, mouseY, amount, verticalAmount) }
}
/*
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
return children().any { it.mouseClicked(mouseX, mouseY, button) }
}
*/
override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean {
if (sideScreenIndex == MOVE_SWAP || sideScreenIndex == EVOLVE) sideScreen.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
if (mainScreenIndex == MOVES) mainScreen.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
@@ -619,7 +616,7 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
this.focused = null
}
if (Cobblemon.config.enableDebugKeys) {
val model = PokemonModelRepository.getPoser(selectedPokemon.species.resourceIdentifier, modelWidget.state)
val model = VaryingModelRepository.getPoser(selectedPokemon.species.resourceIdentifier, modelWidget.state)
if (keyCode == InputConstants.KEY_UP) {
model.profileTranslation = model.profileTranslation.add(0.0, -0.01, 0.0)
}
@@ -648,7 +645,7 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
override fun onClose() {
if (Cobblemon.config.enableDebugKeys) {
val model = PokemonModelRepository.getPoser(selectedPokemon.species.resourceIdentifier, modelWidget.state)
val model = VaryingModelRepository.getPoser(selectedPokemon.species.resourceIdentifier, modelWidget.state)
Minecraft.getInstance().player?.sendSystemMessage(Component.literal("Profile Translation: ${model.profileTranslation}"))
Minecraft.getInstance().player?.sendSystemMessage(Component.literal("Profile Scale: ${model.profileScale}"))
Cobblemon.LOGGER.info("override var profileTranslation = Vec3d(${model.profileTranslation.x}, ${model.profileTranslation.y}, ${model.profileTranslation.z})")
@@ -8,7 +8,9 @@
package com.cobblemon.mod.common.client.gui.summary.widgets
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
import com.cobblemon.mod.common.client.gui.calculateHeadYawAndPitch
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
import com.cobblemon.mod.common.pokemon.RenderablePokemon
import com.cobblemon.mod.common.util.math.fromEulerXYZDegrees
@@ -20,29 +22,39 @@ import org.joml.Vector3f
class ModelWidget(
pX: Int, pY: Int,
pWidth: Int, pHeight: Int,
var pokemon: RenderablePokemon,
pokemon: RenderablePokemon,
val baseScale: Float = 2.7F,
var rotationY: Float = 35F,
var offsetY: Double = 0.0,
val playCryOnClick: Boolean = false,
val shouldFollowCursor: Boolean = false,
): SoundlessWidget(pX, pY, pWidth, pHeight, Component.literal("Summary - ModelWidget")) {
companion object {
var render = true
const val MAX_SECONDS_LOOKING = 6L
}
var pokemon: RenderablePokemon = pokemon
set (value) {
field = value
currentYawAndPitch = Pair(0f, 0f)
}
var state = FloatingState()
val rotVec = Vector3f(13F, rotationY, 0F)
var lookStartTime: Long? = null
var currentYawAndPitch: Pair<Float, Float> = Pair(0f, 0f)
val rotationVector = Vector3f(13F, rotationY, 0F)
override fun renderWidget(context: GuiGraphics, pMouseX: Int, pMouseY: Int, partialTicks: Float) {
if (!render) {
return
}
isHovered = pMouseX >= x && pMouseY >= y && pMouseX < x + width && pMouseY < y + height
renderPKM(context, partialTicks)
renderPKM(context, partialTicks, pMouseX, pMouseY)
}
private fun renderPKM(context: GuiGraphics, partialTicks: Float) {
private fun renderPKM(context: GuiGraphics, partialTicks: Float, mouseX: Int, mouseY: Int) {
val matrices = context.pose()
matrices.pushPose()
@@ -50,19 +62,48 @@ class ModelWidget(
x,
y,
x + width,
y + height
y + height
)
matrices.translate(x + width * 0.5, y.toDouble() + offsetY, 0.0)
matrices.scale(baseScale, baseScale, baseScale)
matrices.pushPose()
if (isHovered) {
lookStartTime = System.currentTimeMillis()
}
val timeLooking = lookStartTime?.let { (System.currentTimeMillis() - it) / 1000 } ?: MAX_SECONDS_LOOKING
val lookedTooMuch = timeLooking >= MAX_SECONDS_LOOKING
val resetToCenter = (!isHovered && lookedTooMuch) || !shouldFollowCursor || !Cobblemon.config.summaryPokemonFollowCursor
if (resetToCenter) {
lookStartTime = null
}
val rotation = Quaternionf().fromEulerXYZDegrees(rotationVector)
if (shouldFollowCursor) {
currentYawAndPitch = calculateHeadYawAndPitch(
x + width / 2f,
y + height / 2f,
rotation,
mouseX,
mouseY,
currentYawAndPitch.first,
currentYawAndPitch.second,
resetToCenter
)
}
drawProfilePokemon(
renderablePokemon = pokemon,
matrixStack = matrices,
rotation = Quaternionf().fromEulerXYZDegrees(rotVec),
rotation = rotation,
state = state,
partialTicks = partialTicks
partialTicks = partialTicks,
headYaw = currentYawAndPitch.first,
headPitch = currentYawAndPitch.second,
)
matrices.popPose()
@@ -72,7 +113,10 @@ class ModelWidget(
}
override fun mouseClicked(pMouseX: Double, pMouseY: Double, pButton: Int): Boolean {
if (this.isHovered) playCry()
if (this.isHovered) {
playCry()
}
return super.mouseClicked(pMouseX, pMouseY, pButton)
}
@@ -13,7 +13,7 @@ import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.keybind.CobblemonKeyBinding
import com.cobblemon.mod.common.client.keybind.KeybindCategories
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.mojang.blaze3d.platform.InputConstants
import net.minecraft.client.Minecraft
import net.minecraft.network.chat.Component
@@ -38,7 +38,7 @@ object DebugKeybindings {
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
if (currentlySelectedPokemon != null) {
val state = FloatingState().also { it.currentAspects = currentlySelectedPokemon.aspects }
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
val model = VaryingModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
model.portraitScale += 0.01F
}
@@ -54,7 +54,7 @@ object DebugKeybindings {
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
if (currentlySelectedPokemon != null) {
val state = FloatingState().also { it.currentAspects = currentlySelectedPokemon.aspects }
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
val model = VaryingModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
model.portraitScale -= 0.01F
}
@@ -71,7 +71,7 @@ object DebugKeybindings {
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
if (currentlySelectedPokemon != null) {
val state = FloatingState().also { it.currentAspects = currentlySelectedPokemon.aspects }
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
val model = VaryingModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
model.portraitTranslation = model.portraitTranslation.add(0.0, -0.01, 0.0)
}
@@ -87,7 +87,7 @@ object DebugKeybindings {
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
if (currentlySelectedPokemon != null) {
val state = FloatingState().also { it.currentAspects = currentlySelectedPokemon.aspects }
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
val model = VaryingModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
model.portraitTranslation = model.portraitTranslation.add(0.0, 0.01, 0.0)
}
@@ -104,7 +104,7 @@ object DebugKeybindings {
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
if (currentlySelectedPokemon != null) {
val state = FloatingState().also { it.currentAspects = currentlySelectedPokemon.aspects }
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
val model = VaryingModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
model.portraitTranslation = model.portraitTranslation.add(-0.01, 0.0, 0.0)
}
@@ -121,7 +121,7 @@ object DebugKeybindings {
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
if (currentlySelectedPokemon != null) {
val state = FloatingState().also { it.currentAspects = currentlySelectedPokemon.aspects }
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
val model = VaryingModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
model.portraitTranslation = model.portraitTranslation.add(0.01, 0.0, 0.0)
}
}
@@ -137,7 +137,7 @@ object DebugKeybindings {
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
if (currentlySelectedPokemon != null) {
val state = FloatingState().also { it.currentAspects = currentlySelectedPokemon.aspects }
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
val model = VaryingModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
Minecraft.getInstance().player?.sendSystemMessage(Component.literal("Portrait Translation: ${model.portraitTranslation}"))
Minecraft.getInstance().player?.sendSystemMessage(Component.literal("Portrait Scale: ${model.portraitScale}"))
Cobblemon.LOGGER.info("override var portraitTranslation = Vec3d(${model.portraitTranslation.x}, ${model.portraitTranslation.y}, ${model.portraitTranslation.z})")
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.net.battle
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.api.text.aqua
import com.cobblemon.mod.common.api.text.green
import com.cobblemon.mod.common.client.ClientMultiBattleTeamMember
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.render.ClientPlayerIcon
import com.cobblemon.mod.common.net.messages.client.battle.TeamMemberAddNotificationPacket
import com.cobblemon.mod.common.util.lang
import net.minecraft.client.Minecraft
object TeamMemberAddNotificationHandler : ClientNetworkPacketHandler<TeamMemberAddNotificationPacket> {
override fun handle(packet: TeamMemberAddNotificationPacket, client: Minecraft) {
if (CobblemonClient.teamData.multiBattleTeamMembers.any { it.uuid == packet.teamMemberUUID }) {
return //already knows about the new member
}
var newMember = ClientMultiBattleTeamMember(packet.teamMemberUUID, packet.teamMemberName)
CobblemonClient.teamData.multiBattleTeamMembers.add(newMember)
ClientPlayerIcon.update(newMember.uuid)
client.player?.sendSystemMessage(
lang(
"team.join.other",
newMember.name.copy().aqua(),
).green()
)
}
}
@@ -9,14 +9,11 @@
package com.cobblemon.mod.common.client.net.pokemon.update
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.client.render.layer.PokemonOnShoulderRenderer
import com.cobblemon.mod.common.net.messages.client.PokemonUpdatePacket
import net.minecraft.client.Minecraft
class PokemonUpdatePacketHandler<T : PokemonUpdatePacket<T>> : ClientNetworkPacketHandler<T> {
override fun handle(packet: T, client: Minecraft) {
packet.applyToPokemon()
val player = client.player ?: return
PokemonOnShoulderRenderer.clearCache(player)
}
}
@@ -0,0 +1,20 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.net.storage.pc
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.ChangePCBoxWallpaperPacket
import net.minecraft.client.Minecraft
object ChangePCBoxWallpaperHandler : ClientNetworkPacketHandler<ChangePCBoxWallpaperPacket> {
override fun handle(packet: ChangePCBoxWallpaperPacket, client: Minecraft) {
CobblemonClient.storage.changeBoxWallpaper(packet.storeID, packet.boxNumber, packet.wallpaper)
}
}
@@ -0,0 +1,20 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.net.storage.pc
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.net.messages.client.storage.pc.RenamePCBoxPacket
import net.minecraft.client.Minecraft
object RenamePCBoxHandler : ClientNetworkPacketHandler<RenamePCBoxPacket> {
override fun handle(packet: RenamePCBoxPacket, client: Minecraft) {
CobblemonClient.storage.renameBox(packet.storeID, packet.boxNumber, packet.name)
}
}
@@ -0,0 +1,22 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.net.storage.pc
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.client.render.gui.PCBoxWallpaperRepository
import com.cobblemon.mod.common.net.messages.server.storage.pc.PCBoxWallpapersPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.RequestPCBoxWallpapersPacket
import net.minecraft.client.Minecraft
object RequestPCBoxWallpapersHandler : ClientNetworkPacketHandler<RequestPCBoxWallpapersPacket> {
override fun handle(packet: RequestPCBoxWallpapersPacket, client: Minecraft) {
PCBoxWallpaperRepository.findWallpapers(client.resourceManager)
PCBoxWallpapersPacket(PCBoxWallpaperRepository.wallpapers).sendToServer()
}
}
@@ -11,15 +11,16 @@ package com.cobblemon.mod.common.client.net.storage.pc
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.storage.ClientBox
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPacket
import net.minecraft.client.Minecraft
import net.minecraft.network.chat.Component
object SetPCBoxPokemonHandler : ClientNetworkPacketHandler<SetPCBoxPokemonPacket> {
override fun handle(packet: SetPCBoxPokemonPacket, client: Minecraft) {
object SetPCBoxHandler : ClientNetworkPacketHandler<SetPCBoxPacket> {
override fun handle(packet: SetPCBoxPacket, client: Minecraft) {
CobblemonClient.storage.pcStores[packet.storeID]?.let { pc ->
val boxNumber = packet.boxNumber
while (pc.boxes.size <= boxNumber) { pc.boxes.add(ClientBox()) }
pc.boxes[boxNumber] = ClientBox()
pc.boxes[boxNumber] = ClientBox(if (packet.name.isBlank()) null else Component.literal(packet.name), packet.wallpaper)
packet.pokemon.forEach { (slot, pokemon) -> pc.boxes[packet.boxNumber].slots[slot] = pokemon(client.level!!.registryAccess()) }
}
}
@@ -0,0 +1,20 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.net.storage.pc
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.client.render.gui.PCBoxWallpaperRepository
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.SetPCBoxWallpapersPacket
import net.minecraft.client.Minecraft
object SetPCBoxWallpapersHandler : ClientNetworkPacketHandler<SetPCBoxWallpapersPacket> {
override fun handle(packet: SetPCBoxWallpapersPacket, client: Minecraft) {
PCBoxWallpaperRepository.wallpapers = packet.wallpapers
}
}
@@ -30,12 +30,12 @@ import org.joml.Vector4f
* @author Hiroku
* @since May 14th, 2022
*/
class VaryingRenderableResolver<T : PosableModel>(
class VaryingRenderableResolver(
val name: ResourceLocation,
val variations: MutableList<ModelAssetVariation>
) {
lateinit var repository: VaryingModelRepository<T>
val posers = mutableMapOf<Pair<ResourceLocation, ResourceLocation>, T>()
lateinit var repository: VaryingModelRepository
val posers = mutableMapOf<Pair<ResourceLocation, ResourceLocation>, PosableModel>()
val models = mutableMapOf<ResourceLocation, Bone>()
fun getResolvedPoser(state: PosableState): ResourceLocation {
@@ -98,19 +98,19 @@ class VaryingRenderableResolver<T : PosableModel>(
.create()
}
fun initialize(repository: VaryingModelRepository<T>) {
fun initialize(repository: VaryingModelRepository) {
this.repository = repository
posers.clear()
getAllModels().forEach { identifier ->
try {
models[identifier] = repository.texturedModels[identifier]!!.invoke(repository.isForLivingEntityRenderer)
models[identifier] = repository.texturedModels[identifier]!!
} catch (e: Exception) {
throw IllegalStateException("Unable to load model $identifier for $name", e)
}
}
}
fun getPoser(state: PosableState): T {
fun getPoser(state: PosableState): PosableModel {
val poserName = getResolvedPoser(state)
val poserSupplier = repository.posers[poserName] ?: throw IllegalStateException("No poser found for name: $poserName for $name")
val modelName = getResolvedModel(state)
@@ -9,8 +9,9 @@
package com.cobblemon.mod.common.client.render.block
import com.cobblemon.mod.common.block.entity.GildedChestBlockEntity
import com.cobblemon.mod.common.client.render.models.blockbench.repository.BlockEntityModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.blockentity.BlockEntityModel
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.math.Axis
import net.minecraft.client.renderer.MultiBufferSource
@@ -40,9 +41,9 @@ class GildedChestBlockRenderer(context: BlockEntityRendererProvider.Context) : B
val poserId = entity.type.poserId
val model = BlockEntityModelRepository.getPoser(poserId, state)
val model = VaryingModelRepository.getPoser(poserId, state) as BlockEntityModel
model.context = context
val texture = BlockEntityModelRepository.getTexture(poserId, state)
val texture = VaryingModelRepository.getTexture(poserId, state)
val vertexConsumer = vertexConsumers.getBuffer(RenderType.entityCutout(texture))
model.bufferProvider = vertexConsumers
state.currentModel = model
@@ -67,7 +68,7 @@ class GildedChestBlockRenderer(context: BlockEntityRendererProvider.Context) : B
ageInTicks = state.animationSeconds * 20
)
model.render(context, matrices, vertexConsumer, light, overlay, -0x1)
model.withLayerContext(vertexConsumers, state, BlockEntityModelRepository.getLayers(poserId, state)) {
model.withLayerContext(vertexConsumers, state, VaryingModelRepository.getLayers(poserId, state)) {
model.render(context, matrices, vertexConsumer, light, OverlayTexture.NO_OVERLAY, -0x1)
}
model.setDefault()
@@ -12,23 +12,24 @@ import com.cobblemon.mod.common.CobblemonBlocks
import com.cobblemon.mod.common.block.entity.RestorationTankBlockEntity
import com.cobblemon.mod.common.block.multiblock.FossilMultiblockStructure
import com.cobblemon.mod.common.client.CobblemonBakingOverrides
import com.cobblemon.mod.common.client.render.models.blockbench.repository.FossilModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.fossil.FossilModel
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.WaveFunction
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.parabolaFunction
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.rerange
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.timeDilate
import com.cobblemon.mod.common.util.cobblemonResource
import kotlin.math.pow
import net.minecraft.world.level.block.HorizontalDirectionalBlock
import net.minecraft.client.renderer.texture.OverlayTexture
import net.minecraft.client.renderer.RenderType
import net.minecraft.client.renderer.MultiBufferSource
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.math.Axis
import kotlin.math.pow
import net.minecraft.client.renderer.MultiBufferSource
import net.minecraft.client.renderer.RenderType
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
import net.minecraft.client.renderer.texture.OverlayTexture
import net.minecraft.core.Direction
import net.minecraft.world.level.block.HorizontalDirectionalBlock
class RestorationTankRenderer(ctx: BlockEntityRendererProvider.Context) : BlockEntityRenderer<RestorationTankBlockEntity> {
val context = RenderContext().also {
@@ -114,8 +115,14 @@ class RestorationTankRenderer(ctx: BlockEntityRendererProvider.Context) : BlockE
state.updatePartialTicks(tickDelta)
state.currentAspects = aspects
var fossilPoserId = fossil.identifier.withPath("${fossil.identifier.path}_fetus")
val completionPercentage = (1 - timeRemaining / FossilMultiblockStructure.TIME_TO_TAKE.toFloat()).coerceIn(0F, 1F)
val fossilFetusModel = FossilModelRepository.getPoser(fossil.identifier, state)
val fossilFetusModel = VaryingModelRepository.getPoser(fossilPoserId, state) as? FossilModel ?: let {
fossilPoserId = cobblemonResource("fossil_fetus")
VaryingModelRepository.getPoser(fossilPoserId, state) as FossilModel
}
fossilFetusModel.context = context
val embryo1Scale = EMBRYO_CURVE_1(completionPercentage)
@@ -124,15 +131,15 @@ class RestorationTankRenderer(ctx: BlockEntityRendererProvider.Context) : BlockE
val fossilScale = FOSSIL_CURVE(completionPercentage)
val identifiersAndScales = listOf(
Pair(EMBRYO_IDENTIFIERS[0], embryo1Scale),
Pair(EMBRYO_IDENTIFIERS[1], embryo2Scale),
Pair(EMBRYO_IDENTIFIERS[2], embryo3Scale),
Pair(fossil.identifier, fossilScale)
Pair(EMBRYO_IDENTIFIERS[0], embryo1Scale),
Pair(EMBRYO_IDENTIFIERS[1], embryo2Scale),
Pair(EMBRYO_IDENTIFIERS[2], embryo3Scale),
Pair(fossilPoserId, fossilScale)
)
identifiersAndScales.forEach { (identifier, scale) ->
val model = FossilModelRepository.getPoser(identifier, state)
val texture = FossilModelRepository.getTexture(identifier, state)
val model = VaryingModelRepository.getPoser(identifier, state) as FossilModel
val texture = VaryingModelRepository.getTexture(identifier, state)
if (scale > 0F) {
val vertexConsumer = vertexConsumers.getBuffer(RenderType.entityCutout(texture))
@@ -175,7 +182,7 @@ class RestorationTankRenderer(ctx: BlockEntityRendererProvider.Context) : BlockE
ageInTicks = state.animationSeconds * 20
)
model.render(context, matrices, vertexConsumer, light, overlay, -0x1)
model.withLayerContext(vertexConsumers, state, FossilModelRepository.getLayers(fossil.identifier, state)) {
model.withLayerContext(vertexConsumers, state, VaryingModelRepository.getLayers(fossilPoserId, state)) {
model.render(context, matrices, vertexConsumer, light, OverlayTexture.NO_OVERLAY, -0x1)
}
model.setDefault()
@@ -0,0 +1,196 @@
/*
* 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.block
import com.cobblemon.mod.common.CobblemonBlocks
import com.cobblemon.mod.common.block.entity.StadiumBlockEntity
import com.cobblemon.mod.common.client.render.models.blockbench.drone.DroneModel
import com.cobblemon.mod.common.client.render.models.blockbench.drone.DroneState
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.util.cobblemonResource
import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.math.Axis
import net.minecraft.client.renderer.MultiBufferSource
import net.minecraft.client.renderer.RenderType
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
import net.minecraft.client.renderer.texture.OverlayTexture
import net.minecraft.core.Direction
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.level.block.HorizontalDirectionalBlock
import net.minecraft.world.level.block.state.BlockState
class StadiumBlockRenderer(ctx: BlockEntityRendererProvider.Context) : BlockEntityRenderer<StadiumBlockEntity> {
val context = RenderContext().also {
it.put(RenderContext.DO_QUIRKS, false)
it.put(RenderContext.RENDER_STATE, RenderContext.RenderState.BLOCK)
}
private var pathIndex = 0
private var animationTime = 0.0
private val droneSpeed = 0.10
override fun render(
blockEntity: StadiumBlockEntity,
tickDelta: Float,
poseStack: PoseStack,
multiBufferSource: MultiBufferSource,
light: Int,
overlay: Int
) {
val blockState = blockEntity.blockState
val yRot = blockState.getValue(HorizontalDirectionalBlock.FACING).toYRot()
val isClientSide = blockEntity.level?.isClientSide == true
if (!isClientSide) return
val stadiumBlockState = blockEntity.level?.getBlockState(blockEntity.blockPos) ?: return
if (stadiumBlockState.block != CobblemonBlocks.STADIUM) {
return
}
val droneState = blockEntity.droneState
poseStack.pushPose()
if (blockEntity.isInUse) {
if (blockEntity.pathPoints.isEmpty()) {
poseStack.popPose()
return
}
spawnDebugParticles(blockEntity) // debug particles
// Center the drone at the block's center
poseStack.translate(0.5, -3.0, 0.5)
//poseStack.mulPose(Axis.XP.rotationDegrees(180F))
//poseStack.mulPose(Axis.YP.rotationDegrees(180F))
val points = blockEntity.pathPoints
val nextIndex = (pathIndex + 1) % points.size
val currentPoint = points[pathIndex]
val nextPoint = points[nextIndex]
animationTime += tickDelta * droneSpeed
if (animationTime >= 1.0) {
animationTime = 0.0
pathIndex = nextIndex
}
val interpolatedPos = currentPoint.lerp(nextPoint, animationTime.toDouble())
println("DEBUG: Drone moving between points:")
println(" - Current Point: ${currentPoint}")
println(" - Next Point: ${nextPoint}")
println(" - Interpolated Position: $interpolatedPos")
poseStack.translate(interpolatedPos.x - blockEntity.blockPos.x,
interpolatedPos.y - blockEntity.blockPos.y,
interpolatedPos.z - blockEntity.blockPos.z)
println("DEBUG: Drone position interpolated to: $interpolatedPos")
poseStack.mulPose(Axis.YP.rotationDegrees(-yRot))
poseStack.mulPose(Axis.ZP.rotationDegrees(180F)) // flip the drone right side up
renderDrone(droneState, "sleep", tickDelta, poseStack, 1.0F, multiBufferSource, light)
} else {
val yRot = blockState.getValue(HorizontalDirectionalBlock.FACING).toYRot()
val poseEntry = poseStack.last()
val matrix = poseEntry.pose()
poseStack.translate(0.5, 0.0, 0.5)
poseStack.mulPose(Axis.YP.rotationDegrees(yRot))
val posX = matrix.m03()
val posY = matrix.m13()
val posZ = matrix.m23()
println("DEBUG: Drone is NOT in use. Rendering default position at: x=$posX, y=$posY, z=$posZ")
poseStack.mulPose(Axis.ZP.rotationDegrees(180F))
renderDrone(droneState, "sleep", tickDelta, poseStack, 1.0F, multiBufferSource, light)
}
poseStack.popPose()
}
fun renderDrone(
state: DroneState,
pose: String,
tickDelta: Float,
poseStack: PoseStack,
scale: Float = 1F,
multiBufferSource: MultiBufferSource,
light: Int,
) {
state.updatePartialTicks(tickDelta)
val droneResource: ResourceLocation = cobblemonResource("rotom_drone")
val model = VaryingModelRepository.getPoser(droneResource, state) as DroneModel
val texture = VaryingModelRepository.getTexture(droneResource, state)
val buffer = multiBufferSource.getBuffer(RenderType.entityCutout(texture))
model.bufferProvider = multiBufferSource
state.currentModel = model
state.setPose(pose)
model.context = context
context.put(RenderContext.TEXTURE, texture)
context.put(RenderContext.RENDER_STATE, RenderContext.RenderState.BLOCK)
context.put(RenderContext.POSABLE_STATE, state)
model.applyAnimations(
entity = null,
state = state,
headYaw = 0F,
headPitch = 0F,
limbSwing = 0F,
limbSwingAmount = 0F,
ageInTicks = state.animationSeconds * 20
)
poseStack.scale(scale, scale, scale)
// TODO: Make drone lighting dynamic (simply using the light arg makes the drone always appear dark)
model.withLayerContext(multiBufferSource, state, VaryingModelRepository.getLayers(droneResource, state)) {
model.render(context, poseStack, buffer, 200, OverlayTexture.NO_OVERLAY, -0x1)
}
model.setDefault()
}
private fun spawnDebugParticles(blockEntity: StadiumBlockEntity) {
val world = blockEntity.level ?: return
if (!world.isClientSide) return // Only run on the client-side
for (point in blockEntity.pathPoints) {
world.addParticle(
net.minecraft.core.particles.ParticleTypes.FLAME, // Test particle (changeable)
point.x, point.y, point.z, // Position of the particle
0.0, 0.02, 0.0 // Slight upward motion
)
}
// Spawn a special particle at the next interpolation point
if (blockEntity.pathPoints.isNotEmpty()) {
val nextPoint = blockEntity.pathPoints[(pathIndex + 1) % blockEntity.pathPoints.size]
world.addParticle(
net.minecraft.core.particles.ParticleTypes.END_ROD, // Different effect for next point
nextPoint.x, nextPoint.y, nextPoint.z,
0.0, 0.05, 0.0
)
}
}
}
@@ -10,8 +10,7 @@ package com.cobblemon.mod.common.client.render.generic
import com.cobblemon.mod.common.client.entity.GenericBedrockClientDelegate
import com.cobblemon.mod.common.client.render.models.blockbench.generic.PosableGenericEntityModel
import com.cobblemon.mod.common.client.render.models.blockbench.repository.GenericBedrockEntityModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.entity.generic.GenericBedrockEntity
import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.math.Axis
@@ -20,11 +19,10 @@ import net.minecraft.client.renderer.RenderType
import net.minecraft.client.renderer.entity.EntityRenderer
import net.minecraft.client.renderer.entity.EntityRendererProvider
import net.minecraft.client.renderer.texture.OverlayTexture
import net.minecraft.resources.ResourceLocation
class GenericBedrockRenderer(context: EntityRendererProvider.Context) : EntityRenderer<GenericBedrockEntity>(context) {
val model = PosableGenericEntityModel()
override fun getTextureLocation(entity: GenericBedrockEntity) = GenericBedrockEntityModelRepository.getTexture(entity.category, (entity.delegate as GenericBedrockClientDelegate))
override fun getTextureLocation(entity: GenericBedrockEntity) = VaryingModelRepository.getTexture(entity.category, (entity.delegate as GenericBedrockClientDelegate))
override fun render(entity: GenericBedrockEntity, yaw: Float, partialTicks: Float, poseStack: PoseStack, buffer: MultiBufferSource, packedLight: Int) {
if (entity.isInvisible) {
return
@@ -32,7 +30,7 @@ class GenericBedrockRenderer(context: EntityRendererProvider.Context) : EntityRe
val state = entity.delegate as GenericBedrockClientDelegate
state.currentAspects = entity.aspects
val model = GenericBedrockEntityModelRepository.getPoser(entity.category, state)
val model = VaryingModelRepository.getPoser(entity.category, state)
this.model.posableModel = model
model.context = this.model.context
this.model.setupEntityTypeContext(entity)
@@ -43,7 +41,7 @@ class GenericBedrockRenderer(context: EntityRendererProvider.Context) : EntityRe
val vertexConsumer = buffer.getBuffer(RenderType.entityCutout(getTextureLocation(entity)))
state.updatePartialTicks(partialTicks)
model.setLayerContext(buffer, state, PokemonModelRepository.getLayers(entity.category, state))
model.setLayerContext(buffer, state, VaryingModelRepository.getLayers(entity.category, state))
this.model.setupAnim(entity, 0f, 0f, entity.tickCount + partialTicks, 0F, 0F)
this.model.renderToBuffer(poseStack, vertexConsumer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.render.gui
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.endsWith
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.packs.resources.ResourceManager
object PCBoxWallpaperRepository {
lateinit var wallpapers: List<ResourceLocation>
var defaultWallpaper = cobblemonResource("textures/gui/pc/pc_screen_overlay.png")
fun findWallpapers(resourceManager: ResourceManager): List<ResourceLocation> {
val wallpapers = mutableListOf<ResourceLocation>(defaultWallpaper)
resourceManager.listResources("textures/gui/pc/wallpaper") { path -> path?.endsWith(".png") == true }.keys.forEach { key ->
wallpapers.add(key)
}
this.wallpapers = wallpapers
return wallpapers
}
}
@@ -9,8 +9,8 @@
package com.cobblemon.mod.common.client.render.item
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.item.PokemonItem
import com.cobblemon.mod.common.util.math.fromEulerXYZDegrees
@@ -38,7 +38,7 @@ class PokemonItemRenderer : CobblemonBuiltinItemRenderer {
val state = FloatingState()
state.currentAspects = aspects
matrices.pushPose()
val model = PokemonModelRepository.getPoser(species.resourceIdentifier, state)
val model = VaryingModelRepository.getPoser(species.resourceIdentifier, state)
model.context = context
context.put(RenderContext.RENDER_STATE, RenderContext.RenderState.PROFILE)
context.put(RenderContext.SPECIES, species.resourceIdentifier)
@@ -46,7 +46,7 @@ class PokemonItemRenderer : CobblemonBuiltinItemRenderer {
context.put(RenderContext.POSABLE_STATE, state)
state.currentModel = model
val renderLayer = RenderType.entityCutout(PokemonModelRepository.getTexture(species.resourceIdentifier, state))
val renderLayer = RenderType.entityCutout(VaryingModelRepository.getTexture(species.resourceIdentifier, state))
val transformations = positions[mode]!!
@@ -75,7 +75,7 @@ class PokemonItemRenderer : CobblemonBuiltinItemRenderer {
// x = red, y = green, z = blue, w = alpha
val tint = pokemonItem.tint(stack)
model.withLayerContext(vertexConsumers, state, PokemonModelRepository.getLayers(species.resourceIdentifier, state)) {
model.withLayerContext(vertexConsumers, state, VaryingModelRepository.getLayers(species.resourceIdentifier, state)) {
val tintRed = (tint.x * 255).toInt()
val tintGreen = (tint.y * 255).toInt()
val tintBlue = (tint.z * 255).toInt()
@@ -11,8 +11,8 @@ package com.cobblemon.mod.common.client.render.layer
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.pokemon.FormData
import com.cobblemon.mod.common.pokemon.Pokemon
@@ -87,27 +87,21 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
) {
val compoundTag = if (pLeftShoulder) livingEntity.shoulderEntityLeft else livingEntity.shoulderEntityRight
if (compoundTag.isPokemonEntity()) {
matrixStack.pushPose()
livingEntity.level().profiler.push("shoulder_render_".plus(if(pLeftShoulder) "left" else "right"))
val uuid = this.extractUuid(compoundTag)
val cache = playerCache.getOrPut(livingEntity.uuid) { ShoulderCache() }
var shoulderData: ShoulderData? = null
if (pLeftShoulder && cache.lastKnownLeft?.uuid != uuid) {
shoulderData = this.extractData(compoundTag, uuid)
cache.lastKnownLeft = shoulderData
}
else if (!pLeftShoulder && cache.lastKnownRight?.uuid != uuid) {
shoulderData = this.extractData(compoundTag, uuid)
cache.lastKnownRight = shoulderData
}
val shoulderData = this.extractData(compoundTag, uuid)
if (pLeftShoulder) cache.lastKnownLeft = shoulderData else cache.lastKnownRight = shoulderData
if (shoulderData == null){
// Could be null
shoulderData = (if (pLeftShoulder) cache.lastKnownLeft else cache.lastKnownRight) ?: return
// Nothing to do
return
}
matrixStack.pushPose()
var state = FloatingState()
state.currentAspects = shoulderData.aspects
val model = PokemonModelRepository.getPoser(shoulderData.species.resourceIdentifier, state)
val model = VaryingModelRepository.getPoser(shoulderData.species.resourceIdentifier, state)
model.context = context
context.put(RenderContext.SPECIES, shoulderData.species.resourceIdentifier)
context.put(RenderContext.ASPECTS, shoulderData.aspects)
@@ -129,6 +123,7 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
)
matrixStack.scale(scale, scale, scale)
matrixStack.translate(0f, 1.5f, 0f)
state = if (pLeftShoulder && shoulderData != lastRenderedLeft) {
leftState = configureState(state, model, true)
@@ -144,7 +139,7 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
state.updatePartialTicks(partialTicks)
context.put(RenderContext.POSABLE_STATE, state)
state.currentModel = model
val vertexConsumer = buffer.getBuffer(RenderType.entityCutout(PokemonModelRepository.getTexture(shoulderData.species.resourceIdentifier, state)))
val vertexConsumer = buffer.getBuffer(RenderType.entityCutout(VaryingModelRepository.getTexture(shoulderData.species.resourceIdentifier, state)))
val i = LivingEntityRenderer.getOverlayCoords(livingEntity, 0.0f)
model.applyAnimations(
@@ -157,11 +152,16 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
ageInTicks = livingEntity.tickCount.toFloat()
)
model.render(context, matrixStack, vertexConsumer, packedLight, i, -0x1)
model.withLayerContext(buffer, state, PokemonModelRepository.getLayers(shoulderData.species.resourceIdentifier, state)) {
model.withLayerContext(buffer, state, VaryingModelRepository.getLayers(shoulderData.species.resourceIdentifier, state)) {
model.render(context, matrixStack, vertexConsumer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
}
model.setDefault()
matrixStack.popPose()
livingEntity.level().profiler.pop()
}
else {
val entry = playerCache.getOrPut(livingEntity.uuid) { ShoulderCache() }
if (pLeftShoulder) entry.lastKnownLeft = null else entry.lastKnownRight = null
}
}
@@ -217,16 +217,5 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
return Pair(cache.lastKnownLeft, cache.lastKnownRight)
}
/**
* Clears the cache for the respective player.
* This is required to be done whenever a Pokémon changes in any way (form, evolution, etc.)
*
* @param player The player whose cache to clear
*/
@JvmStatic
fun clearCache(player: Player) {
playerCache.remove(player.uuid)
}
}
}
@@ -20,8 +20,10 @@ import java.lang.reflect.Type
* @since October 18th, 2022
*/
class JsonModelAdapter<T : PosableModel>(private val constructor: (Bone) -> T) : InstanceCreator<T> {
var modelPart: Bone? = null
var model: T? = null
companion object {
var modelPart: Bone? = null
var model: PosableModel? = null
}
override fun createInstance(type: Type): T {
val rootBone = modelPart!!
return constructor(rootBone).also {
@@ -71,9 +71,6 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
@Transient
lateinit var context: RenderContext
/** Whether the renderer that will process this is going to do the weird -1.5 Y offset bullshit that the living entity renderer does. */
@Transient
open var isForLivingEntityRenderer = true
var poses = mutableMapOf<String, Pose>()
@@ -81,6 +78,8 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
@Transient
lateinit var locatorAccess: LocatorAccess
open var transformedParts = arrayOf<ModelPartTransformation>()
open var portraitScale = 1F
open var portraitTranslation = Vec3(0.0, 0.0, 0.0)
@@ -485,7 +484,7 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
/** Applies the given pose's [ModelPartTransformation]s to the model, if there is a matching pose. */
fun applyPose(state: PosableState, pose: Pose, intensity: Float) = pose.transformedParts.forEach { it.apply(state, intensity) }
fun applyPose(state: PosableState, pose: Pose, intensity: Float) = (pose.transformedParts + transformedParts).forEach { it.apply(state, intensity) }
/** Gets the first pose of this model that matches the given [PoseType]. */
fun getPose(pose: PoseType) = poses.values.firstOrNull { pose in it.poseTypes }
fun getPose(name: String) = poses[name]
@@ -697,11 +696,6 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
matrixStack.scale(-1F, -1F, 1F)
}
if (isForLivingEntityRenderer) {
// Standard living entity offset, only God knows why Mojang did this.
matrixStack.translate(0.0, -1.5, 0.0)
}
locatorAccess.update(matrixStack, entity, scale, state.locatorStates, isRoot = true)
}
@@ -10,9 +10,11 @@ package com.cobblemon.mod.common.client.render.models.blockbench
import com.bedrockk.molang.runtime.MoLangRuntime
import com.cobblemon.mod.common.client.render.models.blockbench.animation.ActiveAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
import com.cobblemon.mod.common.entity.PosableEntity
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.isBattling
import com.cobblemon.mod.common.util.isDusk
import com.cobblemon.mod.common.util.isStandingOnRedSand
import com.cobblemon.mod.common.util.isStandingOnSand
@@ -31,7 +33,6 @@ import java.lang.reflect.Type
* @since October 18th, 2022
*/
class PoseAdapter(
val poseConditionReader: (JsonObject) -> List<(PosableState) -> Boolean>,
val modelFinder: () -> PosableModel
) : JsonDeserializer<Pose> {
companion object {
@@ -62,7 +63,10 @@ class PoseAdapter(
addCondition("isDusk") { entity, expectedValue -> entity.isDusk() == expectedValue }
conditionsList.addAll(poseConditionReader(json))
val mustBeInBattle = json.get("isBattle")?.asBoolean
if (mustBeInBattle != null) {
conditionsList.add { mustBeInBattle == it.isBattling }
}
if (json.has("conditions")) {
val conditionSet = json.get("conditions").asJsonArray.map { it.asString.asExpressionLike() }
@@ -8,8 +8,10 @@
package com.cobblemon.mod.common.client.render.models.blockbench
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.entity.PosableEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import net.minecraft.client.renderer.texture.OverlayTexture
import net.minecraft.client.renderer.RenderType
import com.mojang.blaze3d.vertex.VertexConsumer
@@ -46,6 +48,10 @@ abstract class PosableEntityModel<T : Entity>(
) {
val entity = context.request(RenderContext.ENTITY)
val overlay = getOverlayTexture(entity) ?: packedOverlay
if (entity is LivingEntity) {
// We're using the living entity renderer, ergo we need to apply a Y offset of 24 model units (1.5 blocks) for reasons only God can tell us.
stack.translate(0.0, 1.5, 0.0)
}
posableModel.render(context, stack, buffer, packedLight, overlay, color)
}
@@ -27,8 +27,8 @@ class TexturedModel {
@SerializedName("minecraft:geometry")
val geometry: List<ModelGeometry>? = null
fun create(isForLivingEntityRenderer: Boolean) : LayerDefinition {
return createWithUvOverride(isForLivingEntityRenderer, 0, 0, null, null)
fun create() : LayerDefinition {
return createWithUvOverride(0, 0, null, null)
}
fun resolveParentsFromRoot(boneMap: MutableMap<String, ModelBone>, bone: ModelBone): Set<ModelBone> {
@@ -147,7 +147,7 @@ class TexturedModel {
// return modelBuilder.build()
// }
fun createWithUvOverride(isForLivingEntityRenderer: Boolean, u: Int, v: Int, textureWidth: Int?, textureHeight: Int?) : LayerDefinition {
fun createWithUvOverride(u: Int, v: Int, textureWidth: Int?, textureHeight: Int?) : LayerDefinition {
val modelData = MeshDefinition()
val parts = HashMap<String, PartDefinition>()
val bones = HashMap<String, ModelBone>()
@@ -184,8 +184,7 @@ class TexturedModel {
val modelTransform : PartPose
when {
bone.parent == null -> {
// The root part always has a 24 Y offset. One of life's great mysteries.
modelTransform = PartPose.offset(0F, if (isForLivingEntityRenderer) 24F else 0F, 0F)
modelTransform = PartPose.offset(0F, 0F, 0F)
}
boneRotation != null -> {
modelTransform = PartPose.offsetAndRotation(
@@ -14,9 +14,6 @@ import com.google.gson.annotations.SerializedName
import net.minecraft.client.model.geom.ModelPart
class BlockEntityModel(root: Bone) : PosableModel(root) {
@Transient
@SerializedName("dummy")
override var isForLivingEntityRenderer = false
@Transient
@SerializedName("Don't bloody deserialize this, Gson! I mean it!")
override val rootPart = (root as ModelPart).children.entries.first().let { root.registerChildWithAllChildren(it.key) }
@@ -0,0 +1,39 @@
/*
* Copyright (C) 2025 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.drone
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.animation.PoseAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Bone
import com.cobblemon.mod.common.client.render.models.blockbench.quirk.ModelQuirk
import com.cobblemon.mod.common.entity.PoseType
import com.google.gson.annotations.SerializedName
import net.minecraft.client.model.geom.ModelPart
/**
* A model for rendering the Rotom drone used by the stadium block.
*
* @author Flarkinater
* @since February 14th, 2025
*/
class DroneModel(root: Bone) : PosableModel(root) {
@Transient
@SerializedName("So this name can be literally anything, huh?")
override val rootPart = (root as ModelPart).registerChildWithAllChildren(root.children.entries.first().key)
var droneAnimations: Array<PoseAnimation> = emptyArray()
var droneQuirks: Array<ModelQuirk<*>> = emptyArray()
override fun registerPoses() {
registerPose(
poseType = PoseType.SLEEP,
animations = droneAnimations,
quirks = droneQuirks
)
}
}
@@ -0,0 +1,34 @@
/*
* Copyright (C) 2025 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.drone
import com.cobblemon.mod.common.api.scheduling.SchedulingTracker
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
/**
* State for a drone Rotom attached to a stadium block.
*
* @author Flarkinater
* @since February 12th, 2025
*/
class DroneState() : PosableState() {
init {
setPose("sleep")
age = 0
currentPartialTicks = 0F
}
override fun getEntity() = null
override fun updatePartialTicks(partialTicks: Float) {
currentPartialTicks += partialTicks / 2
}
override val schedulingTracker = SchedulingTracker()
}
@@ -23,9 +23,6 @@ import net.minecraft.client.model.geom.ModelPart
* @since October 30th, 2023
*/
class FossilModel(root: Bone) : PosableModel(root) {
@Transient
@SerializedName("dummy")
override var isForLivingEntityRenderer = false
@Transient
@SerializedName("Something that isn't root part. Gson thinks they're the same as the root field and so field duplication. Stupid.")
override val rootPart = (root as ModelPart).registerChildWithAllChildren(root.children.entries.first().key)
@@ -19,7 +19,6 @@ open class PokeBallModel(root: ModelPart) : PosableModel(root), PokeBallFrame {
override val rootPart = root.registerChildWithAllChildren("poke_ball")
override val base = getPart("bottom")
override val lid = getPart("lid")
override var isForLivingEntityRenderer = false
open lateinit var shut: Pose
open lateinit var open: Pose
@@ -10,8 +10,8 @@ package com.cobblemon.mod.common.client.render.models.blockbench.pokemon
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
import com.cobblemon.mod.common.client.render.models.blockbench.PosableEntityModel
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import net.minecraft.world.entity.Entity
@@ -22,7 +22,7 @@ class PosablePokemonEntityModel : PosableEntityModel<PokemonEntity>() {
context.put(RenderContext.SCALE, it.pokemon.form.baseScale)
context.put(RenderContext.SPECIES, it.pokemon.species.resourceIdentifier)
context.put(RenderContext.ASPECTS, it.pokemon.aspects)
PokemonModelRepository.getTexture(it.pokemon.species.resourceIdentifier, it.delegate as PokemonClientDelegate)
VaryingModelRepository.getTexture(it.pokemon.species.resourceIdentifier, it.delegate as PokemonClientDelegate)
.let { texture -> context.put(RenderContext.TEXTURE, texture) }
}
}
@@ -14,6 +14,8 @@ import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.math.geometry.toRadians
import com.cobblemon.mod.common.util.resolveBoolean
import kotlin.math.absoluteValue
import kotlin.math.sign
import net.minecraft.client.model.geom.ModelPart
/**
@@ -51,9 +53,9 @@ class ModelPartTransformation(val modelPart: ModelPart) {
modelPart.xRot += rotation[0] * intensity
modelPart.yRot += rotation[1] * intensity
modelPart.zRot += rotation[2] * intensity
modelPart.xScale *= (1 - scale[0]) * intensity + 1
modelPart.yScale *= (1 - scale[1]) * intensity + 1
modelPart.zScale *= (1 - scale[2]) * intensity + 1
modelPart.xScale *= ((1 - scale[0]).absoluteValue * intensity) * (scale[0] - 1).sign + 1
modelPart.yScale *= ((1 - scale[1]).absoluteValue * intensity) * (scale[1] - 1).sign + 1
modelPart.zScale *= ((1 - scale[2]).absoluteValue * intensity) * (scale[2] - 1).sign + 1
visibility?.let { modelPart.visible = state.runtime.resolveBoolean(it) }
}
@@ -58,14 +58,12 @@ object BerryModelRepository : JsonDataRegistry<TexturedModel> {
val fruitTex = CobblemonAtlases.BERRY_SPRITE_ATLAS.getSprite(fruitTexId)
val flowerTex = CobblemonAtlases.BERRY_SPRITE_ATLAS.getSprite(flowerTexId)
processedModels[it.fruitModelIdentifier] = fruitModel?.createWithUvOverride(
false,
fruitTex.x,
fruitTex.y,
CobblemonAtlases.BERRY_SPRITE_ATLAS.textureAtlas.width,
CobblemonAtlases.BERRY_SPRITE_ATLAS.textureAtlas.height
)?.bakeRoot()!!
processedModels[it.flowerModelIdentifier] = flowerModel?.createWithUvOverride(
false,
flowerTex.x,
flowerTex.y,
CobblemonAtlases.BERRY_SPRITE_ATLAS.textureAtlas.width,
@@ -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.render.models.blockbench.repository
import com.cobblemon.mod.common.client.render.models.blockbench.blockentity.BlockEntityModel
import com.cobblemon.mod.common.util.cobblemonResource
/**
* This is specifically for BlockEntities where we want to do more complex animation than what Java Edition already allows
* Basically with Java Edition, we can only change the texture applied to a model, if we want to move bones around, need to
* do something else, so we use this
*/
object BlockEntityModelRepository : VaryingModelRepository<BlockEntityModel>() {
override val poserClass = BlockEntityModel::class.java
override val title = "Block Entity"
override val type = "block_entities"
override val variationDirectories: List<String> = listOf("bedrock/$type/variations", "bedrock/$type")
override val poserDirectories: List<String> = listOf("bedrock/$type/posers")
override val modelDirectories: List<String> = listOf("bedrock/$type/models")
override val animationDirectories: List<String> = listOf("bedrock/$type/animations")
override val fallback = cobblemonResource("substitute")
override val isForLivingEntityRenderer = false
override fun registerInBuiltPosers() {}
}
@@ -1,86 +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.repository
import com.cobblemon.mod.common.client.render.models.blockbench.fossil.FossilModel
import com.cobblemon.mod.common.util.cobblemonResource
/**
* Repository for models referenced by fossils, to render in the tank.
*/
object FossilModelRepository : VaryingModelRepository<FossilModel>() {
override val poserClass = FossilModel::class.java
override val title = "Fossil Pokémon"
override val type = "fossils"
override val variationDirectories: List<String> = listOf("bedrock/$type/variations")
override val poserDirectories: List<String> = listOf("bedrock/$type/posers")
override val modelDirectories: List<String> = listOf("bedrock/$type/models")
override val animationDirectories: List<String> = listOf("bedrock/$type/animations")
override val fallback = cobblemonResource("substitute")
override val isForLivingEntityRenderer = false
// override fun loadJsonPoser(json: String): (Bone) -> FossilModel {
// val jsonObject = gson.fromJson<JsonObject>(json)
// val animations = jsonObject.getAsJsonArray("animations")
// val maxScale = jsonObject.get("maxScale")?.asFloat ?: 1F
// val yTranslation = jsonObject.get("yTranslation")?.asFloat ?: 0F
// val yGrowthPoint = jsonObject.get("yGrowthPoint")?.asFloat ?: 0F
//
// return { bone ->
// val model = FossilModel(bone)
// model.maxScale = maxScale
// model.yTranslation = yTranslation
// model.yGrowthPoint = yGrowthPoint
// // Refactor this bullshit to not mention pokemon at all, it should be common to anything using animation factories.
// // Even better: move to molang functions, this is ass
// model.tankAnimations = animations.mapNotNull {
// val animString = it.asString
// val anim = animString.substringBefore("(")
// if (JsonPosableModel.ANIMATION_FACTORIES.contains(anim)) {
// return@mapNotNull JsonPosableModel.ANIMATION_FACTORIES[anim]!!.pose(model, animString)
// } else {
// null
// }
// }.toTypedArray()
//
// // borrowed code from JsonPosableModel's PoseAdapter Deserializer
// val tankQuirks = (jsonObject.get("quirks")?.asJsonArray ?: JsonArray()).map { json ->
// json as JsonObject
// val quirkAnimations: (state: PosableState) -> List<StatefulAnimation> = { _ ->
// (json.get("animations")?.asJsonArray ?: JsonArray()).mapNotNull { animJson ->
// val animString = animJson.asString
//
// val anim = animString.substringBefore("(")
//
// val animation = if (JsonPosableModel.ANIMATION_FACTORIES.contains(anim)) {
// JsonPosableModel.ANIMATION_FACTORIES[anim]?.stateful(model, animString)
// } else {
// null
// }
// animation
// }
// }
// val loopTimes = json.get("loopTimes")?.asInt ?: 1
// val minSeconds = json.get("minSeconds")?.asFloat ?: 8F
// val maxSeconds = json.get("maxSeconds")?.asFloat ?: 30F
//
// model.quirkMultiple(
// secondsBetweenOccurrences = minSeconds to maxSeconds,
// condition = { true },
// loopTimes = 1..loopTimes,
// animations = quirkAnimations
// )
// }
// model.tankQuirks = tankQuirks.toTypedArray()
//
// model
// }
// }
override fun registerInBuiltPosers() {}
}
@@ -1,25 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.render.models.blockbench.repository
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
import com.cobblemon.mod.common.util.cobblemonResource
object GenericBedrockEntityModelRepository : VaryingModelRepository<PosableModel>() {
override val poserClass = PosableModel::class.java
override val title = "Generic"
override val type = "generic"
override val variationDirectories: List<String> = listOf("bedrock/$type/variations")
override val poserDirectories: List<String> = listOf("bedrock/$type/posers")
override val modelDirectories: List<String> = listOf("bedrock/$type/models")
override val animationDirectories: List<String> = listOf("bedrock/$type/animations")
override val isForLivingEntityRenderer = false
override val fallback = cobblemonResource("substitute")
override fun registerInBuiltPosers() {}
}
@@ -38,7 +38,7 @@ object MiscModelRepository : JsonDataRegistry<TexturedModel> {
override fun reload(data: Map<ResourceLocation, TexturedModel>) {
data.forEach { (identifier, model) ->
this.models[identifier] = model.create(false).bakeRoot()
this.models[identifier] = model.create().bakeRoot()
}
observable.emit(this)
Cobblemon.LOGGER.info("Loaded {} misc models",this.models.size)
@@ -1,26 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.render.models.blockbench.repository
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
import com.cobblemon.mod.common.util.cobblemonResource
object NPCModelRepository : VaryingModelRepository<PosableModel>() {
override val poserClass = PosableModel::class.java
override val title = "NPC"
override val type = "npcs"
override val variationDirectories: List<String> = listOf("bedrock/$type/variations")
override val poserDirectories: List<String> = listOf("bedrock/$type/posers")
override val modelDirectories: List<String> = listOf("bedrock/$type/models")
override val animationDirectories: List<String> = listOf("bedrock/$type/animations")
override val fallback = cobblemonResource("npc")
override val isForLivingEntityRenderer = true
override fun registerInBuiltPosers() {}
}
@@ -1,79 +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.repository
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.AncientPokeBallModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.BeastBallModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.PokeBallModel
object PokeBallModelRepository : VaryingModelRepository<PosableModel>() {
override val poserClass = PosableModel::class.java
override val title = "Poké Ball"
override val type = "poke_balls"
override val variationDirectories: List<String> = listOf("bedrock/$type/variations")
override val poserDirectories: List<String> = listOf("bedrock/$type/posers")
override val modelDirectories: List<String> = listOf("bedrock/$type/models")
override val animationDirectories: List<String> = listOf("bedrock/$type/animations")
override val isForLivingEntityRenderer = false
override val fallback = PokeBalls.POKE_BALL.name
override fun registerInBuiltPosers() {
inbuilt("azure_ball", ::PokeBallModel)
inbuilt("beast_ball", ::BeastBallModel)
inbuilt("cherish_ball", ::PokeBallModel)
inbuilt("citrine_ball", ::PokeBallModel)
inbuilt("dive_ball", ::PokeBallModel)
inbuilt("dream_ball", ::PokeBallModel)
inbuilt("dusk_ball", ::PokeBallModel)
inbuilt("fast_ball", ::PokeBallModel)
inbuilt("friend_ball", ::PokeBallModel)
inbuilt("great_ball", ::PokeBallModel)
inbuilt("heal_ball", ::PokeBallModel)
inbuilt("heavy_ball", ::PokeBallModel)
inbuilt("level_ball", ::PokeBallModel)
inbuilt("love_ball", ::PokeBallModel)
inbuilt("lure_ball", ::PokeBallModel)
inbuilt("luxury_ball", ::PokeBallModel)
inbuilt("master_ball", ::PokeBallModel)
inbuilt("moon_ball", ::PokeBallModel)
inbuilt("nest_ball", ::PokeBallModel)
inbuilt("net_ball", ::PokeBallModel)
inbuilt("park_ball", ::PokeBallModel)
inbuilt("poke_ball", ::PokeBallModel)
inbuilt("premier_ball", ::PokeBallModel)
inbuilt("quick_ball", ::PokeBallModel)
inbuilt("repeat_ball", ::PokeBallModel)
inbuilt("roseate_ball", ::PokeBallModel)
inbuilt("safari_ball", ::PokeBallModel)
inbuilt("slate_ball", ::PokeBallModel)
inbuilt("sport_ball", ::PokeBallModel)
inbuilt("strange_ball", ::PokeBallModel)
inbuilt("timer_ball", ::PokeBallModel)
inbuilt("ultra_ball", ::PokeBallModel)
inbuilt("verdant_ball", ::PokeBallModel)
inbuilt("ancient_poke_ball", ::AncientPokeBallModel)
inbuilt("ancient_citrine_ball", ::AncientPokeBallModel)
inbuilt("ancient_verdant_ball", ::AncientPokeBallModel)
inbuilt("ancient_azure_ball", ::AncientPokeBallModel)
inbuilt("ancient_roseate_ball", ::AncientPokeBallModel)
inbuilt("ancient_slate_ball", ::AncientPokeBallModel)
inbuilt("ancient_ivory_ball", ::AncientPokeBallModel)
inbuilt("ancient_great_ball", ::AncientPokeBallModel)
inbuilt("ancient_ultra_ball", ::AncientPokeBallModel)
inbuilt("ancient_feather_ball", ::AncientPokeBallModel)
inbuilt("ancient_wing_ball", ::AncientPokeBallModel)
inbuilt("ancient_jet_ball", ::AncientPokeBallModel)
inbuilt("ancient_heavy_ball", ::AncientPokeBallModel)
inbuilt("ancient_leaden_ball", ::AncientPokeBallModel)
inbuilt("ancient_gigaton_ball", ::AncientPokeBallModel)
}
}
@@ -1,614 +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.repository
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen1.*
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen2.*
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen3.*
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen4.*
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen5.*
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen6.*
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen7.*
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen8.*
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen9.*
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.isBattling
import com.google.gson.JsonObject
object PokemonModelRepository : VaryingModelRepository<PokemonPosableModel>() {
override val poserClass = PokemonPosableModel::class.java
override val title = "Pokémon"
override val type = "pokemon"
override val variationDirectories = listOf("bedrock/$type/resolvers", "bedrock/species")
override val poserDirectories = listOf("bedrock/$type/posers", "bedrock/posers")
override val modelDirectories = listOf("bedrock/$type/models", "bedrock/models")
override val animationDirectories: List<String> = listOf("bedrock/animations", "bedrock/$type/animations")
override val isForLivingEntityRenderer = true
override val fallback = cobblemonResource("substitute")
override fun registerInBuiltPosers() {
inbuilt("squirtle", ::SquirtleModel)
inbuilt("wartortle", ::WartortleModel)
inbuilt("caterpie", ::CaterpieModel)
inbuilt("metapod", ::MetapodModel)
inbuilt("butterfree", ::ButterfreeModel)
inbuilt("weedle", ::WeedleModel)
inbuilt("kakuna", ::KakunaModel)
inbuilt("beedrill", ::BeedrillModel)
inbuilt("rattata", ::RattataModel)
inbuilt("raticate", ::RaticateModel)
inbuilt("rattata_alolan", ::RattataAlolanModel)
inbuilt("raticate_alolan", ::RaticateAlolanModel)
inbuilt("eevee", ::EeveeModel)
inbuilt("pidgey", ::PidgeyModel)
inbuilt("pidgeotto", ::PidgeottoModel)
inbuilt("pidgeot", ::PidgeotModel)
inbuilt("diglett", ::DiglettModel)
inbuilt("dugtrio", ::DugtrioModel)
inbuilt("zubat", ::ZubatModel)
inbuilt("cleffa", ::CleffaModel)
inbuilt("clefable", ::ClefableModel)
inbuilt("clefairy", ::ClefairyModel)
inbuilt("krabby", ::KrabbyModel)
inbuilt("paras", ::ParasModel)
inbuilt("parasect", ::ParasectModel)
inbuilt("mankey", ::MankeyModel)
inbuilt("primeape", ::PrimeapeModel)
inbuilt("oddish", ::OddishModel)
inbuilt("gloom", ::GloomModel)
inbuilt("vileplume", ::VileplumeModel)
inbuilt("bellossom", ::BellossomModel)
inbuilt("voltorb", ::VoltorbModel)
inbuilt("electrode", ::ElectrodeModel)
inbuilt("ekans", ::EkansModel)
inbuilt("machop", ::MachopModel)
inbuilt("machoke", ::MachokeModel)
inbuilt("machamp", ::MachampModel)
inbuilt("arbok", ::ArbokModel)
inbuilt("arcanine", ::ArcanineModel)
inbuilt("articuno", ::ArticunoModel)
inbuilt("chansey", ::ChanseyModel)
inbuilt("crobat", ::CrobatModel)
inbuilt("cubone", ::CuboneModel)
inbuilt("dewgong", ::DewgongModel)
inbuilt("ditto", ::DittoModel)
inbuilt("dodrio", ::DodrioModel)
inbuilt("doduo", ::DoduoModel)
inbuilt("dragonair", ::DragonairModel)
inbuilt("dragonite", ::DragoniteModel)
inbuilt("dratini", ::DratiniModel)
inbuilt("drowzee", ::DrowzeeModel)
inbuilt("electabuzz", ::ElectabuzzModel)
inbuilt("exeggcute", ::ExeggcuteModel)
inbuilt("exeggutor", ::ExeggutorModel)
inbuilt("farfetchd", ::FarfetchdModel)
inbuilt("farfetchd_galarian", ::FarfetchdGalarianModel)
inbuilt("fearow", ::FearowModel)
inbuilt("flareon", ::FlareonModel)
inbuilt("gengar", ::GengarModel)
inbuilt("golbat", ::GolbatModel)
inbuilt("golduck", ::GolduckModel)
inbuilt("grimer", ::GrimerModel)
inbuilt("growlithe", ::GrowlitheModel)
inbuilt("hitmonchan", ::HitmonchanModel)
inbuilt("hitmonlee", ::HitmonleeModel)
inbuilt("hypno", ::HypnoModel)
inbuilt("jolteon", ::JolteonModel)
inbuilt("jynx", ::JynxModel)
inbuilt("kabuto", ::KabutoModel)
inbuilt("kabutops", ::KabutopsModel)
inbuilt("kadabra", ::KadabraModel)
inbuilt("kangaskhan", ::KangaskhanModel)
inbuilt("koffing", ::KoffingModel)
inbuilt("krabby", ::KrabbyModel)
inbuilt("lickitung", ::LickitungModel)
inbuilt("magnemite", ::MagnemiteModel)
inbuilt("magneton", ::MagnetonModel)
inbuilt("marowak", ::MarowakModel)
inbuilt("meowth", ::MeowthModel)
inbuilt("mew", ::MewModel)
inbuilt("mewtwo", ::MewtwoModel)
inbuilt("moltres", ::MoltresModel)
inbuilt("mrmime", ::MrmimeModel)
inbuilt("muk", ::MukModel)
inbuilt("nidoking", ::NidokingModel)
inbuilt("nidoqueen", ::NidoqueenModel)
inbuilt("nidoranf", ::NidoranfModel)
inbuilt("nidoranm", ::NidoranmModel)
inbuilt("nidorina", ::NidorinaModel)
inbuilt("nidorino", ::NidorinoModel)
inbuilt("ninetales", ::NinetalesModel)
inbuilt("omanyte", ::OmanyteModel)
inbuilt("omastar", ::OmastarModel)
inbuilt("persian", ::PersianModel)
inbuilt("pikachu", ::PikachuModel)
inbuilt("pinsir", ::PinsirModel)
inbuilt("poliwag", ::PoliwagModel)
inbuilt("politoed", ::PolitoedModel)
inbuilt("ponyta", ::PonytaModel)
inbuilt("psyduck", ::PsyduckModel)
inbuilt("raichu", ::RaichuModel)
inbuilt("rapidash", ::RapidashModel)
inbuilt("sandshrew", ::SandshrewModel)
inbuilt("sandslash", ::SandslashModel)
inbuilt("scyther", ::ScytherModel)
inbuilt("seel", ::SeelModel)
inbuilt("spearow", ::SpearowModel)
inbuilt("starmie", ::StarmieModel)
inbuilt("staryu", ::StaryuModel)
inbuilt("steelix", ::SteelixModel)
inbuilt("tangela", ::TangelaModel)
inbuilt("tentacool", ::TentacoolModel)
inbuilt("tentacruel", ::TentacruelModel)
inbuilt("vaporeon", ::VaporeonModel)
inbuilt("venomoth", ::VenomothModel)
inbuilt("venonat", ::VenonatModel)
inbuilt("vulpix", ::VulpixModel)
inbuilt("weezing", ::WeezingModel)
inbuilt("zapdos", ::ZapdosModel)
inbuilt("elekid", ::ElekidModel)
inbuilt("pichu", ::PichuModel)
inbuilt("smoochum", ::SmoochumModel)
inbuilt("hitmontop", ::HitmontopModel)
inbuilt("electivire", ::ElectivireModel)
inbuilt("glaceon", ::GlaceonModel)
inbuilt("leafeon", ::LeafeonModel)
inbuilt("lickilicky", ::LickilickyModel)
inbuilt("mimejr", ::MimejrModel)
inbuilt("scizor", ::ScizorModel)
inbuilt("tangrowth", ::TangrowthModel)
inbuilt("sylveon", ::SylveonModel)
inbuilt("umbreon", ::UmbreonModel)
inbuilt("espeon", ::EspeonModel)
inbuilt("blissey", ::BlisseyModel)
inbuilt("piloswine", ::PiloswineModel)
inbuilt("quagsire", ::QuagsireModel)
inbuilt("swinub", ::SwinubModel)
inbuilt("wooper", ::WooperModel)
inbuilt("wooper_paldean", ::WooperPaldeanModel)
inbuilt("yanma", ::YanmaModel)
inbuilt("blaziken", ::BlazikenModel)
inbuilt("combusken", ::CombuskenModel)
inbuilt("minun", ::MinunModel)
inbuilt("plusle", ::PlusleModel)
inbuilt("rayquaza", ::RayquazaModel)
inbuilt("torchic", ::TorchicModel)
inbuilt("bibarel", ::BibarelModel)
inbuilt("bidoof", ::BidoofModel)
inbuilt("buneary", ::BunearyModel)
inbuilt("lopunny", ::LopunnyModel)
inbuilt("mamoswine", ::MamoswineModel)
inbuilt("pachirisu", ::PachirisuModel)
inbuilt("piplup", ::PiplupModel)
inbuilt("yanmega", ::YanmegaModel)
inbuilt("basculin", ::BasculinModel)
inbuilt("emolga", ::EmolgaModel)
inbuilt("maractus", ::MaractusModel)
inbuilt("bounsweet", ::BounsweetModel)
inbuilt("dartrix", ::DartrixModel)
inbuilt("decidueye", ::DecidueyeModel)
inbuilt("mimikyu", ::MimikyuModel)
inbuilt("naganadel", ::NaganadelModel)
inbuilt("poipole", ::PoipoleModel)
inbuilt("rowlet", ::RowletModel)
inbuilt("steenee", ::SteeneeModel)
inbuilt("tsareena", ::TsareenaModel)
inbuilt("centiskorch", ::CentiskorchModel)
inbuilt("sizzlipede", ::SizzlipedeModel)
inbuilt("kleavor", ::KleavorModel)
inbuilt("pyukumuku", ::PyukumukuModel)
inbuilt("deerling", ::DeerlingModel)
inbuilt("sawsbuck", ::SawsbuckModel)
inbuilt("sableye", ::SableyeModel)
inbuilt("natu", ::NatuModel)
inbuilt("xatu", ::XatuModel)
inbuilt("wailmer", ::WailmerModel)
inbuilt("wailord", ::WailordModel)
inbuilt("murkrow", ::MurkrowModel)
inbuilt("honchkrow", ::HonchkrowModel)
inbuilt("nacli", :: NacliModel)
inbuilt("naclstack", :: NaclstackModel)
inbuilt("garganacl", ::GarganaclModel)
inbuilt("dhelmise", :: DhelmiseModel)
inbuilt("alcremie", :: AlcremieModel)
inbuilt("milcery", :: MilceryModel)
inbuilt("turtwig", :: TurtwigModel)
inbuilt("grotle", :: GrotleModel)
inbuilt("torterra", :: TorterraModel)
inbuilt("torterra_cherry", :: TorterraCherryModel)
inbuilt("xerneas", :: XerneasModel)
inbuilt("klink", :: KlinkModel)
inbuilt("klang", :: KlangModel)
inbuilt("klinklang", :: KlinklangModel)
inbuilt("morelull", :: MorelullModel)
inbuilt("shiinotic", :: ShiinoticModel)
inbuilt("treecko", :: TreeckoModel)
inbuilt("grovyle", :: GrovyleModel)
inbuilt("sceptile", :: SceptileModel)
inbuilt("honedge", :: HonedgeModel)
inbuilt("spiritomb", :: SpiritombModel)
inbuilt("chespin", :: ChespinModel)
inbuilt("quilladin", :: QuilladinModel)
inbuilt("chesnaught", :: ChesnaughtModel)
inbuilt("elgyem", :: ElgyemModel)
inbuilt("beheeyem", :: BeheeyemModel)
inbuilt("pineco", :: PinecoModel)
inbuilt("forretress", :: ForretressModel)
inbuilt("doublade", :: DoubladeModel)
inbuilt("aegislash", :: AegislashModel)
inbuilt("lotad", :: LotadModel)
inbuilt("lombre", :: LombreModel)
inbuilt("ludicolo", :: LudicoloModel)
inbuilt("golett", :: GolettModel)
inbuilt("golurk", :: GolurkModel)
inbuilt("stantler", :: StantlerModel)
inbuilt("wyrdeer", :: WyrdeerModel)
inbuilt("sneasel", :: SneaselModel)
inbuilt("weavile", :: WeavileModel)
inbuilt("bergmite", :: BergmiteModel)
inbuilt("avalugg", :: AvaluggModel)
inbuilt("misdreavus", :: MisdreavusModel)
inbuilt("mismagius", :: MismagiusModel)
inbuilt("whismur", :: WhismurModel)
inbuilt("loudred", :: LoudredModel)
inbuilt("exploud", :: ExploudModel)
inbuilt("luvdisc", :: LuvdiscModel)
inbuilt("cryogonal", :: CryogonalModel)
inbuilt("sigilyph", :: SigilyphModel)
inbuilt("pumpkaboo", :: PumpkabooModel)
inbuilt("gourgeist", :: GourgeistModel)
inbuilt("eiscue", :: EiscueModel)
inbuilt("wooloo", :: WoolooModel)
inbuilt("dubwool", :: DubwoolModel)
inbuilt("chimchar", :: ChimcharModel)
inbuilt("monferno", :: MonfernoModel)
inbuilt("infernape", :: InfernapeModel)
inbuilt("seedot", ::SeedotModel)
inbuilt("nuzleaf", ::NuzleafModel)
inbuilt("shiftry", ::ShiftryModel)
inbuilt("kricketot", ::KricketotModel)
inbuilt("kricketune", ::KricketuneModel)
inbuilt("heatmor", ::HeatmorModel)
inbuilt("durant", ::DurantModel)
inbuilt("sharpedo", ::SharpedoModel)
inbuilt("mawile", ::MawileModel)
inbuilt("walkingwake", ::WalkingwakeModel)
inbuilt("ironleaves", ::IronleavesModel)
inbuilt("miltank", ::MiltankModel)
inbuilt("froakie", ::FroakieModel)
inbuilt("frogadier", ::FrogadierModel)
inbuilt("greninja", ::GreninjaModel)
inbuilt("grookey", ::GrookeyModel)
inbuilt("thwackey", ::ThwackeyModel)
inbuilt("rillaboom", ::RillaboomModel)
inbuilt("raboot", ::RabootModel)
inbuilt("oshawott", ::OshawottModel)
inbuilt("dewott", ::DewottModel)
inbuilt("samurott", ::SamurottModel)
inbuilt("snivy", ::SnivyModel)
inbuilt("servine", ::ServineModel)
inbuilt("serperior", ::SerperiorModel)
inbuilt("slugma", ::SlugmaModel)
inbuilt("magcargo", ::MagcargoModel)
inbuilt("slugma_shiny", ::SlugmaShinyModel)
inbuilt("magcargo_shiny", ::MagcargoShinyModel)
inbuilt("nosepass", ::NosepassModel)
inbuilt("probopass", ::ProbopassModel)
inbuilt("chinchou", ::ChinchouModel)
inbuilt("clamperl", ::ClamperlModel)
inbuilt("huntail", ::HuntailModel)
inbuilt("gorebyss", ::GorebyssModel)
inbuilt("spinarak", ::SpinarakModel)
inbuilt("ariados", ::AriadosModel)
inbuilt("shuckle", ::ShuckleModel)
inbuilt("taillow", ::TaillowModel)
inbuilt("swellow", ::SwellowModel)
inbuilt("mudbray", ::MudbrayModel)
inbuilt("mudsdale", ::MudsdaleModel)
inbuilt("comfey", ::ComfeyModel)
inbuilt("tandemaus", ::TandemausModel)
inbuilt("maushold", ::MausholdModel)
inbuilt("mausholdfour", ::MausholdfourModel)
inbuilt("varoom", ::VaroomModel)
inbuilt("revavroom", ::RevavroomModel)
inbuilt("lanturn", ::LanturnModel)
inbuilt("chingling", ::ChinglingModel)
inbuilt("chimecho", ::ChimechoModel)
inbuilt("fidough", ::FidoughModel)
inbuilt("dachsbun", ::DachsbunModel)
inbuilt("chatot", ::ChatotModel)
inbuilt("gligar", ::GligarModel)
inbuilt("gliscor", ::GliscorModel)
inbuilt("poochyena", ::PoochyenaModel)
inbuilt("mightyena", ::MightyenaModel)
inbuilt("floragato", ::FloragatoModel)
inbuilt("meowscarada", ::MeowscaradaModel)
inbuilt("shroomish", ::ShroomishModel)
inbuilt("breloom", ::BreloomModel)
inbuilt("charcadet", ::CharcadetModel)
inbuilt("flittle", ::FlittleModel)
inbuilt("espathra", ::EspathraModel)
inbuilt("surskit", ::SurskitModel)
inbuilt("masquerain", ::MasquerainModel)
inbuilt("cutiefly", ::CutieflyModel)
inbuilt("ribombee", ::RibombeeModel)
inbuilt("carnivine", ::CarnivineModel)
inbuilt("falinks", ::FalinksModel)
inbuilt("stufful", ::StuffulModel)
inbuilt("bewear", ::BewearModel)
inbuilt("scatterbug", ::ScatterbugModel)
inbuilt("spewpa", ::SpewpaModel)
inbuilt("vivillon", ::VivillonModel)
inbuilt("barboach", ::BarboachModel)
inbuilt("whiscash", ::WhiscashModel)
inbuilt("combee", ::CombeeModel)
inbuilt("vespiquen", ::VespiquenModel)
inbuilt("lillipup", ::LillipupModel)
inbuilt("herdier", ::HerdierModel)
inbuilt("stoutland", ::StoutlandModel)
inbuilt("sirfetchd", ::SirfetchdModel)
inbuilt("rookidee", ::RookideeModel)
inbuilt("corvisquire", ::CorvisquireModel)
inbuilt("corviknight", ::CorviknightModel)
inbuilt("duskull", ::DuskullModel)
inbuilt("dusclops", ::DusclopsModel)
inbuilt("dusknoir", ::DusknoirModel)
inbuilt("nickit", ::NickitModel)
inbuilt("thievul", ::ThievulModel)
inbuilt("cacnea", ::CacneaModel)
inbuilt("cacturne", ::CacturneModel)
inbuilt("glimmet", ::GlimmetModel)
inbuilt("glimmora", ::GlimmoraModel)
inbuilt("bonsly", ::BonslyModel)
inbuilt("sudowoodo", ::SudowoodoModel)
inbuilt("bouffalant", ::BouffalantModel)
inbuilt("cetoddle", ::CetoddleModel)
inbuilt("cetitan", ::CetitanModel)
inbuilt("venipede", ::VenipedeModel)
inbuilt("whirlipede", ::WhirlipedeModel)
inbuilt("scolipede", ::ScolipedeModel)
inbuilt("aipom", ::AipomModel)
inbuilt("ambipom", ::AmbipomModel)
inbuilt("hoothoot", ::HoothootModel)
inbuilt("noctowl", ::NoctowlModel)
inbuilt("wingull", ::WingullModel)
inbuilt("pelipper", ::PelipperModel)
inbuilt("shinx", ::ShinxModel)
inbuilt("luxio", ::LuxioModel)
inbuilt("luxray", ::LuxrayModel)
inbuilt("numel", ::NumelModel)
inbuilt("camerupt", ::CameruptModel)
inbuilt("vulpix_alolan", ::VulpixAlolanModel)
inbuilt("ninetales_alolan", ::NinetalesAlolanModel)
inbuilt("roggenrola", ::RoggenrolaModel)
inbuilt("boldore", ::BoldoreModel)
inbuilt("gigalith", ::GigalithModel)
inbuilt("yamask", ::YamaskModel)
inbuilt("cofagrigus", ::CofagrigusModel)
inbuilt("mareep", ::MareepModel)
inbuilt("flaaffy", ::FlaaffyModel)
inbuilt("ampharos", ::AmpharosModel)
inbuilt("patrat", ::PatratModel)
inbuilt("watchog", ::WatchogModel)
inbuilt("skrelp", ::SkrelpModel)
inbuilt("dragalge", ::DragalgeModel)
inbuilt("bunnelby", ::BunnelbyModel)
inbuilt("arrokuda", ::ArrokudaModel)
inbuilt("barraskewda", ::BarraskewdaModel)
inbuilt("shroodle", ::ShroodleModel)
inbuilt("grafaiai", ::GrafaiaiModel)
inbuilt("squawkabilly", ::SquawkabillyModel)
inbuilt("annihilape", ::AnnihilapeModel)
inbuilt("ponyta_galarian", ::PonytaGalarianModel)
inbuilt("rapidash_galarian", ::RapidashGalarianModel)
inbuilt("volbeat", ::VolbeatModel)
inbuilt("illumise", ::IllumiseModel)
inbuilt("yamper", ::YamperModel)
inbuilt("boltund", ::BoltundModel)
inbuilt("tinkatink", ::TinkatinkModel)
inbuilt("tinkatuff", ::TinkatuffModel)
inbuilt("fuecoco", :: FuecocoModel)
inbuilt("crocalor", :: CrocalorModel)
inbuilt("skeledirge", :: SkeledirgeModel)
inbuilt("quaxly", :: QuaxlyModel)
inbuilt("quaxwell", :: QuaxwellModel)
inbuilt("quaquaval", :: QuaquavalModel)
inbuilt("snubbull", :: SnubbullModel)
inbuilt("granbull", :: GranbullModel)
inbuilt("maschiff", :: MaschiffModel)
inbuilt("mabosstiff", :: MabosstiffModel)
inbuilt("phanpy", :: PhanpyModel)
inbuilt("donphan", :: DonphanModel)
inbuilt("buizel", :: BuizelModel)
inbuilt("floatzel", :: FloatzelModel)
inbuilt("zigzagoon", :: ZigzagoonModel)
inbuilt("linoone", :: LinooneModel)
inbuilt("zigzagoon_galarian", :: ZigzagoonGalarianModel)
inbuilt("linoone_galarian", :: LinooneGalarianModel)
inbuilt("obstagoon", :: ObstagoonModel)
inbuilt("cottonee", :: CottoneeModel)
inbuilt("whimsicott", :: WhimsicottModel)
inbuilt("wishiwashi_solo", :: WishiwashiSoloModel)
inbuilt("wishiwashi_schooling", :: WishiwashiSchoolingModel)
inbuilt("meowth_alolan", ::MeowthAlolanModel)
inbuilt("meowth_galarian", ::MeowthGalarianModel)
inbuilt("persian_alolan", ::PersianAlolanModel)
inbuilt("perrserker", ::PerrserkerModel)
inbuilt("starly", ::StarlyModel)
inbuilt("staravia", ::StaraviaModel)
inbuilt("staraptor", ::StaraptorModel)
inbuilt("komala", ::KomalaModel)
inbuilt("phantump", ::PhantumpModel)
inbuilt("totodile", ::TotodileModel)
inbuilt("croconaw", ::CroconawModel)
inbuilt("feraligatr", ::FeraligatrModel)
inbuilt("cyndaquil", ::CyndaquilModel)
inbuilt("quilava", ::QuilavaModel)
inbuilt("typhlosion", ::TyphlosionModel)
inbuilt("chikorita", ::ChikoritaModel)
inbuilt("bayleef", ::BayleefModel)
inbuilt("meganium", ::MeganiumModel)
inbuilt("fletchling", ::FletchlingModel)
inbuilt("fletchinder", ::FletchinderModel)
inbuilt("talonflame", ::TalonflameModel)
inbuilt("crabrawler", ::CrabrawlerModel)
inbuilt("crabominable", ::CrabominableModel)
inbuilt("wimpod", ::WimpodModel)
inbuilt("golisopod", ::GolisopodModel)
inbuilt("shedinja", ::ShedinjaModel)
inbuilt("ralts", ::RaltsModel)
inbuilt("kirlia", ::KirliaModel)
inbuilt("gardevoir", ::GardevoirModel)
inbuilt("gallade", ::GalladeModel)
inbuilt("beldum", ::BeldumModel)
inbuilt("metang", ::MetangModel)
inbuilt("metagross", ::MetagrossModel)
inbuilt("ursaluna", ::UrsalunaModel)
inbuilt("lechonk", ::LechonkModel)
inbuilt("oinkologne_male", ::OinkologneMaleModel)
inbuilt("oinkologne_female", ::OinkologneFemaleModel)
inbuilt("pidove", ::PidoveModel)
inbuilt("tranquill", ::TranquillModel)
inbuilt("unfezant", ::UnfezantModel)
inbuilt("timburr", ::TimburrModel)
inbuilt("gurdurr", ::GurdurrModel)
inbuilt("conkeldurr", ::ConkeldurrModel)
inbuilt("clodsire", ::ClodsireModel)
inbuilt("teddiursa", ::TeddiursaModel)
inbuilt("ursaring", ::UrsaringModel)
inbuilt("litwick", ::LitwickModel)
inbuilt("lampent", ::LampentModel)
inbuilt("chandelure", ::ChandelureModel)
inbuilt("gimmighoulchest", ::GimmighoulChestModel)
inbuilt("gholdengo", ::GholdengoModel)
inbuilt("drifloon", ::DrifloonModel)
inbuilt("drifblim", ::DrifblimModel)
inbuilt("lileep", ::LileepModel)
inbuilt("cradily", ::CradilyModel)
inbuilt("tirtouga", ::TirtougaModel)
inbuilt("carracosta", ::CarracostaModel)
inbuilt("arctovish", ::ArctovishModel)
inbuilt("dracovish", ::DracovishModel)
inbuilt("arctozolt", ::ArctozoltModel)
inbuilt("dracozolt", ::DracozoltModel)
inbuilt("shieldon", ::ShieldonModel)
inbuilt("bastiodon", ::BastiodonModel)
inbuilt("cranidos", ::CranidosModel)
inbuilt("rampardos", ::RampardosModel)
inbuilt("basculegion", ::BasculegionModel)
inbuilt("tyrunt", ::TyruntModel)
inbuilt("tyrantrum", ::TyrantrumModel)
inbuilt("anorith", ::AnorithModel)
inbuilt("armaldo", ::ArmaldoModel)
inbuilt("archen", ::ArchenModel)
inbuilt("archeops", ::ArcheopsModel)
inbuilt("aron", ::AronModel)
inbuilt("lairon", ::LaironModel)
inbuilt("aggron", ::AggronModel)
inbuilt("hippopotas", ::HippopotasModel)
inbuilt("hippowdon", ::HippowdonModel)
inbuilt("zorua", ::ZoruaModel)
inbuilt("zorua_hisuian", ::ZoruaHisuianModel)
inbuilt("zoroark", ::ZoroarkModel)
inbuilt("zoroark_hisuian", ::ZoroarkHisuianModel)
inbuilt("gossifleur", ::GossifleurModel)
inbuilt("eldegoss", ::EldegossModel)
inbuilt("amaura", ::AmauraModel)
inbuilt("aurorus", ::AurorusModel)
inbuilt("voltorb_hisuian", ::VoltorbHisuianModel)
inbuilt("electrode_hisuian", ::ElectrodeHisuianModel)
inbuilt("sentret", ::SentretModel)
inbuilt("qwilfish", ::QwilfishModel)
inbuilt("qwilfish_hisuian", ::QwilfishHisuianModel)
inbuilt("overqwil", ::OverqwilModel)
inbuilt("sneasel_hisuian", ::SneaselHisuianModel)
inbuilt("sneasler", ::SneaslerModel)
inbuilt("tropius", ::TropiusModel)
inbuilt("petilil", ::PetililModel)
inbuilt("lilligant", ::LilligantModel)
inbuilt("petilil_hisui_bias", ::PetililHisuiBiasModel)
inbuilt("lilligant_hisuian", ::LilligantHisuianModel)
inbuilt("darumaka", ::DarumakaModel)
inbuilt("darmanitan", ::DarmanitanModel)
inbuilt("darmanitan_zen", ::DarmanitanZenModel)
inbuilt("turtonator", ::TurtonatorModel)
inbuilt("stonjourner", ::StonjournerModel)
inbuilt("cufant", ::CufantModel)
inbuilt("copperajah", ::CopperajahModel)
inbuilt("budew", ::BudewModel)
inbuilt("roselia", ::RoseliaModel)
inbuilt("roserade", ::RoseradeModel)
inbuilt("woobat", ::WoobatModel)
inbuilt("swoobat", ::SwoobatModel)
inbuilt("frillish", ::FrillishModel)
inbuilt("jellicent", ::JellicentModel)
inbuilt("cubchoo", ::CubchooModel)
inbuilt("beartic", ::BearticModel)
inbuilt("deino", ::DeinoModel)
inbuilt("zweilous", ::ZweilousModel)
inbuilt("larvesta", ::LarvestaModel)
inbuilt("volcarona", ::VolcaronaModel)
inbuilt("dreepy", ::DreepyModel)
inbuilt("drakloak", ::DrakloakModel)
inbuilt("dragapult", ::DragapultModel)
inbuilt("diglett_alolan", ::DiglettAlolanModel)
inbuilt("dugtrio_alolan", ::DugtrioAlolanModel)
inbuilt("makuhita", ::MakuhitaModel)
inbuilt("hariyama", ::HariyamaModel)
inbuilt("alomomola", ::AlomomolaModel)
inbuilt("ferroseed", ::FerroseedModel)
inbuilt("ferrothorn", ::FerrothornModel)
inbuilt("carbink", ::CarbinkModel)
inbuilt("goomy", ::GoomyModel)
inbuilt("goomy_hisui_bias", ::GoomyHisuiBiasModel)
inbuilt("sliggoo", ::SliggooModel)
inbuilt("sliggoo_hisuian", ::SliggooHisuianModel)
inbuilt("goodra", ::GoodraModel)
inbuilt("goodra_hisuian", ::GoodraHisuianModel)
inbuilt("heracross", ::HeracrossModel)
inbuilt("salandit", ::SalanditModel)
inbuilt("salazzle", ::SalazzleModel)
inbuilt("jangmo-o", ::JangmoOModel)
inbuilt("hakamo-o", ::HakamoOModel)
inbuilt("kommo-o", ::KommoOModel)
inbuilt("trapinch", ::TrapinchModel)
inbuilt("vibrava", ::VibravaModel)
inbuilt("flygon", ::FlygonModel)
inbuilt("larvitar", ::LarvitarModel)
inbuilt("pupitar", ::PupitarModel)
inbuilt("tyranitar", ::TyranitarModel)
inbuilt("impidimp", ::ImpidimpModel)
inbuilt("morgrem", ::MorgremModel)
inbuilt("grimmsnarl", ::GrimmsnarlModel)
inbuilt("klefki", ::KlefkiModel)
inbuilt("oshawott_hisui_bias", ::OshawottHisuiBiasModel)
inbuilt("dewott_hisui_bias", ::DewottHisuiBiasModel)
inbuilt("samurott_hisuian", ::SamurottHisuianModel)
inbuilt("cyndaquil_hisui_bias", ::CyndaquilHisuiBiasModel)
inbuilt("quilava_hisui_bias", ::QuilavaHisuiBiasModel)
inbuilt("typhlosion_hisuian", ::TyphlosionHisuianModel)
inbuilt("rowlet_hisui_bias", ::RowletHisuiBiasModel)
inbuilt("dartrix_hisui_bias", ::DartrixHisuiBiasModel)
inbuilt("decidueye_hisuian", ::DecidueyeHisuianModel)
}
override fun conditionParser(json: JsonObject): List<(PosableState) -> Boolean> {
val conditions = mutableListOf<(PosableState) -> Boolean>()
val mustBeInBattle = json.get("isBattle")?.asBoolean
if (mustBeInBattle != null) {
conditions.add { mustBeInBattle == it.isBattling }
}
return conditions
}
}
@@ -17,12 +17,29 @@ import com.cobblemon.mod.common.client.render.SpriteType
import com.cobblemon.mod.common.client.render.VaryingRenderableResolver
import com.cobblemon.mod.common.client.render.models.blockbench.*
import com.cobblemon.mod.common.client.render.models.blockbench.bedrock.animation.BedrockAnimationRepository
import com.cobblemon.mod.common.client.render.models.blockbench.blockentity.BlockEntityModel
import com.cobblemon.mod.common.client.render.models.blockbench.fossil.FossilModel
import com.cobblemon.mod.common.client.render.models.blockbench.drone.DroneModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.AncientPokeBallModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.BeastBallModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.PokeBallModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen1.*
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen2.*
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen3.*
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen4.*
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen5.*
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen6.*
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen7.*
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen8.*
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen9.*
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Bone
import com.cobblemon.mod.common.client.render.models.blockbench.pose.ModelPartTransformation
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository.MixinCompatibilityExclusionStrategy
import com.cobblemon.mod.common.client.util.exists
import com.cobblemon.mod.common.util.adapters.ExpressionAdapter
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
import com.cobblemon.mod.common.util.adapters.ModelPartTransformationAdapter
import com.cobblemon.mod.common.util.adapters.Vec3dAdapter
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.endsWith
@@ -32,16 +49,15 @@ import com.google.gson.FieldAttributes
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonObject
import java.io.File
import java.nio.charset.StandardCharsets
import java.util.Optional
import java.util.function.BiFunction
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.packs.resources.Resource
import net.minecraft.server.packs.resources.ResourceManager
import net.minecraft.world.phys.Vec3
import java.io.File
import java.nio.charset.StandardCharsets
import java.util.Optional
import java.util.function.BiFunction
import java.util.function.Function
/**
* A repository for [PosableModel]s. Can be parameterized with [PosableModel] itself or a subclass.
@@ -52,21 +68,46 @@ import java.util.function.Function
* @author Hiroku
* @since February 28th, 2023
*/
abstract class VaryingModelRepository<T : PosableModel> {
abstract val poserClass: Class<T>
val posers = mutableMapOf<ResourceLocation, (Bone) -> T>()
val variations = mutableMapOf<ResourceLocation, VaryingRenderableResolver<T>>()
val texturedModels = mutableMapOf<ResourceLocation, (isForLivingEntityRenderer: Boolean) -> Bone>()
object VaryingModelRepository {
val posers = mutableMapOf<ResourceLocation, (Bone) -> PosableModel>()
val variations = mutableMapOf<ResourceLocation, VaryingRenderableResolver>()
val texturedModels = mutableMapOf<ResourceLocation, Bone>()
abstract val title: String
abstract val type: String
abstract val variationDirectories: List<String>
abstract val poserDirectories: List<String>
abstract val modelDirectories: List<String>
abstract val animationDirectories: List<String>
abstract val fallback: ResourceLocation
/** When using the living entity renderer in Java Edition, a root joint 24F (1.5) Y offset is necessary. I've no fucking idea why. */
abstract val isForLivingEntityRenderer: Boolean
private val types = listOf(
"pokemon",
"fossils",
"npcs",
"poke_balls",
"generic",
"block_entities",
"drone"
)
val poserDirectories: List<Pair<String, Class<out PosableModel>>> = listOf(
"bedrock/posers" to PosableModel::class.java,
"bedrock/pokemon/posers" to PokemonPosableModel::class.java,
"bedrock/fossils/posers" to FossilModel::class.java,
"bedrock/drone/posers" to DroneModel::class.java,
"bedrock/block_entities/posers" to BlockEntityModel::class.java,
"bedrock/npcs/posers" to PosableModel::class.java,
"bedrock/poke_balls/posers" to PosableModel::class.java,
"bedrock/generic/posers" to PosableModel::class.java,
)
val variationDirectories: List<String> = listOf(
"bedrock/species",
"bedrock/pokemon/resolvers"
) + types.map { "bedrock/$it/variations" }
val modelDirectories: List<String> = listOf(
"bedrock/models"
) + types.map { "bedrock/$it/models" }
val animationDirectories: List<String> = listOf(
"bedrock/animations"
) + types.map { "bedrock/$it/animations" }
val fallback: ResourceLocation = cobblemonResource("substitute")
val gson: Gson by lazy {
GsonBuilder()
@@ -75,32 +116,17 @@ abstract class VaryingModelRepository<T : PosableModel> {
.registerTypeAdapter(Vec3::class.java, Vec3dAdapter)
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
.registerTypeAdapter(PosableModel::class.java, JsonModelAdapter(::PosableModel))
.registerTypeAdapter(PokemonPosableModel::class.java, JsonModelAdapter(::PokemonPosableModel))
.registerTypeAdapter(FossilModel::class.java, JsonModelAdapter(::FossilModel))
.registerTypeAdapter(DroneModel::class.java, JsonModelAdapter(::DroneModel))
.registerTypeAdapter(BlockEntityModel::class.java, JsonModelAdapter(::BlockEntityModel))
.registerTypeAdapter(Pose::class.java, PoseAdapter { JsonModelAdapter.model!! })
.registerTypeAdapter(ModelPartTransformation::class.java, ModelPartTransformationAdapter)
.addDeserializationExclusionStrategy(MixinCompatibilityExclusionStrategy)
.also { configureGson(it) }
.create()
}
lateinit var adapter: JsonModelAdapter<T>
open fun conditionParser(json: JsonObject): List<(PosableState) -> Boolean> = emptyList()
private fun GsonBuilder.setupGsonForJsonPosableModels(
adapter: JsonModelAdapter<T>,
poseConditionReader: (JsonObject) -> List<(PosableState) -> Boolean> = { emptyList() }
): GsonBuilder {
return this
.excludeFieldsWithModifiers()
.registerTypeAdapter(Pose::class.java, PoseAdapter(poseConditionReader) { adapter.model!! })
.registerTypeAdapter(
poserClass,
adapter
)
}
private fun createAdapter(): JsonModelAdapter<T> {
return JsonModelAdapter { poserClass.getConstructor(Bone::class.java).newInstance(it) }
}
//Some mods will inject extra properties into the model part, which we use GSON for (through the Bone interface)
//If through a 3rd party mixin fields get injected that cant be deserialized by default (e.g. optional), we crash
//this strategy aims to skip the known 3rd party libraries that do this to avoid crashing
@@ -126,17 +152,12 @@ abstract class VaryingModelRepository<T : PosableModel> {
}
}
open fun configureGson(gsonBuilder: GsonBuilder) {
adapter = createAdapter()
gsonBuilder.setupGsonForJsonPosableModels(adapter) { json -> conditionParser(json) }
}
open fun loadJsonPoser(fileName: String, json: String): (Bone) -> T {
fun loadJsonPoser(fileName: String, json: String, poserClass: Class<out PosableModel>): (Bone) -> PosableModel {
// Faster to deserialize during asset load rather than rerunning this every time a poser is constructed.
val jsonObject = gson.fromJson(json, JsonObject::class.java)
return {
var boneName = jsonObject.getAsJsonPrimitive("rootBone")
adapter.modelPart = if (boneName != null && it.children[boneName.asString] != null) it.children[boneName.asString] else it.children[fileName] ?: it.children.entries.filter { LocatorAccess.PREFIX !in it.key }.first().value
JsonModelAdapter.modelPart = if (boneName != null && it.children[boneName.asString] != null) it.children[boneName.asString] else it.children[fileName] ?: it.children.entries.filter { LocatorAccess.PREFIX !in it.key }.first().value
gson.fromJson(jsonObject, poserClass).also {
it.poses.forEach { (poseName, pose) -> pose.poseName = poseName }
}
@@ -147,26 +168,642 @@ abstract class VaryingModelRepository<T : PosableModel> {
posers.clear()
registerInBuiltPosers()
registerJsonPosers(resourceManager)
Cobblemon.LOGGER.info("Loaded ${posers.size} $title posers.")
Cobblemon.LOGGER.info("Loaded ${posers.size} posers.")
}
abstract fun registerInBuiltPosers()
fun registerInBuiltPosers() {
inbuilt("azure_ball", ::PokeBallModel)
inbuilt("beast_ball", ::BeastBallModel)
inbuilt("cherish_ball", ::PokeBallModel)
inbuilt("citrine_ball", ::PokeBallModel)
inbuilt("dive_ball", ::PokeBallModel)
inbuilt("dream_ball", ::PokeBallModel)
inbuilt("dusk_ball", ::PokeBallModel)
inbuilt("fast_ball", ::PokeBallModel)
inbuilt("friend_ball", ::PokeBallModel)
inbuilt("great_ball", ::PokeBallModel)
inbuilt("heal_ball", ::PokeBallModel)
inbuilt("heavy_ball", ::PokeBallModel)
inbuilt("level_ball", ::PokeBallModel)
inbuilt("love_ball", ::PokeBallModel)
inbuilt("lure_ball", ::PokeBallModel)
inbuilt("luxury_ball", ::PokeBallModel)
inbuilt("master_ball", ::PokeBallModel)
inbuilt("moon_ball", ::PokeBallModel)
inbuilt("nest_ball", ::PokeBallModel)
inbuilt("net_ball", ::PokeBallModel)
inbuilt("park_ball", ::PokeBallModel)
inbuilt("poke_ball", ::PokeBallModel)
inbuilt("premier_ball", ::PokeBallModel)
inbuilt("quick_ball", ::PokeBallModel)
inbuilt("repeat_ball", ::PokeBallModel)
inbuilt("roseate_ball", ::PokeBallModel)
inbuilt("safari_ball", ::PokeBallModel)
inbuilt("slate_ball", ::PokeBallModel)
inbuilt("sport_ball", ::PokeBallModel)
inbuilt("strange_ball", ::PokeBallModel)
inbuilt("timer_ball", ::PokeBallModel)
inbuilt("ultra_ball", ::PokeBallModel)
inbuilt("verdant_ball", ::PokeBallModel)
inbuilt("ancient_poke_ball", ::AncientPokeBallModel)
inbuilt("ancient_citrine_ball", ::AncientPokeBallModel)
inbuilt("ancient_verdant_ball", ::AncientPokeBallModel)
inbuilt("ancient_azure_ball", ::AncientPokeBallModel)
inbuilt("ancient_roseate_ball", ::AncientPokeBallModel)
inbuilt("ancient_slate_ball", ::AncientPokeBallModel)
inbuilt("ancient_ivory_ball", ::AncientPokeBallModel)
inbuilt("ancient_great_ball", ::AncientPokeBallModel)
inbuilt("ancient_ultra_ball", ::AncientPokeBallModel)
inbuilt("ancient_feather_ball", ::AncientPokeBallModel)
inbuilt("ancient_wing_ball", ::AncientPokeBallModel)
inbuilt("ancient_jet_ball", ::AncientPokeBallModel)
inbuilt("ancient_heavy_ball", ::AncientPokeBallModel)
inbuilt("ancient_leaden_ball", ::AncientPokeBallModel)
inbuilt("ancient_gigaton_ball", ::AncientPokeBallModel)
open fun registerJsonPosers(resourceManager: ResourceManager) {
for (directory in poserDirectories) {
inbuilt("squirtle", ::SquirtleModel)
inbuilt("wartortle", ::WartortleModel)
inbuilt("caterpie", ::CaterpieModel)
inbuilt("metapod", ::MetapodModel)
inbuilt("butterfree", ::ButterfreeModel)
inbuilt("weedle", ::WeedleModel)
inbuilt("kakuna", ::KakunaModel)
inbuilt("beedrill", ::BeedrillModel)
inbuilt("rattata", ::RattataModel)
inbuilt("raticate", ::RaticateModel)
inbuilt("rattata_alolan", ::RattataAlolanModel)
inbuilt("raticate_alolan", ::RaticateAlolanModel)
inbuilt("eevee", ::EeveeModel)
inbuilt("pidgey", ::PidgeyModel)
inbuilt("pidgeotto", ::PidgeottoModel)
inbuilt("pidgeot", ::PidgeotModel)
inbuilt("diglett", ::DiglettModel)
inbuilt("dugtrio", ::DugtrioModel)
inbuilt("zubat", ::ZubatModel)
inbuilt("cleffa", ::CleffaModel)
inbuilt("clefable", ::ClefableModel)
inbuilt("clefairy", ::ClefairyModel)
inbuilt("krabby", ::KrabbyModel)
inbuilt("paras", ::ParasModel)
inbuilt("parasect", ::ParasectModel)
inbuilt("mankey", ::MankeyModel)
inbuilt("primeape", ::PrimeapeModel)
inbuilt("oddish", ::OddishModel)
inbuilt("gloom", ::GloomModel)
inbuilt("vileplume", ::VileplumeModel)
inbuilt("bellossom", ::BellossomModel)
inbuilt("voltorb", ::VoltorbModel)
inbuilt("electrode", ::ElectrodeModel)
inbuilt("ekans", ::EkansModel)
inbuilt("machop", ::MachopModel)
inbuilt("machoke", ::MachokeModel)
inbuilt("machamp", ::MachampModel)
inbuilt("arbok", ::ArbokModel)
inbuilt("arcanine", ::ArcanineModel)
inbuilt("articuno", ::ArticunoModel)
inbuilt("chansey", ::ChanseyModel)
inbuilt("crobat", ::CrobatModel)
inbuilt("cubone", ::CuboneModel)
inbuilt("dewgong", ::DewgongModel)
inbuilt("ditto", ::DittoModel)
inbuilt("dodrio", ::DodrioModel)
inbuilt("doduo", ::DoduoModel)
inbuilt("dragonair", ::DragonairModel)
inbuilt("dragonite", ::DragoniteModel)
inbuilt("dratini", ::DratiniModel)
inbuilt("drowzee", ::DrowzeeModel)
inbuilt("electabuzz", ::ElectabuzzModel)
inbuilt("exeggcute", ::ExeggcuteModel)
inbuilt("exeggutor", ::ExeggutorModel)
inbuilt("farfetchd", ::FarfetchdModel)
inbuilt("farfetchd_galarian", ::FarfetchdGalarianModel)
inbuilt("fearow", ::FearowModel)
inbuilt("flareon", ::FlareonModel)
inbuilt("gengar", ::GengarModel)
inbuilt("geodude", ::GeodudeModel)
inbuilt("golbat", ::GolbatModel)
inbuilt("golduck", ::GolduckModel)
inbuilt("golem", ::GolemModel)
inbuilt("graveler", ::GravelerModel)
inbuilt("grimer", ::GrimerModel)
inbuilt("growlithe", ::GrowlitheModel)
inbuilt("hitmonchan", ::HitmonchanModel)
inbuilt("hitmonlee", ::HitmonleeModel)
inbuilt("hypno", ::HypnoModel)
inbuilt("jolteon", ::JolteonModel)
inbuilt("jynx", ::JynxModel)
inbuilt("kabuto", ::KabutoModel)
inbuilt("kabutops", ::KabutopsModel)
inbuilt("kadabra", ::KadabraModel)
inbuilt("kangaskhan", ::KangaskhanModel)
inbuilt("koffing", ::KoffingModel)
inbuilt("krabby", ::KrabbyModel)
inbuilt("lickitung", ::LickitungModel)
inbuilt("magnemite", ::MagnemiteModel)
inbuilt("magneton", ::MagnetonModel)
inbuilt("marowak", ::MarowakModel)
inbuilt("meowth", ::MeowthModel)
inbuilt("mew", ::MewModel)
inbuilt("mewtwo", ::MewtwoModel)
inbuilt("moltres", ::MoltresModel)
inbuilt("mrmime", ::MrmimeModel)
inbuilt("muk", ::MukModel)
inbuilt("nidoking", ::NidokingModel)
inbuilt("nidoqueen", ::NidoqueenModel)
inbuilt("nidoranf", ::NidoranfModel)
inbuilt("nidoranm", ::NidoranmModel)
inbuilt("nidorina", ::NidorinaModel)
inbuilt("nidorino", ::NidorinoModel)
inbuilt("ninetales", ::NinetalesModel)
inbuilt("omanyte", ::OmanyteModel)
inbuilt("omastar", ::OmastarModel)
inbuilt("persian", ::PersianModel)
inbuilt("pikachu", ::PikachuModel)
inbuilt("pinsir", ::PinsirModel)
inbuilt("poliwag", ::PoliwagModel)
inbuilt("politoed", ::PolitoedModel)
inbuilt("ponyta", ::PonytaModel)
inbuilt("psyduck", ::PsyduckModel)
inbuilt("raichu", ::RaichuModel)
inbuilt("rapidash", ::RapidashModel)
inbuilt("sandshrew", ::SandshrewModel)
inbuilt("sandslash", ::SandslashModel)
inbuilt("scyther", ::ScytherModel)
inbuilt("seel", ::SeelModel)
inbuilt("spearow", ::SpearowModel)
inbuilt("starmie", ::StarmieModel)
inbuilt("staryu", ::StaryuModel)
inbuilt("steelix", ::SteelixModel)
inbuilt("tangela", ::TangelaModel)
inbuilt("tentacool", ::TentacoolModel)
inbuilt("tentacruel", ::TentacruelModel)
inbuilt("vaporeon", ::VaporeonModel)
inbuilt("venomoth", ::VenomothModel)
inbuilt("venonat", ::VenonatModel)
inbuilt("vulpix", ::VulpixModel)
inbuilt("weezing", ::WeezingModel)
inbuilt("zapdos", ::ZapdosModel)
inbuilt("elekid", ::ElekidModel)
inbuilt("pichu", ::PichuModel)
inbuilt("smoochum", ::SmoochumModel)
inbuilt("hitmontop", ::HitmontopModel)
inbuilt("electivire", ::ElectivireModel)
inbuilt("glaceon", ::GlaceonModel)
inbuilt("leafeon", ::LeafeonModel)
inbuilt("lickilicky", ::LickilickyModel)
inbuilt("mimejr", ::MimejrModel)
inbuilt("scizor", ::ScizorModel)
inbuilt("tangrowth", ::TangrowthModel)
inbuilt("sylveon", ::SylveonModel)
inbuilt("umbreon", ::UmbreonModel)
inbuilt("espeon", ::EspeonModel)
inbuilt("blissey", ::BlisseyModel)
inbuilt("piloswine", ::PiloswineModel)
inbuilt("quagsire", ::QuagsireModel)
inbuilt("swinub", ::SwinubModel)
inbuilt("wooper", ::WooperModel)
inbuilt("wooper_paldean", ::WooperPaldeanModel)
inbuilt("yanma", ::YanmaModel)
inbuilt("blaziken", ::BlazikenModel)
inbuilt("combusken", ::CombuskenModel)
inbuilt("minun", ::MinunModel)
inbuilt("plusle", ::PlusleModel)
inbuilt("rayquaza", ::RayquazaModel)
inbuilt("torchic", ::TorchicModel)
inbuilt("bibarel", ::BibarelModel)
inbuilt("bidoof", ::BidoofModel)
inbuilt("buneary", ::BunearyModel)
inbuilt("lopunny", ::LopunnyModel)
inbuilt("mamoswine", ::MamoswineModel)
inbuilt("pachirisu", ::PachirisuModel)
inbuilt("piplup", ::PiplupModel)
inbuilt("yanmega", ::YanmegaModel)
inbuilt("basculin", ::BasculinModel)
inbuilt("emolga", ::EmolgaModel)
inbuilt("maractus", ::MaractusModel)
inbuilt("bounsweet", ::BounsweetModel)
inbuilt("dartrix", ::DartrixModel)
inbuilt("decidueye", ::DecidueyeModel)
inbuilt("mimikyu", ::MimikyuModel)
inbuilt("naganadel", ::NaganadelModel)
inbuilt("poipole", ::PoipoleModel)
inbuilt("rowlet", ::RowletModel)
inbuilt("steenee", ::SteeneeModel)
inbuilt("tsareena", ::TsareenaModel)
inbuilt("centiskorch", ::CentiskorchModel)
inbuilt("sizzlipede", ::SizzlipedeModel)
inbuilt("kleavor", ::KleavorModel)
inbuilt("pyukumuku", ::PyukumukuModel)
inbuilt("deerling", ::DeerlingModel)
inbuilt("sawsbuck", ::SawsbuckModel)
inbuilt("sableye", ::SableyeModel)
inbuilt("natu", ::NatuModel)
inbuilt("xatu", ::XatuModel)
inbuilt("wailmer", ::WailmerModel)
inbuilt("wailord", ::WailordModel)
inbuilt("murkrow", ::MurkrowModel)
inbuilt("honchkrow", ::HonchkrowModel)
inbuilt("nacli", :: NacliModel)
inbuilt("naclstack", :: NaclstackModel)
inbuilt("garganacl", ::GarganaclModel)
inbuilt("dhelmise", :: DhelmiseModel)
inbuilt("alcremie", :: AlcremieModel)
inbuilt("milcery", :: MilceryModel)
inbuilt("turtwig", :: TurtwigModel)
inbuilt("grotle", :: GrotleModel)
inbuilt("torterra", :: TorterraModel)
inbuilt("torterra_cherry", :: TorterraCherryModel)
inbuilt("xerneas", :: XerneasModel)
inbuilt("klink", :: KlinkModel)
inbuilt("klang", :: KlangModel)
inbuilt("klinklang", :: KlinklangModel)
inbuilt("morelull", :: MorelullModel)
inbuilt("shiinotic", :: ShiinoticModel)
inbuilt("treecko", :: TreeckoModel)
inbuilt("grovyle", :: GrovyleModel)
inbuilt("sceptile", :: SceptileModel)
inbuilt("honedge", :: HonedgeModel)
inbuilt("spiritomb", :: SpiritombModel)
inbuilt("chespin", :: ChespinModel)
inbuilt("quilladin", :: QuilladinModel)
inbuilt("chesnaught", :: ChesnaughtModel)
inbuilt("elgyem", :: ElgyemModel)
inbuilt("beheeyem", :: BeheeyemModel)
inbuilt("pineco", :: PinecoModel)
inbuilt("forretress", :: ForretressModel)
inbuilt("doublade", :: DoubladeModel)
inbuilt("aegislash", :: AegislashModel)
inbuilt("lotad", :: LotadModel)
inbuilt("lombre", :: LombreModel)
inbuilt("ludicolo", :: LudicoloModel)
inbuilt("golett", :: GolettModel)
inbuilt("golurk", :: GolurkModel)
inbuilt("stantler", :: StantlerModel)
inbuilt("wyrdeer", :: WyrdeerModel)
inbuilt("sneasel", :: SneaselModel)
inbuilt("weavile", :: WeavileModel)
inbuilt("bergmite", :: BergmiteModel)
inbuilt("avalugg", :: AvaluggModel)
inbuilt("misdreavus", :: MisdreavusModel)
inbuilt("mismagius", :: MismagiusModel)
inbuilt("whismur", :: WhismurModel)
inbuilt("loudred", :: LoudredModel)
inbuilt("exploud", :: ExploudModel)
inbuilt("luvdisc", :: LuvdiscModel)
inbuilt("cryogonal", :: CryogonalModel)
inbuilt("sigilyph", :: SigilyphModel)
inbuilt("pumpkaboo", :: PumpkabooModel)
inbuilt("gourgeist", :: GourgeistModel)
inbuilt("eiscue", :: EiscueModel)
inbuilt("wooloo", :: WoolooModel)
inbuilt("dubwool", :: DubwoolModel)
inbuilt("chimchar", :: ChimcharModel)
inbuilt("monferno", :: MonfernoModel)
inbuilt("infernape", :: InfernapeModel)
inbuilt("seedot", ::SeedotModel)
inbuilt("nuzleaf", ::NuzleafModel)
inbuilt("shiftry", ::ShiftryModel)
inbuilt("kricketot", ::KricketotModel)
inbuilt("kricketune", ::KricketuneModel)
inbuilt("heatmor", ::HeatmorModel)
inbuilt("durant", ::DurantModel)
inbuilt("sharpedo", ::SharpedoModel)
inbuilt("mawile", ::MawileModel)
inbuilt("walkingwake", ::WalkingwakeModel)
inbuilt("ironleaves", ::IronleavesModel)
inbuilt("miltank", ::MiltankModel)
inbuilt("froakie", ::FroakieModel)
inbuilt("frogadier", ::FrogadierModel)
inbuilt("greninja", ::GreninjaModel)
inbuilt("grookey", ::GrookeyModel)
inbuilt("thwackey", ::ThwackeyModel)
inbuilt("rillaboom", ::RillaboomModel)
inbuilt("raboot", ::RabootModel)
inbuilt("oshawott", ::OshawottModel)
inbuilt("dewott", ::DewottModel)
inbuilt("samurott", ::SamurottModel)
inbuilt("snivy", ::SnivyModel)
inbuilt("servine", ::ServineModel)
inbuilt("serperior", ::SerperiorModel)
inbuilt("slugma", ::SlugmaModel)
inbuilt("magcargo", ::MagcargoModel)
inbuilt("slugma_shiny", ::SlugmaShinyModel)
inbuilt("magcargo_shiny", ::MagcargoShinyModel)
inbuilt("nosepass", ::NosepassModel)
inbuilt("probopass", ::ProbopassModel)
inbuilt("chinchou", ::ChinchouModel)
inbuilt("clamperl", ::ClamperlModel)
inbuilt("huntail", ::HuntailModel)
inbuilt("gorebyss", ::GorebyssModel)
inbuilt("spinarak", ::SpinarakModel)
inbuilt("ariados", ::AriadosModel)
inbuilt("shuckle", ::ShuckleModel)
inbuilt("taillow", ::TaillowModel)
inbuilt("swellow", ::SwellowModel)
inbuilt("mudbray", ::MudbrayModel)
inbuilt("mudsdale", ::MudsdaleModel)
inbuilt("comfey", ::ComfeyModel)
inbuilt("tandemaus", ::TandemausModel)
inbuilt("maushold", ::MausholdModel)
inbuilt("mausholdfour", ::MausholdfourModel)
inbuilt("varoom", ::VaroomModel)
inbuilt("revavroom", ::RevavroomModel)
inbuilt("lanturn", ::LanturnModel)
inbuilt("chingling", ::ChinglingModel)
inbuilt("chimecho", ::ChimechoModel)
inbuilt("fidough", ::FidoughModel)
inbuilt("dachsbun", ::DachsbunModel)
inbuilt("chatot", ::ChatotModel)
inbuilt("gligar", ::GligarModel)
inbuilt("gliscor", ::GliscorModel)
inbuilt("poochyena", ::PoochyenaModel)
inbuilt("mightyena", ::MightyenaModel)
inbuilt("floragato", ::FloragatoModel)
inbuilt("meowscarada", ::MeowscaradaModel)
inbuilt("shroomish", ::ShroomishModel)
inbuilt("breloom", ::BreloomModel)
inbuilt("charcadet", ::CharcadetModel)
inbuilt("flittle", ::FlittleModel)
inbuilt("espathra", ::EspathraModel)
inbuilt("surskit", ::SurskitModel)
inbuilt("masquerain", ::MasquerainModel)
inbuilt("cutiefly", ::CutieflyModel)
inbuilt("ribombee", ::RibombeeModel)
inbuilt("carnivine", ::CarnivineModel)
inbuilt("falinks", ::FalinksModel)
inbuilt("stufful", ::StuffulModel)
inbuilt("bewear", ::BewearModel)
inbuilt("scatterbug", ::ScatterbugModel)
inbuilt("spewpa", ::SpewpaModel)
inbuilt("vivillon", ::VivillonModel)
inbuilt("barboach", ::BarboachModel)
inbuilt("whiscash", ::WhiscashModel)
inbuilt("combee", ::CombeeModel)
inbuilt("vespiquen", ::VespiquenModel)
inbuilt("lillipup", ::LillipupModel)
inbuilt("herdier", ::HerdierModel)
inbuilt("stoutland", ::StoutlandModel)
inbuilt("sirfetchd", ::SirfetchdModel)
inbuilt("rookidee", ::RookideeModel)
inbuilt("corvisquire", ::CorvisquireModel)
inbuilt("corviknight", ::CorviknightModel)
inbuilt("duskull", ::DuskullModel)
inbuilt("dusclops", ::DusclopsModel)
inbuilt("dusknoir", ::DusknoirModel)
inbuilt("nickit", ::NickitModel)
inbuilt("thievul", ::ThievulModel)
inbuilt("cacnea", ::CacneaModel)
inbuilt("cacturne", ::CacturneModel)
inbuilt("glimmet", ::GlimmetModel)
inbuilt("glimmora", ::GlimmoraModel)
inbuilt("bonsly", ::BonslyModel)
inbuilt("sudowoodo", ::SudowoodoModel)
inbuilt("bouffalant", ::BouffalantModel)
inbuilt("cetoddle", ::CetoddleModel)
inbuilt("cetitan", ::CetitanModel)
inbuilt("venipede", ::VenipedeModel)
inbuilt("whirlipede", ::WhirlipedeModel)
inbuilt("scolipede", ::ScolipedeModel)
inbuilt("aipom", ::AipomModel)
inbuilt("ambipom", ::AmbipomModel)
inbuilt("hoothoot", ::HoothootModel)
inbuilt("noctowl", ::NoctowlModel)
inbuilt("wingull", ::WingullModel)
inbuilt("pelipper", ::PelipperModel)
inbuilt("shinx", ::ShinxModel)
inbuilt("luxio", ::LuxioModel)
inbuilt("luxray", ::LuxrayModel)
inbuilt("numel", ::NumelModel)
inbuilt("camerupt", ::CameruptModel)
inbuilt("vulpix_alolan", ::VulpixAlolanModel)
inbuilt("ninetales_alolan", ::NinetalesAlolanModel)
inbuilt("roggenrola", ::RoggenrolaModel)
inbuilt("boldore", ::BoldoreModel)
inbuilt("gigalith", ::GigalithModel)
inbuilt("yamask", ::YamaskModel)
inbuilt("cofagrigus", ::CofagrigusModel)
inbuilt("mareep", ::MareepModel)
inbuilt("flaaffy", ::FlaaffyModel)
inbuilt("ampharos", ::AmpharosModel)
inbuilt("patrat", ::PatratModel)
inbuilt("watchog", ::WatchogModel)
inbuilt("skrelp", ::SkrelpModel)
inbuilt("dragalge", ::DragalgeModel)
inbuilt("bunnelby", ::BunnelbyModel)
inbuilt("arrokuda", ::ArrokudaModel)
inbuilt("barraskewda", ::BarraskewdaModel)
inbuilt("shroodle", ::ShroodleModel)
inbuilt("grafaiai", ::GrafaiaiModel)
inbuilt("squawkabilly", ::SquawkabillyModel)
inbuilt("annihilape", ::AnnihilapeModel)
inbuilt("ponyta_galarian", ::PonytaGalarianModel)
inbuilt("rapidash_galarian", ::RapidashGalarianModel)
inbuilt("volbeat", ::VolbeatModel)
inbuilt("illumise", ::IllumiseModel)
inbuilt("yamper", ::YamperModel)
inbuilt("boltund", ::BoltundModel)
inbuilt("tinkatink", ::TinkatinkModel)
inbuilt("tinkatuff", ::TinkatuffModel)
inbuilt("fuecoco", :: FuecocoModel)
inbuilt("crocalor", :: CrocalorModel)
inbuilt("skeledirge", :: SkeledirgeModel)
inbuilt("quaxly", :: QuaxlyModel)
inbuilt("quaxwell", :: QuaxwellModel)
inbuilt("quaquaval", :: QuaquavalModel)
inbuilt("snubbull", :: SnubbullModel)
inbuilt("granbull", :: GranbullModel)
inbuilt("maschiff", :: MaschiffModel)
inbuilt("mabosstiff", :: MabosstiffModel)
inbuilt("phanpy", :: PhanpyModel)
inbuilt("donphan", :: DonphanModel)
inbuilt("buizel", :: BuizelModel)
inbuilt("floatzel", :: FloatzelModel)
inbuilt("zigzagoon", :: ZigzagoonModel)
inbuilt("linoone", :: LinooneModel)
inbuilt("zigzagoon_galarian", :: ZigzagoonGalarianModel)
inbuilt("linoone_galarian", :: LinooneGalarianModel)
inbuilt("obstagoon", :: ObstagoonModel)
inbuilt("cottonee", :: CottoneeModel)
inbuilt("whimsicott", :: WhimsicottModel)
inbuilt("wishiwashi_solo", :: WishiwashiSoloModel)
inbuilt("wishiwashi_schooling", :: WishiwashiSchoolingModel)
inbuilt("meowth_alolan", ::MeowthAlolanModel)
inbuilt("meowth_galarian", ::MeowthGalarianModel)
inbuilt("persian_alolan", ::PersianAlolanModel)
inbuilt("perrserker", ::PerrserkerModel)
inbuilt("starly", ::StarlyModel)
inbuilt("staravia", ::StaraviaModel)
inbuilt("staraptor", ::StaraptorModel)
inbuilt("komala", ::KomalaModel)
inbuilt("phantump", ::PhantumpModel)
inbuilt("totodile", ::TotodileModel)
inbuilt("croconaw", ::CroconawModel)
inbuilt("feraligatr", ::FeraligatrModel)
inbuilt("cyndaquil", ::CyndaquilModel)
inbuilt("quilava", ::QuilavaModel)
inbuilt("typhlosion", ::TyphlosionModel)
inbuilt("chikorita", ::ChikoritaModel)
inbuilt("bayleef", ::BayleefModel)
inbuilt("meganium", ::MeganiumModel)
inbuilt("fletchling", ::FletchlingModel)
inbuilt("fletchinder", ::FletchinderModel)
inbuilt("talonflame", ::TalonflameModel)
inbuilt("crabrawler", ::CrabrawlerModel)
inbuilt("crabominable", ::CrabominableModel)
inbuilt("wimpod", ::WimpodModel)
inbuilt("golisopod", ::GolisopodModel)
inbuilt("shedinja", ::ShedinjaModel)
inbuilt("ralts", ::RaltsModel)
inbuilt("kirlia", ::KirliaModel)
inbuilt("gardevoir", ::GardevoirModel)
inbuilt("gallade", ::GalladeModel)
inbuilt("beldum", ::BeldumModel)
inbuilt("metang", ::MetangModel)
inbuilt("metagross", ::MetagrossModel)
inbuilt("ursaluna", ::UrsalunaModel)
inbuilt("lechonk", ::LechonkModel)
inbuilt("oinkologne_male", ::OinkologneMaleModel)
inbuilt("oinkologne_female", ::OinkologneFemaleModel)
inbuilt("pidove", ::PidoveModel)
inbuilt("tranquill", ::TranquillModel)
inbuilt("unfezant", ::UnfezantModel)
inbuilt("timburr", ::TimburrModel)
inbuilt("gurdurr", ::GurdurrModel)
inbuilt("conkeldurr", ::ConkeldurrModel)
inbuilt("clodsire", ::ClodsireModel)
inbuilt("teddiursa", ::TeddiursaModel)
inbuilt("ursaring", ::UrsaringModel)
inbuilt("litwick", ::LitwickModel)
inbuilt("lampent", ::LampentModel)
inbuilt("chandelure", ::ChandelureModel)
inbuilt("gimmighoulchest", ::GimmighoulChestModel)
inbuilt("gholdengo", ::GholdengoModel)
inbuilt("drifloon", ::DrifloonModel)
inbuilt("drifblim", ::DrifblimModel)
inbuilt("lileep", ::LileepModel)
inbuilt("cradily", ::CradilyModel)
inbuilt("tirtouga", ::TirtougaModel)
inbuilt("carracosta", ::CarracostaModel)
inbuilt("arctovish", ::ArctovishModel)
inbuilt("dracovish", ::DracovishModel)
inbuilt("arctozolt", ::ArctozoltModel)
inbuilt("dracozolt", ::DracozoltModel)
inbuilt("shieldon", ::ShieldonModel)
inbuilt("bastiodon", ::BastiodonModel)
inbuilt("cranidos", ::CranidosModel)
inbuilt("rampardos", ::RampardosModel)
inbuilt("basculegion", ::BasculegionModel)
inbuilt("tyrunt", ::TyruntModel)
inbuilt("tyrantrum", ::TyrantrumModel)
inbuilt("anorith", ::AnorithModel)
inbuilt("armaldo", ::ArmaldoModel)
inbuilt("archen", ::ArchenModel)
inbuilt("archeops", ::ArcheopsModel)
inbuilt("aron", ::AronModel)
inbuilt("lairon", ::LaironModel)
inbuilt("aggron", ::AggronModel)
inbuilt("hippopotas", ::HippopotasModel)
inbuilt("hippowdon", ::HippowdonModel)
inbuilt("zorua", ::ZoruaModel)
inbuilt("zorua_hisuian", ::ZoruaHisuianModel)
inbuilt("zoroark", ::ZoroarkModel)
inbuilt("zoroark_hisuian", ::ZoroarkHisuianModel)
inbuilt("gossifleur", ::GossifleurModel)
inbuilt("eldegoss", ::EldegossModel)
inbuilt("amaura", ::AmauraModel)
inbuilt("aurorus", ::AurorusModel)
inbuilt("voltorb_hisuian", ::VoltorbHisuianModel)
inbuilt("electrode_hisuian", ::ElectrodeHisuianModel)
inbuilt("sentret", ::SentretModel)
inbuilt("qwilfish", ::QwilfishModel)
inbuilt("qwilfish_hisuian", ::QwilfishHisuianModel)
inbuilt("overqwil", ::OverqwilModel)
inbuilt("sneasel_hisuian", ::SneaselHisuianModel)
inbuilt("sneasler", ::SneaslerModel)
inbuilt("tropius", ::TropiusModel)
inbuilt("petilil", ::PetililModel)
inbuilt("lilligant", ::LilligantModel)
inbuilt("petilil_hisui_bias", ::PetililHisuiBiasModel)
inbuilt("lilligant_hisuian", ::LilligantHisuianModel)
inbuilt("darumaka", ::DarumakaModel)
inbuilt("darmanitan", ::DarmanitanModel)
inbuilt("darmanitan_zen", ::DarmanitanZenModel)
inbuilt("turtonator", ::TurtonatorModel)
inbuilt("stonjourner", ::StonjournerModel)
inbuilt("cufant", ::CufantModel)
inbuilt("copperajah", ::CopperajahModel)
inbuilt("budew", ::BudewModel)
inbuilt("roselia", ::RoseliaModel)
inbuilt("roserade", ::RoseradeModel)
inbuilt("woobat", ::WoobatModel)
inbuilt("swoobat", ::SwoobatModel)
inbuilt("frillish", ::FrillishModel)
inbuilt("jellicent", ::JellicentModel)
inbuilt("cubchoo", ::CubchooModel)
inbuilt("beartic", ::BearticModel)
inbuilt("deino", ::DeinoModel)
inbuilt("zweilous", ::ZweilousModel)
inbuilt("larvesta", ::LarvestaModel)
inbuilt("volcarona", ::VolcaronaModel)
inbuilt("dreepy", ::DreepyModel)
inbuilt("drakloak", ::DrakloakModel)
inbuilt("dragapult", ::DragapultModel)
inbuilt("diglett_alolan", ::DiglettAlolanModel)
inbuilt("dugtrio_alolan", ::DugtrioAlolanModel)
inbuilt("makuhita", ::MakuhitaModel)
inbuilt("hariyama", ::HariyamaModel)
inbuilt("alomomola", ::AlomomolaModel)
inbuilt("ferroseed", ::FerroseedModel)
inbuilt("ferrothorn", ::FerrothornModel)
inbuilt("carbink", ::CarbinkModel)
inbuilt("goomy", ::GoomyModel)
inbuilt("goomy_hisui_bias", ::GoomyHisuiBiasModel)
inbuilt("sliggoo", ::SliggooModel)
inbuilt("sliggoo_hisuian", ::SliggooHisuianModel)
inbuilt("goodra", ::GoodraModel)
inbuilt("goodra_hisuian", ::GoodraHisuianModel)
inbuilt("heracross", ::HeracrossModel)
inbuilt("salandit", ::SalanditModel)
inbuilt("salazzle", ::SalazzleModel)
inbuilt("jangmo-o", ::JangmoOModel)
inbuilt("hakamo-o", ::HakamoOModel)
inbuilt("kommo-o", ::KommoOModel)
inbuilt("trapinch", ::TrapinchModel)
inbuilt("vibrava", ::VibravaModel)
inbuilt("flygon", ::FlygonModel)
inbuilt("larvitar", ::LarvitarModel)
inbuilt("pupitar", ::PupitarModel)
inbuilt("tyranitar", ::TyranitarModel)
inbuilt("impidimp", ::ImpidimpModel)
inbuilt("morgrem", ::MorgremModel)
inbuilt("grimmsnarl", ::GrimmsnarlModel)
inbuilt("klefki", ::KlefkiModel)
inbuilt("oshawott_hisui_bias", ::OshawottHisuiBiasModel)
inbuilt("dewott_hisui_bias", ::DewottHisuiBiasModel)
inbuilt("samurott_hisuian", ::SamurottHisuianModel)
inbuilt("cyndaquil_hisui_bias", ::CyndaquilHisuiBiasModel)
inbuilt("quilava_hisui_bias", ::QuilavaHisuiBiasModel)
inbuilt("typhlosion_hisuian", ::TyphlosionHisuianModel)
inbuilt("rowlet_hisui_bias", ::RowletHisuiBiasModel)
inbuilt("dartrix_hisui_bias", ::DartrixHisuiBiasModel)
inbuilt("decidueye_hisuian", ::DecidueyeHisuianModel)
}
fun registerJsonPosers(resourceManager: ResourceManager) {
for ((directory, poserClass) in poserDirectories) {
resourceManager
.listResources(directory) { path -> path.endsWith(".json") }
.forEach { (identifier, resource) ->
resource.open().use { stream ->
val json = String(stream.readAllBytes(), StandardCharsets.UTF_8)
val resolvedIdentifier = ResourceLocation.fromNamespaceAndPath(identifier.namespace, File(identifier.path).nameWithoutExtension)
posers[resolvedIdentifier] = loadJsonPoser(resolvedIdentifier.path, json)
posers[resolvedIdentifier] = loadJsonPoser(resolvedIdentifier.path, json, poserClass)
}
}
}
}
fun inbuilt(name: String, model: (ModelPart) -> T) {
fun inbuilt(name: String, model: (ModelPart) -> PosableModel) {
posers[cobblemonResource(name)] = { bone -> model.invoke(bone as ModelPart) }
}
@@ -193,7 +830,7 @@ abstract class VaryingModelRepository<T : PosableModel> {
variations.values.forEach { it.initialize(this) }
Cobblemon.LOGGER.info("Loaded $variationCount $title variations.")
Cobblemon.LOGGER.info("Loaded $variationCount variations.")
}
fun registerModels(resourceManager: ResourceManager) {
@@ -203,18 +840,18 @@ abstract class VaryingModelRepository<T : PosableModel> {
resourceManager.listResources(directory) { path -> path.endsWith(key) }
.map { func.apply(it.key, it.value) }
.forEach {
texturedModels[it.first] = { isForLivingEntityRenderer -> it.second.apply(isForLivingEntityRenderer) }
texturedModels[it.first] = it.second
models++
}
}
}
Cobblemon.LOGGER.info("Loaded $models $title models.")
Cobblemon.LOGGER.info("Loaded $models models.")
}
fun reload(resourceManager: ResourceManager) {
Cobblemon.LOGGER.info("Loading $title assets...")
Cobblemon.LOGGER.info("Loading varying Bedrock assets...")
this.variations.clear()
this.posers.clear()
registerModels(resourceManager)
@@ -222,14 +859,14 @@ abstract class VaryingModelRepository<T : PosableModel> {
registerVariations(resourceManager)
}
fun getPoser(name: ResourceLocation, state: PosableState): T {
fun getPoser(name: ResourceLocation, state: PosableState): PosableModel {
try {
val poser = this.variations[name]?.getPoser(state)
if (poser != null) {
return poser
}
} catch(e: IllegalStateException) {
// e.printStackTrace()
e.printStackTrace()
}
return this.variations[fallback]!!.getPoser(state)
}
@@ -271,25 +908,22 @@ abstract class VaryingModelRepository<T : PosableModel> {
return null
}
companion object {
fun registerFactory(id: String, factory: BiFunction<ResourceLocation, Resource, Pair<ResourceLocation, Function<Boolean, Bone>>>) {
MODEL_FACTORIES[id] = factory
}
fun registerFactory(id: String, factory: BiFunction<ResourceLocation, Resource, Pair<ResourceLocation, Bone>>) {
MODEL_FACTORIES[id] = factory
}
/*
Needs to be java function to work with non kotlin sidemods.
- Waterpicker
*/
private var MODEL_FACTORIES = mutableMapOf<String, BiFunction<ResourceLocation, Resource, Pair<ResourceLocation, Function<Boolean, Bone>>>>().also {
it[".geo.json"] = BiFunction<ResourceLocation, Resource, Pair<ResourceLocation, Function<Boolean, Bone>>> { identifier: ResourceLocation, resource: Resource ->
resource.open().use { stream ->
val json = String(stream.readAllBytes(), StandardCharsets.UTF_8)
val resolvedIdentifier = ResourceLocation.fromNamespaceAndPath(identifier.namespace, File(identifier.path).nameWithoutExtension)
/*
Needs to be java function to work with non kotlin sidemods.
- Waterpicker
*/
private var MODEL_FACTORIES = mutableMapOf<String, BiFunction<ResourceLocation, Resource, Pair<ResourceLocation, Bone>>>().also {
it[".geo.json"] = BiFunction<ResourceLocation, Resource, Pair<ResourceLocation, Bone>> { identifier: ResourceLocation, resource: Resource ->
resource.open().use { stream ->
val json = String(stream.readAllBytes(), StandardCharsets.UTF_8)
val resolvedIdentifier = ResourceLocation.fromNamespaceAndPath(identifier.namespace, File(identifier.path).nameWithoutExtension)
val texturedModel = TexturedModel.from(json)
val boneCreator: Function<Boolean, Bone> = Function { texturedModel.create(it).bakeRoot() }
Pair(resolvedIdentifier, boneCreator)
}
val texturedModel = TexturedModel.from(json)
resolvedIdentifier to texturedModel.create().bakeRoot()
}
}
}
@@ -11,8 +11,8 @@ package com.cobblemon.mod.common.client.render.npc
import com.cobblemon.mod.common.client.entity.NPCClientDelegate
import com.cobblemon.mod.common.client.render.models.blockbench.PosableEntityModel
import com.cobblemon.mod.common.client.render.models.blockbench.npc.PosableNPCModel
import com.cobblemon.mod.common.client.render.models.blockbench.repository.NPCModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.client.renderer.MultiBufferSource
@@ -23,7 +23,7 @@ import kotlin.math.min
class NPCRenderer(context: Context) : LivingEntityRenderer<NPCEntity, PosableEntityModel<NPCEntity>>(context, PosableNPCModel(), 0.5f) {
override fun getTextureLocation(entity: NPCEntity): ResourceLocation {
return NPCModelRepository.getTexture(entity.npc.resourceIdentifier, (entity.delegate as NPCClientDelegate))
return VaryingModelRepository.getTexture(entity.npc.resourceIdentifier, (entity.delegate as NPCClientDelegate))
}
override fun render(
@@ -38,14 +38,14 @@ class NPCRenderer(context: Context) : LivingEntityRenderer<NPCEntity, PosableEnt
val clientDelegate = entity.delegate as NPCClientDelegate
clientDelegate.currentAspects = aspects
shadowRadius = min((entity.boundingBox.maxX - entity.boundingBox.minX), (entity.boundingBox.maxZ) - (entity.boundingBox.minZ)).toFloat() / 1.5F
val model = NPCModelRepository.getPoser(entity.npc.resourceIdentifier, clientDelegate)
val model = VaryingModelRepository.getPoser(entity.npc.resourceIdentifier, clientDelegate)
this.model.posableModel = model
model.context = this.model.context
this.model.setupEntityTypeContext(entity)
this.model.context.put(RenderContext.TEXTURE, getTextureLocation(entity))
clientDelegate.updatePartialTicks(partialTicks)
model.setLayerContext(buffer, clientDelegate, NPCModelRepository.getLayers(entity.npc.resourceIdentifier, clientDelegate))
model.setLayerContext(buffer, clientDelegate, VaryingModelRepository.getLayers(entity.npc.resourceIdentifier, clientDelegate))
poseMatrix.pushPose()
poseMatrix.scale(entity.npc.modelScale, entity.npc.modelScale, entity.npc.modelScale)
@@ -21,8 +21,9 @@ import kotlin.random.Random
abstract class PokeBallPosableState : PosableState(), Schedulable {
abstract val stateEmitter: SettableObservable<EmptyPokeBallEntity.CaptureState>
abstract val shakeEmitter: Observable<Unit>
private val group: String
protected open val group: String
get() = if (this.currentModel is AncientPokeBallModel) "ancient_poke_ball" else "poke_ball"
protected open var lastKnownState: EmptyPokeBallEntity.CaptureState? = null
open fun initSubscriptions() {
stateEmitter.subscribe { state ->
@@ -44,9 +45,17 @@ abstract class PokeBallPosableState : PosableState(), Schedulable {
}
EmptyPokeBallEntity.CaptureState.FALL -> {}
EmptyPokeBallEntity.CaptureState.SHAKE -> {
EmptyPokeBallEntity.CaptureState.CRITICAL -> {
doLater {
setActiveAnimations(currentModel!!.bedrockStateful(group, "bounce"))
setActiveAnimations(currentModel!!.bedrockStateful(group, "critical"))
}
}
EmptyPokeBallEntity.CaptureState.SHAKE -> {
if (this.lastKnownState != EmptyPokeBallEntity.CaptureState.CRITICAL) {
// Skip the bounce on a critical capture, the animation replaces this step
doLater {
setActiveAnimations(currentModel!!.bedrockStateful(group, "bounce"))
}
}
shakeEmitter
.pipe(Observable.emitWhile { stateEmitter.get() == EmptyPokeBallEntity.CaptureState.SHAKE })
@@ -60,11 +69,6 @@ abstract class PokeBallPosableState : PosableState(), Schedulable {
setActiveAnimations(currentModel!!.bedrockStateful(group, "capture"))
}
}
EmptyPokeBallEntity.CaptureState.CAPTURED_CRITICAL -> {
doLater {
setActiveAnimations(currentModel!!.bedrockStateful(group, "critical"))
}
}
EmptyPokeBallEntity.CaptureState.BROKEN_FREE -> {
doLater {
setActiveAnimations(currentModel!!.bedrockStateful(group, "break"))
@@ -72,6 +76,7 @@ abstract class PokeBallPosableState : PosableState(), Schedulable {
}
else -> {}
}
this.lastKnownState = state
}
}
}
@@ -10,9 +10,8 @@ package com.cobblemon.mod.common.client.render.pokeball
import com.cobblemon.mod.common.client.entity.EmptyPokeBallClientDelegate
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.PosablePokeBallModel
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokeBallModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.math.Axis
@@ -28,7 +27,7 @@ class PokeBallRenderer(context: EntityRendererProvider.Context) : EntityRenderer
val model = PosablePokeBallModel()
override fun getTextureLocation(pEntity: EmptyPokeBallEntity): ResourceLocation {
return PokeBallModelRepository.getTexture(pEntity.pokeBall.name, pEntity.delegate as EmptyPokeBallClientDelegate)
return VaryingModelRepository.getTexture(pEntity.pokeBall.name, pEntity.delegate as EmptyPokeBallClientDelegate)
}
override fun render(entity: EmptyPokeBallEntity, yaw: Float, partialTicks: Float, poseStack: PoseStack, buffer: MultiBufferSource, packedLight: Int) {
@@ -36,7 +35,7 @@ class PokeBallRenderer(context: EntityRendererProvider.Context) : EntityRenderer
this.model.context.put(RenderContext.POSABLE_STATE, state)
this.model.context.put(RenderContext.ASPECTS, entity.aspects)
state.currentAspects = entity.aspects
val model = PokeBallModelRepository.getPoser(entity.pokeBall.name, state)
val model = VaryingModelRepository.getPoser(entity.pokeBall.name, state)
this.model.posableModel = model
this.model.posableModel.context = this.model.context
this.model.setupEntityTypeContext(entity)
@@ -46,7 +45,7 @@ class PokeBallRenderer(context: EntityRendererProvider.Context) : EntityRenderer
poseStack.scale(0.7F, -0.7F, -0.7F)
val vertexConsumer = ItemRenderer.getFoilBufferDirect(buffer, RenderType.entityCutout(getTextureLocation(entity)), false, false)
state.updatePartialTicks(partialTicks)
model.setLayerContext(buffer, state, PokemonModelRepository.getLayers(entity.pokeBall.name, state))
model.setLayerContext(buffer, state, VaryingModelRepository.getLayers(entity.pokeBall.name, state))
this.model.setupAnim(entity, 0f, 0f, entity.tickCount + partialTicks, 0F, 0F)
this.model.renderToBuffer(poseStack, vertexConsumer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
Loaded 100 of 223 files, more files were not shown because too many files have changed in this diff. Show more