Compare commits

..
154 Commits
Author SHA1 Message Date
jeffw773 0b85132e0b - Debugging State for Mouse Clicks for addon 2024-02-02 10:01:14 -08:00
jeffw773 9b06f6a31f - Zooming with scroll wheel works now 2024-02-01 19:52:36 -08:00
jeffw773 b3696dd45c - Test adding new stuff to Photodex test for addon 2024-02-01 10:54:46 -08:00
jeffw773 aeda9d94a6 Made some test code to create an item called the Photodex which aims to look like the camera in the Pokemon Snap games that can be aimed at a Pokemon from far away and used to detect what kind of pokemon you are aiming at. Hoping it helps lay some ground work for making a functioning camera object in the future 2023-10-29 21:03:16 -07:00
Nick e817675abc Merge branch 'licious/354' into 'main'
Make pasture blocks connect to all wall-like blocks

Closes #354

See merge request cable-mc/cobblemon!730
2023-10-29 17:20:17 +00:00
Licious 49ebd740b6 Change up pasture block bottom voxelshape to be able to connect to blocks like walls. Remove unnecessary FenceBlockMixin due to changes. 2023-10-29 16:42:37 +00:00
Licious a96b550618 Merge branch 'advancement-fixes-and-additions' into 'main'
Advancement Evolution crash fix

Closes #608

See merge request cable-mc/cobblemon!729
2023-10-29 10:59:51 +00:00
MoeBoy76 b1431b1be1 Update file CHANGELOG.md 2023-10-29 09:47:03 +00:00
MoeBoy76 19400a71f2 added evolution ID 2023-10-29 20:37:56 +11:00
MoeBoy76 87661224da be more verbose with error message and use fancy Kotlin thingy 2023-10-29 19:45:37 +11:00
MoeBoy76 92dc6fefe0 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into advancement-fixes-and-additions
# Conflicts:
#	CHANGELOG.md
2023-10-29 19:19:35 +11:00
Hiroku c99b1503cb Merge branch 'spawning-json-fix' into 'main'
Fixed json spawning files

Closes #650

See merge request cable-mc/cobblemon!723
2023-10-28 23:21:58 +00:00
JPAKx4 8ede54739b Added a tool to check for mistakes in spawning jsons. also fixed the json problems that were reported. 2023-10-28 18:01:18 -05:00
JPAKx4 921f3796c1 Drop is an intended property. 2023-10-28 17:57:32 -05:00
Hiroku 225d170ee3 Merge branch 'licious/620' into 'main'
Add EvolutionTestedEvent

Closes #620

See merge request cable-mc/cobblemon!728
2023-10-28 21:39:53 +00:00
MoeBoy76 5e3479eb8f added catch for bad evolution data crashing the AdvancementHandler and print warning for the evolution that has bad data. 2023-10-29 07:59:50 +11:00
Licious 13379eb8d0 Add EvolutionTestedEvent. 2023-10-28 21:09:43 +01:00
Nick 47f05d0b37 Merge branch 'licious/612' into 'main'
Fixed the SpawnEvent not respecting usage of Cancelable#cancel

Closes #612

See merge request cable-mc/cobblemon!727
2023-10-28 19:30:36 +00:00
Nick 5f6bfa03aa Merge branch 'licious/stat-fix' into 'main'
Fix some more stuff in PokemonStats

See merge request cable-mc/cobblemon!726
2023-10-28 19:08:53 +00:00
Licious 83ac0388d6 Fixed the SpawnEvent not respecting usage of Cancelable#cancel 2023-10-28 19:38:11 +01:00
Licious 454c2b368a Fix coercion for present stat 2023-10-28 19:26:36 +01:00
Licious 4395514376 Fix some more stuff in PokemonStats 2023-10-28 19:25:05 +01:00
Hiroku a8f7141c14 Merge branch 'main' into 'main'
Update `SpawnAction#run` to `open`

See merge request cable-mc/cobblemon!724
2023-10-28 04:46:23 +00:00
corgi in tights eba32fbf60 Update SpawnAction#run to open 2023-10-28 04:30:58 +00:00
JPAKx4 57a3ad9c9b Added a tool to check for mistakes in spawning jsons. also fixed the json problems that were reported. 2023-10-27 21:36:57 -05:00
JPAKx4 40c2c843a2 Merge remote-tracking branch 'origin/main' 2023-10-27 20:27:39 -05:00
Hiroku b20db43afa Merge branch 'curseMessageFix' into 'main'
Fixed cursed battle message

Closes #632

See merge request cable-mc/cobblemon!722
2023-10-27 22:07:49 +00:00
e81c025152 Fixed cursed battle message
Closes #632

Co-authored-by: Plastered_Crab <jeffw773@gmail.com><name@example.com>
Co-authored-by: Hiroku <paul_l_preston@hotmail.com>
2023-10-27 23:09:30 +02:00
Hiroku 39a9c60a84 Merge branch 'Extra-Brewing-Stand-Hopper-Items' into 'main'
More Brewing Stand Insertables

See merge request cable-mc/cobblemon!717
2023-10-27 20:18:11 +00:00
Hiroku dd3787896b Merge branch 'passengerDefaultPose' into 'main'
Default pose for Passenger Pokemon = PosteType.STAND

Closes #636

See merge request cable-mc/cobblemon!720
2023-10-27 20:17:16 +00:00
Hiroku 80ddbaf50c Merge branch 'main' into 'passengerDefaultPose'
# Conflicts:
#   CHANGELOG.md
2023-10-27 20:16:52 +00:00
Hiroku 62c9654f97 Merge branch 'fix-iv-loading' into 'main'
Query all stats on data read, even if they don't exist. Fixes #625

Closes #625

See merge request cable-mc/cobblemon!721
2023-10-27 20:16:02 +00:00
Nick 98b5d69d01 Query all stats on data read, even if they don't exist. Fixes #625 2023-10-27 20:16:02 +00:00
Waldleufer 87f0811c2b Default pose for Passenger Pokemon = PosteType.STAND
Added the fix to the changelog
2023-10-27 17:58:36 +02:00
Waldleufer ec58079b4f Default pose for Passenger Pokemon = PosteType.STAND 2023-10-26 15:51:15 +02:00
Charzard4261 7c3cf3f498 Simplified the check to just check against the BrewingRecipes.brewableItems list. 2023-10-26 11:01:38 +01:00
Hiroku a7c0a911e3 Merge branch 'pokemon-drop-credit' into 'main'
Credits the player who defeated the pokemon in battle for drops.

See merge request cable-mc/cobblemon!718
2023-10-26 09:54:10 +00:00
Hiroku fee8634661 Merge branch 'ai-actor-tweak' into 'main'
Move choice request to its own method that can be overridden.

See merge request cable-mc/cobblemon!719
2023-10-26 09:53:29 +00:00
Hiroku 68a517332f Merge branch 'clefairy-moon-phase' into 'main'
Fixed Clefairy moon phase issue

See merge request cable-mc/cobblemon!716
2023-10-26 09:52:58 +00:00
Deltric b78bdd727f Move choice request to its own method that can be overridden. 2023-10-25 18:19:09 -05:00
Deltric 610e197236 Credits the player who defeated the pokemon in battle for drops. 2023-10-25 17:43:49 -05:00
Charzard4261 27ee34573d Added PP Restoring and Status Healing items to the BrewingStandBlockEntityMixin isValid check for Hopper Insertion. 2023-10-25 23:07:17 +01:00
Plastered_Crab e4bd024567 Added: "Fixed Moonphases for Clefairy line" 2023-10-25 17:40:06 +00:00
Plastered_Crab e41d94b5dc Update 0173_cleffa.json 2023-10-25 17:38:36 +00:00
Plastered_Crab 00ae3841db Update 0036_clefable.json 2023-10-25 17:37:44 +00:00
Plastered_Crab b0a54a408f Update 0035_clefairy.json 2023-10-25 17:37:10 +00:00
Hiroku a34735891a Merge branch 'sound' into 'main'
Sound stuff

See merge request cable-mc/cobblemon!715
2023-10-25 10:05:20 +00:00
Sterrezo 17552017f9 Update CHANGELOG.md 2023-10-25 11:31:17 +02:00
Sterrezo d90cd5b9a8 Merge branch 'main' into sound 2023-10-25 11:30:13 +02:00
Sterrezo 33fe1a7c32 Made sounds.json easier to look at 2023-10-25 11:27:13 +02:00
Hiroku 17096f3bb7 Merge branch 'cooking-with-berries' into 'main'
Two Tags

Closes #598

See merge request cable-mc/cobblemon!703
2023-10-25 07:36:18 +00:00
Hiroku 81f733e89f Merge branch 'main' into 'cooking-with-berries'
# Conflicts:
#   CHANGELOG.md
2023-10-25 07:08:43 +00:00
Hiroku fac7419225 Merge branch 'Licenses-are-fun' into 'main'
Fixing Licenses

See merge request cable-mc/cobblemon!714
2023-10-25 06:56:30 +00:00
JPAKx4 69d174b6a6 Merge remote-tracking branch 'origin/main' 2023-10-24 19:07:22 -05:00
Hiroku d66f534b95 Merge branch 'roggenrola_drop_fix' into 'main'
fixing drops for roggenrola

See merge request cable-mc/cobblemon!713
2023-10-24 20:14:24 +00:00
Waldleufer 6f342045f4 Fixing Licenses for Jordan
I'm not mad, just disappointed.
2023-10-24 22:01:56 +02:00
Waldleufer 726aeac836 fixing drops for roggenrola
and some auto reformatting that happens when the .py script runs.
2023-10-24 21:22:05 +02:00
JPAKx4 f01c5a5ceb Merge remote-tracking branch 'origin/main'
# Conflicts:
#	CHANGELOG.md
2023-10-23 19:31:52 -05:00
Licious 5876d83147 Merge branch 'chansey_drop_fix' into 'main'
fix drops for chansey/blissey

Closes #628

See merge request cable-mc/cobblemon!712
2023-10-23 19:01:20 +00:00
Lily ae1a55fa98 fix drops for chansey/blissey 2023-10-23 18:14:14 +00:00
Hiroku 417fefa911 Merge branch 'Brewing-Stand-Hopper-Interaction' into 'main'
Allow Hoppers to insert Medicinal Brew / Poke Potions into Brewing Stands

See merge request cable-mc/cobblemon!698
2023-10-23 05:11:12 +00:00
Hiroku e30cc3dce8 Merge branch 'main' into 'Brewing-Stand-Hopper-Interaction'
# Conflicts:
#   CHANGELOG.md
2023-10-23 03:59:30 +00:00
Hiroku 63f721bc9b Merge branch 'main' into 'main'
Created a system to add blocks to the flammable registry in FireBlock and...

Closes #553

See merge request cable-mc/cobblemon!711
2023-10-23 00:33:04 +00:00
Jordan 27248fd17d Created a system to add blocks to the flammable registry in FireBlock and... 2023-10-23 00:33:04 +00:00
JPAKx4 c198aee827 Moved the array into the init method and adjusted wording to be better. 2023-10-22 19:22:16 -05:00
JPAKx4 a8c6d58499 Merge remote-tracking branch 'origin/main' 2023-10-22 19:20:57 -05:00
Hiroku 9e748cc9cf Merge branch 'mintedNatureQOLChanges' into 'main'
Italicized Nature and Hovertext for Minted Natures in Info, PC and Trade Screen.

Closes #480

See merge request cable-mc/cobblemon!702
2023-10-22 23:32:00 +00:00
Waldleufer 5890918e04 Added MPL Header 2023-10-22 21:49:49 +02:00
Waldleufer c0567ac11f The nature of Cobblemon will now indicate minted Nature. 2023-10-22 21:38:18 +02:00
Waldleufer 5036e334dc Compostability 2023-10-22 21:23:01 +02:00
Waldleufer 9f798cddf5 Display MintedNature Italicized and with Tooltip showing the Mint used. 2023-10-22 21:09:48 +02:00
Waldleufer eb2828e0a4 Moved Minted Nature reformatting to its own file. 2023-10-22 21:09:48 +02:00
Waldleufer 53f127fc23 added onHover for Text 2023-10-22 21:09:48 +02:00
Waldleufer c463bb6e06 Compostable integration 2023-10-22 21:09:17 +02:00
Waldleufer 4e9d45d38c MutableText.onHover() now is actually drawn if text is being hovered
#480
2023-10-22 21:08:15 +02:00
Waldleufer 4e2f7d3bc5 InfoWidget refactored into multiple smaller widgets.
#480
2023-10-22 21:08:15 +02:00
Waldleufer 8975b099ad InfoWidget reworked.
#480
2023-10-22 21:08:09 +02:00
Waldleufer 308380706a Implemented Hovertext and italicized Nature for Minted Natures in Info and Trade Screen.
I am sure there is a better way to do that though.

#480
2023-10-22 21:01:31 +02:00
Waldleufer ef80924526 Display MintedNature Italicized and with Tooltip showing the Mint used. 2023-10-22 20:58:43 +02:00
Waldleufer fadf57046d Moved Minted Nature reformatting to its own file. 2023-10-22 20:44:17 +02:00
JPAKx4 13cedaaf73 Refactored the flammable blocks system, it's now in one centralized place and has comments to make things clearer. The values are all based on the vanilla counterparts. 2023-10-22 10:08:27 -05:00
Waldleufer 0a0806716b added onHover for Text 2023-10-22 15:18:35 +02:00
Waldleufer af59cb5e58 Using Map for better performance 2023-10-22 15:16:22 +02:00
Charzard4261 c0f8e37206 Merge branch 'main' into 'Brewing-Stand-Hopper-Interaction'
# Conflicts:
#   CHANGELOG.md
2023-10-22 13:14:34 +00:00
Waldleufer e64aaf66ab MutableText.onHover() now is actually drawn if text is being hovered
#480
2023-10-22 14:49:58 +02:00
Waldleufer a946dfea1f InfoWidget refactored into multiple smaller widgets.
#480
2023-10-22 14:49:25 +02:00
dhi_holo f2c459cc06 Pain, Suffering Even
Moved the tags to only be in their respective modloaders, that took way too long to figure out, updated the Forge version to what Farmer's Delight uses because of failed testing, and added this to the changelog
2023-10-22 15:39:19 +10:00
Jordan 6f12f53e85 Update CHANGELOG to include branch changes 2023-10-22 04:14:11 +00:00
JPAKx4 073ee8e283 Merge https://gitlab.com/superpizzaman10/cobblemon-compost-fix 2023-10-21 22:44:25 -05:00
JPAKx4 d3a5ad8efa Created a system to add blocks to the flammable registry in FireBlock and added apricorn wood to it. 2023-10-21 22:43:19 -05:00
Jordan 62a2dcc606 Merge branch cobblemon:main into main 2023-10-22 03:37:25 +00:00
dhi_holo a7f71eb437 Merge branch 'main' into cooking-with-berries 2023-10-22 13:03:28 +10:00
JPAKx4 b65dab7f30 Merge remote-tracking branch 'origin/main' 2023-10-21 20:15:53 -05:00
Hiroku ac76878002 Merge branch 'main' into 'main'
Simplified composting as well as made mint, apricorn, and berries more consistent.

See merge request cable-mc/cobblemon!710
2023-10-22 01:13:46 +00:00
Jordan fe219e52e6 Simplified composting as well as made mint, apricorn, and berries more consistent. 2023-10-22 01:13:45 +00:00
Jordan bfd28ec9b0 Update CHANGELOG.md 2023-10-22 01:05:18 +00:00
JPAKx4 1063441b0e Merge https://gitlab.com/superpizzaman10/cobblemon-compost-fix into tempBranch 2023-10-21 18:39:29 -05:00
JPAKx4 4e89f45253 Simplified composting as well as made mint, apricorn, and berries more consistent. 2023-10-21 16:00:18 -05:00
dhi_holo 56aa5ae8d8 Merge branch 'main' into cooking-with-berries 2023-10-21 12:53:21 +10:00
Hiroku 156a7a70eb Merge branch 'battle-potion-fix' into 'main'
Fix Potions, Super Potions, and Hyper Potions not working during Battle

See merge request cable-mc/cobblemon!708
2023-10-21 02:21:09 +00:00
Hiroku 3b13b9f246 Merge branch 'PlasteredCrab-main-patch-56636' into 'main'
Update CHANGELOG.md to include Potion use during battle issue

See merge request cable-mc/cobblemon!709
2023-10-21 02:21:03 +00:00
Plastered_Crab 0a8d920285 Update CHANGELOG.md to include Potion use during battle issue 2023-10-21 02:15:28 +00:00
Plastered_Crab f5418a8088 Update PotionItem.kt to fix Potions, Super Potions, and Hyper Potions not working during Battle 2023-10-21 02:07:00 +00:00
Hiroku cae097bf2c Merge branch 'berry-juice-bowl' into 'main'
Fixed Berry Juice so bowl is given back to player

See merge request cable-mc/cobblemon!706
2023-10-21 01:56:36 +00:00
Hiroku f760003c3a Merge branch 'PlasteredCrab-main-patch-58336' into 'main'
Update CHANGELOG.md to include Berry Juice changes

See merge request cable-mc/cobblemon!707
2023-10-21 01:56:17 +00:00
Plastered_Crab 38f70c5960 Update CHANGELOG.md to include Berry Juice changes 2023-10-21 01:55:00 +00:00
Plastered_Crab 81b00d7f85 Fixed Berry Juice so that when it is used in and outside of Battle when in Survival Mode a wooden bowl is given back to the player 2023-10-21 01:47:43 +00:00
Paul 948ceeaa8d Merge remote-tracking branch 'origin/main' 2023-10-21 10:14:25 +10:00
Paul 1eda446897 Fixed bad PC loading from JSON and NBT store adapters due to 392b6993 2023-10-21 10:14:15 +10:00
Charzard4261 49d03c0336 Merge branch 'main' into 'Brewing-Stand-Hopper-Interaction'
# Conflicts:
#   CHANGELOG.md
2023-10-20 21:57:53 +00:00
Licious c5d254cca7 Merge branch 'Berries-On-Modded-Farmland' into 'main'
Allow Berries on Modded Farmland

See merge request cable-mc/cobblemon!705
2023-10-20 20:29:52 +00:00
Waldleufer 4f7fda1e96 InfoWidget reworked.
#480
2023-10-20 20:22:01 +02:00
Charzard4261 d3e10cb570 Merge remote-tracking branch 'origin/Berries-On-Modded-Farmland' into Berries-On-Modded-Farmland 2023-10-20 19:12:34 +01:00
Charzard4261 51d7d2cb04 Added Forge and Fabric (unofficial but according to their standards) farmlands tag to facilitate better compatibility, as advised by Licious. 2023-10-20 19:12:19 +01:00
Charzard4261 ac53d2da95 Merge branch 'main' into 'Berries-On-Modded-Farmland'
# Conflicts:
#   CHANGELOG.md
2023-10-20 16:43:45 +00:00
Charzard4261 17e41f5f0b Updated CHANGELOG.md 2023-10-20 17:30:29 +01:00
Charzard4261 4bd70698ce Added a "below.block is FarmlandBlock" check for Berry blocks to allow them to be placed on other blocks that extend from it. 2023-10-20 17:25:57 +01:00
Sterrezo 23b750d5e9 Added a sound for giving Pokemon items and taking items from them 2023-10-20 17:46:43 +02:00
Charzard4261 ab2b67c426 Merge branch 'main' into 'Brewing-Stand-Hopper-Interaction'
# Conflicts:
#   CHANGELOG.md
2023-10-20 12:17:00 +00:00
Hiroku d68c912ca6 Merge branch 'Dispenser-Shear-Apricorn-Fix' into 'main'
Fixed Dispensers being unable to shear grown Apricorns

See merge request cable-mc/cobblemon!701
2023-10-20 09:32:17 +00:00
Hiroku c391d1a5e0 Merge branch 'main' into 'Dispenser-Shear-Apricorn-Fix'
# Conflicts:
#   CHANGELOG.md
2023-10-20 07:42:04 +00:00
Nick 0af39118eb Merge branch 'multi-party-fix' into 'main'
Allows PlayerPartyStore's to have their own unique storage id, separate from the player uuid.

See merge request cable-mc/cobblemon!704
2023-10-20 07:21:03 +00:00
Deltric 392b69937f Allows PlayerPartyStore's to have their own unique storage id, separate from the player uuid. 2023-10-20 01:53:32 -05:00
Hiroku e32af733f1 Merge branch 'more-mod-compat' into 'main'
Fix compatibility with the Forge version of Carry On, add compatibility for Adorn.

See merge request cable-mc/cobblemon!697
2023-10-20 06:41:13 +00:00
dhi_holo e1509c9dab Two Tags
Adds Cobblemon Berries to the Forge and Fabric general tags for berries (which aren't core to their APIs), allowing for Farmer's Delight compatibility, unsure if anything else actually uses it but eh, doesn't hurt to have this set up
2023-10-20 12:30:14 +10:00
Waldleufer 1cb6baee59 Implemented Hovertext and italicized Nature for Minted Natures in Info and Trade Screen.
I am sure there is a better way to do that though.

#480
2023-10-20 00:09:19 +02:00
Sterrezo 9403cb6296 Merge branch 'main' into sound 2023-10-19 23:59:55 +02:00
Sterrezo fd157fae4f Lowered the volume of all cries 2023-10-19 23:59:08 +02:00
Charzard4261 9ca472ccaf Fixed Dispensers being unable to shear grown Apricorns. 2023-10-19 11:48:27 +01:00
Charzard4261 13b7e0d418 Update CHANGELOG.md 2023-10-19 10:20:07 +00:00
Charzard4261 a6ddc1e4ae Add missing MAX_POTION check. 2023-10-19 00:30:10 +01:00
Charzard4261 a5b1b87ec5 Add a new Mixin for BrewingStandBlockEntity that allows for Hopper interaction with Cobblemon POTIONs and MEDICINAL_BREW. 2023-10-18 22:24:59 +01:00
Licious b3255045fa Fix compatibility with the Forge version of Carry On, add compatibility for Adorn. 2023-10-18 22:17:35 +01:00
Hiroku 90f3acebac Merge branch 'main' into 'main'
Check chunks are loaded before running AreaSpawner

See merge request cable-mc/cobblemon!692
2023-10-18 20:00:56 +00:00
Nick 0da91fb255 Merge branch 'Miltank-Milk-Revert-Fix' into 'main'
Fix Miltank Bucket Reversion

See merge request cable-mc/cobblemon!696
2023-10-18 18:22:23 +00:00
Charzard4261 ba3b26ac74 Fix desync that was causing milk buckets occasionally reverting to regular buckets by removing the ServerClientPlayer check in PokemonEntity.interactMob for Shearing and Milking, and modifying it slightly to be the same calls as CowEntity (minus the SFX). 2023-10-18 17:49:47 +01:00
Xander Forrest 966761776d Merge branch cobblemon:main into main 2023-10-18 10:20:29 +00:00
Nick 24f07c58a0 Merge branch 'fabric-roots-spreading-fix' into 'main'
Fix Fabric big root spreading.

See merge request cable-mc/cobblemon!695
2023-10-17 23:06:24 +00:00
Xander Forrest a8b5f649a8 Merge branch cobblemon:main into main 2023-10-17 21:49:58 +00:00
Xander Forrest 295c73ae69 Don't create chunk in SpawningProspector 2023-10-17 22:47:38 +01:00
Xander Forrest 899bdb38ac Removes ServerChunkManagerMixin.java
Update chunk logic in AreaSpawner.constrainArea to reflect this
Updated Prospector to not use SCCM when getting chunks
2023-10-17 21:40:47 +01:00
Nick f30e5bda1e Merge branch 'improve-mongo-db-store-override' into 'main'
Improve the ability to reuse and override the MongoDBStoreAdapter.

See merge request cable-mc/cobblemon!694
2023-10-17 19:50:18 +00:00
Licious 76c870b472 Fix Fabric big root spreading. 2023-10-17 20:40:43 +01:00
Nick 963448e173 Merge branch 'composter-registration-changes' into 'main'
Update Composter block valid item registration

See merge request cable-mc/cobblemon!693
2023-10-17 19:30:03 +00:00
Licious 48d2fc6e2e Improve the ability to reuse and override the MongoDBStoreAdapter. 2023-10-17 20:08:49 +01:00
Licious 5868d39431 Rework Composter item registration to be platform implementation specific. 2023-10-17 19:53:48 +01:00
Xander Forrest c47b3a21db Move isBoxLoaded to WorldExtensions.kt 2023-10-17 10:41:47 +01:00
Xander Forrest 0d12fb1f1c When running AreaSpawner, check area box's chunks are all loaded before attempting to get all entities in the area 2023-10-17 10:18:05 +01:00
Hiroku 78c7188a11 Merge branch 'update_version' into 'main'
update version

See merge request cable-mc/cobblemon!691
2023-10-16 03:49:53 +00:00
Hiroku ff5f63a998 Merge branch 'main' into 'update_version'
# Conflicts:
#   gradle.properties
2023-10-16 03:49:34 +00:00
Lily b9a8a9be11 update version 2023-10-15 22:24:29 -04:00
Paul 2046482252 Turn snapshot back on, 1.4 looks good 2023-10-14 17:46:43 +10:00
Hiroku 6a737999a9 Merge branch 'sendingOutShoulderedCobblemon' into 'main'
Dismounting Shouldered Cobblemon

Closes #473

See merge request cable-mc/cobblemon!680
2023-10-14 07:04:34 +00:00
Waldleufer 89d37e583b Dismounting Shouldered Cobblemon 2023-10-14 07:04:33 +00:00
181 changed files with 4967 additions and 1621 deletions

No files matched your search

+35 -1
View File
@@ -1,4 +1,39 @@
# Changelog
## [1.4.1](#1-4-1)
### Changes
- Slightly lowered the volume of all cries
- Pasture blocks will now also connect their bottom left and right sides to walls, iron bars, glass panes and any other modded block that follows the same connection rules.
### Additions
- Cobblemon now has compatibility with [Adorn](https://modrinth.com/mod/adorn) allowing you to craft Apricorn wood furniture.
- Berries can now be used in recipes from [Farmer's Delight](https://modrinth.com/mod/farmers-delight) and [Farmer's Delight (Fabric)](https://modrinth.com/mod/farmers-delight-fabric), as well as any other mods using the same berry tags.
- The nature of cobblemon will now be displayed italicized when a mint has been applied. Hovering over the nature will display the mint that was applied. This is the intended behaviour, because the original nature and taste of the Cobblemon does not change when a mint is applied.
- Giving Pokémon items now plays a sound
### Fixes
- Fixed various stone related blocks not being valid for Big Roots to spread on the Fabric version.
- Updated the registration of compostable items to improve compatibility with Fabric forks such as Quilt. Please note this does not mean we officially support Quilt, this change was only done since it was possible by correcting the registration to use the new intended way in the Fabric API.
- Fixed Dispensers being unable to shear grown Apricorns.
- Fixed Bowl not being given back to player after using Berry Juice
- Fixed Moonphases for Clefairy line
- Fixed issue where Potions, Super Potions, and Hyper Potions did not work during battle
- Fixed the compatibility patch with the Forge version of [Carry On](https://modrinth.com/mod/carry-on) due to a bug on the mod, the Fabric version was unchanged and is still compatible.
- Added the ability to place Berries on modded Farmland blocks.
- Shouldered Pokémon now hop off when selected in team and r is pressed. This also is in effect in battles leading to shouldered Pokémon jumping of the shoulder of the trainer when it is their turn.
- Made more items compostable and changed the process for making items compostable.
- Added the ability for Hoppers to fill Brewing Stands with Medicinal Brews and Potions.
- Apricorn blocks are now flammable.
- The default pose for Pokémon being passengers is now "standing".
- Fixed issue where some IVs were changing every player relog.
- Fixed cursed battle message
- Fixed mistakes in pokemon spawning JSONs
- Fixed advancement crash from bad datapack evolution data.
### Developer
- Fixed the `SpawnEvent` not respecting usage of `Cancelable#cancel`.
- Added the `EvolutionTestedEvent`, this allows listening and overriding the final result of evolution requirement tests.
## [1.4.0 - The Friends and Farms Update (October 13th, 2023)](#1-4-0)
### Additions
- Added pasture blocks, used to let your PC Pokémon roam around an area.
@@ -797,7 +832,6 @@
- Fixed Magnitude battle messages.
- Moves that are disabled or out of PP now show transparently in the battle GUI instead of being hidden completely.
- Statuses like sleep and frozen no longer last forever if it was carried over from a previous battle.
- Fixed a formatting error that affected Pokemon nicknames when the storage type is JSON.
### Localization
- Added species, ability, and move translations for `ko_ko`, `jp_jp`, `fr_fr`, `es_es`, `it_it`, and `zh_cn`.
+2
View File
@@ -19,6 +19,7 @@ architectury {
repositories {
maven(url = "${rootProject.projectDir}/deps")
maven(url = "https://api.modrinth.com/maven")
mavenLocal()
}
@@ -31,6 +32,7 @@ dependencies {
// modCompileOnly(libs.flywheelFabric)
modApi(libs.molang)
compileOnlyApi(libs.jeiApi)
modCompileOnly(libs.adornFabric)
// For Showdown
modCompileOnly(libs.graal)
@@ -1,47 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.CobblemonBlocks;
import com.cobblemon.mod.common.block.PastureBlock;
import net.minecraft.block.BlockState;
import net.minecraft.block.FenceBlock;
import net.minecraft.block.HorizontalFacingBlock;
import net.minecraft.util.math.Direction;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(value = FenceBlock.class)
public abstract class FenceBlockMixin {
// This could be done with a modify variable but it just doesn't seem to want to work, very crude unfinished explanation I had on Fabric discord was
// "boolean is a primitive, it isnt passed by reference but by value and you have your own object references anyway so assigning a new object to non-primitive references (variables) wont modify it after your mixin returns
//(you cant modify a random argument that mixin passes you that way, target the boolean not the FenceBlock)"
// However the issue is the only way to get all the params which we need is by passing in the entire method reference which enforces the return type.
@Redirect(method = "getStateForNeighborUpdate", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/FenceBlock;canConnect(Lnet/minecraft/block/BlockState;ZLnet/minecraft/util/math/Direction;)Z"))
private boolean cobblemon$getStateForNeighborUpdate(FenceBlock instance, BlockState state, boolean neighborIsFullSquare, Direction dir) {
return instance.canConnect(state, neighborIsFullSquare, dir) || this.cobblemon$canConnect(state, dir);
}
@Redirect(method = "getPlacementState", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/FenceBlock;canConnect(Lnet/minecraft/block/BlockState;ZLnet/minecraft/util/math/Direction;)Z"))
private boolean cobblemon$getPlacementState(FenceBlock instance, BlockState state, boolean neighborIsFullSquare, Direction dir) {
return instance.canConnect(state, neighborIsFullSquare, dir) || this.cobblemon$canConnect(state, dir);
}
private boolean cobblemon$canConnect(BlockState state, Direction dir) {
if (state.isOf(CobblemonBlocks.PASTURE) && state.get(PastureBlock.Companion.getPART()) == PastureBlock.PasturePart.BOTTOM) {
final Direction pastureFacing = state.get(HorizontalFacingBlock.FACING);
return dir == pastureFacing.rotateYClockwise() || dir == pastureFacing.rotateYCounterclockwise();
}
return false;
}
}
@@ -1,44 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.api.spawning.mixins.CachedOnlyChunkAccessor;
import com.mojang.datafixers.util.Either;
import net.minecraft.server.world.ChunkHolder;
import net.minecraft.server.world.ServerChunkManager;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.ChunkManager;
import net.minecraft.world.chunk.ChunkStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.concurrent.CompletableFuture;
@Mixin(ServerChunkManager.class)
public abstract class ServerChunkManagerMixin extends ChunkManager implements CachedOnlyChunkAccessor {
@Shadow @Nullable protected abstract ChunkHolder getChunkHolder(long pos);
@Override
public Chunk cobblemon$request(int x, int z, @NotNull ChunkStatus status) {
long l = ChunkPos.toLong(x, z);
ChunkHolder holder = getChunkHolder(l);
if (holder != null) {
CompletableFuture<Either<Chunk, ChunkHolder.Unloaded>> future = holder.getFutureFor(status);
if (future.isDone()) {
return future.join().left().orElse(null);
}
}
return null;
}
}
@@ -0,0 +1,35 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.entity;
import com.cobblemon.mod.common.brewing.BrewingRecipes;
import net.minecraft.block.entity.BrewingStandBlockEntity;
import net.minecraft.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(BrewingStandBlockEntity.class)
public abstract class BrewingStandBlockEntityMixin
{
@Inject(
method = "isValid",
at = @At(value = "HEAD"),
cancellable = true
)
private void cobblemon$isValid(int slot, ItemStack stack, CallbackInfoReturnable<Boolean> cir) {
final BrewingStandBlockEntity entity = (BrewingStandBlockEntity) (Object) this;
if (slot < 3)
{
if (entity.getStack(slot).isEmpty() && BrewingRecipes.brewableItems.contains(stack.getItem()))
cir.setReturnValue(true);
}
}
}
@@ -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.mixin.invoker;
import net.minecraft.block.Block;
import org.spongepowered.asm.mixin.Mixin;
import net.minecraft.block.FireBlock;
import net.minecraft.block.Blocks;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(FireBlock.class)
public interface FireBlockInvoker {
@Invoker("registerFlammableBlock") void registerNewFlammableBlock(Block block, int burnChance, int spreadChance);
}
@@ -33,6 +33,8 @@ import net.minecraft.util.math.intprovider.UniformIntProvider
@Suppress("SameParameterValue", "HasPlatformType", "MemberVisibilityCanBePrivate", "unused")
object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<Block>>, Block>() {
override val registry: Registry<Block> = Registries.BLOCK
override val registryKey: RegistryKey<Registry<Block>> = RegistryKeys.BLOCK
@@ -228,6 +230,8 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
APRICORN_LOG to STRIPPED_APRICORN_LOG
)
private fun apricornBlock(name: String, apricorn: Apricorn): ApricornBlock = this.create(name, ApricornBlock(AbstractBlock.Settings.create().mapColor(apricorn.mapColor()).ticksRandomly().strength(Blocks.OAK_LOG.hardness, Blocks.OAK_LOG.blastResistance).sounds(BlockSoundGroup.WOOD).nonOpaque(), apricorn))
private val berries = mutableMapOf<Identifier, BerryBlock>()
@@ -302,6 +306,25 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
val WIKI_BERRY = this.berryBlock("wiki")
val YACHE_BERRY = this.berryBlock("yache")
init {
/**
* Makes all blocks in array flammable by adding them to FireBlock's flammableRegistry.
* second value is burn chance and third value is spread chance
*/
arrayOf(
Triple(APRICORN_LOG, 5, 5),
Triple(STRIPPED_APRICORN_LOG, 5, 5),
Triple(APRICORN_WOOD, 5, 5),
Triple(STRIPPED_APRICORN_WOOD, 5, 5),
Triple(APRICORN_PLANKS, 5, 20),
Triple(APRICORN_LEAVES, 30, 60),
Triple(APRICORN_FENCE, 5, 20),
Triple(APRICORN_FENCE_GATE, 5, 20),
Triple(APRICORN_SLAB, 5, 20),
Triple(APRICORN_STAIRS, 5, 20)
).onEach{ data -> setFlammable(data.first, data.second, data.third) }
}
fun berries() = this.berries.toMap()
private fun berryBlock(name: String): BerryBlock {
@@ -312,14 +335,28 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
}
/**
* Helper method for creating logs
* copied over from Vanilla
* Calls helper method from Vanilla
*/
private fun log(name: String, arg: MapColor = MapColor.DIRT_BROWN, arg2: MapColor = MapColor.DIRT_BROWN): PillarBlock {
val block = BlocksInvoker.createLogBlock(arg, arg2)
return this.create(name, block)
}
/**
* Method uses generic E in order to keep the block as the same return type.
* If E is not a block then it will not be set as flammable.
* Calls Vanilla implementation of registering a flammable block.
* Mixins looks cursed but it is java's fault.
*/
private fun <E> setFlammable(block: E, burnChance: Int, spreadChance: Int): E {
if(block !is Block) return block
var fireBlock: FireBlock = Blocks.FIRE as FireBlock
//Cursed Mixin stuff
(fireBlock as FireBlockInvoker).registerNewFlammableBlock(block as Block, burnChance, spreadChance)
return block
}
private fun evolutionStoneOre(name: String) = this.create(name, ExperienceDroppingBlock(AbstractBlock.Settings.copy(Blocks.IRON_ORE), UniformIntProvider.create(1, 2)))
private fun deepslateEvolutionStoneOre(name: String) = this.create(name, ExperienceDroppingBlock(AbstractBlock.Settings.copy(Blocks.DEEPSLATE_IRON_ORE), UniformIntProvider.create(1, 2)))
@@ -15,7 +15,9 @@ import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
import com.mojang.brigadier.arguments.ArgumentType
import kotlin.reflect.KClass
import net.minecraft.advancement.criterion.Criterion
import net.minecraft.block.ComposterBlock
import net.minecraft.command.argument.serialize.ArgumentSerializer
import net.minecraft.item.ItemConvertible
import net.minecraft.network.PacketByteBuf
import net.minecraft.network.listener.ClientPlayPacketListener
import net.minecraft.network.packet.Packet
@@ -26,6 +28,7 @@ import net.minecraft.resource.ResourceReloader
import net.minecraft.resource.ResourceType
import net.minecraft.server.MinecraftServer
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.text.Text
import net.minecraft.util.Identifier
import net.minecraft.world.GameRules
import net.minecraft.world.biome.Biome
@@ -169,6 +172,44 @@ interface CobblemonImplementation {
* @param manager The [ResourceManager] to reload from.
*/
fun <T> reloadJsonRegistry(registry: JsonDataRegistry<T>, manager: ResourceManager): HashMap<Identifier, T>
/**
* Registers an item to the [ComposterBlock].
*
* @param item The [ItemConvertible] being registered.
* @param chance The chance % of increasing the composter level, 0 to 1 expected.
*/
fun registerCompostable(item: ItemConvertible, chance: Float)
/**
* Registers a builtin resource pack.
*
* @param id The unique [Identifier] of this pack.
* @param title The title displayed in the resource pack GUI, the description is still a part of the pack metadata.
* @param activationBehaviour The [ResourcePackActivationBehaviour] for this pack.
*/
fun registerBuiltinResourcePack(id: Identifier, title: Text, activationBehaviour: ResourcePackActivationBehaviour)
}
enum class ResourcePackActivationBehaviour {
/**
* The resource pack will start disabled.
*/
NORMAL,
/**
* The resource pack will start enabled.
*/
DEFAULT_ENABLED,
/**
* The resource pack will always be enabled.
* The user can reorder it but cannot remove it.
*/
ALWAYS_ENABLED;
}
enum class ModAPI {
@@ -14,6 +14,7 @@ import com.cobblemon.mod.common.api.pokemon.Natures
import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.api.pokemon.status.Statuses
import com.cobblemon.mod.common.block.BerryBlock
import com.cobblemon.mod.common.block.MintBlock
import com.cobblemon.mod.common.block.MintBlock.MintType
import com.cobblemon.mod.common.item.*
import com.cobblemon.mod.common.item.battle.DireHitItem
@@ -32,7 +33,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.block.Block
import net.minecraft.block.ComposterBlock
import net.minecraft.entity.LivingEntity
import net.minecraft.entity.effect.StatusEffectInstance
import net.minecraft.entity.effect.StatusEffects
@@ -117,40 +117,40 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
val CHERISH_BALL = pokeBallItem(PokeBalls.CHERISH_BALL)
@JvmField
val VIVICHOKE = create("vivichoke", Item(Item.Settings()))
val VIVICHOKE = compostableItem("vivichoke")
@JvmField
val VIVICHOKE_SEEDS = create("vivichoke_seeds", VivichokeItem(CobblemonBlocks.VIVICHOKE_SEEDS))
val VIVICHOKE_SEEDS = compostableItem("vivichoke_seeds", VivichokeItem(CobblemonBlocks.VIVICHOKE_SEEDS))
@JvmField
val RED_APRICORN = create("red_apricorn", ApricornItem(CobblemonBlocks.RED_APRICORN))
val RED_APRICORN = apricronItem("red", ApricornItem(CobblemonBlocks.RED_APRICORN))
@JvmField
val YELLOW_APRICORN = create("yellow_apricorn", ApricornItem(CobblemonBlocks.YELLOW_APRICORN))
val YELLOW_APRICORN = apricronItem("yellow", ApricornItem(CobblemonBlocks.YELLOW_APRICORN))
@JvmField
val GREEN_APRICORN = create("green_apricorn", ApricornItem(CobblemonBlocks.GREEN_APRICORN))
val GREEN_APRICORN = apricronItem("green", ApricornItem(CobblemonBlocks.GREEN_APRICORN))
@JvmField
val BLUE_APRICORN = create("blue_apricorn", ApricornItem(CobblemonBlocks.BLUE_APRICORN))
val BLUE_APRICORN = apricronItem("blue", ApricornItem(CobblemonBlocks.BLUE_APRICORN))
@JvmField
val PINK_APRICORN = create("pink_apricorn", ApricornItem(CobblemonBlocks.PINK_APRICORN))
val PINK_APRICORN = apricronItem("pink", ApricornItem(CobblemonBlocks.PINK_APRICORN))
@JvmField
val BLACK_APRICORN = create("black_apricorn", ApricornItem(CobblemonBlocks.BLACK_APRICORN))
val BLACK_APRICORN = apricronItem("black", ApricornItem(CobblemonBlocks.BLACK_APRICORN))
@JvmField
val WHITE_APRICORN = create("white_apricorn", ApricornItem(CobblemonBlocks.WHITE_APRICORN))
val WHITE_APRICORN = apricronItem("white", ApricornItem(CobblemonBlocks.WHITE_APRICORN))
@JvmField
val RED_APRICORN_SEED = create("red_apricorn_seed", ApricornSeedItem(CobblemonBlocks.RED_APRICORN_SAPLING))
val RED_APRICORN_SEED = apricronSeedItem("red", ApricornSeedItem(CobblemonBlocks.RED_APRICORN_SAPLING))
@JvmField
val YELLOW_APRICORN_SEED = create("yellow_apricorn_seed", ApricornSeedItem(CobblemonBlocks.YELLOW_APRICORN_SAPLING))
val YELLOW_APRICORN_SEED = apricronSeedItem("yellow", ApricornSeedItem(CobblemonBlocks.YELLOW_APRICORN_SAPLING))
@JvmField
val GREEN_APRICORN_SEED = create("green_apricorn_seed", ApricornSeedItem(CobblemonBlocks.GREEN_APRICORN_SAPLING))
val GREEN_APRICORN_SEED = apricronSeedItem("green", ApricornSeedItem(CobblemonBlocks.GREEN_APRICORN_SAPLING))
@JvmField
val BLUE_APRICORN_SEED = create("blue_apricorn_seed", ApricornSeedItem(CobblemonBlocks.BLUE_APRICORN_SAPLING))
val BLUE_APRICORN_SEED = apricronSeedItem("blue", ApricornSeedItem(CobblemonBlocks.BLUE_APRICORN_SAPLING))
@JvmField
val PINK_APRICORN_SEED = create("pink_apricorn_seed", ApricornSeedItem(CobblemonBlocks.PINK_APRICORN_SAPLING))
val PINK_APRICORN_SEED = apricronSeedItem("pink", ApricornSeedItem(CobblemonBlocks.PINK_APRICORN_SAPLING))
@JvmField
val BLACK_APRICORN_SEED = create("black_apricorn_seed", ApricornSeedItem(CobblemonBlocks.BLACK_APRICORN_SAPLING))
val BLACK_APRICORN_SEED = apricronSeedItem("black", ApricornSeedItem(CobblemonBlocks.BLACK_APRICORN_SAPLING))
@JvmField
val WHITE_APRICORN_SEED = create("white_apricorn_seed", ApricornSeedItem(CobblemonBlocks.WHITE_APRICORN_SAPLING))
val WHITE_APRICORN_SEED = apricronSeedItem("white", ApricornSeedItem(CobblemonBlocks.WHITE_APRICORN_SAPLING))
@JvmField
val APRICORN_LOG = blockItem("apricorn_log", CobblemonBlocks.APRICORN_LOG)
@@ -163,13 +163,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
@JvmField
val APRICORN_PLANKS = blockItem("apricorn_planks", CobblemonBlocks.APRICORN_PLANKS)
@JvmField
val APRICORN_LEAVES = blockItem("apricorn_leaves", CobblemonBlocks.APRICORN_LEAVES).also {
val compostChance = ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE.getFloat(Items.OAK_LEAVES)
// Should always pass unless Mojang reworks leaves to no longer work in the Composter, in that case we already updated w.o doing anything
if (compostChance != ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE.defaultReturnValue()) {
ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE[it] = compostChance
}
}
val APRICORN_LEAVES = compostableBlockItem("apricorn_leaves", CobblemonBlocks.APRICORN_LEAVES)
@JvmField
val APRICORN_DOOR = blockItem("apricorn_door", CobblemonBlocks.APRICORN_DOOR)
@@ -353,11 +347,11 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
}
})
@JvmField
val ENERGY_ROOT = create("energy_root", EnergyRootItem(CobblemonBlocks.ENERGY_ROOT, Item.Settings().food(FoodComponent.Builder().hunger(1).snack().saturationModifier(0.2f).build())))
val ENERGY_ROOT = compostableItem("energy_root", EnergyRootItem(CobblemonBlocks.ENERGY_ROOT, Item.Settings().food(FoodComponent.Builder().hunger(1).snack().saturationModifier(0.2f).build())))
@JvmField
val REVIVAL_HERB = create("revival_herb", RevivalHerbItem(CobblemonBlocks.REVIVAL_HERB))
val REVIVAL_HERB = compostableItem("revival_herb", RevivalHerbItem(CobblemonBlocks.REVIVAL_HERB))
@JvmField
val PEP_UP_FLOWER = blockItem("pep_up_flower", CobblemonBlocks.PEP_UP_FLOWER)
val PEP_UP_FLOWER = compostableBlockItem("pep_up_flower", CobblemonBlocks.PEP_UP_FLOWER)
@JvmField
val MEDICINAL_BREW = create("medicinal_brew", Item(Item.Settings()))
@JvmField
@@ -392,72 +386,74 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
val PP_MAX = create("pp_max", PPUpItem(3))
@JvmField
val RED_MINT_SEEDS = blockItem("red_mint_seeds", MintType.RED.getCropBlock())
val RED_MINT_SEEDS = mintSeed("red", MintType.RED.getCropBlock())
@JvmField
val RED_MINT_LEAF = create("red_mint_leaf", MintLeafItem(MintType.RED))
val RED_MINT_LEAF = mintLeaf("red", MintLeafItem(MintType.RED))
@JvmField
val BLUE_MINT_SEEDS = blockItem("blue_mint_seeds", MintType.BLUE.getCropBlock())
val BLUE_MINT_SEEDS = mintSeed("blue", MintType.BLUE.getCropBlock())
@JvmField
val BLUE_MINT_LEAF = create("blue_mint_leaf", MintLeafItem(MintType.BLUE))
val BLUE_MINT_LEAF = mintLeaf("blue", MintLeafItem(MintType.BLUE))
@JvmField
val CYAN_MINT_SEEDS = blockItem("cyan_mint_seeds", MintType.CYAN.getCropBlock())
val CYAN_MINT_SEEDS = mintSeed("cyan", MintType.CYAN.getCropBlock())
@JvmField
val CYAN_MINT_LEAF = create("cyan_mint_leaf", MintLeafItem(MintType.CYAN))
val CYAN_MINT_LEAF = mintLeaf("cyan", MintLeafItem(MintType.CYAN))
@JvmField
val PINK_MINT_SEEDS = blockItem("pink_mint_seeds", MintType.PINK.getCropBlock())
val PINK_MINT_SEEDS = mintSeed("pink", MintType.PINK.getCropBlock())
@JvmField
val PINK_MINT_LEAF = create("pink_mint_leaf", MintLeafItem(MintType.PINK))
val PINK_MINT_LEAF = mintLeaf("pink", MintLeafItem(MintType.PINK))
@JvmField
val GREEN_MINT_SEEDS = blockItem("green_mint_seeds", MintType.GREEN.getCropBlock())
val GREEN_MINT_SEEDS = mintSeed("green", MintType.GREEN.getCropBlock())
@JvmField
val GREEN_MINT_LEAF = create("green_mint_leaf", MintLeafItem(MintType.GREEN))
val GREEN_MINT_LEAF = mintLeaf("green", MintLeafItem(MintType.GREEN))
@JvmField
val WHITE_MINT_SEEDS = blockItem("white_mint_seeds", MintType.WHITE.getCropBlock())
val WHITE_MINT_SEEDS = mintSeed("white", MintType.WHITE.getCropBlock())
@JvmField
val WHITE_MINT_LEAF = create("white_mint_leaf", MintLeafItem(MintType.WHITE))
val WHITE_MINT_LEAF = mintLeaf("white", MintLeafItem(MintType.WHITE))
val mints = mutableMapOf<String, MintItem>()
@JvmField
val LONELY_MINT = create("lonely_mint", MintItem(Natures.LONELY))
val LONELY_MINT = mintItem("lonely_mint", MintItem(Natures.LONELY))
@JvmField
val ADAMANT_MINT = create("adamant_mint", MintItem(Natures.ADAMANT))
val ADAMANT_MINT = mintItem("adamant_mint", MintItem(Natures.ADAMANT))
@JvmField
val NAUGHTY_MINT = create("naughty_mint", MintItem(Natures.NAUGHTY))
val NAUGHTY_MINT = mintItem("naughty_mint", MintItem(Natures.NAUGHTY))
@JvmField
val BRAVE_MINT = create("brave_mint", MintItem(Natures.BRAVE))
val BRAVE_MINT = mintItem("brave_mint", MintItem(Natures.BRAVE))
@JvmField
val BOLD_MINT = create("bold_mint", MintItem(Natures.BOLD))
val BOLD_MINT = mintItem("bold_mint", MintItem(Natures.BOLD))
@JvmField
val IMPISH_MINT = create("impish_mint", MintItem(Natures.IMPISH))
val IMPISH_MINT = mintItem("impish_mint", MintItem(Natures.IMPISH))
@JvmField
val LAX_MINT = create("lax_mint", MintItem(Natures.LAX))
val LAX_MINT = mintItem("lax_mint", MintItem(Natures.LAX))
@JvmField
val RELAXED_MINT = create("relaxed_mint", MintItem(Natures.RELAXED))
val RELAXED_MINT = mintItem("relaxed_mint", MintItem(Natures.RELAXED))
@JvmField
val MODEST_MINT = create("modest_mint", MintItem(Natures.MODEST))
val MODEST_MINT = mintItem("modest_mint", MintItem(Natures.MODEST))
@JvmField
val MILD_MINT = create("mild_mint", MintItem(Natures.MILD))
val MILD_MINT = mintItem("mild_mint", MintItem(Natures.MILD))
@JvmField
val RASH_MINT = create("rash_mint", MintItem(Natures.RASH))
val RASH_MINT = mintItem("rash_mint", MintItem(Natures.RASH))
@JvmField
val QUIET_MINT = create("quiet_mint", MintItem(Natures.QUIET))
val QUIET_MINT = mintItem("quiet_mint", MintItem(Natures.QUIET))
@JvmField
val CALM_MINT = create("calm_mint", MintItem(Natures.CALM))
val CALM_MINT = mintItem("calm_mint", MintItem(Natures.CALM))
@JvmField
val GENTLE_MINT = create("gentle_mint", MintItem(Natures.GENTLE))
val GENTLE_MINT = mintItem("gentle_mint", MintItem(Natures.GENTLE))
@JvmField
val CAREFUL_MINT = create("careful_mint", MintItem(Natures.CAREFUL))
val CAREFUL_MINT = mintItem("careful_mint", MintItem(Natures.CAREFUL))
@JvmField
val SASSY_MINT = create("sassy_mint", MintItem(Natures.SASSY))
val SASSY_MINT = mintItem("sassy_mint", MintItem(Natures.SASSY))
@JvmField
val TIMID_MINT = create("timid_mint", MintItem(Natures.TIMID))
val TIMID_MINT = mintItem("timid_mint", MintItem(Natures.TIMID))
@JvmField
val HASTY_MINT = create("hasty_mint", MintItem(Natures.HASTY))
val HASTY_MINT = mintItem("hasty_mint", MintItem(Natures.HASTY))
@JvmField
val JOLLY_MINT = create("jolly_mint", MintItem(Natures.JOLLY))
val JOLLY_MINT = mintItem("jolly_mint", MintItem(Natures.JOLLY))
@JvmField
val NAIVE_MINT = create("naive_mint", MintItem(Natures.NAIVE))
val NAIVE_MINT = mintItem("naive_mint", MintItem(Natures.NAIVE))
@JvmField
val SERIOUS_MINT = create("serious_mint", MintItem(Natures.SERIOUS))
val SERIOUS_MINT = mintItem("serious_mint", MintItem(Natures.SERIOUS))
@JvmField val X_ACCURACY = create("x_${Stats.ACCURACY.identifier.path}", XStatItem(Stats.ACCURACY))
@JvmField val X_ATTACK = create("x_${Stats.ATTACK.identifier.path}", XStatItem(Stats.ATTACK))
@@ -616,11 +612,11 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
@JvmField
val WISE_GLASSES = heldItem("wise_glasses")
@JvmField
val MENTAL_HERB = heldItem("mental_herb")
val MENTAL_HERB = compostableHeldItem("mental_herb")
@JvmField
val MIRROR_HERB = heldItem("mirror_herb")
val MIRROR_HERB = compostableHeldItem("mirror_herb")
@JvmField
val POWER_HERB = heldItem("power_herb")
val POWER_HERB = compostableHeldItem("power_herb")
@JvmField
val WHITE_HERB = heldItem("white_herb")
@JvmField
@@ -670,10 +666,17 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
@JvmField
val POKEMON_MODEL = this.create("pokemon_model", PokemonItem())
//Keyitems
@JvmField
val PHOTODEX = photodexItem("photodex")
private fun blockItem(name: String, block: Block): BlockItem = this.create(name, BlockItem(block, Item.Settings()))
private fun noSettingsItem(name: String): CobblemonItem = this.create(name, CobblemonItem(Item.Settings()))
private fun photodexItem(name: String): PhotodexItem = this.create(name, PhotodexItem())
fun berries() = this.berries.toMap()
private fun mulchItem(name: String, mulchVariant: MulchVariant): MulchItem = this.create(name, MulchItem(mulchVariant))
@@ -696,9 +699,12 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
}
)
private fun compostable(item: Item, increaseLevelChance: Float) = Cobblemon.implementation.registerCompostable(item, increaseLevelChance)
private fun berryItem(name: String, berryBlock: BerryBlock): BerryItem {
val finalName = "${name}_berry"
val item = this.create(finalName, BerryItem(berryBlock))
compostable(item, .65f)
this.berries[cobblemonResource(finalName)] = item
return item
}
@@ -706,7 +712,62 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
private fun berryItem(name: String, berryItem: BerryItem): BerryItem {
val finalName = "${name}_berry"
val item = this.create(finalName, berryItem)
compostable(item, .65f)
this.berries[cobblemonResource(finalName)] = item
return item
}
private fun mintItem(name: String, mintItem: MintItem): MintItem {
val item = this.create(name, mintItem)
mints[item.nature.displayName] = item
compostable(item, .65f)
return item
}
private fun apricronItem(name: String, apricornItem: ApricornItem): ApricornItem {
val finalName = "${name}_apricorn"
val item = this.create(finalName, apricornItem)
compostable(item, .65f)
return item
}
private fun apricronSeedItem(name: String, apricronSeedItem: ApricornSeedItem): ApricornSeedItem {
val finalName = "${name}_apricorn_seed"
val item = this.create(finalName, apricronSeedItem)
compostable(item, .65f)
return item
}
private fun mintSeed(name: String, mintBlock: MintBlock): Item {
val finalName = "${name}_mint_seeds"
val item = this.blockItem(finalName, mintBlock)
compostable(item, .65f)
return item
}
private fun mintLeaf(name: String, mintLeafItem: MintLeafItem): MintLeafItem {
val finalName = "${name}_mint_leaf"
val item = this.create(finalName, mintLeafItem)
compostable(item, .65f)
return item
}
private fun compostableItem(name: String, item: Item? = null, increaseLevelChance: Float = .65f): Item {
val createdItem = this.create(name, item ?: Item(Item.Settings()))
compostable(createdItem, increaseLevelChance)
return createdItem
}
private fun compostableHeldItem(name: String, remappedName: String? = null, increaseLevelChance: Float = .65f): CobblemonItem {
val createdItem = heldItem(name, remappedName)
compostable(createdItem, increaseLevelChance)
return createdItem
}
private fun compostableBlockItem(name: String, block: Block, increaseLevelChance: Float = .65f): Item {
val createdItem = this.blockItem(name, block)
compostable(createdItem, increaseLevelChance)
return createdItem
}
}
@@ -26,13 +26,20 @@ abstract class AIBattleActor(
super.sendUpdate(packet)
if (packet is BattleMakeChoicePacket) {
try {
setActionResponses(request!!.iterate(this.activePokemon, battleAI::choose))
} catch (exception: IllegalActionChoiceException) {
LOGGER.error("AI was unable to choose a move, we're going to need to pass!")
exception.printStackTrace()
setActionResponses(request!!.iterate(this.activePokemon) { _, _, _ -> PassActionResponse })
}
this.onChoiceRequested()
}
}
/**
* Called when the AI is requested to make a choice.
*/
open fun onChoiceRequested() {
try {
setActionResponses(request!!.iterate(this.activePokemon, battleAI::choose))
} catch (exception: IllegalActionChoiceException) {
LOGGER.error("AI was unable to choose a move, we're going to need to pass!")
exception.printStackTrace()
setActionResponses(request!!.iterate(this.activePokemon) { _, _, _ -> PassActionResponse })
}
}
}
@@ -31,6 +31,7 @@ import com.cobblemon.mod.common.api.events.pokemon.*
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionAcceptedEvent
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEvent
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionDisplayEvent
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionTestedEvent
import com.cobblemon.mod.common.api.events.pokemon.interaction.ExperienceCandyUseEvent
import com.cobblemon.mod.common.api.events.starter.StarterChosenEvent
import com.cobblemon.mod.common.api.events.storage.ReleasePokemonEvent
@@ -43,6 +44,7 @@ import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import net.minecraft.server.network.ServerPlayerEntity
@Suppress("unused")
object CobblemonEvents {
@JvmField
@@ -58,6 +60,8 @@ object CobblemonEvents {
@JvmField
val EVOLUTION_DISPLAY = EventObservable<EvolutionDisplayEvent>()
@JvmField
val EVOLUTION_TESTED = EventObservable<EvolutionTestedEvent>()
@JvmField
val EVOLUTION_COMPLETE = EventObservable<EvolutionCompleteEvent>()
@JvmField
val POKEMON_NICKNAMED = CancelableObservable<PokemonNicknamedEvent>()
@@ -109,7 +113,10 @@ object CobblemonEvents {
val POKEMON_ENTITY_SPAWN = ENTITY_SPAWN
.pipe(
filter { it.entity is PokemonEntity },
map { it as SpawnEvent<PokemonEntity> }
map {
@Suppress("UNCHECKED_CAST")
it as SpawnEvent<PokemonEntity>
}
)
@JvmField
@@ -23,6 +23,6 @@ import com.cobblemon.mod.common.pokemon.Pokemon
* @since April 28th, 2022
*/
data class EvolutionAcceptedEvent(
val pokemon: Pokemon,
val evolution: Evolution
) : Cancelable()
override val pokemon: Pokemon,
override val evolution: Evolution
) : Cancelable(), EvolutionEvent
@@ -21,6 +21,6 @@ import com.cobblemon.mod.common.pokemon.Pokemon
* @since October 2nd, 2022
*/
data class EvolutionCompleteEvent(
val pokemon: Pokemon,
val evolution: Evolution
)
override val pokemon: Pokemon,
override val evolution: Evolution
) : EvolutionEvent
@@ -25,7 +25,7 @@ import com.cobblemon.mod.common.pokemon.Pokemon
* @since May 3rd, 2022
*/
data class EvolutionDisplayEvent(
val pokemon: Pokemon,
override val pokemon: Pokemon,
var display: EvolutionDisplay,
val evolution: Evolution
)
override val evolution: Evolution
) : EvolutionEvent
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.pokemon.evolution
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.pokemon.Pokemon
/**
* The root of the various evolution related events.
*/
interface EvolutionEvent {
/**
* The Pokémon impacted in this event.
*/
val pokemon: Pokemon
/**
* The evolution triggering this event.
*/
val evolution: Evolution
}
@@ -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.api.events.pokemon.evolution
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.pokemon.Pokemon
/**
* An event fired when [Evolution.test] has been performed.
* The final state [result] will be the return value of the test function.
*
* @property pokemon The [Pokemon] being tested against.
* @property evolution The [Evolution] instance performing the test.
* @property originalResult The base result from the Cobblemon implementation.
* @property result The final value returned by [Evolution.test].
*/
data class EvolutionTestedEvent(
override val pokemon: Pokemon,
override val evolution: Evolution,
val originalResult: Boolean,
var result: Boolean
) : EvolutionEvent
@@ -122,16 +122,27 @@ fun drawText(
y: Number,
centered: Boolean = false,
colour: Int,
shadow: Boolean = true
) {
shadow: Boolean = true,
pMouseX: Number? = null,
pMouseY: Number? = null
): Boolean {
val comp = if (font == null) text else text.setStyle(text.style.withFont(font))
val textRenderer = MinecraftClient.getInstance().textRenderer
var x = x
val width = textRenderer.getWidth(comp)
if (centered) {
val width = textRenderer.getWidth(comp)
x = x.toDouble() - width / 2
}
context.drawText(textRenderer, comp, x.toInt(), y.toInt(), colour, shadow)
var isHovered = false
if (pMouseY != null && pMouseX != null) {
if (pMouseX.toInt() >= x.toInt() && pMouseX.toInt() <= x.toInt() + width &&
pMouseY.toInt() >= y.toInt() && pMouseY.toInt() <= y.toInt() + textRenderer.fontHeight
) {
isHovered = true
}
}
return isHovered
}
fun drawText(
@@ -9,9 +9,9 @@
package com.cobblemon.mod.common.api.pokemon.evolution
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.abilities.AbilityPool
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEvent
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionTestedEvent
import com.cobblemon.mod.common.api.moves.BenchedMove
import com.cobblemon.mod.common.api.moves.MoveTemplate
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
@@ -67,7 +67,12 @@ interface Evolution : EvolutionLike {
* @param pokemon The [Pokemon] being queried.
* @return If the [Evolution] can start.
*/
fun test(pokemon: Pokemon) = this.requirements.all { requirement -> requirement.check(pokemon) }
fun test(pokemon: Pokemon): Boolean {
val result = this.requirements.all { requirement -> requirement.check(pokemon) }
val event = EvolutionTestedEvent(pokemon, this, result, result)
CobblemonEvents.EVOLUTION_TESTED.post(event)
return event.result
}
/**
* Starts this evolution or queues it if [optional] is true.
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.api.spawning
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.Cobblemon.config
import com.cobblemon.mod.common.api.spawning.mixins.CachedOnlyChunkAccessor
import com.cobblemon.mod.common.api.spawning.prospecting.SpawningProspector
import com.cobblemon.mod.common.api.spawning.spawner.Spawner
import com.cobblemon.mod.common.api.spawning.spawner.SpawningArea
@@ -81,8 +80,7 @@ object CobblemonSpawningProspector : SpawningProspector {
for (x in area.baseX until area.baseX + area.length) {
for (z in area.baseZ until area.baseZ + area.width) {
val query = chunks.computeIfAbsent(Pair(getSectionCoord(x), getSectionCoord(z))) {
val manager = world.chunkManager as CachedOnlyChunkAccessor
manager.`cobblemon$request`(it.first, it.second, ChunkStatus.FULL)
world.getChunk(it.first, it.second, ChunkStatus.FULL, false)
} ?: continue
var canSeeSky = world.isSkyVisibleAllowingSea(pos.set(x, yRange.first, z))
@@ -28,13 +28,12 @@ abstract class SpawnAction<T : Entity>(
) {
abstract fun createEntity(): T?
fun run() {
open fun run() {
ctx.influences.forEach { it.affectAction(this) }
val e = createEntity() ?: return
e.setPosition(ctx.position.toVec3d().add(0.5, 1.0, 0.5))
entity.emit(e)
CobblemonEvents.ENTITY_SPAWN.post(SpawnEvent(e, ctx))
ctx.world.spawnEntity(e)
CobblemonEvents.ENTITY_SPAWN.postThen(SpawnEvent(e, ctx), ifSucceeded = { ctx.world.spawnEntity(e) })
}
/**
@@ -47,4 +46,4 @@ abstract class SpawnAction<T : Entity>(
val entity: SimpleObservable<T> = SimpleObservable<T>().apply {
subscribe { entity -> ctx.afterSpawn(entity) }
}
}
}
@@ -1,18 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.spawning.mixins
import net.minecraft.world.chunk.Chunk
import net.minecraft.world.chunk.ChunkStatus
interface CachedOnlyChunkAccessor {
fun `cobblemon$request`(x: Int, z: Int, status: ChunkStatus): Chunk?
}
@@ -17,9 +17,9 @@ import com.cobblemon.mod.common.api.spawning.context.calculators.AreaSpawningCon
import com.cobblemon.mod.common.api.spawning.context.calculators.SpawningContextCalculator.Companion.prioritizedAreaCalculators
import com.cobblemon.mod.common.api.spawning.detail.SpawnDetail
import com.cobblemon.mod.common.api.spawning.detail.SpawnPool
import com.cobblemon.mod.common.api.spawning.mixins.CachedOnlyChunkAccessor
import com.cobblemon.mod.common.api.spawning.prospecting.SpawningProspector
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.isBoxLoaded
import com.cobblemon.mod.common.util.squeezeWithinBounds
import com.cobblemon.mod.common.util.toVec3f
import net.minecraft.entity.ai.pathing.NavigationType
@@ -31,6 +31,7 @@ import net.minecraft.world.World
import net.minecraft.world.chunk.Chunk
import net.minecraft.world.chunk.ChunkStatus
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules.DO_POKEMON_SPAWNING
import net.minecraft.util.math.ChunkPos
/**
* A type of [TickingSpawner] that operates within some area. When this spawner type
@@ -59,6 +60,7 @@ abstract class AreaSpawner(
var resolver: AreaContextResolver = Cobblemon.areaContextResolver
var contextCalculators: List<AreaSpawningContextCalculator<*>> = prioritizedAreaCalculators
override fun run(cause: SpawnCause): Pair<SpawningContext, SpawnDetail>? {
val area = getArea(cause)
if (area?.world?.gameRules?.getBoolean(DO_POKEMON_SPAWNING) == false) {
@@ -66,9 +68,15 @@ abstract class AreaSpawner(
}
val constrainedArea = if (area != null) constrainArea(area) else null
if (constrainedArea != null) {
val areaBox = Box.of(Vec3d(constrainedArea.getCenter().toVec3f()), CHUNK_REACH * 16.0 * 2, 1000.0, CHUNK_REACH * 16.0 * 2)
if (!constrainedArea.world.isBoxLoaded(areaBox)) {
return null
}
val numberNearby = constrainedArea.world.getEntitiesByClass(
PokemonEntity::class.java,
Box.of(Vec3d(constrainedArea.getCenter().toVec3f()), CHUNK_REACH * 16.0 * 2, 1000.0, CHUNK_REACH * 16.0 * 2)
areaBox
) { true }.size
val chunksCovered = CHUNK_REACH * CHUNK_REACH
@@ -117,7 +125,11 @@ abstract class AreaSpawner(
val originalY = area.baseY
val (chunkX, chunkZ) = Pair(ChunkSectionPos.getSectionCoord(area.baseX), ChunkSectionPos.getSectionCoord(area.baseZ))
val chunk = (area.world.chunkManager as CachedOnlyChunkAccessor).`cobblemon$request`(chunkX, chunkZ, ChunkStatus.FULL) ?: return null
// if the chunk isn't loaded, we don't want to go further & we don't want the getChunk function below to load/create the chunk.
if (!area.world.isChunkLoaded(ChunkPos.toLong(chunkX, chunkZ))) return null
val chunk = area.world.getChunk(chunkX, chunkZ, ChunkStatus.FULL) ?: return null
var valid = isValidStartPoint(area.world, chunk, basePos)
@@ -32,29 +32,19 @@ import java.util.UUID
* @author Pebbles
* @since August 23rd, 2023
*/
@Suppress("MemberVisibilityCanBePrivate")
open class MongoDBStoreAdapter(
private val mongoClient: MongoClient,
private val databaseName: String,
protected val mongoClient: MongoClient,
protected val databaseName: String,
) : CobblemonAdapterParent<JsonObject>(), FileStoreAdapter<JsonObject> {
private fun getCollection(storeClass: Class<out PokemonStore<*>>): MongoCollection<Document> {
val collectionName = when (storeClass) {
PlayerPartyStore::class.java -> "PlayerPartyCollection"
PCStore::class.java -> "PCCollection"
else -> "OtherCollection"
}
return mongoClient.getDatabase(databaseName).getCollection(collectionName)
}
private val gson: Gson = Gson()
protected val gson: Gson = this.createGson()
override fun <E : StorePosition, T : PokemonStore<E>> serialize(store: T): JsonObject {
return store.saveToJSON(JsonObject())
}
override fun <E : StorePosition, T : PokemonStore<E>> serialize(store: T): JsonObject = store.saveToJSON(JsonObject())
override fun save(storeClass: Class<out PokemonStore<*>>, uuid: UUID, serialized: JsonObject) {
val document = Document.parse(gson.toJson(serialized))
document.put("uuid", uuid.toString())
val document = Document.parse(this.gson.toJson(serialized))
document["uuid"] = uuid.toString()
val collection = getCollection(storeClass)
val filter = Document("uuid", uuid.toString())
collection.replaceOne(filter, document, ReplaceOptions().upsert(true))
@@ -76,7 +66,7 @@ open class MongoDBStoreAdapter(
val document = collection.find(filter).first()
if (document != null) {
val json = gson.fromJson(document.toJson(), JsonObject::class.java)
val json = this.gson.fromJson(document.toJson(), JsonObject::class.java)
val store = storeClass.getConstructor(UUID::class.java).newInstance(uuid)
store.loadFromJSON(json)
return store
@@ -98,4 +88,15 @@ open class MongoDBStoreAdapter(
return null
}
protected open fun createGson(): Gson = Gson()
protected open fun getCollection(storeClass: Class<out PokemonStore<*>>): MongoCollection<Document> {
val collectionName = when (storeClass) {
PlayerPartyStore::class.java -> "PlayerPartyCollection"
PCStore::class.java -> "PCCollection"
else -> "OtherCollection"
}
return this.mongoClient.getDatabase(this.databaseName).getCollection(collectionName)
}
}
@@ -48,7 +48,11 @@ open class JSONStoreAdapter(
val br = BufferedReader(FileReader(file))
val json = gson.fromJson<JsonObject>(br)
br.close()
val store = storeClass.getConstructor(UUID::class.java).newInstance(uuid)
val store = try {
storeClass.getConstructor(UUID::class.java, UUID::class.java).newInstance(uuid, uuid)
} catch (exception: NoSuchMethodException) {
storeClass.getConstructor(UUID::class.java).newInstance(uuid)
}
store.loadFromJSON(json)
store
} catch (e: Exception) {
@@ -31,7 +31,12 @@ open class NBTStoreAdapter(
override fun <E : StorePosition, T : PokemonStore<E>> serialize(store: T) = store.saveToNBT(NbtCompound())
override fun save(file: File, serialized: NbtCompound) = NbtIo.writeCompressed(serialized, file)
override fun <E, T : PokemonStore<E>> load(file: File, storeClass: Class<out T>, uuid: UUID): T? {
val store = storeClass.getConstructor(UUID::class.java).newInstance(uuid)
val store = try {
storeClass.getConstructor(UUID::class.java, UUID::class.java).newInstance(uuid, uuid)
} catch (exception: NoSuchMethodException) {
storeClass.getConstructor(UUID::class.java).newInstance(uuid)
}
return try {
val nbt = NbtIo.readCompressed(file)
store.loadFromNBT(nbt)
@@ -38,8 +38,10 @@ import kotlin.random.Random
*/
open class PlayerPartyStore(
/** The UUID of the player this store is for. */
val playerUUID: UUID
) : PartyStore(playerUUID) {
val playerUUID: UUID,
/** The UUID of the store. This is the same as [playerUUID] by default, but can be changed to allow for multiple parties. */
storageUUID: UUID = playerUUID
) : PartyStore(storageUUID) {
private var secondsSinceFriendshipUpdate = 0
@@ -158,6 +158,7 @@ fun String.stripCodes(): String = this.replace("[&§][A-Ea-e0-9K-Ok-oRr]".toRege
fun MutableText.onClick(consumed: AtomicBoolean, action: (p: ServerPlayerEntity) -> Unit) = also { it.style = it.style.withClickEvent(click(consumed, action)) }
fun MutableText.onClick(onlyOnce: Boolean = false, action: (p: ServerPlayerEntity) -> Unit) = also { it.style = it.style.withClickEvent(click(onlyOnce, action)) }
fun MutableText.onHover(string: String) = also { it.style = it.style.withHoverEvent(hover(string)) }
fun MutableText.onHover(text: Text) = also { it.style = it.style.withHoverEvent(hover(text)) }
fun MutableText.onHover(text: MutableText) = also { it.style = it.style.withHoverEvent(hover(text)) }
fun MutableText.underline() = also { it.style = it.style.withUnderline(true) }
fun MutableText.bold() = also { it.style = it.style.withBold(true) }
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.Cobblemon.LOGGER
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.battles.interpreter.*
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
import com.cobblemon.mod.common.api.battles.model.actor.EntityBackedBattleActor
import com.cobblemon.mod.common.api.data.ShowdownIdentifiable
@@ -24,6 +25,7 @@ import com.cobblemon.mod.common.api.pokemon.status.Statuses
import com.cobblemon.mod.common.api.scheduling.after
import com.cobblemon.mod.common.api.text.*
import com.cobblemon.mod.common.api.types.ElementalTypes
import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
import com.cobblemon.mod.common.battles.dispatch.BattleDispatch
import com.cobblemon.mod.common.battles.dispatch.DispatchResult
import com.cobblemon.mod.common.battles.dispatch.GO
@@ -579,6 +581,17 @@ object ShowdownInterpreter {
battle.end()
val wasCaught = battle.showdownMessages.any { "capture" in it }
// If the battle was a PvW battle, we need to set the killer of the wild Pokémon to the player
if (battle.isPvW) {
val nonPlayerActor = battle.actors.first { it.type == ActorType.WILD }
val wildPokemon: BattlePokemon = nonPlayerActor.pokemonList.first()
if (!wasCaught && losers.any { it.uuid == wildPokemon.uuid }) {
wildPokemon.effectedPokemon.entity?.killer = (battle.actors.firstOrNull { it.type == ActorType.PLAYER } as? PlayerBattleActor)?.entity
}
}
CobblemonEvents.BATTLE_VICTORY.post(BattleVictoryEvent(battle, winners, losers, wasCaught))
this.lastCauser.remove(battle.battleId)
@@ -888,6 +901,8 @@ object ShowdownInterpreter {
"confusion", "perish3" -> return@dispatch GO // Skip
"perish2", "perish1", "perish0" -> battleLang("start.perish", pokemon.getName(), effectID.last().digitToInt())
"dynamax" -> battleLang("start.${message.effectAt(2)?.id ?: effectID}", pokemon.getName()).yellow()
"disable" -> battleLang("start.disable", pokemon.getName(), message.effectAt(2)!!.rawData)
"curse" -> battleLang("start.curse", message.getSourceBattlePokemon(battle)!!.getName(), pokemon.getName())
else -> battleLang("start.$effectID", pokemon.getName())
}
battle.broadcastChatMessage(lang)
@@ -166,7 +166,7 @@ class ApricornBlock(settings: Settings, val apricorn: Apricorn) : HorizontalFaci
}
override fun attemptShear(world: World, state: BlockState, pos: BlockPos, successCallback: () -> Unit): Boolean {
if (state.get(AGE) == MAX_AGE) {
if (state.get(AGE) != MAX_AGE) {
return false
}
world.playSound(null, pos, SoundEvents.ENTITY_SHEEP_SHEAR, SoundCategory.BLOCKS, 1F, 1F)
@@ -24,6 +24,7 @@ import net.minecraft.block.BlockRenderType
import net.minecraft.block.BlockState
import net.minecraft.block.BlockWithEntity
import net.minecraft.block.Blocks
import net.minecraft.block.FarmlandBlock
import net.minecraft.block.Fertilizable
import net.minecraft.block.ShapeContext
import net.minecraft.block.entity.BlockEntity
@@ -186,7 +187,9 @@ class BerryBlock(private val berryIdentifier: Identifier, settings: Settings) :
@Deprecated("Deprecated in Java")
override fun canPlaceAt(state: BlockState, world: WorldView, pos: BlockPos): Boolean {
val below = world.getBlockState(pos.down())
return (state.get(WAS_GENERATED) && below.isIn(CobblemonBlockTags.BERRY_WILD_SOIL)) || below.isIn(CobblemonBlockTags.BERRY_SOIL)
return (state.get(WAS_GENERATED) && below.isIn(CobblemonBlockTags.BERRY_WILD_SOIL))
|| below.isIn(CobblemonBlockTags.BERRY_SOIL)
|| below.block is FarmlandBlock
}
@Deprecated("Deprecated in Java")
@@ -114,7 +114,10 @@ class PastureBlock(properties: Settings): BlockWithEntity(properties), Waterlogg
voxelShape(0.1875, 0.25, 0.25, 0.1875, 0.4375, 0.875, direction),
voxelShape(0.8125, 0.25, 0.25, 0.8125, 0.4375, 0.875, direction),
voxelShape(0.1875, 0.3125, 0.3125, 0.8125, 0.5, 0.3125, direction),
voxelShape(0.25, 0.75, 0.3125, 0.75, 1.0, 0.8125, direction)
voxelShape(0.25, 0.75, 0.3125, 0.75, 1.0, 0.8125, direction),
// I'm lazy and this gets optimized in union anyway
voxelShape(0.0, 0.0, 0.0, 0.0625, 1.0, 1.0, direction),
voxelShape(0.9375, 0.0, 0.0, 1.0, 1.0, 1.0, direction),
)
}
}
@@ -17,6 +17,7 @@ import com.cobblemon.mod.common.client.gui.ExitButton
import com.cobblemon.mod.common.client.gui.TypeIcon
import com.cobblemon.mod.common.client.gui.summary.Summary
import com.cobblemon.mod.common.client.gui.summary.widgets.ModelWidget
import com.cobblemon.mod.common.client.gui.summary.widgets.common.reformatNatureTextIfMinted
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.client.storage.ClientPC
import com.cobblemon.mod.common.client.storage.ClientParty
@@ -31,7 +32,6 @@ import net.minecraft.client.gui.DrawContext
import net.minecraft.client.gui.screen.Screen
import net.minecraft.client.sound.PositionedSoundInstance
import net.minecraft.client.util.InputUtil
import net.minecraft.client.util.math.MatrixStack
import net.minecraft.sound.SoundEvent
import net.minecraft.text.Text
@@ -309,14 +309,18 @@ class PCGUI(
).render(context)
// Nature
val natureText = reformatNatureTextIfMinted(pokemon)
drawScaledText(
context = context,
text = pokemon.nature.displayName.asTranslated(),
text = natureText,
x = x + 39,
y = y + 137,
centered = true,
shadow = true,
scale = SCALE
scale = SCALE,
colour = 0x32CBFF,
pMouseX = mouseX,
pMouseY = mouseY
)
// Ability
@@ -402,8 +406,14 @@ class PCGUI(
if (pokemon != null && !pokemon.heldItemNoCopy().isEmpty) {
val itemX = x + 3
val itemY = y + 98
val itemHovered = mouseX.toFloat() in (itemX.toFloat()..(itemX.toFloat() + 16)) && mouseY.toFloat() in (itemY.toFloat()..(itemY.toFloat() + 16))
if (itemHovered) context.drawItemTooltip(MinecraftClient.getInstance().textRenderer, pokemon.heldItemNoCopy(), mouseX, mouseY)
val itemHovered =
mouseX.toFloat() in (itemX.toFloat()..(itemX.toFloat() + 16)) && mouseY.toFloat() in (itemY.toFloat()..(itemY.toFloat() + 16))
if (itemHovered) context.drawItemTooltip(
MinecraftClient.getInstance().textRenderer,
pokemon.heldItemNoCopy(),
mouseX,
mouseY
)
}
}
@@ -416,12 +426,22 @@ class PCGUI(
}
override fun mouseScrolled(mouseX: Double, mouseY: Double, amount: Double): Boolean {
if (storageWidget.pastureWidget != null) storageWidget.pastureWidget!!.pastureScrollList.mouseScrolled(mouseX, mouseY, amount)
if (storageWidget.pastureWidget != null) storageWidget.pastureWidget!!.pastureScrollList.mouseScrolled(
mouseX,
mouseY,
amount
)
return children().any { it.mouseScrolled(mouseX, mouseY, amount) }
}
override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean {
if (storageWidget.pastureWidget != null) storageWidget.pastureWidget!!.pastureScrollList.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
if (storageWidget.pastureWidget != null) storageWidget.pastureWidget!!.pastureScrollList.mouseDragged(
mouseX,
mouseY,
button,
deltaX,
deltaY
)
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
}
@@ -431,10 +451,12 @@ class PCGUI(
playSound(CobblemonSounds.PC_OFF)
UnlinkPlayerFromPCPacket().sendToServer()
}
InputUtil.GLFW_KEY_RIGHT -> {
playSound(CobblemonSounds.PC_CLICK)
this.storageWidget.box += 1
}
InputUtil.GLFW_KEY_LEFT -> {
playSound(CobblemonSounds.PC_CLICK)
this.storageWidget.box -= 1
@@ -454,7 +476,7 @@ class PCGUI(
ticksElapsed++
// Calculate select pointer offset
var delayFactor = 3
val delayFactor = 3
if (ticksElapsed % (2 * delayFactor) == 0) selectPointerOffsetIncrement = !selectPointerOffsetIncrement
if (ticksElapsed % delayFactor == 0) selectPointerOffsetY += if (selectPointerOffsetIncrement) 1 else -1
}
@@ -480,8 +502,8 @@ class PCGUI(
offsetY = -10.0
)
} else {
previewPokemon = null;
modelWidget = null;
previewPokemon = null
modelWidget = null
}
}
}
@@ -0,0 +1,30 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.gui.summary.widgets.common
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.api.text.italicise
import com.cobblemon.mod.common.api.text.onHover
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.asTranslated
import net.minecraft.text.MutableText
/**
* Italicizes the nature text and makes it include the name of the MintItem used to mint the Pokémon's nature
*/
fun reformatNatureTextIfMinted(pokemon: Pokemon): MutableText {
var natureText = pokemon.nature.displayName.asTranslated()
if (pokemon.mintedNature != null) {
CobblemonItems.mints[pokemon.mintedNature!!.displayName]?.let { mint ->
natureText = natureText.italicise().onHover(mint.name)
}
}
return natureText
}
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.gui.summary.widgets.screens.info
import com.cobblemon.mod.common.api.text.*
import com.cobblemon.mod.common.client.gui.summary.widgets.SoundlessWidget
import com.cobblemon.mod.common.client.render.drawScaledText
import net.minecraft.client.gui.DrawContext
import net.minecraft.text.MutableText
import net.minecraft.text.Text
import net.minecraft.util.Identifier
class InfoBlockWidget(
pX: Int,
pY: Int,
blockWidth: Int,
blockHeight: Int,
private val text: MutableText,
private val withinRowVerticalTextOffset: Int,
private val font: Identifier,
) : SoundlessWidget(pX, pY, blockWidth, blockHeight, Text.literal("InfoBlockWidget")) {
override fun renderButton(context: DrawContext, pMouseX: Int, pMouseY: Int, pPartialTicks: Float) {
drawScaledText(
context = context,
font = font,
text = text.bold(),
x = x,
y = y + withinRowVerticalTextOffset,
shadow = true,
pMouseX = pMouseX,
pMouseY = pMouseY
)
}
}
@@ -0,0 +1,62 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.gui.summary.widgets.screens.info
import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.gui.summary.widgets.SoundlessWidget
import net.minecraft.client.MinecraftClient
import net.minecraft.client.gui.DrawContext
import net.minecraft.text.MutableText
import net.minecraft.text.Text
class InfoOneLineWidget(
pX: Int,
pY: Int,
width: Int,
height: Int = ROW_HEIGHT,
private val label: MutableText,
private val value: MutableText,
) : SoundlessWidget(pX, pY, width, height, Text.literal("InfoOneLineWidget")) {
companion object {
private val FONT = CobblemonResources.DEFAULT_LARGE
private const val ROW_HEIGHT = 15
private const val WITHIN_ROW_VERTICAL_OFFSET = 6
private const val LABEL_HORIZONTAL_OFFSET = 8
private const val VALUE_HORIZONTAL_OFFSET = 53
}
override fun renderButton(context: DrawContext, pMouseX: Int, pMouseY: Int, pPartialTicks: Float) {
// Label
val label = InfoBlockWidget(
pX = x + LABEL_HORIZONTAL_OFFSET,
pY = y,
blockWidth = MinecraftClient.getInstance().textRenderer.getWidth(label),
blockHeight = height,
text = label,
font = FONT,
withinRowVerticalTextOffset = WITHIN_ROW_VERTICAL_OFFSET
)
label.render(context, pMouseX, pMouseY, pPartialTicks)
// Value
val value = InfoBlockWidget(
pX = x + VALUE_HORIZONTAL_OFFSET,
pY = y,
blockWidth = MinecraftClient.getInstance().textRenderer.getWidth(value),
blockHeight = height,
text = value,
font = FONT,
withinRowVerticalTextOffset = WITHIN_ROW_VERTICAL_OFFSET
)
value.render(context, pMouseX, pMouseY, pPartialTicks)
}
}
@@ -11,11 +11,10 @@ package com.cobblemon.mod.common.client.gui.summary.widgets.screens.info
import com.cobblemon.mod.common.api.gui.ColourLibrary
import com.cobblemon.mod.common.api.gui.MultiLineLabelK
import com.cobblemon.mod.common.api.gui.blitk
import com.cobblemon.mod.common.api.text.bold
import com.cobblemon.mod.common.api.text.plus
import com.cobblemon.mod.common.api.text.text
import com.cobblemon.mod.common.api.text.*
import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.gui.summary.widgets.SoundlessWidget
import com.cobblemon.mod.common.client.gui.summary.widgets.common.reformatNatureTextIfMinted
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.asTranslated
@@ -23,17 +22,21 @@ import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.lang
import net.minecraft.client.MinecraftClient
import net.minecraft.client.gui.DrawContext
import net.minecraft.text.MutableText
import net.minecraft.text.Text
import net.minecraft.text.TextContent
class InfoWidget(
pX: Int,
pY: Int,
private val pokemon: Pokemon
): SoundlessWidget(pX, pY, WIDTH, HEIGHT, Text.literal("InfoWidget")) {
) : SoundlessWidget(pX, pY, WIDTH, HEIGHT, Text.literal("InfoWidget")) {
companion object {
private const val WIDTH = 134
private const val HEIGHT = 148
private val infoBaseResource = cobblemonResource("textures/gui/summary/summary_info_base.png")
private const val ROW_HEIGHT = 15
}
override fun renderButton(context: DrawContext, pMouseX: Int, pMouseY: Int, pPartialTicks: Float) {
@@ -42,137 +45,89 @@ class InfoWidget(
blitk(
matrixStack = matrices,
texture = infoBaseResource,
x= x,
x = x,
y = y,
width = width,
height = height
)
// Pokédex Number
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = lang("ui.info.pokedex_number").bold(),
x = x + 8,
y = y + 6,
shadow = true
)
// Pokédex Number
// Add preceding zeroes if Pokédex number is less than 3 digits
var dexNo = pokemon.species.nationalPokedexNumber.toString()
while(dexNo.length < 3) {
dexNo = "0$dexNo";
while (dexNo.length < 3) {
dexNo = "0$dexNo"
}
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = dexNo.text().bold(),
x = x + 53,
y = y + 6,
shadow = true
val pokedexNumberWidget = InfoOneLineWidget(
pX = x,
pY = y,
width = width,
label = lang("ui.info.pokedex_number"),
value = dexNo.text()
)
pokedexNumberWidget.render(context, pMouseX, pMouseY, pPartialTicks)
// Species
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = lang("ui.info.species").bold(),
x = x + 8,
y = y + 21,
shadow = true
)
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = pokemon.species.translatedName.bold(),
x = x + 53,
y = y + 21,
shadow = true
val speciesWidget = InfoOneLineWidget(
pX = x,
pY = y + ROW_HEIGHT,
width = width,
label = lang("ui.info.species"),
value = pokemon.species.translatedName
)
speciesWidget.render(context, pMouseX, pMouseY, pPartialTicks)
// Type
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = lang("ui.info.type").bold(),
x = x + 8,
y = y + 36,
shadow = true
)
val type = pokemon.types.map { it.displayName.copy() }.reduce { acc, next -> acc.plus("/").plus(next) }
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = type.bold(),
x = x + 53,
y = y + 36,
shadow = true
val typeWidget = InfoOneLineWidget(
pX = x,
pY = y + 2 * ROW_HEIGHT,
width = width,
label = lang("ui.info.type"),
value = type
)
typeWidget.render(context, pMouseX, pMouseY, pPartialTicks)
// OT
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = lang("ui.info.original_trainer").bold(),
x = x + 8,
y = y + 51,
shadow = true
)
var displayName: MutableText = MutableText.of(TextContent.EMPTY)
if (pokemon.isPlayerOwned() && pokemon.getOwnerPlayer() != null) {
pokemon.getOwnerPlayer()?.displayName?.copy()?.let {
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = it.bold(),
x = x + 53,
y = y + 51,
shadow = true
)
}
displayName = pokemon.getOwnerPlayer()!!.displayName.copy()
}
val otWidget = InfoOneLineWidget(
pX = x,
pY = y + 3 * ROW_HEIGHT,
width = width,
label = lang("ui.info.original_trainer"),
value = displayName // You'll need to provide the value for the Original Trainer
)
otWidget.render(context, pMouseX, pMouseY, pPartialTicks)
// Nature
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = lang("ui.info.nature").bold(),
x = x + 8,
y = y + 66,
shadow = true
)
// Get the name of the MintItem used to mint the Pokémon's nature
val natureText = reformatNatureTextIfMinted(pokemon)
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = pokemon.nature.displayName.asTranslated().bold(),
x = x + 53,
y = y + 66,
shadow = true
val natureWidget = InfoOneLineWidget(
pX = x,
pY = y + 4 * ROW_HEIGHT,
width = width,
label = lang("ui.info.nature"),
value = natureText,
)
natureWidget.render(context, pMouseX, pMouseY, pPartialTicks)
// Ability
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = lang("ui.info.ability").bold(),
x = x + 8,
y = y + 81,
shadow = true
)
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = pokemon.ability.displayName.asTranslated().bold(),
x = x + 53,
y = y + 81,
shadow = true
val abilityWidget = InfoOneLineWidget(
pX = x,
pY = y + 5 * ROW_HEIGHT,
width = width,
label = lang("ui.info.ability").bold(),
value = pokemon.ability.displayName.asTranslated().bold()
)
abilityWidget.render(context, pMouseX, pMouseY, pPartialTicks)
val smallTextScale = 0.5F
@@ -212,8 +167,10 @@ class InfoWidget(
val mcFont = MinecraftClient.getInstance().textRenderer
val experience = pokemon.experience.toString().text()
val experienceForThisLevel = pokemon.experience - if (pokemon.level == 1) 0 else pokemon.experienceGroup.getExperience(pokemon.level)
val experienceToNext = pokemon.experienceGroup.getExperience(pokemon.level + 1) - pokemon.experienceGroup.getExperience(pokemon.level)
val experienceForThisLevel =
pokemon.experience - if (pokemon.level == 1) 0 else pokemon.experienceGroup.getExperience(pokemon.level)
val experienceToNext =
pokemon.experienceGroup.getExperience(pokemon.level + 1) - pokemon.experienceGroup.getExperience(pokemon.level)
drawScaledText(
context = context,
@@ -19,6 +19,7 @@ import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.gui.ExitButton
import com.cobblemon.mod.common.client.gui.TypeIcon
import com.cobblemon.mod.common.client.gui.summary.Summary
import com.cobblemon.mod.common.client.gui.summary.widgets.common.reformatNatureTextIfMinted
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.client.trade.ClientTrade
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket.TradeablePokemon
@@ -36,7 +37,6 @@ import net.minecraft.client.gui.DrawContext
import net.minecraft.client.gui.screen.Screen
import net.minecraft.client.sound.PositionedSoundInstance
import net.minecraft.client.util.InputUtil
import net.minecraft.client.util.math.MatrixStack
import net.minecraft.sound.SoundEvent
import net.minecraft.text.MutableText
@@ -266,8 +266,8 @@ class TradeGUI(
renderInfoLabels(context, x, y)
renderPokemonInfo(offeredPokemon, false, context, x, y)
renderPokemonInfo(opposingOfferedPokemon, true, context, x, y)
renderPokemonInfo(offeredPokemon, false, context, x, y, mouseX, mouseY)
renderPokemonInfo(opposingOfferedPokemon, true, context, x, y, mouseX, mouseY)
if (trade.acceptedOppositeOffer) {
blitk(
@@ -373,7 +373,7 @@ class TradeGUI(
}
// Calculate select pointer offset
var delayFactor = 3
val delayFactor = 3
if (ticksElapsed % (2 * delayFactor) == 0) selectPointerOffsetIncrement = !selectPointerOffsetIncrement
if (ticksElapsed % delayFactor == 0) selectPointerOffsetY += if (selectPointerOffsetIncrement) 1 else -1
@@ -422,7 +422,7 @@ class TradeGUI(
MinecraftClient.getInstance().soundManager.play(PositionedSoundInstance.master(soundEvent, 1.0F))
}
private fun renderPokemonInfo(pokemon: Pokemon?, isOpposing: Boolean, context: DrawContext, x: Int, y: Int) {
private fun renderPokemonInfo(pokemon: Pokemon?, isOpposing: Boolean, context: DrawContext, x: Int, y: Int, mouseX: Int, mouseY: Int) {
if (pokemon != null) {
val matrices = context.matrices
// Level
@@ -530,14 +530,17 @@ class TradeGUI(
val labelXOffset = if (isOpposing) 77 else 0
// Nature
val natureText = reformatNatureTextIfMinted(pokemon)
drawScaledText(
context = context,
text = pokemon.nature.displayName.asTranslated(),
text = natureText,
x = x + 108 + labelXOffset,
y = y + 146.5,
centered = true,
shadow = true,
scale = SCALE
scale = SCALE,
pMouseX = mouseX,
pMouseY = mouseY
)
// Ability
@@ -115,6 +115,7 @@ fun getDepletableRedGreen(
return r.toFloat() to g.toFloat()
}
fun drawScaledText(
context: DrawContext,
font: Identifier? = null,
@@ -126,7 +127,9 @@ fun drawScaledText(
maxCharacterWidth: Int = Int.MAX_VALUE,
colour: Int = 0x00FFFFFF + ((opacity.toFloat() * 255).toInt() shl 24),
centered: Boolean = false,
shadow: Boolean = false
shadow: Boolean = false,
pMouseX: Int? = null,
pMouseY: Int? = null
) {
if (opacity.toFloat() < 0.05F) {
return
@@ -138,7 +141,7 @@ fun drawScaledText(
val matrices = context.matrices
matrices.push()
matrices.scale(scale * extraScale, scale * extraScale, 1F)
drawText(
val isHovered = drawText(
context = context,
font = font,
text = text,
@@ -146,9 +149,15 @@ fun drawScaledText(
y = y.toFloat() / (scale * extraScale) + (1 - extraScale) * fontHeight * scale,
centered = centered,
colour = colour,
shadow = shadow
shadow = shadow,
pMouseX = pMouseX?.toFloat()?.div((scale * extraScale)),
pMouseY = pMouseY?.toFloat()?.div(scale * extraScale)?.plus((1 - extraScale) * fontHeight * scale)
)
matrices.pop()
// Draw tooltip that was created with onHover and is attached to the MutableText
if (isHovered) {
context.drawHoverEvent(MinecraftClient.getInstance().textRenderer, text.style, pMouseX!!, pMouseY!!)
}
}
fun drawScaledText(
@@ -148,6 +148,16 @@ class PokemonRenderer(
pMatrixStack.scale(scale, scale, scale)
}
/**
* Renders a beam between the Cobblemon and the target.
*
* @param matrixStack The matrix stack to render with.
* @param partialTicks The partial ticks.
* @param entity The Cobblemon.
* @param beamTarget The target.
* @param colour The colour of the beam.
* @param buffer The vertex consumer provider.
*/
fun renderBeam(matrixStack: MatrixStack, partialTicks: Float, entity: PokemonEntity, beamTarget: Entity, colour: Vector4f, buffer: VertexConsumerProvider) {
val clientDelegate = entity.delegate as PokemonClientDelegate
val pokemonPosition = entity.pos.add(0.0, entity.height / 2.0 * clientDelegate.entityScaleModifier.toDouble(), 0.0)
@@ -538,27 +538,19 @@ class PokemonEntity(
override fun interactMob(player: PlayerEntity, hand: Hand) : ActionResult {
val itemStack = player.getStackInHand(hand)
if (player is ServerPlayerEntity) {
if (itemStack.isOf(Items.SHEARS) && this.isShearable) {
this.sheared(SoundCategory.PLAYERS)
this.emitGameEvent(GameEvent.SHEAR, player)
itemStack.damage(1, player) { it.sendToolBreakStatus(hand) }
return ActionResult.SUCCESS
}
else if (itemStack.isOf(Items.BUCKET)) {
if (pokemon.getFeature<FlagSpeciesFeature>(DataKeys.CAN_BE_MILKED) != null) {
world.playSoundFromEntity(
null,
this,
SoundEvents.ENTITY_GOAT_MILK,
SoundCategory.PLAYERS,
1.0F,
1.0F
)
val milkBucket = ItemUsage.exchangeStack(itemStack, player, ItemStack(Items.MILK_BUCKET))
player.setStackInHand(hand, milkBucket)
return ActionResult.SUCCESS
}
if (itemStack.isOf(Items.SHEARS) && this.isShearable) {
this.sheared(SoundCategory.PLAYERS)
this.emitGameEvent(GameEvent.SHEAR, player)
itemStack.damage(1, player) { it.sendToolBreakStatus(hand) }
return ActionResult.SUCCESS
}
else if (itemStack.isOf(Items.BUCKET)) {
if (pokemon.getFeature<FlagSpeciesFeature>(DataKeys.CAN_BE_MILKED) != null) {
player.playSound(SoundEvents.ENTITY_GOAT_MILK, 1.0f, 1.0f)
val milkBucket = ItemUsage.exchangeStack(itemStack, player, Items.MILK_BUCKET.defaultStack)
player.setStackInHand(hand, milkBucket)
return ActionResult.success(world.isClient)
}
}
@@ -738,6 +730,7 @@ class PokemonEntity(
}
player.giveOrDropItemStack(returned)
player.sendMessage(text)
this.world.playSoundServer(position = this.pos, sound = SoundEvents.ENTITY_ITEM_PICKUP, volume = 0.6F, pitch = 1.4F)
return true
}
@@ -160,10 +160,12 @@ class PokemonServerDelegate : PokemonSideDelegate {
fun updatePoseType() {
val isSleeping = entity.pokemon.status?.status == Statuses.SLEEP && entity.behaviour.resting.canSleep
val isMoving = entity.isMoving.get()
val isPassenger = entity.hasVehicle()
val isUnderwater = entity.getIsSubmerged()
val isFlying = entity.getBehaviourFlag(PokemonBehaviourFlag.FLYING)
val poseType = when {
isPassenger -> PoseType.STAND
isSleeping -> PoseType.SLEEP
isMoving && isUnderwater -> PoseType.SWIM
isUnderwater -> PoseType.FLOAT
@@ -51,19 +51,24 @@ object AdvancementHandler {
fun onEvolve(event: EvolutionCompleteEvent) {
val player = event.pokemon.getOwnerPlayer()
if (player != null) {
val playerData = Cobblemon.playerData.get(player)
val advancementData = playerData.advancementData
advancementData.updateTotalEvolvedCount()
advancementData.updateAspectsCollected(player, event.pokemon)
Cobblemon.playerData.saveSingle(playerData)
CobblemonCriteria.EVOLVE_POKEMON.trigger(
player, EvolvePokemonContext(
event.pokemon.preEvolution!!.species.resourceIdentifier,
event.pokemon.species.resourceIdentifier,
advancementData.totalEvolvedCount
if (event.pokemon.preEvolution != null) {
val playerData = Cobblemon.playerData.get(player)
val advancementData = playerData.advancementData
advancementData.updateTotalEvolvedCount()
advancementData.updateAspectsCollected(player, event.pokemon)
Cobblemon.playerData.saveSingle(playerData)
CobblemonCriteria.EVOLVE_POKEMON.trigger(
player, EvolvePokemonContext(
event.pokemon.preEvolution!!.species.resourceIdentifier,
event.pokemon.species.resourceIdentifier,
advancementData.totalEvolvedCount
)
)
)
CobblemonCriteria.COLLECT_ASPECT.trigger(player, advancementData.aspectsCollected)
CobblemonCriteria.COLLECT_ASPECT.trigger(player, advancementData.aspectsCollected)
}
else {
Cobblemon.LOGGER.warn("Evolution triggered by ${player.displayName} has missing evolution data for ${event.pokemon.species.resourceIdentifier}. Incomplete evolution data: ${event.evolution.id}, please report to the datapack creator!")
}
}
}
@@ -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.integration.adorn
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.ResourcePackActivationBehaviour
import com.cobblemon.mod.common.util.cobblemonResource
import juuxel.adorn.block.variant.BlockKind
import juuxel.adorn.block.variant.BlockVariant
import juuxel.adorn.block.variant.BlockVariantSet
import juuxel.adorn.block.variant.BlockVariantSets
import net.minecraft.text.Text
import org.jetbrains.annotations.ApiStatus
@ApiStatus.Internal
object AdornCompatibility : BlockVariantSet {
override val woodVariants: List<BlockVariant> = listOf(
BlockVariant.Wood("${Cobblemon.MODID}/apricorn")
)
private val registerMethod by lazy {
BlockVariantSets::class.java.getDeclaredMethod("register", BlockKind::class.java, BlockVariant::class.java).apply { isAccessible = true }
}
@ApiStatus.Internal
fun register() {
var count = 0
Cobblemon.implementation.registerBuiltinResourcePack(cobblemonResource("adorncompatibility"), Text.literal("Adorn Compatibility"), ResourcePackActivationBehaviour.ALWAYS_ENABLED)
BlockKind.values().forEach { kind ->
this.woodVariants.forEach { variant ->
// We use this hack because we can't just call BlockVariantSets#register
// This would attempt to register blocks and items multiple times
// Unfortunately Adorn does all these registrations on mod initialization on all implementations making it impossible to "correctly" add our things
this.registerMethod.invoke(BlockVariantSets, kind, variant)
count++
}
}
Cobblemon.LOGGER.info("Registered {} blocks to Adorn", count)
}
}
@@ -10,17 +10,10 @@ package com.cobblemon.mod.common.item
import com.cobblemon.mod.common.block.ApricornBlock
import net.minecraft.block.BlockState
import net.minecraft.block.ComposterBlock
import net.minecraft.item.AliasedBlockItem
import net.minecraft.item.ItemPlacementContext
class ApricornItem(block: ApricornBlock) : AliasedBlockItem(block, Settings()) {
init {
// 65% to raise composter level
ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE[this] = .65F
}
override fun canPlace(context: ItemPlacementContext, state: BlockState) = context.player?.isCreative != false && super.canPlace(context, state)
}
@@ -9,14 +9,6 @@
package com.cobblemon.mod.common.item
import com.cobblemon.mod.common.block.ApricornSaplingBlock
import net.minecraft.block.ComposterBlock
import net.minecraft.item.AliasedBlockItem
class ApricornSeedItem(block: ApricornSaplingBlock) : AliasedBlockItem(block, Settings()) {
init {
// 65% to raise composter level
ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE[this] = .65F
}
}
class ApricornSeedItem(block: ApricornSaplingBlock) : AliasedBlockItem(block, Settings())
@@ -9,15 +9,9 @@
package com.cobblemon.mod.common.item
import com.cobblemon.mod.common.block.BerryBlock
import net.minecraft.block.ComposterBlock
import net.minecraft.item.AliasedBlockItem
open class BerryItem(private val berryBlock: BerryBlock) : AliasedBlockItem(berryBlock, Settings()) {
init {
// 65% to raise composter level
ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE[this] = .65F
}
fun berry() = this.berryBlock.berry()
}
@@ -8,8 +8,8 @@
package com.cobblemon.mod.common.item
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.block.MedicinalLeekBlock
import net.minecraft.block.ComposterBlock
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.*
import net.minecraft.util.ActionResult
@@ -21,7 +21,7 @@ import net.minecraft.world.World
class MedicinalLeekItem(block: MedicinalLeekBlock, settings: Settings) : AliasedBlockItem(block, settings) {
init {
ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE[this] = .65F
Cobblemon.implementation.registerCompostable(this, .65F)
}
override fun useOnBlock(context: ItemUsageContext): ActionResult = ActionResult.PASS
@@ -9,6 +9,7 @@
package com.cobblemon.mod.common.item
import com.bedrockk.molang.runtime.MoLangRuntime
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonMechanics
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
@@ -19,7 +20,6 @@ import com.cobblemon.mod.common.block.RevivalHerbBlock
import com.cobblemon.mod.common.item.battle.BagItem
import com.cobblemon.mod.common.pokemon.Pokemon
import kotlin.math.ceil
import net.minecraft.block.ComposterBlock
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.AliasedBlockItem
import net.minecraft.item.ItemStack
@@ -34,7 +34,7 @@ class RevivalHerbItem(block: RevivalHerbBlock) : AliasedBlockItem(block, Setting
init {
// 65% to raise composter level
ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE[this] = .65F
Cobblemon.implementation.registerCompostable(this, .65F)
}
private val runtime = MoLangRuntime()
@@ -64,16 +64,16 @@ class RevivalHerbItem(block: RevivalHerbBlock) : AliasedBlockItem(block, Setting
stack: ItemStack,
pokemon: Pokemon
): TypedActionResult<ItemStack>? {
if (pokemon.isFainted()) {
return if (pokemon.isFainted()) {
player.playSound(CobblemonSounds.MEDICINE_HERB_USE, SoundCategory.PLAYERS, 1F, 1F)
pokemon.currentHealth = ceil(pokemon.hp / 4F).toInt()
pokemon.decrementFriendship(CobblemonMechanics.remedies.getFriendshipDrop(runtime))
if (!player.isCreative) {
stack.decrement(1)
}
return TypedActionResult.success(stack)
TypedActionResult.success(stack)
} else {
return TypedActionResult.pass(stack)
TypedActionResult.pass(stack)
}
}
@@ -9,7 +9,6 @@
package com.cobblemon.mod.common.item
import com.cobblemon.mod.common.block.VivichokeBlock
import net.minecraft.block.*
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.AliasedBlockItem
import net.minecraft.item.ItemStack
@@ -22,12 +21,7 @@ import net.minecraft.world.RaycastContext
import net.minecraft.world.World
class VivichokeItem(block: VivichokeBlock) : AliasedBlockItem(block, Settings()) {
init {
ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE[this] = .65F
}
override fun use(world: World?, user: PlayerEntity, hand: Hand?): TypedActionResult<ItemStack?>? {
override fun use(world: World?, user: PlayerEntity, hand: Hand?): TypedActionResult<ItemStack?> {
val blockHitResult = PlaceableOnWaterItem.raycast(world, user, RaycastContext.FluidHandling.SOURCE_ONLY)
val blockHitResult2 = blockHitResult.withBlockPos(blockHitResult.blockPos.up())
val actionResult: ActionResult = super.useOnBlock(ItemUsageContext(user, hand, blockHitResult2))
@@ -360,6 +360,12 @@ object CobblemonItemGroups {
CobblemonItems.pokeBalls.forEach(entries::add)
}
private fun keyitemsentries(displayContext: DisplayContext): List<Item> = arrayListOf(
CobblemonItems.PHOTODEX
)
private fun foodInjections(displayContext: DisplayContext): List<Item> = arrayListOf(
CobblemonItems.ROASTED_LEEK,
CobblemonItems.LEEK_AND_POTATO_STEW,
@@ -23,6 +23,7 @@ import net.minecraft.sound.SoundCategory
import net.minecraft.util.Hand
import net.minecraft.util.TypedActionResult
import net.minecraft.world.World
import net.minecraft.item.Items
class BerryJuiceItem : CobblemonItem(Settings()), PokemonSelectingItem {
override val bagItem = object : BagItem {
@@ -51,6 +52,11 @@ class BerryJuiceItem : CobblemonItem(Settings()), PokemonSelectingItem {
player.playSound(CobblemonSounds.BERRY_EAT, SoundCategory.PLAYERS, 1F, 1F)
if (!player.isCreative) {
stack.decrement(1)
val woodenBowlItemStack = ItemStack(Items.BOWL)
if (!player.inventory.insertStack(woodenBowlItemStack)) {
// Drop the item into the world if the inventory is full
player.dropItem(woodenBowlItemStack, false)
}
}
return TypedActionResult.success(stack)
}
@@ -58,5 +64,12 @@ class BerryJuiceItem : CobblemonItem(Settings()), PokemonSelectingItem {
override fun applyToBattlePokemon(player: ServerPlayerEntity, stack: ItemStack, battlePokemon: BattlePokemon) {
super.applyToBattlePokemon(player, stack, battlePokemon)
player.playSound(CobblemonSounds.BERRY_EAT, SoundCategory.PLAYERS, 1F, 1F)
if (!player.isCreative) {
val woodenBowlItemStack = ItemStack(Items.BOWL)
if (!player.inventory.insertStack(woodenBowlItemStack)) {
// Drop the item into the world if the inventory is full
player.dropItem(woodenBowlItemStack, false)
}
}
}
}
}
@@ -0,0 +1,265 @@
/*
* 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.item.interactive
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import net.fabricmc.api.EnvType
import net.fabricmc.api.Environment
import net.minecraft.client.MinecraftClient
import net.minecraft.client.render.*
import net.minecraft.client.util.math.MatrixStack
import net.minecraft.entity.Entity
import net.minecraft.entity.LivingEntity
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
import net.minecraft.item.SpyglassItem
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.text.Text
import net.minecraft.util.Hand
import net.minecraft.util.Identifier
import net.minecraft.util.TypedActionResult
import net.minecraft.util.math.Box
import net.minecraft.world.World
import org.lwjgl.glfw.GLFW
import org.lwjgl.glfw.GLFWMouseButtonCallback
import org.lwjgl.glfw.GLFWScrollCallback
import java.util.logging.LogManager
class PhotodexItem : /*CobblemonItem(Settings()),*/ SpyglassItem(Settings()) {
private var inUse = false
private var isZooming = false
private var zoomLevel = 1.0
private var scrollCallback = -1L
private var mouseCallback = -1L
private var isScrollCallbackRegistered = false
private var isMouseButtonCallbackRegistered = false
private var leftMouseButtonPressedLastTick = false
fun changeFOV(double: Double) {
val client = MinecraftClient.getInstance()
val newFov = (70 / zoomLevel).coerceIn(30.0, 110.0).toInt() // Clamping the FOV value
client.options.fov.setValue(newFov)
}
// todo use method to toggle on functionality of camera
/*override fun use(world: World, user: PlayerEntity, hand: Hand): TypedActionResult<ItemStack> {
if (world.isClient) {
inUse = !inUse // toggle inUse state
if (inUse) {
//registerInputHandlers() // Activate input handling
zoomLevel = 1.0 // Initialize zoom level
} else {
//unregisterInputHandlers() // Deactivate input handling
zoomLevel = 1.0 // Reset zoom level
changeFOV(70.0) // Reset FOV
}
return TypedActionResult.success(user.getStackInHand(hand))
}
return TypedActionResult.pass(user.getStackInHand(hand))
}*/
// todo use method for holding down right click to enable camera like the spyglass
override fun use(world: World, user: PlayerEntity, hand: Hand): TypedActionResult<ItemStack> {
if (world.isClient) {
if (!inUse) {
inUse = true // Activate only on initial click
registerInputHandlers() // Activate input handling
zoomLevel = 1.0 // Initialize zoom level
changeFOV(70.0) // Set initial FOV
}
return TypedActionResult.success(user.getStackInHand(hand))
}
return TypedActionResult.pass(user.getStackInHand(hand))
}
// todo onStoppedUsing for ending the camera use when letting go of the Right Click
override fun onStoppedUsing(stack: ItemStack?, world: World, entity: LivingEntity, timeLeft: Int) {
println("Triggered onStoppedUsing function")
super.onStoppedUsing(stack, world, entity, timeLeft)
if (world.isClient && entity is PlayerEntity) {
inUse = false // Reset on release
unregisterInputHandlers()
zoomLevel = 1.0
changeFOV(70.0) // Reset FOV
}
}
@Environment(EnvType.CLIENT)
private fun registerInputHandlers() {
val windowHandle = MinecraftClient.getInstance().window.handle
if (!isScrollCallbackRegistered) {
// Register scroll callback
GLFW.glfwSetScrollCallback(windowHandle) { _, _, yOffset ->
println("Scroll Callback Triggered: yOffset = $yOffset")
if (yOffset != 0.0) {
zoomLevel += yOffset * 0.05 // Smaller increment
zoomLevel = zoomLevel.coerceIn(1.0, 4.0) // More controlled zoom range
changeFOV(70 / zoomLevel)
}
}
isScrollCallbackRegistered = true
}
if (!isMouseButtonCallbackRegistered) {
// Register mouse button callback
GLFW.glfwSetMouseButtonCallback(windowHandle) { _, button, action, _ ->
//println("Mouse Button Callback Triggered")
//println("inUse is " + inUse.toString())
// todo NOTE: BUTTON_1 is apparently LEFT BUTTON_2 is apparently RIGHT but we might need to check
if (inUse && button == GLFW.GLFW_MOUSE_BUTTON_1 && action == GLFW.GLFW_PRESS) {
println("Mouse Button 1 Left Pressed")
MinecraftClient.getInstance().player?.let {
if (it.world.isClient) {
detectPokemon(it.world, it, Hand.MAIN_HAND)
}
}
}
else if (inUse && button == GLFW.GLFW_MOUSE_BUTTON_1 && action == GLFW.GLFW_RELEASE) {
println("Mouse Button 1 Left Released")
// Implement your logic for release here
}
if (inUse && button == GLFW.GLFW_MOUSE_BUTTON_2 && action == GLFW.GLFW_PRESS) {
println("Mouse Button 2 Right Pressed")
}
else if (inUse && button == GLFW.GLFW_MOUSE_BUTTON_2 && action == GLFW.GLFW_RELEASE) {
println("Mouse Button 2 Right Released")
inUse = false
unregisterInputHandlers()
zoomLevel = 1.0
changeFOV(70.0) // Reset FOV
}
/*if (inUse && button == GLFW.GLFW_MOUSE_BUTTON_1 && action == GLFW.GLFW_PRESS) {
println("Mouse Button Callback Triggered")
MinecraftClient.getInstance().player?.let {
if (it.world.isClient) {
detectPokemon(it.world, it, Hand.MAIN_HAND)
}
}
}*/
}
isMouseButtonCallbackRegistered = true
}
}
private fun unregisterInputHandlers() {
val windowHandle = MinecraftClient.getInstance().window.handle
if (isScrollCallbackRegistered) {
GLFW.glfwSetScrollCallback(windowHandle, null)?.free()
isScrollCallbackRegistered = false
}
if (isMouseButtonCallbackRegistered) {
GLFW.glfwSetMouseButtonCallback(windowHandle, null)?.free()
isMouseButtonCallbackRegistered = false
}
}
fun detectPokemon(world: World, user: PlayerEntity, hand: Hand) {
if (user is ServerPlayerEntity && inUse) {
val eyePos = user.getCameraPosVec(1.0F)
val lookVec = user.getRotationVec(1.0F)
val maxDistance = 100.0 // Set this to how far you want the ray to go
var closestEntity: Entity? = null
var closestDistance = maxDistance
// Send a chat message to the player
//user.sendMessage(Text.of("Trying to Detect Entity"));
// Define a large bounding box around the player
val boundingBox = Box(
user.x - 200.0, user.y - 200.0, user.z - 200.0,
user.x + 200.0, user.y + 200.0, user.z + 200.0
)
// Get all entities within the bounding box
val entities = user.world.getEntitiesByClass(Entity::class.java, boundingBox, { it != user })
for (entity in entities) {
val entityBox: Box = entity.boundingBox
val intersection = entityBox.raycast(eyePos, eyePos.add(lookVec.multiply(maxDistance)))
if (intersection.isPresent) {
val distanceToEntity = eyePos.distanceTo(intersection.get())
if (distanceToEntity < closestDistance) {
closestEntity = entity
closestDistance = distanceToEntity
}
}
}
if (closestEntity != null && closestEntity is PokemonEntity) {
user.sendMessage(Text.of("You have scanned a: ${closestEntity.pokemon.species.name}"))
}
}
}
/*override fun onStoppedUsing(stack: ItemStack, world: World, entity: LivingEntity, timeLeft: Int) {
inUse = false
}*/
fun renderPhotodexOverlay(matrixStack: MatrixStack) {
// Assuming your texture is meant to cover the full screen or a significant portion of it.
// These dimensions will scale the texture to fit as desired.
val screenWidth = MinecraftClient.getInstance().window.scaledWidth
val screenHeight = MinecraftClient.getInstance().window.scaledHeight
// Your custom overlay texture
val photodexOverlayTexture = Identifier("textures/item/keyitems/PhotodexLens.png")
// Binding the texture
MinecraftClient.getInstance().textureManager.bindTexture(photodexOverlayTexture)
// Enable blending for transparency
//RenderSystem.enableBlend()
//RenderSystem.blendFuncSeparate(RenderSystem.SourceFactor.SRC_ALPHA, RenderSystem.DestFactor.ONE_MINUS_SRC_ALPHA, RenderSystem.SourceFactor.ONE, RenderSystem.DestFactor.ZERO)
// RenderSystem.enableBlend()
// RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA)
// Drawing the overlay
drawTexture(matrixStack, 0, 0, screenWidth, screenHeight, 0f, 0f, 256, 256, 256, 256)
// Disable blending if you enabled it earlier
// RenderSystem.disableBlend()
}
// Adjusted to accept float texture coordinates and dimensions
private fun drawTexture(
matrices: MatrixStack,
x: Int, y: Int, width: Int, height: Int,
u0: Float, v0: Float, regionWidth: Int, regionHeight: Int, textureWidth: Int, textureHeight: Int
) {
val drawMode = VertexFormat.DrawMode.QUADS // Quads
val tessellator = Tessellator.getInstance()
val bufferBuilder = tessellator.buffer
bufferBuilder.begin(drawMode, VertexFormats.POSITION_TEXTURE)
bufferBuilder.vertex(matrices.peek().positionMatrix, x.toFloat(), (y + height).toFloat(), 0f).texture(u0 / textureWidth, (v0 + regionHeight) / textureHeight).next()
bufferBuilder.vertex(matrices.peek().positionMatrix, (x + width).toFloat(), (y + height).toFloat(), 0f).texture((u0 + regionWidth) / textureWidth, (v0 + regionHeight) / textureHeight).next()
bufferBuilder.vertex(matrices.peek().positionMatrix, (x + width).toFloat(), y.toFloat(), 0f).texture((u0 + regionWidth) / textureWidth, v0 / textureHeight).next()
bufferBuilder.vertex(matrices.peek().positionMatrix, x.toFloat(), y.toFloat(), 0f).texture(u0 / textureWidth, v0 / textureHeight).next()
tessellator.draw()
}
}
@@ -69,17 +69,17 @@ class PotionItem(val type: PotionType) : CobblemonItem(Settings()), PokemonSelec
enum class PotionType(val amountToHeal: () -> Expression, val curesStatus: Boolean) : BagItem {
POTION({ com.cobblemon.mod.common.CobblemonMechanics.potions.potionRestoreAmount }, false) {
override val itemName = "item.cobblemon.potion"
override fun getShowdownInput(actor: BattleActor, battlePokemon: BattlePokemon, data: String?) = "potion $amountToHeal"
override fun getShowdownInput(actor: BattleActor, battlePokemon: BattlePokemon, data: String?) = "potion ${genericRuntime.resolveInt(amountToHeal(), battlePokemon)}"
override fun canUse(battle: PokemonBattle, target: BattlePokemon) = target.health < target.maxHealth && target.health > 0
},
SUPER_POTION({ com.cobblemon.mod.common.CobblemonMechanics.potions.superPotionRestoreAmount }, false) {
override val itemName = "item.cobblemon.super_potion"
override fun getShowdownInput(actor: BattleActor, battlePokemon: BattlePokemon, data: String?) = "potion $amountToHeal"
override fun getShowdownInput(actor: BattleActor, battlePokemon: BattlePokemon, data: String?) = "potion ${genericRuntime.resolveInt(amountToHeal(), battlePokemon)}"
override fun canUse(battle: PokemonBattle, target: BattlePokemon) = target.health < target.maxHealth && target.health > 0
},
HYPER_POTION({ com.cobblemon.mod.common.CobblemonMechanics.potions.hyperPotionRestoreAmount }, false) {
override val itemName = "item.cobblemon.hyper_potion"
override fun getShowdownInput(actor: BattleActor, battlePokemon: BattlePokemon, data: String?) = "potion $amountToHeal"
override fun getShowdownInput(actor: BattleActor, battlePokemon: BattlePokemon, data: String?) = "potion ${genericRuntime.resolveInt(amountToHeal(), battlePokemon)}"
override fun canUse(battle: PokemonBattle, target: BattlePokemon) = target.health < target.maxHealth && target.health > 0
},
MAX_POTION({ 999999.0.asExpression() }, false) {
@@ -92,4 +92,4 @@ enum class PotionType(val amountToHeal: () -> Expression, val curesStatus: Boole
override fun getShowdownInput(actor: BattleActor, battlePokemon: BattlePokemon, data: String?) = "full_restore"
override fun canUse(battle: PokemonBattle, target: BattlePokemon) = target.health < target.maxHealth && target.health > 0
}
}
}
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
import com.cobblemon.mod.common.pokemon.activestate.ActivePokemonState
import com.cobblemon.mod.common.pokemon.activestate.ShoulderedState
import com.cobblemon.mod.common.util.toVec3d
import com.cobblemon.mod.common.util.traceBlockCollision
import net.minecraft.server.MinecraftServer
@@ -31,11 +32,11 @@ object SendOutPokemonHandler : ServerNetworkPacketHandler<SendOutPokemonPacket>
}
val state = pokemon.state
if (state !is ActivePokemonState) {
if (state is ShoulderedState || state !is ActivePokemonState) {
val trace = player.traceBlockCollision(maxDistance = 15F)
if (trace != null && !player.world.getBlockState(trace.blockPos.up()).isSolid) {
val position = Vec3d(trace.location.x, trace.blockPos.up().toVec3d().y, trace.location.z)
pokemon.sendOutWithAnimation(player, player.serverWorld, position)
pokemon.sendOutWithAnimation(player, player.serverWorld, position)
}
} else {
val entity = state.entity
@@ -19,31 +19,15 @@ import com.cobblemon.mod.common.api.data.ShowdownIdentifiable
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.CobblemonEvents.FRIENDSHIP_UPDATED
import com.cobblemon.mod.common.api.events.CobblemonEvents.POKEMON_FAINTED
import com.cobblemon.mod.common.api.events.pokemon.ExperienceGainedPostEvent
import com.cobblemon.mod.common.api.events.pokemon.ExperienceGainedPreEvent
import com.cobblemon.mod.common.api.events.pokemon.FriendshipUpdatedEvent
import com.cobblemon.mod.common.api.events.pokemon.LevelUpEvent
import com.cobblemon.mod.common.api.events.pokemon.PokemonFaintedEvent
import com.cobblemon.mod.common.api.events.pokemon.PokemonRecalledEvent
import com.cobblemon.mod.common.api.events.pokemon.PokemonSentPostEvent
import com.cobblemon.mod.common.api.events.pokemon.PokemonSentPreEvent
import com.cobblemon.mod.common.api.moves.BenchedMove
import com.cobblemon.mod.common.api.moves.BenchedMoves
import com.cobblemon.mod.common.api.moves.Move
import com.cobblemon.mod.common.api.moves.MoveSet
import com.cobblemon.mod.common.api.moves.MoveTemplate
import com.cobblemon.mod.common.api.moves.Moves
import com.cobblemon.mod.common.api.events.pokemon.*
import com.cobblemon.mod.common.api.moves.*
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.api.pokemon.Natures
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.pokemon.PokemonPropertyExtractor
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
import com.cobblemon.mod.common.api.pokemon.aspect.AspectProvider
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.api.pokemon.evolution.EvolutionController
import com.cobblemon.mod.common.api.pokemon.evolution.EvolutionDisplay
import com.cobblemon.mod.common.api.pokemon.evolution.EvolutionProxy
import com.cobblemon.mod.common.api.pokemon.evolution.PreEvolution
import com.cobblemon.mod.common.api.pokemon.evolution.*
import com.cobblemon.mod.common.api.pokemon.experience.ExperienceGroup
import com.cobblemon.mod.common.api.pokemon.experience.ExperienceSource
import com.cobblemon.mod.common.api.pokemon.feature.SpeciesFeature
@@ -70,10 +54,7 @@ import com.cobblemon.mod.common.net.messages.client.PokemonUpdatePacket
import com.cobblemon.mod.common.net.messages.client.pokemon.update.*
import com.cobblemon.mod.common.net.serverhandling.storage.SendOutPokemonHandler.SEND_OUT_DURATION
import com.cobblemon.mod.common.pokeball.PokeBall
import com.cobblemon.mod.common.pokemon.activestate.ActivePokemonState
import com.cobblemon.mod.common.pokemon.activestate.InactivePokemonState
import com.cobblemon.mod.common.pokemon.activestate.PokemonState
import com.cobblemon.mod.common.pokemon.activestate.SentOutState
import com.cobblemon.mod.common.pokemon.activestate.*
import com.cobblemon.mod.common.pokemon.evolution.CobblemonEvolutionProxy
import com.cobblemon.mod.common.pokemon.evolution.progress.DamageTakenEvolutionProgress
import com.cobblemon.mod.common.pokemon.evolution.progress.RecoilEvolutionProgress
@@ -81,26 +62,12 @@ import com.cobblemon.mod.common.pokemon.feature.SeasonFeatureHandler
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
import com.cobblemon.mod.common.pokemon.status.PersistentStatus
import com.cobblemon.mod.common.pokemon.status.PersistentStatusContainer
import com.cobblemon.mod.common.util.DataKeys
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.lang
import com.cobblemon.mod.common.util.playSoundServer
import com.cobblemon.mod.common.util.server
import com.cobblemon.mod.common.util.setPositionSafely
import com.cobblemon.mod.common.util.toBlockPos
import com.cobblemon.mod.common.util.*
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import com.mojang.serialization.Dynamic
import com.mojang.serialization.JsonOps
import java.util.Optional
import java.util.UUID
import java.util.concurrent.CompletableFuture
import kotlin.math.absoluteValue
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt
import kotlin.random.Random
import net.minecraft.entity.LivingEntity
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
@@ -119,6 +86,13 @@ import net.minecraft.util.InvalidIdentifierException
import net.minecraft.util.math.MathHelper.ceil
import net.minecraft.util.math.MathHelper.clamp
import net.minecraft.util.math.Vec3d
import java.util.*
import java.util.concurrent.CompletableFuture
import kotlin.math.absoluteValue
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt
import kotlin.random.Random
open class Pokemon : ShowdownIdentifiable {
var uuid = UUID.randomUUID()
@@ -469,8 +443,12 @@ open class Pokemon : ShowdownIdentifiable {
position: Vec3d,
battleId: UUID? = null,
doCry: Boolean = true,
mutation: (PokemonEntity) -> Unit = {}
mutation: (PokemonEntity) -> Unit = {},
): CompletableFuture<PokemonEntity> {
// Handle special case of shouldered Cobblemon
if (this.state is ShoulderedState) return sendOutFromShoulder(source as ServerPlayerEntity, level, position, battleId, doCry, mutation)
// Proceed as normal for non-shouldered Cobblemon
val future = CompletableFuture<PokemonEntity>()
sendOut(level, position) {
level.playSoundServer(position, CobblemonSounds.POKE_BALL_SEND_OUT, volume = 0.6F)
@@ -492,6 +470,52 @@ open class Pokemon : ShowdownIdentifiable {
}
return future
}
/**
* Send out the Pokémon from the player's shoulder.
*/
fun sendOutFromShoulder(
player: ServerPlayerEntity,
level: ServerWorld,
targetPosition: Vec3d,
battleId: UUID? = null,
doCry: Boolean = true,
mutation: (PokemonEntity) -> Unit = {}
): CompletableFuture<PokemonEntity> {
val future = CompletableFuture<PokemonEntity>()
// get the current position of the cobblemon on the players shoulder
val isLeftShoulder = (state as ShoulderedState).isLeftShoulder
val arbitraryXOffset = player.width * 0.3 + this.form.hitbox.width * 0.3
val shoulderHorizontalOffset = if (isLeftShoulder) arbitraryXOffset else -arbitraryXOffset
val rotation = player.yaw
Cobblemon.LOGGER.info("rotation: $rotation")
val approxShoulderMonHight = player.height.toDouble() - this.form.hitbox.height * 0.4
val rotatedOffset = Vec3d(shoulderHorizontalOffset, approxShoulderMonHight, 0.0).rotateY(-rotation * (Math.PI.toFloat() / 180f))
val currentPosition = player.pos.add(rotatedOffset)
sendOut(level, currentPosition) {
// Play some sound indicating hopping off
level.playSoundServer(currentPosition, CobblemonSounds.PC_DROP, volume = 0.6F)
// Make the Cobblemon walk to the target Position with haste
it.moveControl.moveTo(targetPosition.x, targetPosition.y, targetPosition.z, 1.2)
it.battleId.set(Optional.ofNullable(battleId))
afterOnMain(seconds = SEND_OUT_DURATION) {
future.complete(it)
CobblemonEvents.POKEMON_SENT_POST.post(PokemonSentPostEvent(this, it))
if (doCry) {
it.cry()
}
}
mutation(it)
}
return future
}
fun recall() {
CobblemonEvents.POKEMON_RECALLED.post(PokemonRecalledEvent(this, this.entity))
val state = this.state as? ActivePokemonState
@@ -753,7 +777,7 @@ open class Pokemon : ShowdownIdentifiable {
json.addProperty(DataKeys.POKEMON_LAST_SAVED_VERSION, Cobblemon.VERSION)
json.addProperty(DataKeys.POKEMON_UUID, uuid.toString())
json.addProperty(DataKeys.POKEMON_SPECIES_IDENTIFIER, species.resourceIdentifier.toString())
nickname?.let { json.add(DataKeys.POKEMON_NICKNAME, Text.Serializer.toJsonTree(it)) }
nickname?.let { json.addProperty(DataKeys.POKEMON_NICKNAME, Text.Serializer.toJson(it)) }
json.addProperty(DataKeys.POKEMON_FORM_ID, form.formOnlyShowdownId())
json.addProperty(DataKeys.POKEMON_EXPERIENCE, experience)
json.addProperty(DataKeys.POKEMON_LEVEL, level)
@@ -803,7 +827,7 @@ open class Pokemon : ShowdownIdentifiable {
} catch (e: InvalidIdentifierException) {
throw IllegalStateException("Failed to deserialize a species identifier")
}
nickname = json.get(DataKeys.POKEMON_NICKNAME)?.let { Text.Serializer.fromJson(it) }
nickname = json.get(DataKeys.POKEMON_NICKNAME)?.asString?.takeIf { it.isNotBlank() }?.let { Text.Serializer.fromJson(it) }
form = species.forms.find { it.formOnlyShowdownId() == json.get(DataKeys.POKEMON_FORM_ID).asString } ?: species.standardForm
level = json.get(DataKeys.POKEMON_LEVEL).asInt
experience = json.get(DataKeys.POKEMON_EXPERIENCE).asInt.takeIf { experienceGroup.getLevel(it) == level } ?: experienceGroup.getExperience(level)
@@ -904,7 +928,14 @@ open class Pokemon : ShowdownIdentifiable {
fun getOwnerUUID() : UUID? {
storeCoordinates.get().let {
if (isPlayerOwned()) return it!!.store.uuid
if (!isPlayerOwned()) {
return@let
}
if (it!!.store is PlayerPartyStore) {
return (it.store as PlayerPartyStore).playerUUID
}
return it.store.uuid
}
return null
}
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.pokemon
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.pokemon.stats.Stat
import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.net.IntSize
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
@@ -73,12 +74,9 @@ abstract class PokemonStats : Iterable<Map.Entry<Stat, Int>> {
fun loadFromNBT(nbt: NbtCompound): PokemonStats {
stats.clear()
nbt.keys.forEach { statId ->
try {
val identifier = statId.asIdentifierDefaultingNamespace()
val stat = Cobblemon.statProvider.fromIdentifier(identifier) ?: return@forEach
this[stat] = nbt.getShort(statId).toInt()
} catch (_: InvalidIdentifierException) {}
Stats.PERMANENT.forEach { stat ->
val identifier = this.cleanStatIdentifier(stat.identifier)
this[stat] = nbt.getShort(identifier).toInt().coerceIn(this.acceptableRange)
}
return this
}
@@ -95,12 +93,11 @@ abstract class PokemonStats : Iterable<Map.Entry<Stat, Int>> {
fun loadFromJSON(json: JsonObject): PokemonStats {
stats.clear()
json.entrySet().forEach { (key, element) ->
try {
val identifier = key.asIdentifierDefaultingNamespace()
val stat = Cobblemon.statProvider.fromIdentifier(identifier) ?: return@forEach
this[stat] = element.asInt
} catch (_: InvalidIdentifierException) {}
Stats.PERMANENT.forEach { stat ->
val identifier = this.cleanStatIdentifier(stat.identifier)
this[stat] = json.get(identifier)?.asInt?.coerceIn(this.acceptableRange)
?: this.defaultValue
}
return this
}
@@ -11,14 +11,8 @@ package com.cobblemon.mod.common.pokemon.activestate
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.DataKeys
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.getPlayer
import com.cobblemon.mod.common.util.isPokemonEntity
import com.cobblemon.mod.common.util.party
import com.cobblemon.mod.common.util.playSoundServer
import com.cobblemon.mod.common.util.*
import com.google.gson.JsonObject
import java.util.UUID
import net.minecraft.nbt.NbtCompound
import net.minecraft.network.PacketByteBuf
import net.minecraft.registry.RegistryKey
@@ -26,6 +20,7 @@ import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.sound.SoundEvents
import net.minecraft.util.Identifier
import net.minecraft.world.World
import java.util.*
sealed class PokemonState {
companion object {
@@ -176,6 +171,9 @@ class ShoulderedState() : ActivePokemonState() {
return this
}
/**
* Removes the cobblemon from the player's shoulder. (currently not used)
*/
override fun recall() {
val player = playerUUID.getPlayer() ?: return
val nbt = if (isLeftShoulder) player.shoulderEntityLeft else player.shoulderEntityRight
@@ -15,11 +15,9 @@ import net.minecraft.registry.tag.FluidTags
import net.minecraft.server.world.ServerWorld
import net.minecraft.sound.SoundCategory
import net.minecraft.sound.SoundEvent
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Box
import net.minecraft.util.math.*
import net.minecraft.util.math.MathHelper.ceil
import net.minecraft.util.math.MathHelper.floor
import net.minecraft.util.math.Vec3d
import net.minecraft.world.BlockView
import net.minecraft.world.World
@@ -48,6 +46,23 @@ fun World.squeezeWithinBounds(pos: BlockPos): BlockPos {
)
}
fun ServerWorld.isBoxLoaded(box: Box): Boolean {
val startChunkX = ChunkSectionPos.getSectionCoord(box.minX)
val startChunkZ = ChunkSectionPos.getSectionCoord(box.minZ)
val endChunkX = ChunkSectionPos.getSectionCoord(box.maxX)
val endChunkZ = ChunkSectionPos.getSectionCoord(box.maxZ)
for (chunkX in startChunkX..endChunkX) {
for (chunkZ in startChunkZ..endChunkZ) {
if (!this.isChunkLoaded(ChunkPos.toLong(chunkX, chunkZ))) {
return false
}
}
}
return true
}
fun Box.getRanges(): Triple<IntRange, IntRange, IntRange> {
return Triple(floor(minX)..ceil(maxX), minY.toInt()..ceil(maxY), minZ.toInt()..ceil(maxZ))
}
@@ -761,6 +761,9 @@
"cobblemon.battle.weather.hail.end": "The hail stopped.",
"cobblemon.battle.start.bide": "%1$s begins storing energy!",
"cobblemon.battle.start.disable": "%1$s's %2$s was disabled!",
"cobblemon.battle.start.foresight": "%1$s was identified!",
"cobblemon.battle.start.telekinesis": "%1$s was hurled into the air!",
"cobblemon.battle.start.yawn": "%1$s grew drowsy!",
"cobblemon.battle.start.perish": "%1$s's perish count fell to %2$s.",
"cobblemon.battle.start.leechseed": "%1$s was seeded!",
@@ -773,6 +776,7 @@
"cobblemon.battle.start.uproar": "%1$s caused an uproar!",
"cobblemon.battle.start.curse": "%1$s cut its own HP and put a curse on %2$s!",
"cobblemon.battle.start.miracleeye": "%1$s was identified!",
"cobblemon.battle.start.laserfocus": "%1$s concentrated intensely!",
"cobblemon.battle.start.dynamax": "%1$s Dynamaxed!",
"cobblemon.battle.start.gmax": "%1$s Gigantamaxed!",
@@ -925,6 +929,7 @@
"cobblemon.battle.damage.whirlpool": "%1$s was hurt by Whirlpool!",
"cobblemon.battle.damage.clamp": "%1$s was hurt by Clamp!",
"cobblemon.battle.damage.curse": "%1$s was afflicted by the curse!",
"cobblemon.battle.damage.firespin": "%1$s is hurt by Fire Spin!",
"cobblemon.battle.end.bind": "%1$s is no longer being squeezed!",
"cobblemon.battle.end.wrap": "%1$s was freed from wrap!",
@@ -937,6 +942,7 @@
"cobblemon.battle.end.whirlpool": "%1$s was freed from the vortex!",
"cobblemon.battle.end.clamp": "%1$s was freed from Clamp!",
"cobblemon.battle.end.dynamax": "%1$s returned to normal!",
"cobblemon.battle.end.telekinesis": "%1$s was freed from the telekinesis!",
"cobblemon.battle.sethp.painsplit": "The battlers shared their pain!",
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/keyitems/photodex"
}
}
File diff suppressed because it is too large. Load diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

@@ -0,0 +1,40 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"adorn:cobblemon/apricorn_bench"
]
},
"criteria": {
"has_slab": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"items": ["cobblemon:apricorn_slab"]
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "adorn:cobblemon/apricorn_bench"
}
}
},
"requirements": [
[
"has_slab",
"has_the_recipe"
]
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,42 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"adorn:cobblemon/apricorn_chair"
]
},
"criteria": {
"has_slab": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"items": [
"cobblemon:apricorn_slab"
]
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "adorn:cobblemon/apricorn_chair"
}
}
},
"requirements": [
[
"has_slab",
"has_the_recipe"
]
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,42 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"adorn:cobblemon/apricorn_coffee_table"
]
},
"criteria": {
"has_slab": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"items": [
"cobblemon:apricorn_slab"
]
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "adorn:cobblemon/apricorn_coffee_table"
}
}
},
"requirements": [
[
"has_slab",
"has_the_recipe"
]
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,42 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"adorn:cobblemon/apricorn_drawer"
]
},
"criteria": {
"has_slab": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"items": [
"cobblemon:apricorn_slab"
]
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "adorn:cobblemon/apricorn_drawer"
}
}
},
"requirements": [
[
"has_slab",
"has_the_recipe"
]
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,42 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"adorn:cobblemon/apricorn_kitchen_counter"
]
},
"criteria": {
"has_planks": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"items": [
"cobblemon:apricorn_planks"
]
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "adorn:cobblemon/apricorn_kitchen_counter"
}
}
},
"requirements": [
[
"has_planks",
"has_the_recipe"
]
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,55 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"adorn:cobblemon/apricorn_kitchen_cupboard"
]
},
"criteria": {
"has_planks": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"items": [
"cobblemon:apricorn_planks"
]
}
]
}
},
"has_kitchen_counter": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"items": [
"adorn:cobblemon/apricorn_kitchen_counter"
]
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "adorn:cobblemon/apricorn_kitchen_cupboard"
}
}
},
"requirements": [
[
"has_planks",
"has_kitchen_counter",
"has_the_recipe"
]
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,42 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"adorn:cobblemon/apricorn_kitchen_sink"
]
},
"criteria": {
"has_planks": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"items": [
"cobblemon:apricorn_planks"
]
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "adorn:cobblemon/apricorn_kitchen_sink"
}
}
},
"requirements": [
[
"has_planks",
"has_the_recipe"
]
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,42 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"adorn:cobblemon/apricorn_platform"
]
},
"criteria": {
"has_slab": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"items": [
"cobblemon:apricorn_slab"
]
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "adorn:cobblemon/apricorn_platform"
}
}
},
"requirements": [
[
"has_slab",
"has_the_recipe"
]
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,42 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"adorn:cobblemon/apricorn_post"
]
},
"criteria": {
"has_apricorn_planks": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"items": [
"cobblemon:apricorn_planks"
]
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "adorn:cobblemon/apricorn_post"
}
}
},
"requirements": [
[
"has_apricorn_planks",
"has_the_recipe"
]
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,42 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"adorn:cobblemon/apricorn_shelf"
]
},
"criteria": {
"has_slab": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"items": [
"cobblemon:apricorn_slab"
]
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "adorn:cobblemon/apricorn_shelf"
}
}
},
"requirements": [
[
"has_slab",
"has_the_recipe"
]
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,42 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"adorn:cobblemon/apricorn_step"
]
},
"criteria": {
"has_slab": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"items": [
"cobblemon:apricorn_slab"
]
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "adorn:cobblemon/apricorn_step"
}
}
},
"requirements": [
[
"has_slab",
"has_the_recipe"
]
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,42 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"adorn:cobblemon/apricorn_table"
]
},
"criteria": {
"has_slab": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"items": [
"cobblemon:apricorn_slab"
]
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "adorn:cobblemon/apricorn_table"
}
}
},
"requirements": [
[
"has_slab",
"has_the_recipe"
]
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,27 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "adorn:cobblemon/apricorn_bench"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"cobblemon:forge_load_conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,36 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "adorn:cobblemon/apricorn_chair",
"conditions": [
{
"block": "adorn:cobblemon/apricorn_chair",
"properties": {
"half": "lower"
},
"condition": "minecraft:block_state_property"
}
]
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"cobblemon:forge_load_conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,27 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "adorn:cobblemon/apricorn_coffee_table"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"cobblemon:forge_load_conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,33 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "adorn:cobblemon/apricorn_drawer",
"functions": [
{
"function": "minecraft:copy_name",
"source": "block_entity"
}
]
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"cobblemon:forge_load_conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,27 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "adorn:cobblemon/apricorn_kitchen_counter"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"cobblemon:forge_load_conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,33 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "adorn:cobblemon/apricorn_kitchen_cupboard",
"functions": [
{
"function": "minecraft:copy_name",
"source": "block_entity"
}
]
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"cobblemon:forge_load_conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,27 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "adorn:cobblemon/apricorn_kitchen_sink"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"cobblemon:forge_load_conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,27 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "adorn:cobblemon/apricorn_platform"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"cobblemon:forge_load_conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,27 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "adorn:cobblemon/apricorn_post"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"cobblemon:forge_load_conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,27 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "adorn:cobblemon/apricorn_shelf"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"cobblemon:forge_load_conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,27 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "adorn:cobblemon/apricorn_step"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"cobblemon:forge_load_conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,27 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "adorn:cobblemon/apricorn_table"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
],
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"cobblemon:forge_load_conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,25 @@
{
"type": "crafting_shaped",
"group": "adorn:bench",
"pattern": [
"SSS",
"S S"
],
"key": {
"S": {
"item": "cobblemon:apricorn_slab"
}
},
"result": {
"item": "adorn:cobblemon/apricorn_bench",
"count": 2
},
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,29 @@
{
"type": "crafting_shaped",
"group": "adorn:chair",
"pattern": [
" S",
"SS",
"##"
],
"key": {
"S": {
"item": "cobblemon:apricorn_slab"
},
"#": {
"tag": "c:wooden_rods"
}
},
"result": {
"item": "adorn:cobblemon/apricorn_chair",
"count": 2
},
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,31 @@
{
"type": "crafting_shaped",
"group": "adorn:coffee_table",
"pattern": [
"S-S",
"# #"
],
"key": {
"S": {
"item": "cobblemon:apricorn_slab"
},
"#": {
"tag": "c:wooden_rods"
},
"-": {
"tag": "c:glass_panes"
}
},
"result": {
"item": "adorn:cobblemon/apricorn_coffee_table",
"count": 2
},
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,29 @@
{
"type": "crafting_shaped",
"group": "adorn:drawer",
"pattern": [
"S",
"C",
"S"
],
"key": {
"C": {
"tag": "c:wooden_chests"
},
"S": {
"item": "cobblemon:apricorn_slab"
}
},
"result": {
"item": "adorn:cobblemon/apricorn_drawer",
"count": 2
},
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,28 @@
{
"type": "crafting_shaped",
"group": "adorn:kitchen_counter",
"pattern": [
"SS",
"PP"
],
"key": {
"S": {
"item": "minecraft:polished_andesite_slab"
},
"P": {
"item": "cobblemon:apricorn_planks"
}
},
"result": {
"item": "adorn:cobblemon/apricorn_kitchen_counter",
"count": 3
},
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,27 @@
{
"type": "crafting_shapeless",
"group": "adorn:kitchen_cupboard",
"ingredients": [
{
"tag": "c:wooden_chests"
},
{
"item": "adorn:cobblemon/apricorn_kitchen_counter"
},
{
"item": "adorn:cobblemon/apricorn_kitchen_counter"
}
],
"result": {
"item": "adorn:cobblemon/apricorn_kitchen_cupboard",
"count": 2
},
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,24 @@
{
"type": "crafting_shapeless",
"group": "adorn:kitchen_sink",
"ingredients": [
{
"item": "adorn:cobblemon/apricorn_kitchen_counter"
},
{
"item": "minecraft:bucket"
}
],
"result": {
"item": "adorn:cobblemon/apricorn_kitchen_sink",
"count": 1
},
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,28 @@
{
"type": "crafting_shaped",
"group": "adorn:platform",
"pattern": [
"S",
"P"
],
"key": {
"S": {
"item": "cobblemon:apricorn_slab"
},
"P": {
"item": "adorn:cobblemon/apricorn_post"
}
},
"result": {
"item": "adorn:cobblemon/apricorn_platform",
"count": 2
},
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,29 @@
{
"type": "crafting_shaped",
"group": "adorn:post",
"pattern": [
"/",
"/",
"#"
],
"key": {
"#": {
"item": "cobblemon:apricorn_planks"
},
"/": {
"tag": "c:wooden_rods"
}
},
"result": {
"item": "adorn:cobblemon/apricorn_post",
"count": 4
},
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,28 @@
{
"type": "crafting_shaped",
"group": "adorn:shelf",
"pattern": [
"---",
"/ /"
],
"key": {
"-": {
"item": "cobblemon:apricorn_slab"
},
"/": {
"tag": "c:wooden_rods"
}
},
"result": {
"item": "adorn:cobblemon/apricorn_shelf",
"count": 3
},
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,28 @@
{
"type": "crafting_shaped",
"group": "adorn:step",
"pattern": [
"S",
"#"
],
"key": {
"S": {
"item": "cobblemon:apricorn_slab"
},
"#": {
"tag": "c:wooden_rods"
}
},
"result": {
"item": "adorn:cobblemon/apricorn_step",
"count": 1
},
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -0,0 +1,29 @@
{
"type": "crafting_shaped",
"group": "adorn:table",
"pattern": [
"SSS",
"# #",
"# #"
],
"key": {
"S": {
"item": "cobblemon:apricorn_slab"
},
"#": {
"tag": "c:wooden_rods"
}
},
"result": {
"item": "adorn:cobblemon/apricorn_table",
"count": 3
},
"fabric:load_conditions": [{
"condition": "fabric:all_mods_loaded",
"values": ["adorn"]
}],
"conditions": [{
"type": "forge:mod_loaded",
"modid": "adorn"
}]
}
@@ -57,7 +57,7 @@
"#cobblemon:is_hills"
],
"timeRange": "night",
"moonPhase": 1
"moonPhase": 0
}
},
{
@@ -85,4 +85,4 @@
}
}
]
}
}
Loaded 100 of 181 files, more files were not shown because too many files have changed in this diff. Show more