Compare commits
163
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e3724a623 | ||
|
|
4940afbd81 | ||
|
|
d29e471ab4 | ||
|
|
6c1e6677b3 | ||
|
|
aaa7fcee47 | ||
|
|
37b050f2e5 | ||
|
|
16ccd6bcc3 | ||
|
|
8b0d228339 | ||
|
|
5019026472 | ||
|
|
ace38ad6be | ||
|
|
5c885112ef | ||
|
|
a37532579e | ||
|
|
0f751eb732 | ||
|
|
9840a2758a | ||
|
|
ad52d1ed5f | ||
|
|
74464dc13a | ||
|
|
f280ec8979 | ||
|
|
25ca0fbd13 | ||
|
|
2c8d544088 | ||
|
|
7dbe31d084 | ||
|
|
de05133b31 | ||
|
|
3b70b8351a | ||
|
|
784439475a | ||
|
|
2024ddb4f0 | ||
|
|
ad35be7ddb | ||
|
|
dbf688fade | ||
|
|
17d3d5f829 | ||
|
|
fba00c23b4 | ||
|
|
cfe516e086 | ||
|
|
63d921cb12 | ||
|
|
6acde8c90f | ||
|
|
196ce2ab6d | ||
|
|
6fb6ea2927 | ||
|
|
538027cb1b | ||
|
|
51fcc91d88 | ||
|
|
63c603cc01 | ||
|
|
a7406dd321 | ||
|
|
0e1611fd8e | ||
|
|
51e575c6a6 | ||
|
|
8789d16a53 | ||
|
|
f7986d5ccf | ||
|
|
c7423408a9 | ||
|
|
52b0c63751 | ||
|
|
7ae20ccd60 | ||
|
|
621b867d14 | ||
|
|
b0ea22d220 | ||
|
|
dfb54b3bc3 | ||
|
|
2928667500 | ||
|
|
1c528a909c | ||
|
|
1083e770d0 | ||
|
|
920f3f114b | ||
|
|
9ca5d12f84 | ||
|
|
cc9bb528a8 | ||
|
|
1cbd00691f | ||
|
|
f4c847fdd5 | ||
|
|
ec6e1403e7 | ||
|
|
10a4a03a8b | ||
|
|
e0a86f8794 | ||
|
|
767e024ec4 | ||
|
|
c8b0f36049 | ||
|
|
be2a0be806 | ||
|
|
ba4d42ccf6 | ||
|
|
5545d3498f | ||
|
|
641bd7ebaa | ||
|
|
234c4fa0d4 | ||
|
|
3dfda71ed5 | ||
|
|
65ee6de93f | ||
|
|
be88b727bc | ||
|
|
a69fc462ee | ||
|
|
7d5c30d27c | ||
|
|
f7c9c9d4f4 | ||
|
|
41bc14168a | ||
|
|
9540c38a72 | ||
|
|
7a96ed7cd1 | ||
|
|
677adc8d2f | ||
|
|
a99b1dfc6c | ||
|
|
4a718ad0f6 | ||
|
|
ddd417d458 | ||
|
|
10a12a897e | ||
|
|
9fce99ed73 | ||
|
|
c35f60dd5d | ||
|
|
54e5a5e819 | ||
|
|
79ae35ea9e | ||
|
|
58f85e6d0d | ||
|
|
71bfdf41f4 | ||
|
|
9976965673 | ||
|
|
098df1a5a6 | ||
|
|
f49f34efa3 | ||
|
|
eac19929c4 | ||
|
|
59cced5b2c | ||
|
|
f07707221f | ||
|
|
89b89592ab | ||
|
|
cdeb977769 | ||
|
|
78192c43a7 | ||
|
|
a3987b433c | ||
|
|
99de91bd7e | ||
|
|
4b292b1241 | ||
|
|
1e6e4d8c5f | ||
|
|
9a61c3471b | ||
|
|
77f7439853 | ||
|
|
439161c180 | ||
|
|
e9718b7e8b | ||
|
|
4cadd4e20f | ||
|
|
17a3d86324 | ||
|
|
48653073f5 | ||
|
|
82c7c03e28 | ||
|
|
2d7f3257d1 | ||
|
|
bc7b4f94c2 | ||
|
|
7a9e9d7ced | ||
|
|
0f85ece16f | ||
|
|
c4656e1a4e | ||
|
|
0c48a318c5 | ||
|
|
dab89a9f8c | ||
|
|
53fd2dba2d | ||
|
|
a5b15c6127 | ||
|
|
174fb59bbb | ||
|
|
2f8bd44938 | ||
|
|
9d58c7126e | ||
|
|
2afd722125 | ||
|
|
c9cfe489d6 | ||
|
|
4ee029fa54 | ||
|
|
e2ebb32708 | ||
|
|
b0466447cc | ||
|
|
727ff96ff8 | ||
|
|
9307f957b7 | ||
|
|
d48978f6a4 | ||
|
|
d1a8171079 | ||
|
|
d4b673ea38 | ||
|
|
de21b7c402 | ||
|
|
10fe3c4362 | ||
|
|
aca1433595 | ||
|
|
082c382179 | ||
|
|
c2d85a0cdf | ||
|
|
7cea5ad69e | ||
|
|
0b9b5ac306 | ||
|
|
8941f3079b | ||
|
|
e9a0815ca6 | ||
|
|
db25ebf7f1 | ||
|
|
fe48da6277 | ||
|
|
12c9c1c295 | ||
|
|
7471b336be | ||
|
|
948f299f8f | ||
|
|
5c075d7d29 | ||
|
|
854f02d34f | ||
|
|
a3c3fa12e5 | ||
|
|
3527da02a6 | ||
|
|
96f537fa27 | ||
|
|
e9f58df359 | ||
|
|
6885569f9e | ||
|
|
601927406c | ||
|
|
347b0bfa37 | ||
|
|
efa63b105f | ||
|
|
18d8c19df7 | ||
|
|
8d7c92f30e | ||
|
|
4e7b7d8d59 | ||
|
|
1213fc9145 | ||
|
|
071038dc09 | ||
|
|
2688e37f77 | ||
|
|
e8a9ea1185 | ||
|
|
4770c273f9 | ||
|
|
0e2e42b826 | ||
|
|
de819828ce | ||
|
|
fed34e9b98 |
No files matched your search
@@ -71,6 +71,7 @@
|
||||
- Octillery
|
||||
- Mantine
|
||||
- Smeargle
|
||||
- Delibird
|
||||
|
||||
#### Gen 3
|
||||
- Slakoth
|
||||
@@ -250,6 +251,7 @@
|
||||
### Model updates for the following Pokémon
|
||||
- Bulbasaur, Ivysaur, Venusaur
|
||||
- Charmander, Charmeleon, Charizard
|
||||
- Caterpie
|
||||
- Kakuna, Beedrill
|
||||
- Lapras
|
||||
- Porygon, Porygon2, Porygon-Z
|
||||
@@ -285,9 +287,11 @@
|
||||
- Phantump, Trevenant
|
||||
- Litten, Torracat, Incineroar
|
||||
- Popplio, Brionne, Primarina
|
||||
- Mudbray
|
||||
- Lurantis
|
||||
- Scorbunny, Cinderace
|
||||
- Quaxly
|
||||
- Skeledirge
|
||||
- Tatsugiri
|
||||
|
||||
### Changes
|
||||
@@ -343,6 +347,7 @@
|
||||
- A short jump indicates that you caught the Pokémon.
|
||||
- Pokémon sent out during battle will spawn facing their opponent.
|
||||
- Pokémon sent out outside a battle will spawn facing their trainer.
|
||||
- Wailord is now 25% bigger
|
||||
|
||||
### Fixes
|
||||
- Fixed Ability Patches not reverting Hidden Abilities back to Normal Abilities.
|
||||
@@ -397,6 +402,11 @@
|
||||
- Fixed Alolan Exeggutor's tail not showing in the party UI. It will now also stand in front of all Pokémon in the party menu :)
|
||||
- Fixed Timburr duplicating its log while fainting.
|
||||
- Fixed hitbox sizes for Grotle and Torterra being set to default values.
|
||||
- Fixed Hisuian Sneasel using Johtonian Sneasel's cry
|
||||
- Fixed Trevenant t-posing after 8 seconds of sleep.
|
||||
- Fixed Bewear t-posing for a bit if a wild one fainted.
|
||||
- Fixed Noctowl's placeholder fly animation.
|
||||
- Corrected Lotad's kotlin poser to use its own blink animation instead of Charmander's.
|
||||
- Fixed reviving items throwing an exception when used in battle.
|
||||
- Fixed messages for Focus Sash, Confusion, Mummy, Ice Face, Own Tempo, and Revive.
|
||||
- Improve error handling when loading spawn-sets to ensure invalid configurations don't crash the server.
|
||||
@@ -427,6 +437,8 @@
|
||||
- Prevent summary stats tab from making sounds when clicking on an already open tab.
|
||||
- Fixed display case not being able to be fed items from underneath.
|
||||
- Fixed Pokémon battling in water continuously sinking to the bottom.
|
||||
- Fixed passive healing and wake from faint not disabling when their config values are set to 0.
|
||||
- Fixed an issue where rebinding the R key to a mouse button prevented players from closing the battle interface using that button.
|
||||
|
||||
### Developer
|
||||
- `SpawnCause` is now an implementation of `SpawningInfluence`.
|
||||
@@ -458,6 +470,7 @@
|
||||
- Added HealingSource, an interface applied to all sources of healing from player actions, for easier tracking of healing sources.
|
||||
- Move Change
|
||||
- Shiny Chance Calculation Event (with player context)
|
||||
- Dex Information Changed; this event is fired when the Pokédex is updated with new information.
|
||||
- Rebuilt large swaths of the model animation code to simplify it.
|
||||
- Renamed a bunch of things from %Poseable% to %Posable% because spelling.
|
||||
- Renamed StatelessAnimation to PoseAnimation.
|
||||
@@ -486,6 +499,10 @@
|
||||
- Added support for conditional pose animations.
|
||||
- Added a new universal locator called "top".
|
||||
- Added `eggs_collected` and `eggs_hatched` Advancement triggers.
|
||||
- Added missing `minYaw` configuration to the `q.look()` function for JSON posers.
|
||||
- Some pose condition names have been changed:
|
||||
- `isTouchingWaterOrRain` has been changed to `isInWaterOrRain`
|
||||
- `isSubermegedInWater` has been changed to `isUnderWater`
|
||||
|
||||
### Localization
|
||||
- Updated translations for:
|
||||
@@ -1720,6 +1737,7 @@ Thank you so much to all of our community translators that bring the mod to the
|
||||
- Lowered spawn rate of Tauros.
|
||||
- Sableye now spawns near gem ores as well as amethyst.
|
||||
- Added evolution stones and items to item tags
|
||||
- Pokémon now play their cry animations when clicked on the starter selection screen.
|
||||
|
||||
### Fixes
|
||||
- Fixed catch rates being entirely too difficult.
|
||||
|
||||
@@ -54,7 +54,10 @@ import com.cobblemon.mod.common.api.storage.pc.PCStore
|
||||
import com.cobblemon.mod.common.api.storage.pc.link.PCLinkManager
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreManager
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreTypes
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.*
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.DexDataMongoBackend
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.DexDataNbtBackend
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.PlayerDataJsonBackend
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.PlayerDataMongoBackend
|
||||
import com.cobblemon.mod.common.api.storage.player.factory.CachedPlayerDataStoreFactory
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonEntityTypeTags
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
@@ -65,16 +68,7 @@ import com.cobblemon.mod.common.battles.BattleSide
|
||||
import com.cobblemon.mod.common.battles.ShowdownThread
|
||||
import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.command.argument.DexArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.DialogueArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.FormArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.MoveArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.NPCClassArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PartySlotArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PokemonPropertiesArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PokemonStoreArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.SpawnBucketArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.SpeciesArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.*
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import com.cobblemon.mod.common.config.LastChangedVersion
|
||||
import com.cobblemon.mod.common.config.constraint.IntConstraint
|
||||
@@ -94,17 +88,21 @@ import com.cobblemon.mod.common.pokemon.evolution.variants.BlockClickEvolution
|
||||
import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.pokemon.properties.AspectPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.BattleCloneProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.FreezeFrameProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.HiddenAbilityPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.NoAIProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.UnaspectPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.BattleCloneProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.tags.PokemonFlagProperty
|
||||
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
|
||||
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
|
||||
import com.cobblemon.mod.common.trade.TradeManager
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.ifDedicatedServer
|
||||
import com.cobblemon.mod.common.util.isLaterVersion
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import com.cobblemon.mod.common.world.feature.CobblemonPlacedFeatures
|
||||
import com.cobblemon.mod.common.world.feature.ore.CobblemonOrePlacedFeatures
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
@@ -116,7 +114,7 @@ import java.io.File
|
||||
import java.io.FileReader
|
||||
import java.io.FileWriter
|
||||
import java.io.PrintWriter
|
||||
import java.util.*
|
||||
import java.util.UUID
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.properties.Delegates
|
||||
import kotlin.reflect.full.memberProperties
|
||||
@@ -386,8 +384,13 @@ object Cobblemon {
|
||||
BattleFormat.GEN_9_SINGLES,
|
||||
BattleSide(PokemonBattleActor(UUID.randomUUID(), BattlePokemon(Pokemon().initialize()), -1F)),
|
||||
BattleSide(PokemonBattleActor(UUID.randomUUID(), BattlePokemon(Pokemon().initialize()), -1F)),
|
||||
true
|
||||
).ifSuccessful { it.mute = true }
|
||||
false
|
||||
).ifSuccessful {
|
||||
it.mute = true
|
||||
}.ifErrored {
|
||||
val errors = it.errors.joinToString("\n") { it.javaClass.name }
|
||||
LOGGER.error("Failed to start dummy Showdown battle: $errors")
|
||||
}
|
||||
}
|
||||
|
||||
registerEventHandlers()
|
||||
|
||||
@@ -276,6 +276,81 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val CHISELED_BLACK_TUMBLESTONE_BRICKS = this.create("chiseled_black_tumblestone_bricks", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
|
||||
@JvmField
|
||||
val GEM_BUG_BLOCK = this.create("gem_bug_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_DARK_BLOCK = this.create("gem_dark_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_DRAGON_BLOCK = this.create("gem_dragon_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_ELECTRIC_BLOCK = this.create("gem_electric_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_FAIRY_BLOCK = this.create("gem_fairy_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_FIGHTING_BLOCK = this.create("gem_fighting_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_FIRE_BLOCK = this.create("gem_fire_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_FLYING_BLOCK = this.create("gem_flying_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_GHOST_BLOCK = this.create("gem_ghost_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_GRASS_BLOCK = this.create("gem_grass_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_GROUND_BLOCK = this.create("gem_ground_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_ICE_BLOCK = this.create("gem_ice_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_NORMAL_BLOCK = this.create("gem_normal_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_POISON_BLOCK = this.create("gem_poison_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_PSYCHIC_BLOCK = this.create("gem_psychic_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_ROCK_BLOCK = this.create("gem_rock_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_STEEL_BLOCK = this.create("gem_steel_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_WATER_BLOCK = this.create("gem_water_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
|
||||
@JvmField
|
||||
val GEM_BUG_BUDDING = this.create("gem_bug_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_DARK_BUDDING = this.create("gem_dark_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_DRAGON_BUDDING = this.create("gem_dragon_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_ELECTRIC_BUDDING = this.create("gem_electric_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_FAIRY_BUDDING = this.create("gem_fairy_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_FIGHTING_BUDDING = this.create("gem_fighting_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_FIRE_BUDDING = this.create("gem_fire_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_FLYING_BUDDING = this.create("gem_flying_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_GHOST_BUDDING = this.create("gem_ghost_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_GRASS_BUDDING = this.create("gem_grass_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_GROUND_BUDDING = this.create("gem_ground_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_ICE_BUDDING = this.create("gem_ice_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_NORMAL_BUDDING = this.create("gem_normal_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_POISON_BUDDING = this.create("gem_poison_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_PSYCHIC_BUDDING = this.create("gem_psychic_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_ROCK_BUDDING = this.create("gem_rock_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_STEEL_BUDDING = this.create("gem_steel_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val GEM_WATER_BUDDING = this.create("gem_water_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
|
||||
|
||||
@JvmField
|
||||
val FIRE_STONE_BLOCK = this.create("fire_stone_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.FIRE).strength(1.0F).sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BIT).lightLevel{13}))
|
||||
@JvmField
|
||||
|
||||
@@ -56,6 +56,7 @@ object CobblemonCommands {
|
||||
AbandonMultiTeam.register(dispatcher)
|
||||
FreezePokemonCommand.register(dispatcher)
|
||||
ApplyPlayerTextureCommand.register(dispatcher)
|
||||
RunMolangScriptCommand.register(dispatcher)
|
||||
|
||||
// Possibly lock down registration if and only if under dev environment or running in an environment
|
||||
// with a certain system environment variable set
|
||||
|
||||
@@ -48,6 +48,8 @@ object CobblemonFlows : DataRegistry {
|
||||
val flows = hashMapOf<ResourceLocation, MutableList<ExpressionLike>>()
|
||||
|
||||
override fun reload(manager: ResourceManager) {
|
||||
clientFlows.clear()
|
||||
flows.clear()
|
||||
val folderBeforeNameRegex = ".*\\/([^\\/]+)\\/[^\\/]+\$".toRegex()
|
||||
manager.listResources("flows") { path -> path.endsWith(CobblemonScripts.MOLANG_EXTENSION) }.forEach { (identifier, resource) ->
|
||||
resource.openAsReader().use { stream ->
|
||||
|
||||
@@ -54,6 +54,9 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
override val registry: Registry<Item> = BuiltInRegistries.ITEM
|
||||
override val resourceKey: ResourceKey<Registry<Item>> = Registries.ITEM
|
||||
|
||||
@JvmField
|
||||
val NPC_EDITOR = create("npc_editor", CobblemonItem(Item.Properties().stacksTo(1)))
|
||||
|
||||
@JvmField
|
||||
val pokeBalls = mutableListOf<PokeBallItem>()
|
||||
@JvmField
|
||||
@@ -1224,6 +1227,80 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
//@JvmField
|
||||
//val BINDING_SOIL = blockItem("binding_soil", CobblemonBlocks.BINDING_SOIL)
|
||||
|
||||
@JvmField
|
||||
val GEM_BUG_BLOCK = blockItem("gem_bug_block", CobblemonBlocks.GEM_BUG_BLOCK)
|
||||
@JvmField
|
||||
val GEM_DARK_BLOCK = blockItem("gem_dark_block", CobblemonBlocks.GEM_DARK_BLOCK)
|
||||
@JvmField
|
||||
val GEM_DRAGON_BLOCK = blockItem("gem_dragon_block", CobblemonBlocks.GEM_DRAGON_BLOCK)
|
||||
@JvmField
|
||||
val GEM_ELECTRIC_BLOCK = blockItem("gem_electric_block", CobblemonBlocks.GEM_ELECTRIC_BLOCK)
|
||||
@JvmField
|
||||
val GEM_FAIRY_BLOCK = blockItem("gem_fairy_block", CobblemonBlocks.GEM_FAIRY_BLOCK)
|
||||
@JvmField
|
||||
val GEM_FIGHTING_BLOCK = blockItem("gem_fighting_block", CobblemonBlocks.GEM_FIGHTING_BLOCK)
|
||||
@JvmField
|
||||
val GEM_FIRE_BLOCK = blockItem("gem_fire_block", CobblemonBlocks.GEM_FIRE_BLOCK)
|
||||
@JvmField
|
||||
val GEM_FLYING_BLOCK = blockItem("gem_flying_block", CobblemonBlocks.GEM_FLYING_BLOCK)
|
||||
@JvmField
|
||||
val GEM_GHOST_BLOCK = blockItem("gem_ghost_block", CobblemonBlocks.GEM_GHOST_BLOCK)
|
||||
@JvmField
|
||||
val GEM_GRASS_BLOCK = blockItem("gem_grass_block", CobblemonBlocks.GEM_GRASS_BLOCK)
|
||||
@JvmField
|
||||
val GEM_GROUND_BLOCK = blockItem("gem_ground_block", CobblemonBlocks.GEM_GROUND_BLOCK)
|
||||
@JvmField
|
||||
val GEM_ICE_BLOCK = blockItem("gem_ice_block", CobblemonBlocks.GEM_ICE_BLOCK)
|
||||
@JvmField
|
||||
val GEM_NORMAL_BLOCK = blockItem("gem_normal_block", CobblemonBlocks.GEM_NORMAL_BLOCK)
|
||||
@JvmField
|
||||
val GEM_POISON_BLOCK = blockItem("gem_poison_block", CobblemonBlocks.GEM_POISON_BLOCK)
|
||||
@JvmField
|
||||
val GEM_PSYCHIC_BLOCK = blockItem("gem_psychic_block", CobblemonBlocks.GEM_PSYCHIC_BLOCK)
|
||||
@JvmField
|
||||
val GEM_ROCK_BLOCK = blockItem("gem_rock_block", CobblemonBlocks.GEM_ROCK_BLOCK)
|
||||
@JvmField
|
||||
val GEM_STEEL_BLOCK = blockItem("gem_steel_block", CobblemonBlocks.GEM_STEEL_BLOCK)
|
||||
@JvmField
|
||||
val GEM_WATER_BLOCK = blockItem("gem_water_block", CobblemonBlocks.GEM_WATER_BLOCK)
|
||||
|
||||
@JvmField
|
||||
val GEM_BUG_BUDDING = blockItem("gem_bug_budding", CobblemonBlocks.GEM_BUG_BUDDING)
|
||||
@JvmField
|
||||
val GEM_DARK_BUDDING = blockItem("gem_dark_budding", CobblemonBlocks.GEM_DARK_BUDDING)
|
||||
@JvmField
|
||||
val GEM_DRAGON_BUDDING = blockItem("gem_dragon_budding", CobblemonBlocks.GEM_DRAGON_BUDDING)
|
||||
@JvmField
|
||||
val GEM_ELECTRIC_BUDDING = blockItem("gem_electric_budding", CobblemonBlocks.GEM_ELECTRIC_BUDDING)
|
||||
@JvmField
|
||||
val GEM_FAIRY_BUDDING = blockItem("gem_fairy_budding", CobblemonBlocks.GEM_FAIRY_BUDDING)
|
||||
@JvmField
|
||||
val GEM_FIGHTING_BUDDING = blockItem("gem_fighting_budding", CobblemonBlocks.GEM_FIGHTING_BUDDING)
|
||||
@JvmField
|
||||
val GEM_FIRE_BUDDING = blockItem("gem_fire_budding", CobblemonBlocks.GEM_FIRE_BUDDING)
|
||||
@JvmField
|
||||
val GEM_FLYING_BUDDING = blockItem("gem_flying_budding", CobblemonBlocks.GEM_FLYING_BUDDING)
|
||||
@JvmField
|
||||
val GEM_GHOST_BUDDING = blockItem("gem_ghost_budding", CobblemonBlocks.GEM_GHOST_BUDDING)
|
||||
@JvmField
|
||||
val GEM_GRASS_BUDDING = blockItem("gem_grass_budding", CobblemonBlocks.GEM_GRASS_BUDDING)
|
||||
@JvmField
|
||||
val GEM_GROUND_BUDDING = blockItem("gem_ground_budding", CobblemonBlocks.GEM_GROUND_BUDDING)
|
||||
@JvmField
|
||||
val GEM_ICE_BUDDING = blockItem("gem_ice_budding", CobblemonBlocks.GEM_ICE_BUDDING)
|
||||
@JvmField
|
||||
val GEM_NORMAL_BUDDING = blockItem("gem_normal_budding", CobblemonBlocks.GEM_NORMAL_BUDDING)
|
||||
@JvmField
|
||||
val GEM_POISON_BUDDING = blockItem("gem_poison_budding", CobblemonBlocks.GEM_POISON_BUDDING)
|
||||
@JvmField
|
||||
val GEM_PSYCHIC_BUDDING = blockItem("gem_psychic_budding", CobblemonBlocks.GEM_PSYCHIC_BUDDING)
|
||||
@JvmField
|
||||
val GEM_ROCK_BUDDING = blockItem("gem_rock_budding", CobblemonBlocks.GEM_ROCK_BUDDING)
|
||||
@JvmField
|
||||
val GEM_STEEL_BUDDING = blockItem("gem_steel_budding", CobblemonBlocks.GEM_STEEL_BUDDING)
|
||||
@JvmField
|
||||
val GEM_WATER_BUDDING = blockItem("gem_water_budding", CobblemonBlocks.GEM_WATER_BUDDING)
|
||||
|
||||
private fun blockItem(name: String, block: Block): BlockItem = this.create(name, BlockItem(block, Item.Properties()))
|
||||
|
||||
private fun noSettingsItem(name: String): CobblemonItem = this.create(name, CobblemonItem(Item.Properties()))
|
||||
|
||||
@@ -55,6 +55,8 @@ object CobblemonCriteria : PlatformRegistry<Registry<CriterionTrigger<*>>, Resou
|
||||
|
||||
val CAST_POKE_ROD = this.create("cast_poke_rod", SimpleCriterionTrigger(CastPokeRodCriterionCondition.CODEC))
|
||||
|
||||
val REEL_IN_POKEMON = this.create("reel_in_pokemon", SimpleCriterionTrigger(ReelInPokemonCriterionCondition.CODEC))
|
||||
|
||||
// Advancement criteria for [grow_tumblestone.json]
|
||||
val PLANT_TUMBLESTONE = this.create("plant_tumblestone", SimpleCriterionTrigger(PlantTumblestoneCriterion.CODEC))
|
||||
|
||||
|
||||
+14
-10
@@ -8,26 +8,30 @@
|
||||
|
||||
package com.cobblemon.mod.common.advancement.criterion
|
||||
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.PrimitiveCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import java.util.Optional
|
||||
import net.minecraft.advancements.critereon.ContextAwarePredicate
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class CastPokeRodContext(val baitId: ResourceLocation)
|
||||
|
||||
class CastPokeRodCriterionCondition(
|
||||
playerCtx: Optional<ContextAwarePredicate>,
|
||||
val hasBait: Boolean
|
||||
): SimpleCriterionCondition<Boolean>(playerCtx) {
|
||||
playerCtx: Optional<ContextAwarePredicate>,
|
||||
val baitId: String
|
||||
): SimpleCriterionCondition<CastPokeRodContext>(playerCtx) {
|
||||
|
||||
companion object {
|
||||
val CODEC: Codec<CastPokeRodCriterionCondition> = RecordCodecBuilder.create { it.group(
|
||||
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(CastPokeRodCriterionCondition::playerCtx),
|
||||
PrimitiveCodec.BOOL.fieldOf("hasBait").forGetter(CastPokeRodCriterionCondition::hasBait)
|
||||
).apply(it, ::CastPokeRodCriterionCondition) }
|
||||
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(CastPokeRodCriterionCondition::playerCtx),
|
||||
Codec.STRING.optionalFieldOf("baitId", "empty_bait").forGetter(CastPokeRodCriterionCondition::baitId)
|
||||
).apply(it, { playerCtx, baitId -> CastPokeRodCriterionCondition(playerCtx, baitId.ifEmpty { "empty_bait" }) }) }
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: Boolean): Boolean {
|
||||
return hasBait == context
|
||||
override fun matches(player: ServerPlayer, context: CastPokeRodContext): Boolean {
|
||||
return (context.baitId == this.baitId.asIdentifierDefaultingNamespace() || this.baitId.equals("empty_bait"))
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -26,7 +26,7 @@ class PartyCheckCriterion(
|
||||
companion object {
|
||||
val CODEC: Codec<PartyCheckCriterion> = RecordCodecBuilder.create { it.group(
|
||||
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(PartyCheckCriterion::playerCtx),
|
||||
ResourceLocation.CODEC.listOf().optionalFieldOf("id", listOf()).forGetter(PartyCheckCriterion::party)
|
||||
ResourceLocation.CODEC.listOf().optionalFieldOf("party", listOf()).forGetter(PartyCheckCriterion::party)
|
||||
).apply(it, ::PartyCheckCriterion) }
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ class PartyCheckCriterion(
|
||||
matches.add(it.species.resourceIdentifier)
|
||||
}
|
||||
}
|
||||
return matches.containsAll(party) && matches.size == partyCount
|
||||
return matches.containsAll(party) && matches.size == party.size
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.advancement.criterion
|
||||
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import java.util.Optional
|
||||
import net.minecraft.advancements.critereon.ContextAwarePredicate
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class ReelInPokemonContext(val pokemonId : ResourceLocation, val baitId: ResourceLocation)
|
||||
|
||||
class ReelInPokemonCriterionCondition(
|
||||
playerCtx: Optional<ContextAwarePredicate>,
|
||||
val pokemonId: String,
|
||||
val baitId: String
|
||||
) : SimpleCriterionCondition<ReelInPokemonContext>(playerCtx) {
|
||||
|
||||
companion object {
|
||||
val CODEC: Codec<ReelInPokemonCriterionCondition> = RecordCodecBuilder.create { it.group(
|
||||
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter { it.playerCtx },
|
||||
Codec.STRING.optionalFieldOf("pokemonId", "any").forGetter { it.pokemonId },
|
||||
Codec.STRING.optionalFieldOf("baitId", "empty_bait").forGetter { it.baitId }
|
||||
).apply(it, { playerCtx, pokemonId, baitId -> ReelInPokemonCriterionCondition(playerCtx, pokemonId, baitId.ifEmpty { "empty_bait" }) }) }
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: ReelInPokemonContext): Boolean {
|
||||
return (context.pokemonId == this.pokemonId.asIdentifierDefaultingNamespace() || this.pokemonId == "any") && (context.baitId == this.baitId.asIdentifierDefaultingNamespace() || this.baitId == "empty_bait")
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ open class ItemDropEntry : DropEntry {
|
||||
|
||||
if (dropMethod == ItemDropMethod.ON_PLAYER && player != null) {
|
||||
world.addFreshEntity(ItemEntity(player.level(), player.x, player.y, player.z, stack))
|
||||
} else if (dropMethod == ItemDropMethod.TO_INVENTORY && player != null) {
|
||||
} else if (dropMethod == ItemDropMethod.TO_INVENTORY && player != null && !stack.isEmpty) {
|
||||
val name = stack.hoverName
|
||||
val count = stack.count
|
||||
val succeeded = player.addItem(stack)
|
||||
|
||||
@@ -192,6 +192,8 @@ object CobblemonEvents {
|
||||
val POKEMON_GAINED = EventObservable<PokemonGainedEvent>()
|
||||
@JvmField
|
||||
val POKEMON_SEEN = EventObservable<PokemonSeenEvent>()
|
||||
@JvmField
|
||||
val POKEDEX_DATA_CHANGED = EventObservable<PokedexDataChangedEvent>()
|
||||
|
||||
// Fishing
|
||||
@JvmField
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.pokedex.FormDexRecord
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.api.pokedex.AbstractPokedexManager
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.getPlayer
|
||||
import com.mojang.datafixers.util.Either
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* Event that fires when a Pokémon's information is gained or updated in the Pokédex.
|
||||
*/
|
||||
data class PokedexDataChangedEvent(
|
||||
val dataSource: Either<PokedexEntityData, Pokemon>,
|
||||
val knowledge: PokedexEntryProgress,
|
||||
val playerUUID: UUID,
|
||||
val record: FormDexRecord
|
||||
) {
|
||||
val pokedexManager: AbstractPokedexManager
|
||||
get() = record.speciesDexRecord.pokedexManager
|
||||
|
||||
val context = mutableMapOf<String, MoValue>(
|
||||
"player" to (playerUUID.getPlayer()?.asMoLangValue() ?: DoubleValue.ZERO),
|
||||
"pokemon" to dataSource.map({ DoubleValue.ZERO }, { it.struct }),
|
||||
"data" to dataSource.map({ it.struct }, { DoubleValue.ZERO }),
|
||||
"knowledge" to StringValue(knowledge.name.lowercase()),
|
||||
"pokedex" to pokedexManager.struct
|
||||
)
|
||||
}
|
||||
+1
-2
@@ -14,5 +14,4 @@ import java.util.UUID
|
||||
data class PokemonGainedEvent(
|
||||
val playerId: UUID,
|
||||
val pokemon: Pokemon
|
||||
) {
|
||||
}
|
||||
)
|
||||
+1
-3
@@ -9,11 +9,9 @@
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import java.util.UUID
|
||||
|
||||
data class PokemonSeenEvent(
|
||||
val playerId: UUID,
|
||||
val pokemon: Pokemon
|
||||
) {
|
||||
}
|
||||
)
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.gui
|
||||
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import net.minecraft.client.gui.components.AbstractWidget
|
||||
import net.minecraft.client.gui.components.Renderable
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener
|
||||
@@ -22,7 +23,7 @@ abstract class ParentWidget(
|
||||
pX: Int, pY: Int,
|
||||
pWidth: Int, pHeight: Int,
|
||||
component: Component
|
||||
): Renderable, AbstractWidget(pX, pY, pWidth, pHeight, component) {
|
||||
): CobblemonRenderable, AbstractWidget(pX, pY, pWidth, pHeight, component) {
|
||||
|
||||
val children: MutableList<GuiEventListener> = mutableListOf()
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ abstract class RequestManager<T : ServerPlayerActionRequest> {
|
||||
?: this.getInboundRequest(receiver.uuid, requestID)
|
||||
|
||||
/** Determines whether [player] can receive a [T]. */
|
||||
open fun isBusy(player: ServerPlayer): Boolean = player.isInBattle() || player.isTrading()
|
||||
open fun isBusy(player: ServerPlayer): Boolean = player.isInBattle() || player.isTrading() || player.party().find { it.entity?.isBusy == true } != null
|
||||
|
||||
/** Determines if the [target] is a valid interaction request target. */
|
||||
abstract fun isValidInteraction(player: ServerPlayer, target: ServerPlayer): Boolean
|
||||
@@ -176,7 +176,7 @@ abstract class RequestManager<T : ServerPlayerActionRequest> {
|
||||
else if (!this.isValidInteraction(player, target ?: request.sender)) // with teams anyone can accept
|
||||
request.notify(player, true, "ui.interact.failed")
|
||||
// if sending player is occupied, can't accept response
|
||||
else if (this.isBusy(request.sender)) // TODO enhancement: allow retries - modify client so we don't remove request when sending acceptance
|
||||
else if (this.isBusy(request.sender) || this.isBusy(request.receiver)) // TODO enhancement: allow retries - modify client so we don't remove request when sending acceptance
|
||||
request.notify(player, true, "ui.interact.unavailable")
|
||||
// if no condition is blocking acceptance, accept
|
||||
else if (this.canAccept(request))
|
||||
|
||||
@@ -38,8 +38,9 @@ import net.minecraft.world.phys.AABB
|
||||
*/
|
||||
interface PokemonSelectingItem {
|
||||
fun use(player: ServerPlayer, stack: ItemStack): InteractionResultHolder<ItemStack> {
|
||||
val range = player.entityInteractionRange()
|
||||
val entity = player.level()
|
||||
.getEntities(player, AABB.ofSize(player.position(), 16.0, 16.0, 16.0))
|
||||
.getEntities(player, AABB.ofSize(player.position(), range, range, range))
|
||||
.filter { player.isLookingAt(it, stepDistance = 0.1F) }
|
||||
.minByOrNull { it.distanceTo(player) } as? PokemonEntity?
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.item.ability
|
||||
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
import com.cobblemon.mod.common.api.abilities.*
|
||||
import com.cobblemon.mod.common.item.interactive.ability.AbilityTypeChanger
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
@@ -33,7 +34,7 @@ interface AbilityChanger<T : PotentialAbility> {
|
||||
* @param pokemon The [Pokemon] being queried.
|
||||
* @return A set containing all their legal abilities associated with [type], can be empty.
|
||||
*/
|
||||
fun queryPossible(pokemon: Pokemon): Set<AbilityTemplate>
|
||||
fun queryPossible(pokemon: Pokemon): Set<Pair<AbilityTemplate, Priority>>
|
||||
|
||||
/**
|
||||
* Attempts to update the ability of the given [pokemon].
|
||||
|
||||
@@ -29,6 +29,13 @@ import com.cobblemon.mod.common.api.dialogue.ReferenceDialogueFaceProvider
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffects
|
||||
import com.cobblemon.mod.common.api.moves.animations.NPCProvider
|
||||
import com.cobblemon.mod.common.api.pokedex.AbstractPokedexManager
|
||||
import com.cobblemon.mod.common.api.pokedex.CaughtCount
|
||||
import com.cobblemon.mod.common.api.pokedex.CaughtPercent
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexManager
|
||||
import com.cobblemon.mod.common.api.pokedex.SeenCount
|
||||
import com.cobblemon.mod.common.api.pokedex.SeenPercent
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
|
||||
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
|
||||
@@ -40,6 +47,8 @@ import com.cobblemon.mod.common.api.storage.pc.PCStore
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.battles.BattleRegistry
|
||||
import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
|
||||
import com.cobblemon.mod.common.client.particle.BedrockParticleOptionsRepository
|
||||
import com.cobblemon.mod.common.client.particle.ParticleStorm
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.WaveFunctions
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.entity.npc.NPCBattleActor
|
||||
@@ -49,11 +58,15 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.PokemonMoveControl
|
||||
import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.Species
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.mojang.datafixers.util.Either
|
||||
import java.util.UUID
|
||||
import kotlin.math.sqrt
|
||||
import net.minecraft.client.multiplayer.ClientLevel
|
||||
import net.minecraft.commands.arguments.EntityAnchorArgument
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Holder
|
||||
@@ -102,6 +115,12 @@ object MoLangFunctions {
|
||||
val message = params.get<MoValue>(0).asString()
|
||||
Cobblemon.LOGGER.info(message)
|
||||
},
|
||||
"set_query" to java.util.function.Function { params ->
|
||||
val variable = params.getString(0)
|
||||
val value = params.get<MoValue>(1)
|
||||
params.environment.query.addFunction(variable) { value }
|
||||
return@Function value
|
||||
},
|
||||
"replace" to java.util.function.Function { params ->
|
||||
val text = params.getString(0)
|
||||
val search = params.getString(1)
|
||||
@@ -221,6 +240,31 @@ object MoLangFunctions {
|
||||
world.addFreshEntity(lightning)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
// q.entity.world.spawn_bedrock_particles(effect, x, y, z, [player]) - sends to everyone nearby or just to the player if they're set.
|
||||
map.put("spawn_bedrock_particles") { params ->
|
||||
val particle = params.getString(0).asResource()
|
||||
val x = params.getDouble(1)
|
||||
val y = params.getDouble(2)
|
||||
val z = params.getDouble(3)
|
||||
val player = params.getOrNull<MoValue>(4)?.let {
|
||||
if (it is StringValue) world.getPlayerByUUID(UUID.fromString(it.value))
|
||||
else if (it is ObjectValue<*>) it.obj
|
||||
else null
|
||||
} as? ServerPlayer
|
||||
val pos = Vec3(x, y, z)
|
||||
|
||||
if (world !is ClientLevel) {
|
||||
val packet = SpawnSnowstormParticlePacket(particle, pos)
|
||||
if (player != null) {
|
||||
packet.sendToPlayer(player)
|
||||
} else {
|
||||
packet.sendToPlayersAround(x, y, z, 64.0, world.dimension())
|
||||
}
|
||||
} else {
|
||||
val effect = BedrockParticleOptionsRepository.getEffect(particle) ?: return@put DoubleValue.ZERO
|
||||
ParticleStorm.createAtPosition(world, effect, pos).spawn()
|
||||
}
|
||||
}
|
||||
map.put("get_entities_around") { params ->
|
||||
val x = params.getDouble(0)
|
||||
val y = params.getDouble(1)
|
||||
@@ -320,6 +364,8 @@ object MoLangFunctions {
|
||||
val data = Cobblemon.molangData.load(player.uuid)
|
||||
if (data.map.containsKey(npcId)) {
|
||||
return@put (data.map[npcId] as VariableStruct).map[variable] ?: DoubleValue.ZERO
|
||||
} else {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
map.put("set_npc_variable") { params ->
|
||||
@@ -328,16 +374,14 @@ object MoLangFunctions {
|
||||
val value = params.get<MoValue>(2)
|
||||
val saveAfterwards = params.getBooleanOrNull(3) != false
|
||||
val data = Cobblemon.molangData.load(player.uuid)
|
||||
if (data.map.containsKey(npcId)) {
|
||||
(data.map[npcId] as VariableStruct).map[variable] = value
|
||||
if (saveAfterwards) {
|
||||
Cobblemon.molangData.save(player.uuid)
|
||||
}
|
||||
return@put DoubleValue.ONE
|
||||
} else {
|
||||
return@put DoubleValue.ZERO
|
||||
val npcData = data.map.getOrPut(npcId) { VariableStruct() } as VariableStruct
|
||||
npcData.map[variable] = value
|
||||
if (saveAfterwards) {
|
||||
Cobblemon.molangData.save(player.uuid)
|
||||
}
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map.put("pokedex") { player.pokedex().struct }
|
||||
}
|
||||
map
|
||||
}
|
||||
@@ -445,7 +489,42 @@ object MoLangFunctions {
|
||||
map.put("play_animation") { params ->
|
||||
val animation = params.getString(0)
|
||||
val packet = PlayPosableAnimationPacket(entity.id, setOf(animation), emptyList())
|
||||
val target = params.getStringOrNull(1)
|
||||
if (target != null) {
|
||||
val targetPlayer = if (target.asUUID != null) {
|
||||
entity.level().getPlayerByUUID(target.asUUID!!) as ServerPlayer
|
||||
} else if (entity.level() is ServerLevel) {
|
||||
entity.level().server!!.playerList.getPlayerByName(target)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
if (targetPlayer != null) {
|
||||
packet.sendToPlayer(targetPlayer)
|
||||
return@put DoubleValue.ONE
|
||||
} else {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
} else {
|
||||
packet.sendToPlayersAround(entity.x, entity.y, entity.z, 64.0, entity.level().dimension())
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
}
|
||||
}
|
||||
// q.entity.spawn_bedrock_particles(effect, locator, [player]) - sends to everyone nearby or just to the player if they're set. Locator is necessary even if unused on non-posables.
|
||||
map.put("spawn_bedrock_particles") { params ->
|
||||
val particle = params.getString(0).asResource()
|
||||
val locator = params.getString(1)
|
||||
val player = params.getOrNull<MoValue>(2)?.let {
|
||||
if (it is StringValue) entity.level().getPlayerByUUID(UUID.fromString(it.value))
|
||||
else if (it is ObjectValue<*>) it.obj
|
||||
else null
|
||||
} as? ServerPlayer
|
||||
|
||||
val packet = SpawnSnowstormEntityParticlePacket(particle, entity.id, listOf(locator))
|
||||
if (player == null) {
|
||||
packet.sendToPlayersAround(entity.x, entity.y, entity.z, 64.0, entity.level().dimension())
|
||||
} else {
|
||||
packet.sendToPlayer(player)
|
||||
}
|
||||
}
|
||||
map
|
||||
@@ -594,6 +673,7 @@ object MoLangFunctions {
|
||||
}
|
||||
map.put("is_wild") { DoubleValue(pokemon.entity?.let { it.ownerUUID == null } == true) }
|
||||
map.put("is_shiny") { DoubleValue(pokemon.shiny) }
|
||||
map.put("species") { pokemon.species.struct }
|
||||
map.put("form") { StringValue(pokemon.form.name) }
|
||||
map.put("weight") { DoubleValue(pokemon.species.weight.toDouble()) }
|
||||
map.put("matches") { params -> DoubleValue(params.getString(0).toProperties().matches(pokemon)) }
|
||||
@@ -804,6 +884,78 @@ object MoLangFunctions {
|
||||
}
|
||||
)
|
||||
|
||||
val pokedexFunctions: MutableList<(AbstractPokedexManager) -> HashMap<String, java.util.function.Function<MoParams, Any>>> = mutableListOf(
|
||||
{ pokedex ->
|
||||
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
map.put("get_species_record") { params ->
|
||||
val speciesId = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
pokedex.speciesRecords[speciesId]?.struct ?: QueryStruct(hashMapOf())
|
||||
}
|
||||
|
||||
map.put("has_seen") { params ->
|
||||
val speciesId = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
val formName = params.getStringOrNull(1)
|
||||
|
||||
if (formName == null) {
|
||||
return@put DoubleValue(pokedex.getHighestKnowledgeForSpecies(speciesId).ordinal >= PokedexEntryProgress.ENCOUNTERED.ordinal)
|
||||
} else {
|
||||
return@put DoubleValue((pokedex.getSpeciesRecord(speciesId)?.getFormRecord(formName)?.knowledge?.ordinal ?: 0) >= PokedexEntryProgress.ENCOUNTERED.ordinal)
|
||||
}
|
||||
}
|
||||
|
||||
map.put("has_caught") { params ->
|
||||
val speciesId = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
val formName = params.getStringOrNull(1)
|
||||
if (formName == null) {
|
||||
return@put DoubleValue(pokedex.getHighestKnowledgeForSpecies(speciesId) == PokedexEntryProgress.CAUGHT)
|
||||
} else {
|
||||
return@put DoubleValue(pokedex.getSpeciesRecord(speciesId)?.getFormRecord(formName)?.knowledge == PokedexEntryProgress.CAUGHT)
|
||||
}
|
||||
}
|
||||
map.put("caught_count") { DoubleValue(pokedex.getGlobalCalculatedValue(CaughtCount)) }
|
||||
map.put("seen_count") { DoubleValue(pokedex.getGlobalCalculatedValue(SeenCount)) }
|
||||
map.put("caught_percent") { DoubleValue(pokedex.getGlobalCalculatedValue(CaughtPercent)) }
|
||||
map.put("seen_percent") { DoubleValue(pokedex.getGlobalCalculatedValue(SeenPercent)) }
|
||||
|
||||
if (pokedex is PokedexManager) {
|
||||
map.put("player_id") { StringValue(pokedex.uuid.toString()) }
|
||||
map.put("see") { params ->
|
||||
val pokemon = params.get<ObjectValue<Pokemon>>(0).obj
|
||||
pokedex.encounter(pokemon)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map.put("catch") { params ->
|
||||
val pokemon = params.get<ObjectValue<Pokemon>>(0).obj
|
||||
pokedex.catch(pokemon)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
}
|
||||
|
||||
map
|
||||
}
|
||||
)
|
||||
|
||||
val speciesFunctions: MutableList<(Species) -> HashMap<String, java.util.function.Function<MoParams, Any>>> = mutableListOf(
|
||||
{ species ->
|
||||
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
|
||||
map.put("identifier") { StringValue(species.resourceIdentifier.toString()) }
|
||||
map.put("name") { StringValue(species.name) }
|
||||
map.put("primary_type") { StringValue(species.primaryType.name) }
|
||||
map.put("secondary_type") { StringValue(species.secondaryType?.name ?: "null") }
|
||||
map.put("experience_group") { StringValue(species.experienceGroup.name) }
|
||||
map.put("height") { DoubleValue(species.height) }
|
||||
map.put("weight") { DoubleValue(species.weight) }
|
||||
map.put("base_scale") { DoubleValue(species.baseScale) }
|
||||
map.put("hitbox_width") { DoubleValue(species.hitbox.width) }
|
||||
map.put("hitbox_height") { DoubleValue(species.hitbox.height) }
|
||||
map.put("hitbox_fixed") { DoubleValue(species.hitbox.fixed) }
|
||||
map.put("catch_rate") { DoubleValue(species.catchRate) }
|
||||
|
||||
map
|
||||
}
|
||||
)
|
||||
|
||||
fun Holder<Biome>.asBiomeMoLangValue() = asMoLangValue(Registries.BIOME).addFunctions(biomeFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
|
||||
fun Holder<Level>.asWorldMoLangValue() = asMoLangValue(Registries.DIMENSION).addFunctions(worldFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
|
||||
fun Holder<Block>.asBlockMoLangValue() = asMoLangValue(Registries.BLOCK).addFunctions(blockFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
|
||||
@@ -935,6 +1087,22 @@ object MoLangFunctions {
|
||||
return this
|
||||
}
|
||||
|
||||
fun QueryStruct.addPokedexFunctions(pokedexManager: AbstractPokedexManager): QueryStruct {
|
||||
val addedFunctions = pokedexFunctions
|
||||
.flatMap { it.invoke(pokedexManager).entries }
|
||||
.associate { it.key to it.value }
|
||||
functions.putAll(addedFunctions)
|
||||
return this
|
||||
}
|
||||
|
||||
fun QueryStruct.addSpeciesFunctions(species: Species): QueryStruct {
|
||||
val addedFunctions = speciesFunctions
|
||||
.flatMap { it.invoke(species).entries }
|
||||
.associate { it.key to it.value }
|
||||
functions.putAll(addedFunctions)
|
||||
return this
|
||||
}
|
||||
|
||||
fun QueryStruct.addPokemonFunctions(pokemon: Pokemon): QueryStruct {
|
||||
val addedFunctions = pokemonFunctions
|
||||
.flatMap { it.invoke(pokemon).entries }
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ class AnimationActionEffectKeyframe : ConditionalActionEffectKeyframe(), EntityC
|
||||
// Treat them as expressions if possible but otherwise yeah just send them as strings
|
||||
val animation = animation.map {
|
||||
try {
|
||||
it.asExpressionLike().resolveString(context.runtime).takeIf { it != "0.0" } ?: it
|
||||
it.asExpressionLike().resolveString(context.runtime).takeIf { it != "0" } ?: it
|
||||
} catch (e: Exception) {
|
||||
it
|
||||
}
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ class EntityParticlesActionEffectKeyframe : ConditionalActionEffectKeyframe(), E
|
||||
.flatMap { prov -> prov.entities.filter { test(context, it, isUser = prov is UsersProvider) } }
|
||||
|
||||
val effectIdentifier = try {
|
||||
effect?.asExpressionLike()?.resolveString(context.runtime)?.takeIf { it != "0.0" } ?: effect
|
||||
effect?.asExpressionLike()?.resolveString(context.runtime)?.takeIf { it != "0" } ?: effect
|
||||
} catch (e: Exception) {
|
||||
effect
|
||||
}?.asIdentifierDefaultingNamespace() ?: return skip()
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ class EntitySoundActionEffectKeyframe : ConditionalActionEffectKeyframe(), Entit
|
||||
.flatMap { prov -> prov.entities.filter { test(context, it, isUser = prov is UsersProvider) } }
|
||||
|
||||
val soundIdentifier = try {
|
||||
sound?.asExpressionLike()?.resolveString(context.runtime)?.takeIf { it != "0.0" } ?: sound
|
||||
sound?.asExpressionLike()?.resolveString(context.runtime)?.takeIf { it != "0" } ?: sound
|
||||
} catch (e: Exception) {
|
||||
sound
|
||||
}?.asIdentifierDefaultingNamespace() ?: return skip()
|
||||
|
||||
@@ -38,7 +38,8 @@ class NPCClass {
|
||||
var resourceIdentifier: ResourceLocation = cobblemonResource("dummy")
|
||||
var names: MutableList<Component> = mutableListOf()
|
||||
var aspects: MutableSet<String> = mutableSetOf() // These only make sense when applied via presets
|
||||
var hitbox = EntityDimensions.scalable(0.6F, 1.8F)
|
||||
var hitbox = EntityDimensions.scalable(0.6F, 1.8F).withEyeHeight(1.62F)
|
||||
var modelScale: Float = 0.94F
|
||||
var battleConfiguration = NPCBattleConfiguration()
|
||||
var interaction: NPCInteractConfiguration? = null
|
||||
var canDespawn = true
|
||||
@@ -48,6 +49,7 @@ class NPCClass {
|
||||
var party: NPCPartyProvider? = null
|
||||
var skill: Int = 0
|
||||
var autoHealParty: Boolean = true
|
||||
var randomizePartyOrder: Boolean = false
|
||||
var battleTheme: ResourceLocation? = null
|
||||
var ai: MutableList<BrainConfig> = mutableListOf()
|
||||
var isMovable: Boolean = true
|
||||
@@ -60,9 +62,9 @@ class NPCClass {
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeString(resourceIdentifier.toString())
|
||||
buffer.writeCollection(names) { _, v -> buffer.writeText(v) }
|
||||
buffer.writeFloat(this.hitbox.width)
|
||||
buffer.writeFloat(this.hitbox.height)
|
||||
buffer.writeBoolean(this.hitbox.fixed)
|
||||
buffer.writeFloat(hitbox.width)
|
||||
buffer.writeFloat(hitbox.height)
|
||||
buffer.writeBoolean(hitbox.fixed)
|
||||
battleConfiguration.encode(buffer)
|
||||
buffer.writeNullable(interaction) { _, value ->
|
||||
buffer.writeString(value.type)
|
||||
@@ -83,6 +85,7 @@ class NPCClass {
|
||||
}
|
||||
buffer.writeInt(skill)
|
||||
buffer.writeBoolean(autoHealParty)
|
||||
buffer.writeBoolean(randomizePartyOrder)
|
||||
buffer.writeMapK(size = IntSize.U_BYTE, map = variables) { (key, value) ->
|
||||
buffer.writeString(key)
|
||||
buffer.writeString(value.asString())
|
||||
@@ -127,6 +130,7 @@ class NPCClass {
|
||||
}.toMutableList()
|
||||
skill = buffer.readInt()
|
||||
autoHealParty = buffer.readBoolean()
|
||||
randomizePartyOrder = buffer.readBoolean()
|
||||
buffer.readMapK(size = IntSize.U_BYTE, map = variables) {
|
||||
val key = buffer.readString()
|
||||
val value = buffer.readString()
|
||||
|
||||
@@ -30,6 +30,7 @@ class NPCPreset {
|
||||
var ai: List<BrainConfig>? = null
|
||||
var skill: Int? = null
|
||||
var autoHealParty: Boolean? = null
|
||||
var randomizePartyOrder: Boolean? = null
|
||||
var battleTheme: ResourceLocation? = null
|
||||
var isMovable: Boolean? = null
|
||||
var isInvulnerable: Boolean? = null
|
||||
@@ -53,6 +54,7 @@ class NPCPreset {
|
||||
hitbox?.let { npcClass.hitbox = it }
|
||||
skill?.let { npcClass.skill = it }
|
||||
autoHealParty?.let { npcClass.autoHealParty = it }
|
||||
randomizePartyOrder?.let { npcClass.randomizePartyOrder = it }
|
||||
battleTheme?.let { npcClass.battleTheme = it }
|
||||
ai?.let { npcClass.ai.addAll(it) }
|
||||
isMovable?.let { npcClass.isMovable = it }
|
||||
|
||||
@@ -77,6 +77,7 @@ any number of presets and the properties of those presets will be merged into th
|
||||
"canDespawn": false,
|
||||
"skill": 5,
|
||||
"autoHealParty": true,
|
||||
"randomizePartyOrder": true,
|
||||
"party": {
|
||||
"type": "simple",
|
||||
"pokemon": [
|
||||
@@ -282,15 +283,20 @@ is not mentioned in the Pokémon properties will be set to the seed level.
|
||||
The "pool" party type is a way to define a party of Pokémon using a more complicated format that involves some
|
||||
randomization and weighting to different Pokémon options.
|
||||
|
||||
A pool party provider can be static or dynamic depending on the value of `isStatic`. It specifies the minimum
|
||||
and maximum number of Pokémon that can be in the party using `minPokemon` and `maxPokemon`. The `pool` property dictates all of the possible Pokémon, with
|
||||
each being an object with several properties.
|
||||
A pool party provider can be static or dynamic depending on the value of `isStatic`. If `useFixedRandom` is true, the Pokémon it selects
|
||||
from the pool will be constant for a single spawned NPC entity. This is slightly different to a static party because
|
||||
the level of the Pokémon can still be modified dynamically using MoLang values inside each entry's `level` field.
|
||||
|
||||
The pool specifies the minimum and maximum number of Pokémon that can be in the party using `minPokemon` and `maxPokemon`.
|
||||
|
||||
The `pool` property dictates all the possible Pokémon with each being an object with several properties.
|
||||
|
||||
- The `pokemon` property is the Pokémon properties as used in commands and spawn files that will generate the Pokémon.
|
||||
- The `weight` property is a decimal number that represents how likely that Pokémon is to be chosen. If the weight is -1, it will be guaranteed to be selected. Defaults to 1. The larger the value, the more likely it will be chosen.
|
||||
- The `selectableTimes` property is the maximum number of times that the entry can be selected in the party. Defaults to 1.
|
||||
- The `npcLevels` property is a range of seed levels that the Pokémon can be generated at. For example, if the NPC is spawned with seed level 10, and the range is 5-9, the Pokémon will not be selected. The actual level of the Pokémon will be the seed level. Defaults to "1-100".
|
||||
- The `levelVariation` property is the amount of variation the Pokémon's level can have from the NPC seed level. For example, a value of 2 will mean that for an NPC generated with seed level 10, the Pokémon will be generated somewhere between level 8 and 12 inclusive. Defaults to zero.
|
||||
- The `level` property can be used instead of `levelVariation` to force a specific level. This is a MoLang expression.
|
||||
|
||||
For `minPokemon`, `maxPokemon`, `weight`, `selectableTimes`, and `levelVariation`, the values can be a simple number or be full MoLang expressions. At the time
|
||||
of seeding an NPC, the cosmetic variations have already been applied. Therefore, it's possible to make these properties
|
||||
@@ -306,7 +312,8 @@ a single battle challenge and this is a dynamic party, there will also be a `q.p
|
||||
"type": "pool",
|
||||
"minPokemon": "3",
|
||||
"maxPokemon": "6",
|
||||
"isStatic": true,
|
||||
"isStatic": false,
|
||||
"useFixedRandom": true,
|
||||
"pool": [
|
||||
{
|
||||
"pokemon": "weedle",
|
||||
@@ -343,7 +350,9 @@ a single battle challenge and this is a dynamic party, there will also be a `q.p
|
||||
"pokemon": "butterfree",
|
||||
"weight": "5",
|
||||
"npcLevels": "10-15",
|
||||
"selectableTimes": "1"
|
||||
"selectableTimes": "1",
|
||||
"level": "q.player.party.highest_level"
|
||||
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -395,6 +404,11 @@ the NPC and move them using leads.
|
||||
Controls whether the NPC can be hit by projectiles. Disabling this option prevents unwanted
|
||||
interactions, such as players moving the NPC with fishing rods or other projectiles.
|
||||
|
||||
### randomizePartyOrder
|
||||
Whether the NPC's party order will be randomized between battles. When true, this NPC's party (regardless of
|
||||
whether it was dynamic or static) will choose its initial send-out Pokémon randomly instead of always choosing the first
|
||||
Pokémon in the party.
|
||||
|
||||
### ai
|
||||
The AI property is an array of brain configurations. This is used to configure the behaviours of the NPC. See
|
||||
the documentation for brain configurations at [AI Configuration](../ai/config/README.md).
|
||||
+19
-11
@@ -26,6 +26,7 @@ import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonPrimitive
|
||||
import kotlin.random.Random
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
/**
|
||||
@@ -50,6 +51,7 @@ class PoolPartyProvider : NPCPartyProvider {
|
||||
override val type = TYPE
|
||||
|
||||
override var isStatic: Boolean = false
|
||||
var useFixedRandom: Boolean = false
|
||||
var minPokemon: Expression = "1".asExpression()
|
||||
var maxPokemon: Expression = "6".asExpression()
|
||||
var pool = mutableListOf<DynamicPokemon>()
|
||||
@@ -63,6 +65,7 @@ class PoolPartyProvider : NPCPartyProvider {
|
||||
return@map DynamicPokemon(
|
||||
PokemonProperties.parse(it.asString),
|
||||
"0".asExpression(),
|
||||
null,
|
||||
1..100,
|
||||
"1".asExpression(),
|
||||
"1".asExpression()
|
||||
@@ -71,19 +74,22 @@ class PoolPartyProvider : NPCPartyProvider {
|
||||
|
||||
it as JsonObject
|
||||
DynamicPokemon(
|
||||
PokemonProperties.parse(it.getAsJsonPrimitive("pokemon").asString),
|
||||
it.getAsJsonPrimitive("levelVariation")?.asString?.asExpression() ?: "0".asExpression(),
|
||||
it.getAsJsonPrimitive("npcLevels")?.asString?.split("-")?.let { it[0].toInt()..it[1].toInt() } ?: 1..100,
|
||||
it.getAsJsonPrimitive("selectableTimes")?.asString?.asExpression() ?: "1".asExpression(),
|
||||
it.getAsJsonPrimitive("weight")?.asString?.asExpression() ?: "1".asExpression()
|
||||
PokemonProperties.parse(it.get("pokemon").asString),
|
||||
it.get("levelVariation")?.asString?.asExpression() ?: "0".asExpression(),
|
||||
it.get("level")?.asString?.asExpression(),
|
||||
it.get("npcLevels")?.asString?.split("-")?.let { it[0].toInt()..it[1].toInt() } ?: 1..100,
|
||||
it.get("selectableTimes")?.asString?.asExpression() ?: "1".asExpression(),
|
||||
it.get("weight")?.asString?.asExpression() ?: "1".asExpression()
|
||||
)
|
||||
}.toMutableList()
|
||||
isStatic = json.getAsJsonPrimitive("isStatic").asBoolean
|
||||
isStatic = json.get("isStatic").asBoolean
|
||||
json.get("useFixedRandom")?.asBoolean?.let { useFixedRandom = it }
|
||||
}
|
||||
|
||||
class DynamicPokemon(
|
||||
val pokemon: PokemonProperties,
|
||||
val levelVariation: Expression,
|
||||
val level: Expression? = null,
|
||||
val npcLevels: IntRange,
|
||||
val selectableTimes: Expression,
|
||||
val weight: Expression = "1".asExpression()
|
||||
@@ -99,6 +105,7 @@ class PoolPartyProvider : NPCPartyProvider {
|
||||
|
||||
fun formulateParty(npc: NPCEntity, level: Int, players: List<ServerPlayer>, party: NPCPartyStore) {
|
||||
val runtime = MoLangRuntime().setup().withQueryValue("npc", npc.struct)
|
||||
val random = if (useFixedRandom) Random(npc.uuid.hashCode()) else Random.Default
|
||||
runtime.withQueryValue("level", DoubleValue(level))
|
||||
runtime.withQueryValue("players", players.asArrayValue { it.asMoLangValue() })
|
||||
if (players.size == 1) {
|
||||
@@ -107,14 +114,14 @@ class PoolPartyProvider : NPCPartyProvider {
|
||||
}
|
||||
val minPokemon = runtime.resolveInt(this.minPokemon)
|
||||
val maxPokemon = runtime.resolveInt(this.maxPokemon)
|
||||
var desiredPokemonCount = (minPokemon..maxPokemon).random()
|
||||
var desiredPokemonCount = (minPokemon..maxPokemon).random(random)
|
||||
|
||||
val workingPool = pool.filter { level in it.npcLevels && runtime.resolveInt(it.selectableTimes) > 0 }.toMutableList()
|
||||
val useCounts = mutableMapOf<DynamicPokemon, Int>()
|
||||
|
||||
while (desiredPokemonCount > 0 && workingPool.any { it.hasWeight(runtime) }) {
|
||||
val selected = workingPool.filter { it.getWeight(runtime) == -1F }.randomOrNull()
|
||||
?: workingPool.weightedSelection { it.getWeight(runtime) }
|
||||
val selected = workingPool.filter { it.getWeight(runtime) == -1F }.randomOrNull(random)
|
||||
?: workingPool.weightedSelection(random = random) { it.getWeight(runtime) }
|
||||
?: break
|
||||
useCounts[selected] = useCounts.getOrDefault(selected, 0) + 1
|
||||
val allowedSelections = runtime.resolveInt(selected.selectableTimes)
|
||||
@@ -124,9 +131,10 @@ class PoolPartyProvider : NPCPartyProvider {
|
||||
desiredPokemonCount--
|
||||
|
||||
// If the Pokémon's props specifies a level then use that, otherwise choose a random level within the range
|
||||
val levelVariation = (0..runtime.resolveInt(selected.levelVariation)).random()
|
||||
val levelVariation = (0..runtime.resolveInt(selected.levelVariation)).random(random)
|
||||
val randomLevel = level + levelVariation
|
||||
val instance = selected.pokemon.copy().also { it.level = it.level ?: randomLevel }.create()
|
||||
val dictatedLevel = selected.level?.let { runtime.resolveInt(it) }
|
||||
val instance = selected.pokemon.copy().also { it.level = it.level ?: dictatedLevel ?: randomLevel }.create()
|
||||
party.add(instance)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -32,5 +32,5 @@ class WeightedNPCVariationProvider : NPCVariationProvider {
|
||||
override val aspects: Set<String>
|
||||
get() = options.flatMap(WeightedAspect::aspects).toSet()
|
||||
|
||||
override fun provideAspects(npcEntity: NPCEntity) = options.weightedSelection(WeightedAspect::weight)?.aspects ?: emptySet()
|
||||
override fun provideAspects(npcEntity: NPCEntity) = options.weightedSelection { it.weight }?.aspects ?: emptySet()
|
||||
}
|
||||
@@ -82,6 +82,8 @@ object CobblemonPermissions {
|
||||
|
||||
val ABANDON_MULTITEAM = this.create("${COMMAND_PREFIX}abandonmultiteam", PermissionLevel.NONE)
|
||||
|
||||
val RUN_MOLANG_SCRIPT = this.create("${COMMAND_PREFIX}runmolangscript", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
fun all(): Iterable<Permission> = this.permissions
|
||||
|
||||
private fun create(node: String, level: PermissionLevel): Permission {
|
||||
|
||||
+5
-7
@@ -8,13 +8,13 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.pokedex
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addPokedexFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addStandardFunctions
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexForm
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
abstract class AbstractPokedexManager {
|
||||
@@ -23,11 +23,9 @@ abstract class AbstractPokedexManager {
|
||||
private val globalCalculatedValues = mutableMapOf<GlobalPokedexValueCalculator<*>, Any>()
|
||||
|
||||
@Transient
|
||||
val struct = QueryStruct(hashMapOf()).addStandardFunctions()
|
||||
.addFunction("get_species_record") { params ->
|
||||
val speciesId = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
speciesRecords[speciesId]?.struct ?: QueryStruct(hashMapOf())
|
||||
}
|
||||
val struct = ObjectValue<AbstractPokedexManager>(this)
|
||||
.addStandardFunctions()
|
||||
.addPokedexFunctions(this)
|
||||
|
||||
fun deleteSpeciesRecord(speciesId: ResourceLocation) {
|
||||
speciesRecords.remove(speciesId)
|
||||
|
||||
@@ -11,6 +11,8 @@ package com.cobblemon.mod.common.api.pokedex
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.struct.VariableStruct
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.pokemon.PokedexDataChangedEvent
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
@@ -19,6 +21,7 @@ import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeEnumConstant
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import com.google.common.collect.Sets
|
||||
import com.mojang.datafixers.util.Either
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.ListCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
@@ -123,6 +126,10 @@ class FormDexRecord {
|
||||
}
|
||||
speciesDexRecord.addInformation(pokemon, knowledge)
|
||||
speciesDexRecord.onFormRecordUpdated(this)
|
||||
|
||||
(speciesDexRecord.pokedexManager as? PokedexManager)?.let { pokedexManager ->
|
||||
CobblemonEvents.POKEDEX_DATA_CHANGED.post(PokedexDataChangedEvent(Either.right(pokemon), knowledge, pokedexManager.uuid, this))
|
||||
}
|
||||
}
|
||||
|
||||
private fun addInformation(pokedexEntityData: PokedexEntityData, knowledge: PokedexEntryProgress) {
|
||||
@@ -133,6 +140,10 @@ class FormDexRecord {
|
||||
}
|
||||
speciesDexRecord.addInformation(pokedexEntityData, knowledge)
|
||||
speciesDexRecord.onFormRecordUpdated(this)
|
||||
|
||||
(speciesDexRecord.pokedexManager as? PokedexManager)?.let { pokedexManager ->
|
||||
CobblemonEvents.POKEDEX_DATA_CHANGED.post(PokedexDataChangedEvent(Either.left(pokedexEntityData), knowledge, pokedexManager.uuid, this))
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns whether the given [Pokemon] and [knowledge] would add new information to the Pokédex.*/
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.cobblemon.mod.common.api.moves.MoveTemplate
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.requirement.EvolutionRequirement
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.item.PokeBallItem
|
||||
import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimationPacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
@@ -162,7 +163,7 @@ interface Evolution : EvolutionLike {
|
||||
evolutionMethod(pokemon)
|
||||
pokemon.getOwnerPlayer()?.sendSystemMessage(lang("ui.evolve.into", preEvoName, pokemon.species.translatedName))
|
||||
} else {
|
||||
pokemonEntity.busyLocks.add("evolving")
|
||||
pokemonEntity.entityData.set(PokemonEntity.EVOLUTION_STARTED, true)
|
||||
pokemonEntity.navigation.stop()
|
||||
pokemonEntity.after(1F) {
|
||||
evolutionAnimation(pokemonEntity)
|
||||
@@ -172,7 +173,7 @@ interface Evolution : EvolutionLike {
|
||||
}
|
||||
pokemonEntity.after( seconds = 12F ) {
|
||||
cryAnimation(pokemonEntity)
|
||||
pokemonEntity.busyLocks.remove("evolving")
|
||||
pokemonEntity.entityData.set(PokemonEntity.EVOLUTION_STARTED, false)
|
||||
pokemon.getOwnerPlayer()?.sendSystemMessage(lang("ui.evolve.into", preEvoName, pokemon.species.translatedName))
|
||||
}
|
||||
}
|
||||
|
||||
+38
-2
@@ -12,6 +12,8 @@ import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
|
||||
import com.cobblemon.mod.common.api.spawning.context.FishingSpawningContext
|
||||
import com.cobblemon.mod.common.util.itemRegistry
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper
|
||||
import net.minecraft.world.item.enchantment.Enchantments
|
||||
import net.minecraft.world.level.block.Block
|
||||
|
||||
/**
|
||||
@@ -33,9 +35,43 @@ class FishingSpawningCondition: SpawningCondition<FishingSpawningContext>() {
|
||||
return false
|
||||
} else if (neededNearbyBlocks != null && neededNearbyBlocks!!.none { cond -> ctx.nearbyBlockTypes.any { cond.fits(it, ctx.blockRegistry) } }) {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
|
||||
if (minLureLevel != null) { // check for the lureLevel of the rod
|
||||
val pokerodStack = ctx.rodStack
|
||||
val lureLevel = EnchantmentHelper.getItemEnchantmentLevel(
|
||||
ctx.enchantmentRegistry.getHolder(Enchantments.LURE).get(),
|
||||
pokerodStack
|
||||
)
|
||||
if (lureLevel < minLureLevel!!) {
|
||||
return false
|
||||
} else if (maxLureLevel != null && lureLevel > maxLureLevel!!) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if (bait != null) { // check for the bait on the bobber
|
||||
val pokerodBait = ctx.rodBait?.item
|
||||
if (pokerodBait != bait) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if (rodType != null) { // check for the type of pokerod being used
|
||||
val pokerodItem = ctx.rodItem
|
||||
if (pokerodItem?.pokeRodId != rodType) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/*if (ctx is FishingSpawningContext && (ctx as FishingSpawningContext).rodItem != null) { // check if the bait attracts certain EV yields
|
||||
val pokerodItem = (ctx as FishingSpawningContext).rodItem
|
||||
|
||||
// todo check if the EV yield of the berry matches the bait EV attract maybe?
|
||||
|
||||
if (// todo if bait EV yield != EV yield of pokemon consideration //Registries.ITEM.getId(pokerodItem?.bait?.item).path == )
|
||||
return false
|
||||
}*/
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
-27
@@ -116,24 +116,6 @@ abstract class SpawningCondition<T : SpawningContext> {
|
||||
}
|
||||
) {
|
||||
return false
|
||||
} else if (minLureLevel != null && ctx is FishingSpawningContext) { // check for the lureLevel of the rod
|
||||
val pokerodStack = (ctx as FishingSpawningContext).rodStack
|
||||
val lureLevel = EnchantmentHelper.getItemEnchantmentLevel(ctx.enchantmentRegistry.getHolder(Enchantments.LURE).get(), pokerodStack)
|
||||
if (lureLevel < minLureLevel!!) {
|
||||
return false
|
||||
} else if (maxLureLevel != null && lureLevel > maxLureLevel!!) {
|
||||
return false
|
||||
}
|
||||
} else if (bait != null && ctx is FishingSpawningContext) { // check for the bait on the bobber
|
||||
val pokerodBait = (ctx as FishingSpawningContext).rodBait?.item
|
||||
if (pokerodBait != bait) {
|
||||
return false
|
||||
}
|
||||
} else if (rodType != null && ctx is FishingSpawningContext) { // check for the type of pokerod being used
|
||||
val pokerodItem = (ctx as FishingSpawningContext).rodItem
|
||||
if (pokerodItem?.pokeRodId != rodType) {
|
||||
return false
|
||||
}
|
||||
} else if (isSlimeChunk != null && isSlimeChunk != false) {
|
||||
val isSlimeChunk = WorldgenRandom.seedSlimeChunk(ctx.position.x shr 4, ctx.position.z shr 4, ctx.world.seed, 987234911L).nextInt(10) == 0
|
||||
|
||||
@@ -152,15 +134,6 @@ abstract class SpawningCondition<T : SpawningContext> {
|
||||
return random.nextInt(10) == 0*/
|
||||
}
|
||||
|
||||
/*else if (ctx is FishingSpawningContext && (ctx as FishingSpawningContext).rodItem != null) { // check if the bait attracts certain EV yields
|
||||
val pokerodItem = (ctx as FishingSpawningContext).rodItem
|
||||
|
||||
// todo check if the EV yield of the berry matches the bait EV attract maybe?
|
||||
|
||||
if (// todo if bait EV yield != EV yield of pokemon consideration //Registries.ITEM.getId(pokerodItem?.bait?.item).path == )
|
||||
return false
|
||||
}*/
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -16,7 +16,6 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.feature.SeasonFeatureHandler
|
||||
import com.cobblemon.mod.common.util.weightedSelection
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.player.Player
|
||||
|
||||
/**
|
||||
* A [SpawnAction] that will spawn a single [PokemonEntity].
|
||||
|
||||
+5
@@ -33,6 +33,11 @@ open class PlayerLevelRangeInfluence(
|
||||
val noPokemonRange: IntRange = 1 .. config.minimumLevelRangeMax,
|
||||
val recalculationMillis: Long = 5000L
|
||||
) : SpawningInfluence {
|
||||
companion object {
|
||||
/** The internally tuned variation for player level range influences */
|
||||
val TYPICAL_VARIATION = 5
|
||||
}
|
||||
|
||||
val uuid = player.uuid
|
||||
var lastCalculatedTime: Long = 0
|
||||
var previousRange: IntRange = noPokemonRange
|
||||
|
||||
+2
-1
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.api.spawning.CobblemonSpawnRules
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnerManager
|
||||
import com.cobblemon.mod.common.api.spawning.detail.SpawnPool
|
||||
import com.cobblemon.mod.common.api.spawning.influence.PlayerLevelRangeInfluence
|
||||
import com.cobblemon.mod.common.api.spawning.influence.PlayerLevelRangeInfluence.Companion.TYPICAL_VARIATION
|
||||
import com.cobblemon.mod.common.api.spawning.influence.RestrictedSpawnBlocksInfluence
|
||||
import com.cobblemon.mod.common.api.spawning.influence.SpawningInfluence
|
||||
import com.cobblemon.mod.common.api.spawning.rules.SpawnRule
|
||||
@@ -42,7 +43,7 @@ object PlayerSpawnerFactory {
|
||||
var influenceBuilders = mutableListOf<(player: ServerPlayer) -> SpawningInfluence?>({
|
||||
PlayerLevelRangeInfluence(
|
||||
it,
|
||||
variation = 5
|
||||
variation = TYPICAL_VARIATION
|
||||
)
|
||||
}, { RestrictedSpawnBlocksInfluence() })
|
||||
|
||||
|
||||
+2
-1
@@ -30,8 +30,9 @@ abstract class TriggerSpawner<T : SpawnCause>(override val name: String, var spa
|
||||
private var selector: SpawningSelector = FlatContextWeightedSelector()
|
||||
override val influences = mutableListOf<SpawningInfluence>()
|
||||
|
||||
open fun run(cause: T, world: ServerLevel, pos: BlockPos): CompletableFuture<*>? {
|
||||
open fun run(cause: T, world: ServerLevel, pos: BlockPos, influences: List<SpawningInfluence> = emptyList()): CompletableFuture<*>? {
|
||||
val context = parseContext(cause, world, pos) ?: return null
|
||||
context.influences.addAll(influences)
|
||||
selector.select(this, listOf(context))?.let { (_, spawn) ->
|
||||
val action = spawn.doSpawn(context)
|
||||
action.complete()
|
||||
|
||||
@@ -269,7 +269,7 @@ open class PartyStore(override val uuid: UUID) : PokemonStore<PartyPosition>() {
|
||||
BattlePokemon.playerOwned(it)
|
||||
}.also { if (healPokemon) it.effectedPokemon.heal() }
|
||||
}.toMutableList()
|
||||
if(leadingPokemon != null) {
|
||||
if (leadingPokemon != null) {
|
||||
Collections.rotate(result, result.size - this.indexOfFirst { it.uuid == leadingPokemon })
|
||||
}
|
||||
return result
|
||||
|
||||
+23
-11
@@ -102,20 +102,32 @@ open class PlayerPartyStore(
|
||||
for (pokemon in this) {
|
||||
// Awake from fainted
|
||||
if (pokemon.isFainted()) {
|
||||
pokemon.faintedTimer -= 1
|
||||
if (pokemon.faintedTimer <= -1) {
|
||||
val php = ceil(pokemon.maxHealth * Cobblemon.config.faintAwakenHealthPercent)
|
||||
pokemon.currentHealth = php.toInt()
|
||||
player.sendSystemMessage(Component.translatable("cobblemon.party.faintRecover", pokemon.getDisplayName()))
|
||||
//Skip awaken logic check if config value is 0
|
||||
if (Cobblemon.config.faintAwakenHealthPercent > 0) {
|
||||
pokemon.faintedTimer -= 1
|
||||
if (pokemon.faintedTimer <= -1) {
|
||||
val php = ceil(pokemon.maxHealth * Cobblemon.config.faintAwakenHealthPercent)
|
||||
pokemon.currentHealth = php.toInt()
|
||||
player.sendSystemMessage(
|
||||
Component.translatable(
|
||||
"cobblemon.party.faintRecover",
|
||||
pokemon.getDisplayName()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Passive healing while less than full health
|
||||
else if (pokemon.currentHealth < pokemon.maxHealth) {
|
||||
pokemon.healTimer--
|
||||
if (pokemon.healTimer <= -1) {
|
||||
pokemon.healTimer = Cobblemon.config.healTimer
|
||||
val healAmount = 1.0.coerceAtLeast(pokemon.maxHealth.toDouble() * Cobblemon.config.healPercent)
|
||||
pokemon.currentHealth = pokemon.currentHealth + round(healAmount).toInt()
|
||||
//Skip passive healing logic check if config value is 0
|
||||
if (Cobblemon.config.healPercent > 0) {
|
||||
pokemon.healTimer--
|
||||
if (pokemon.healTimer <= -1) {
|
||||
pokemon.healTimer = Cobblemon.config.healTimer
|
||||
val healAmount =
|
||||
1.0.coerceAtLeast(pokemon.maxHealth.toDouble() * Cobblemon.config.healPercent)
|
||||
pokemon.currentHealth = pokemon.currentHealth + round(healAmount).toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,4 +216,4 @@ open class PlayerPartyStore(
|
||||
super.set(position, pokemon)
|
||||
pokemon.getOwnerPlayer()?.let { CobblemonCriteria.PARTY_CHECK.trigger(it, this) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,6 +100,10 @@ object BattleBuilder {
|
||||
)
|
||||
}
|
||||
|
||||
if (actor.pokemonList.any { it.entity?.isBusy == true }) {
|
||||
errors.participantErrors[actor] += BattleStartError.targetIsBusy(player.displayName ?: player.name)
|
||||
}
|
||||
|
||||
if (BattleRegistry.getBattleByParticipatingPlayer(player) != null) {
|
||||
errors.participantErrors[actor] += BattleStartError.alreadyInBattle(player)
|
||||
}
|
||||
@@ -109,16 +113,13 @@ object BattleBuilder {
|
||||
player2Actor.battleTheme = player1.getBattleTheme()
|
||||
|
||||
return if (errors.isEmpty) {
|
||||
var result: BattleStartResult = errors
|
||||
BattleRegistry.startBattle(
|
||||
battleFormat = battleFormat,
|
||||
side1 = BattleSide(player1Actor),
|
||||
side2 = BattleSide(player2Actor)
|
||||
).ifSuccessful {
|
||||
it.battlePartyStores.addAll(battlePartyStores)
|
||||
result = SuccessfulBattleStart(it)
|
||||
}
|
||||
result
|
||||
} else {
|
||||
errors
|
||||
}
|
||||
@@ -178,6 +179,10 @@ object BattleBuilder {
|
||||
)
|
||||
}
|
||||
|
||||
if (actor.pokemonList.any { it.entity?.isBusy == true }) {
|
||||
errors.participantErrors[actor] += BattleStartError.targetIsBusy(player.displayName ?: player.name)
|
||||
}
|
||||
|
||||
if (BattleRegistry.getBattleByParticipatingPlayer(player) != null) {
|
||||
errors.participantErrors[actor] += BattleStartError.alreadyInBattle(player)
|
||||
}
|
||||
@@ -206,13 +211,12 @@ object BattleBuilder {
|
||||
|
||||
return if (errors.isEmpty) {
|
||||
BattleRegistry.startBattle(
|
||||
battleFormat = battleFormat,
|
||||
side1 = BattleSide(playerActors[0], playerActors[1]),
|
||||
side2 = BattleSide(playerActors[2], playerActors[3])
|
||||
battleFormat = battleFormat,
|
||||
side1 = BattleSide(playerActors[0], playerActors[1]),
|
||||
side2 = BattleSide(playerActors[2], playerActors[3])
|
||||
).ifSuccessful {
|
||||
it.battlePartyStores.addAll(battlePartyStores)
|
||||
}
|
||||
errors
|
||||
} else {
|
||||
errors
|
||||
}
|
||||
@@ -248,7 +252,7 @@ object BattleBuilder {
|
||||
val wildActor = PokemonBattleActor(pokemonEntity.pokemon.uuid, BattlePokemon(pokemonEntity.pokemon), fleeDistance)
|
||||
val errors = ErroredBattleStart()
|
||||
|
||||
if(playerTeam.isNotEmpty() && playerTeam[0].health <= 0){
|
||||
if (playerTeam.isNotEmpty() && playerTeam[0].health <= 0){
|
||||
errors.participantErrors[playerActor] += BattleStartError.insufficientPokemon(
|
||||
actorEntity = player,
|
||||
requiredCount = battleFormat.battleType.slotsPerActor,
|
||||
@@ -264,6 +268,10 @@ object BattleBuilder {
|
||||
)
|
||||
}
|
||||
|
||||
if (playerActor.pokemonList.any { it.entity?.isBusy == true }) {
|
||||
errors.participantErrors[playerActor] += BattleStartError.targetIsBusy(player.displayName ?: player.name)
|
||||
}
|
||||
|
||||
if (BattleRegistry.getBattleByParticipatingPlayer(player) != null) {
|
||||
errors.participantErrors[playerActor] += BattleStartError.alreadyInBattle(playerActor)
|
||||
}
|
||||
@@ -275,7 +283,6 @@ object BattleBuilder {
|
||||
playerActor.battleTheme = pokemonEntity.getBattleTheme()
|
||||
|
||||
return if (errors.isEmpty) {
|
||||
var result: BattleStartResult = errors
|
||||
BattleRegistry.startBattle(
|
||||
battleFormat = battleFormat,
|
||||
side1 = BattleSide(playerActor),
|
||||
@@ -284,9 +291,7 @@ object BattleBuilder {
|
||||
if (!cloneParties) {
|
||||
pokemonEntity.battleId = it.battleId
|
||||
}
|
||||
result = SuccessfulBattleStart(it)
|
||||
}
|
||||
result
|
||||
} else {
|
||||
errors
|
||||
}
|
||||
@@ -348,19 +353,20 @@ object BattleBuilder {
|
||||
)
|
||||
}
|
||||
|
||||
if (playerActor.pokemonList.any { it.entity?.isBusy == true }) {
|
||||
errors.participantErrors[playerActor] += BattleStartError.targetIsBusy(player.displayName ?: player.name)
|
||||
}
|
||||
|
||||
playerActor.battleTheme = npcEntity.getBattleTheme()
|
||||
|
||||
return if (errors.isEmpty) {
|
||||
var result: BattleStartResult = errors
|
||||
BattleRegistry.startBattle(
|
||||
battleFormat = battleFormat,
|
||||
side1 = BattleSide(playerActor),
|
||||
side2 = BattleSide(npcActor)
|
||||
).ifSuccessful { battle ->
|
||||
npcEntity.entityData.update(NPCEntity.BATTLE_IDS) { it + battle.battleId }
|
||||
result = SuccessfulBattleStart(battle)
|
||||
}
|
||||
result
|
||||
} else {
|
||||
errors
|
||||
}
|
||||
@@ -394,7 +400,7 @@ interface BattleStartError {
|
||||
fun alreadyInBattle(pokemonEntity: PokemonEntity) = AlreadyInBattleError(pokemonEntity.uuid, pokemonEntity.effectiveName())
|
||||
fun alreadyInBattle(actor: BattleActor) = AlreadyInBattleError(actor.uuid, actor.getName())
|
||||
fun noParty(npcEntity: NPCEntity) = NoPartyError(npcEntity)
|
||||
fun targetIsBusy(targetName: MutableComponent) = BusyError(targetName)
|
||||
fun targetIsBusy(targetName: Component) = BusyError(targetName)
|
||||
fun insufficientPokemon(
|
||||
actorEntity: Entity,
|
||||
requiredCount: Int,
|
||||
@@ -474,7 +480,7 @@ class AlreadyInBattleError(
|
||||
}
|
||||
}
|
||||
class BusyError(
|
||||
val targetName: MutableComponent
|
||||
val targetName: Component
|
||||
): BattleStartError {
|
||||
override fun getMessageFor(entity: Entity) = battleLang("errors.busy", targetName)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.battles
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleStartedPostEvent
|
||||
@@ -178,19 +179,35 @@ object BattleRegistry {
|
||||
ShowdownService.service.startBattle(battle, messages.toTypedArray())
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new [PokemonBattle] and launches the Showdown service.
|
||||
*
|
||||
* @param battleFormat The format to use for the battle.
|
||||
* @param side1 The first side for the battle.
|
||||
* @param side2 The second side for the battle.
|
||||
* @param canPreempt Whether the battle can be blocked by subscribers to [CobblemonEvents.BATTLE_STARTED_PRE].
|
||||
*
|
||||
* NOTE: this does NOT validate the [battleFormat] or sides before launching Showdown.
|
||||
* This creates the battle and hands it off to Showdown - YOU WILL GET ISSUES IF THE BATTLE IS INVALID!
|
||||
* See [BattleBuilder] functions for how the various types of battles are built and validated.
|
||||
*/
|
||||
fun startBattle(
|
||||
battleFormat: BattleFormat,
|
||||
side1: BattleSide,
|
||||
side2: BattleSide,
|
||||
silent: Boolean = false
|
||||
canPreempt: Boolean = true
|
||||
): BattleStartResult {
|
||||
val battle = PokemonBattle(battleFormat, side1, side2)
|
||||
if (silent) return SuccessfulBattleStart(battle)
|
||||
val start: () -> Unit = {
|
||||
battleMap[battle.battleId] = battle
|
||||
startShowdown(battle)
|
||||
}
|
||||
|
||||
if (!canPreempt) start().also { return SuccessfulBattleStart(battle) }
|
||||
|
||||
val preBattleEvent = BattleStartedPreEvent(battle)
|
||||
CobblemonEvents.BATTLE_STARTED_PRE.postThen(preBattleEvent) {
|
||||
battleMap[battle.battleId] = battle
|
||||
startShowdown(battle)
|
||||
start()
|
||||
CobblemonEvents.BATTLE_STARTED_POST.post(BattleStartedPostEvent(battle))
|
||||
return SuccessfulBattleStart(battle)
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ object ShowdownInterpreter {
|
||||
updateInstructionParser["-copyboost"] = { _, _, message, _ -> CopyBoostInstruction(message) }
|
||||
updateInstructionParser["-crit"] = { _, instructionSet, message, _ -> CritInstruction(message, instructionSet) }
|
||||
updateInstructionParser["-curestatus"] = { _, _, message, _ -> CureStatusInstruction(message) }
|
||||
updateInstructionParser["detailschange"] = { _, _, message, _ -> DetailsChangeInstruction(message) }
|
||||
updateInstructionParser["detailschange"] = { _, _, message, _ -> FormeChangeInstruction(message) }
|
||||
updateInstructionParser["-endability"] = { _, _, message, _ -> EndAbilityInstruction(message) }
|
||||
updateInstructionParser["-end"] = { _, _, message, _ -> EndInstruction(message) }
|
||||
updateInstructionParser["-enditem"] = { _, _, message, _ -> EndItemInstruction(message) }
|
||||
@@ -78,6 +78,7 @@ object ShowdownInterpreter {
|
||||
updateInstructionParser["-fieldactivate"] = { _, _, message, _ -> FieldActivateInstruction(message) }
|
||||
updateInstructionParser["-fieldend"] = { _, _, message, _ -> FieldEndInstruction(message) }
|
||||
updateInstructionParser["-fieldstart"] = { _, _, message, _ -> FieldStartInstruction(message) }
|
||||
updateInstructionParser["-formechange"] = { _, _, message, _ -> FormeChangeInstruction(message) }
|
||||
updateInstructionParser["-hitcount"] = { _, _, message, _ -> HitCountInstruction(message) }
|
||||
updateInstructionParser["-immune"] = { _, _, message, _ -> ImmuneInstruction(message) }
|
||||
updateInstructionParser["-invertboost"] = { _, _, message, _ -> InvertBoostInstruction(message) }
|
||||
|
||||
-34
@@ -1,34 +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.battles.interpreter.instructions
|
||||
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleMessage
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
|
||||
/**
|
||||
* Format: |detailschange|POKEMON|DETAILS|HP STATUS
|
||||
*
|
||||
* POKEMON has changed formes permanently (i.e. Mega Evolution) to DETAILS.
|
||||
* @author Segfault Guy
|
||||
* @since September 10th, 2023
|
||||
*/
|
||||
class DetailsChangeInstruction(val message: BattleMessage): InterpreterInstruction {
|
||||
|
||||
override fun invoke(battle: PokemonBattle) {
|
||||
val battlePokemon = message.battlePokemon(0, battle) ?: return
|
||||
val formName = message.argumentAt(1)?.split(',')?.get(0)?.substringAfter('-')?.lowercase() ?: return
|
||||
battle.dispatchWaiting {
|
||||
val pokemonName = battlePokemon.getName()
|
||||
battle.broadcastChatMessage(battleLang("detailschange.$formName", pokemonName))
|
||||
battle.majorBattleActions[battlePokemon.uuid] = message
|
||||
}
|
||||
}
|
||||
}
|
||||
+48
@@ -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.battles.interpreter.instructions
|
||||
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleMessage
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.battles.ShowdownInterpreter
|
||||
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
|
||||
/**
|
||||
* Format: |-formechange|POKEMON|SPECIES|HP STATUS or |detailschange|POKEMON|DETAILS|HP STATUS
|
||||
*
|
||||
* POKEMON has temporarily (-formechange) or permanently (detailschange) changed form to SPECIES/DETAILS.
|
||||
* @author Segfault Guy
|
||||
* @since December 9th, 2024
|
||||
*/
|
||||
class FormeChangeInstruction(val message: BattleMessage): InterpreterInstruction {
|
||||
|
||||
override fun invoke(battle: PokemonBattle) {
|
||||
val battlePokemon = message.battlePokemon(0, battle) ?: return
|
||||
val details = message.argumentAt(1)?.split(',')?.get(0)?.lowercase() ?: return
|
||||
val speciesName = details.substringBefore('-')
|
||||
val formName = details.substringAfterLast('-').ifBlank { speciesName }
|
||||
val typeKey = if (message.id == "detailschange") "permanent" else "temporary"
|
||||
|
||||
ShowdownInterpreter.broadcastOptionalAbility(battle, message.effect(), battlePokemon)
|
||||
|
||||
battle.dispatchWaiting {
|
||||
battle.minorBattleActions[battlePokemon.uuid] = message
|
||||
|
||||
val pokemonName = battlePokemon.getName()
|
||||
val lang = when(formName) {
|
||||
"busted", "hero", "complete" -> return@dispatchWaiting
|
||||
"school", "wishiwashi", "meteor", "minior" -> battleLang("formechange.$formName", pokemonName)
|
||||
speciesName -> battleLang("formechange.default.temporary.end", pokemonName)
|
||||
else -> battleLang("formechange.default.$typeKey", pokemonName, formName)
|
||||
}
|
||||
battle.broadcastChatMessage(lang)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,6 @@ class PCBlock(properties: Properties): BaseEntityBlock(properties), SimpleWaterl
|
||||
val CODEC = simpleCodec(::PCBlock)
|
||||
val PART = EnumProperty.create("part", PCPart::class.java)
|
||||
val ON = BooleanProperty.create("on")
|
||||
val WATERLOGGED = BooleanProperty.create("waterlogged")
|
||||
val NATURAL = BooleanProperty.create("natural")
|
||||
|
||||
private val NORTH_AABB_TOP = Shapes.or(
|
||||
@@ -235,7 +234,7 @@ class PCBlock(properties: Properties): BaseEntityBlock(properties), SimpleWaterl
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun isPathfindable(
|
||||
blockState: BlockState?,
|
||||
blockState: BlockState,
|
||||
pathComputationType: PathComputationType
|
||||
): Boolean = false
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ class GildedChestBlock(settings: Properties, val type: Type = Type.RED) : BaseEn
|
||||
// The yaw based on the block's facing direction
|
||||
val yaw = facingToYaw[state.getValue(HorizontalDirectionalBlock.FACING)] ?: 0.0F
|
||||
|
||||
entity.entityData.set(PokemonEntity.SPAWN_DIRECTION, facingToYaw[state.getValue(HorizontalDirectionalBlock.FACING)])
|
||||
entity.entityData.set(PokemonEntity.SPAWN_DIRECTION, yaw)
|
||||
val offsetDir = state.getValue(HorizontalDirectionalBlock.FACING)
|
||||
val vec = pos.toVec3d().add(offsetDir.stepX * 0.1 + 0.5, 0.0, offsetDir.stepZ * 0.1 + 0.5)
|
||||
entity.moveTo(vec.x, vec.y, vec.z, yaw, entity.xRot)
|
||||
|
||||
@@ -17,9 +17,9 @@ import net.minecraft.world.item.alchemy.Potions
|
||||
|
||||
object BrewingRecipes {
|
||||
|
||||
val recipes: List<Triple<CobblemonIngredient, CobblemonIngredient, Item>> by lazy {
|
||||
val recipes: List<Triple<CobblemonIngredient, Item, Item>> by lazy {
|
||||
listOf(
|
||||
Triple(CobblemonPotionIngredient(Potions.WATER), CobblemonItemIngredient(CobblemonItems.MEDICINAL_LEEK), CobblemonItems.MEDICINAL_BREW),
|
||||
Triple(CobblemonPotionIngredient(Potions.WATER), CobblemonItems.MEDICINAL_LEEK, CobblemonItems.MEDICINAL_BREW),
|
||||
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.LEPPA_BERRY, CobblemonItems.ETHER),
|
||||
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.HOPO_BERRY, CobblemonItems.ELIXIR),
|
||||
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.ORAN_BERRY, CobblemonItems.POTION),
|
||||
@@ -50,8 +50,8 @@ object BrewingRecipes {
|
||||
)
|
||||
}
|
||||
|
||||
private fun convert(input: Item, ingredient: Item, output: Item): Triple<CobblemonIngredient, CobblemonIngredient, Item> {
|
||||
return Triple(CobblemonItemIngredient(input), CobblemonItemIngredient(ingredient), output)
|
||||
private fun convert(input: Item, ingredient: Item, output: Item): Triple<CobblemonIngredient, Item, Item> {
|
||||
return Triple(CobblemonItemIngredient(input), ingredient, output)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -125,6 +125,7 @@ object ClientMoLangFunctions {
|
||||
val maxPitch = params.getDoubleOrNull(3) ?: 70F
|
||||
val minPitch = params.getDoubleOrNull(4) ?: -45F
|
||||
val maxYaw = params.getDoubleOrNull(5) ?: 45F
|
||||
val minYaw = params.getDoubleOrNull(6) ?: -45F
|
||||
ObjectValue(
|
||||
SingleBoneLookAnimation(
|
||||
bone = model.getPart(boneName),
|
||||
@@ -132,7 +133,8 @@ object ClientMoLangFunctions {
|
||||
yawMultiplier = yawMultiplier.toFloat(),
|
||||
maxPitch = maxPitch.toFloat(),
|
||||
minPitch = minPitch.toFloat(),
|
||||
maxYaw = maxYaw.toFloat()
|
||||
maxYaw = maxYaw.toFloat(),
|
||||
minYaw = minYaw.toFloat()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import net.minecraft.client.gui.components.Renderable
|
||||
|
||||
interface CobblemonRenderable : Renderable
|
||||
@@ -18,7 +18,7 @@ import net.minecraft.network.chat.Component
|
||||
class ExitButton(
|
||||
pX: Int, pY: Int,
|
||||
onPress: OnPress
|
||||
): Button(pX, pY, WIDTH.toInt(), HEIGHT.toInt(), Component.literal("Exit"), onPress, DEFAULT_NARRATION) {
|
||||
): Button(pX, pY, WIDTH.toInt(), HEIGHT.toInt(), Component.literal("Exit"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private const val WIDTH = 26F
|
||||
|
||||
@@ -31,7 +31,7 @@ abstract class ScrollingWidget<T : ObjectSelectionList.Entry<T>>(
|
||||
height, // Height
|
||||
top, // Top
|
||||
slotHeight // Slot Height
|
||||
) {
|
||||
), CobblemonRenderable {
|
||||
override fun renderListBackground(guiGraphics: GuiGraphics) {}
|
||||
override fun renderSelection(context: GuiGraphics, y: Int, entryWidth: Int, entryHeight: Int, borderColor: Int, fillColor: Int) {}
|
||||
override fun renderDecorations(context: GuiGraphics, mouseX: Int, mouseY: Int) {}
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.battles.ShowdownActionResponse
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.battle.ClientBattleActor
|
||||
import com.cobblemon.mod.common.client.battle.SingleActionRequest
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.battle.subscreen.BattleActionSelection
|
||||
import com.cobblemon.mod.common.client.gui.battle.subscreen.BattleBackButton
|
||||
import com.cobblemon.mod.common.client.gui.battle.subscreen.BattleGeneralActionSelection
|
||||
@@ -29,7 +30,7 @@ import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
|
||||
class BattleGUI : Screen(battleLang("gui.title")) {
|
||||
class BattleGUI : Screen(battleLang("gui.title")), CobblemonRenderable {
|
||||
companion object {
|
||||
const val OPTION_VERTICAL_SPACING = 3
|
||||
const val OPTION_HORIZONTAL_SPACING = 3
|
||||
@@ -183,15 +184,16 @@ class BattleGUI : Screen(battleLang("gui.title")) {
|
||||
|
||||
override fun charTyped(chr: Char, modifiers: Int): Boolean {
|
||||
if (chr.toString().equals(PartySendBinding.boundKey().displayName.string, ignoreCase = true) && CobblemonClient.battleOverlay.opacity == BattleOverlay.MAX_OPACITY && PartySendBinding.canAction()) {
|
||||
val battle = CobblemonClient.battle ?: return false
|
||||
battle.minimised = !battle.minimised
|
||||
PartySendBinding.actioned()
|
||||
return true
|
||||
return minimizeBattle()
|
||||
}
|
||||
return super.charTyped(chr, modifiers)
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
if (button == PartySendBinding.boundKey().value && CobblemonClient.battleOverlay.opacity == BattleOverlay.MAX_OPACITY && PartySendBinding.canAction()) {
|
||||
return minimizeBattle()
|
||||
}
|
||||
|
||||
val battle = CobblemonClient.battle
|
||||
if (battle?.spectating == true && specBackButton.isHovered(mouseX, mouseY)) {
|
||||
RemoveSpectatorPacket(battle.battleId).sendToServer()
|
||||
@@ -199,4 +201,11 @@ class BattleGUI : Screen(battleLang("gui.title")) {
|
||||
}
|
||||
return super.mouseClicked(mouseX, mouseY, button)
|
||||
}
|
||||
|
||||
private fun minimizeBattle(): Boolean {
|
||||
val battle = CobblemonClient.battle ?: return false
|
||||
battle.minimised = !battle.minimised
|
||||
PartySendBinding.actioned()
|
||||
return true
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -9,18 +9,19 @@
|
||||
package com.cobblemon.mod.common.client.gui.battle.subscreen
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
|
||||
class BattleBackButton(val x: Float, val y: Float) {
|
||||
class BattleBackButton(val x: Float, val y: Float) : CobblemonRenderable {
|
||||
companion object {
|
||||
const val WIDTH = 58
|
||||
const val HEIGHT = 34
|
||||
const val SCALE = 0.5F
|
||||
}
|
||||
|
||||
fun render(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
override fun render(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = cobblemonResource("textures/gui/battle/battle_back.png"),
|
||||
|
||||
+2
-1
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.battle.widgets
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.battle.ClientBattleMessageQueue
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.Minecraft
|
||||
@@ -32,7 +33,7 @@ class BattleMessagePane(
|
||||
FRAME_HEIGHT, // height
|
||||
1, // top
|
||||
LINE_HEIGHT
|
||||
) {
|
||||
), CobblemonRenderable {
|
||||
var opacity = 1F
|
||||
private var scrolling = false
|
||||
|
||||
|
||||
+2
-1
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.client.gui.battle.widgets
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.battle.BattleGUI
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
@@ -28,7 +29,7 @@ class BattleOptionTile(
|
||||
val resource: ResourceLocation,
|
||||
val text: MutableComponent,
|
||||
val onClick: () -> Unit
|
||||
) : Renderable, GuiEventListener, NarratableEntry {
|
||||
) : CobblemonRenderable, GuiEventListener, NarratableEntry {
|
||||
companion object {
|
||||
const val OPTION_WIDTH = 90
|
||||
const val OPTION_HEIGHT = 26
|
||||
|
||||
+2
-1
@@ -17,6 +17,7 @@ import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.client.ClientMoLangFunctions.setupClient
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.dialogue.widgets.DialogueBox
|
||||
import com.cobblemon.mod.common.client.gui.dialogue.widgets.DialoguePortraitWidget
|
||||
import com.cobblemon.mod.common.client.gui.dialogue.widgets.DialogueNameWidget
|
||||
@@ -36,7 +37,7 @@ import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
|
||||
class DialogueScreen(var dialogueDTO: DialogueDTO) : Screen("gui.dialogue".asTranslated()) {
|
||||
class DialogueScreen(var dialogueDTO: DialogueDTO) : Screen("gui.dialogue".asTranslated()), CobblemonRenderable {
|
||||
val speakers = dialogueDTO.speakers?.mapNotNull { (key, value) ->
|
||||
val name = value.name
|
||||
when (val face = value.face) {
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.gui.dialogue.widgets
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
@@ -22,7 +23,7 @@ class DialogueNameWidget(
|
||||
val width: Int,
|
||||
val height: Int,
|
||||
val text: MutableComponent?
|
||||
) : Renderable, GuiEventListener {
|
||||
) : CobblemonRenderable, GuiEventListener {
|
||||
companion object {
|
||||
val nameResource = cobblemonResource("textures/gui/dialogue/dialogue_name.png")
|
||||
}
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.gui.dialogue.widgets
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.dialogue.DialogueScreen
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
@@ -22,7 +23,7 @@ class DialoguePortraitWidget(
|
||||
val y: Int,
|
||||
val width: Int,
|
||||
val height: Int
|
||||
) : Renderable, GuiEventListener {
|
||||
) : CobblemonRenderable, GuiEventListener {
|
||||
companion object {
|
||||
val DIALOGUE_ARROW_HEIGHT = 11
|
||||
val DIALOGUE_ARROW_WIDTH = 6
|
||||
|
||||
+2
-1
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.dialogue.widgets
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.gui.drawCenteredText
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.dialogue.DialogueScreen
|
||||
import com.cobblemon.mod.common.net.messages.client.dialogue.dto.DialogueInputDTO
|
||||
import com.cobblemon.mod.common.net.messages.server.dialogue.InputToDialoguePacket
|
||||
@@ -36,7 +37,7 @@ class DialogueTextInputWidget(
|
||||
width,
|
||||
height,
|
||||
"gui_dialogue_text_input".text()
|
||||
) {
|
||||
), CobblemonRenderable {
|
||||
init {
|
||||
setMaxLength(maxLength)
|
||||
isFocused = true
|
||||
|
||||
+2
-1
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.client.gui.dialogue.widgets
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.dialogue.DialogueScreen
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
@@ -22,7 +23,7 @@ class DialogueTimerWidget(
|
||||
val y: Int,
|
||||
val width: Int,
|
||||
val height: Int,
|
||||
) : Renderable, GuiEventListener {
|
||||
) : CobblemonRenderable, GuiEventListener {
|
||||
companion object {
|
||||
val timerResource = cobblemonResource("textures/gui/dialogue/dialogue_timer_bar.png")
|
||||
}
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@ import com.cobblemon.mod.common.battles.BattleFormat
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.battle.ClientBattleChallenge
|
||||
import com.cobblemon.mod.common.client.battle.ClientTeamRequest
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.*
|
||||
@@ -35,7 +36,7 @@ class BattleConfigureGUI(
|
||||
private val packet: PlayerInteractOptionsPacket,
|
||||
private val activeRequest: ClientBattleChallenge? = null,
|
||||
private val activeTeamRequest: ClientTeamRequest? = null
|
||||
) : Screen(lang("ui.challenge.challenge_title")) {
|
||||
) : Screen(lang("ui.challenge.challenge_title")), CobblemonRenderable {
|
||||
companion object {
|
||||
const val SIZE = 113
|
||||
private val backgroundResource = cobblemonResource("textures/gui/interact/request/battle_request.png")
|
||||
|
||||
+2
-1
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.client.gui.interact.battleRequest
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
@@ -25,7 +26,7 @@ class BattleRequestNavigationButton(
|
||||
private val forwardIcon: ResourceLocation = forwardButtonResource,
|
||||
private val backwardIcon: ResourceLocation = backwardsButtonResource,
|
||||
onPress: OnPress
|
||||
): Button(pX.toInt(), pY.toInt(), (WIDTH * SCALE).toInt(), (clickHeight * SCALE).toInt(), Component.literal("Navigation"), onPress, DEFAULT_NARRATION) {
|
||||
): Button(pX.toInt(), pY.toInt(), (WIDTH * SCALE).toInt(), (clickHeight * SCALE).toInt(), Component.literal("Navigation"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
const val HEIGHT = 16
|
||||
|
||||
+2
-1
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.client.gui.interact.battleRequest
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
@@ -21,7 +22,7 @@ class BattleResponseButton(
|
||||
pX: Int, pY: Int,
|
||||
private val accept: Boolean,
|
||||
onPress: OnPress
|
||||
): Button(pX, pY, (WIDTH * SCALE).toInt(), (HEIGHT * SCALE).toInt(), Component.literal("Navigation"), onPress, DEFAULT_NARRATION) {
|
||||
): Button(pX, pY, (WIDTH * SCALE).toInt(), (HEIGHT * SCALE).toInt(), Component.literal("Navigation"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private const val WIDTH = 34F
|
||||
|
||||
+2
-1
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
@@ -24,7 +25,7 @@ class BattleRequestButton(
|
||||
pX: Int, pY: Int,
|
||||
var text: MutableComponent,
|
||||
onPress: OnPress
|
||||
): Button(pX, pY, (WIDTH * SCALE).toInt(), (HEIGHT * SCALE).toInt(), text, onPress, DEFAULT_NARRATION) {
|
||||
): Button(pX, pY, (WIDTH * SCALE).toInt(), (HEIGHT * SCALE).toInt(), text, onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private const val WIDTH = 69F
|
||||
|
||||
+2
-1
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.CobblemonNetwork
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.callback.MoveSelectDTO
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.ExitButton
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectedPacket
|
||||
@@ -35,7 +36,7 @@ class MoveSelectConfiguration(
|
||||
|
||||
class MoveSelectGUI(
|
||||
val config: MoveSelectConfiguration
|
||||
) : Screen(Component.translatable("cobblemon.ui.interact.moveselect")) {
|
||||
) : Screen(Component.translatable("cobblemon.ui.interact.moveselect")), CobblemonRenderable {
|
||||
companion object {
|
||||
const val WIDTH = 122
|
||||
const val HEIGHT = 133
|
||||
|
||||
+2
-1
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.api.text.gold
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.MoveCategoryIcon
|
||||
import com.cobblemon.mod.common.client.gui.TypeIcon
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
@@ -35,7 +36,7 @@ class MoveSlotButton(
|
||||
val ppMax: Int,
|
||||
val enabled: Boolean = true,
|
||||
onPress: OnPress
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("Move"), onPress, CreateNarration { "".text() }) {
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("Move"), onPress, CreateNarration { "".text() }), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private val moveResource = cobblemonResource("textures/gui/summary/summary_move.png")
|
||||
|
||||
+2
-1
@@ -14,6 +14,7 @@ import com.cobblemon.mod.common.api.callback.PartySelectPokemonDTO
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.ExitButton
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.party.PartyPokemonSelectedPacket
|
||||
@@ -37,7 +38,7 @@ class PartySelectConfiguration(
|
||||
)
|
||||
class PartySelectGUI(
|
||||
val config: PartySelectConfiguration
|
||||
) : Screen(Component.translatable("cobblemon.ui.interact.moveselect")) {
|
||||
) : Screen(Component.translatable("cobblemon.ui.interact.moveselect")), CobblemonRenderable {
|
||||
companion object {
|
||||
const val WIDTH = 163
|
||||
const val HEIGHT = 132
|
||||
|
||||
+2
-1
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.PartySlotWidget
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
@@ -42,7 +43,7 @@ class PartySlotButton(
|
||||
val enabled: Boolean = true,
|
||||
val parent: PartySelectGUI,
|
||||
onPress: OnPress
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("Pokemon"), onPress, CreateNarration { "".text() }) {
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("Pokemon"), onPress, CreateNarration { "".text() }), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private val slotResource = cobblemonResource("textures/gui/interact/party_select_slot.png")
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.gui.interact.wheel
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
@@ -29,7 +30,7 @@ class InteractWheelButton(
|
||||
private val colour: () -> Vector3f?,
|
||||
onPress: OnPress,
|
||||
private val canHover: (Double, Double) -> Boolean
|
||||
) : Button(x, y, BUTTON_SIZE, BUTTON_SIZE, Component.literal("Interact"), onPress, DEFAULT_NARRATION) {
|
||||
) : Button(x, y, BUTTON_SIZE, BUTTON_SIZE, Component.literal("Interact"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
const val BUTTON_SIZE = 69
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.gui.interact.wheel
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.startselection.widgets.preview.ArrowButton
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.common.collect.Multimap
|
||||
@@ -20,7 +21,7 @@ import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.network.chat.Component
|
||||
import kotlin.math.max
|
||||
|
||||
class InteractWheelGUI(private val options: Multimap<Orientation, InteractWheelOption>, title: Component) : Screen(title) {
|
||||
class InteractWheelGUI(private val options: Multimap<Orientation, InteractWheelOption>, title: Component) : Screen(title), CobblemonRenderable {
|
||||
companion object {
|
||||
const val SIZE = 140
|
||||
const val OPTION_SIZE = 71
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.npc
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.client.sounds.SoundManager
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
|
||||
class NPCEditorButton(
|
||||
var buttonX: Float,
|
||||
var buttonY: Float,
|
||||
var label: MutableComponent,
|
||||
var cycleButtonState: Boolean? = null,
|
||||
var buttonWidth: Int = Minecraft.getInstance().font.width(label) + (BUTTON_PADDING * 2),
|
||||
val silent: Boolean = false,
|
||||
val alignRight: Boolean = false,
|
||||
val clickAction: OnPress
|
||||
): Button(if (alignRight) (buttonX - buttonWidth).toInt() else buttonX.toInt(), buttonY.toInt(), buttonWidth, HEIGHT, "".text(), clickAction, DEFAULT_NARRATION) {
|
||||
|
||||
companion object {
|
||||
val HEIGHT = 16
|
||||
val BORDER_WIDTH = 2
|
||||
val BUTTON_PADDING = 6
|
||||
val buttonResource = cobblemonResource("textures/gui/npc/button_base.png")
|
||||
val buttonBorderResource = cobblemonResource("textures/gui/npc/button_border.png")
|
||||
}
|
||||
|
||||
var isWidgetActive = false
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, partialTicks: Float) {
|
||||
val matrices = context.pose()
|
||||
|
||||
// Left border
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = buttonBorderResource,
|
||||
x = x,
|
||||
y = y,
|
||||
width = BORDER_WIDTH,
|
||||
height = HEIGHT,
|
||||
vOffset = if (isMouseOver(mouseX.toDouble(), mouseY.toDouble()) || isWidgetActive) HEIGHT else 0,
|
||||
textureWidth = 3,
|
||||
textureHeight = HEIGHT * 2,
|
||||
)
|
||||
// Base
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = buttonResource,
|
||||
x = x + BORDER_WIDTH,
|
||||
y = y,
|
||||
width = buttonWidth - (BORDER_WIDTH * 2),
|
||||
height = HEIGHT,
|
||||
vOffset = if (isMouseOver(mouseX.toDouble(), mouseY.toDouble()) || isWidgetActive) HEIGHT else 0,
|
||||
textureHeight = HEIGHT * 2,
|
||||
)
|
||||
// Right border
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = buttonBorderResource,
|
||||
x = x + (buttonWidth - BORDER_WIDTH),
|
||||
y = y,
|
||||
width = BORDER_WIDTH,
|
||||
height = HEIGHT,
|
||||
uOffset = 1,
|
||||
vOffset = if (isMouseOver(mouseX.toDouble(), mouseY.toDouble()) || isWidgetActive) HEIGHT else 0,
|
||||
textureWidth = 3,
|
||||
textureHeight = HEIGHT * 2,
|
||||
)
|
||||
|
||||
var buttonLabel = if (cycleButtonState != null) "options.${if (cycleButtonState as Boolean) "on" else "off"}.composed".asTranslated(label) else label
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = buttonLabel,
|
||||
x = x + (buttonWidth / 2),
|
||||
y = y + 4,
|
||||
centered = true,
|
||||
shadow = true
|
||||
)
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
if (active && isMouseOver(mouseX, mouseY)) {
|
||||
super.mouseClicked(mouseX, mouseY, button)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun playDownSound(soundManager: SoundManager) {
|
||||
if (active && !this.silent) {
|
||||
soundManager.play(SimpleSoundInstance.forUI(CobblemonSounds.GUI_CLICK, 1.0F))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,25 +8,36 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.npc
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.gui.drawText
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.npc.widgets.ConfigVariableList
|
||||
import com.cobblemon.mod.common.client.gui.npc.widgets.NPCRenderWidget
|
||||
import com.cobblemon.mod.common.client.gui.npc.widgets.NPCRenderWidget.Companion.HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.npc.widgets.NPCRenderWidget.Companion.WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.npc.widgets.SimpleNPCTextInputWidget
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.drawScaledTextJustifiedRight
|
||||
import com.cobblemon.mod.common.net.messages.client.npc.dto.NPCConfigurationDTO
|
||||
import com.cobblemon.mod.common.net.messages.server.npc.SaveNPCPacket
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import java.util.UUID
|
||||
|
||||
class NPCEditorScreen(
|
||||
val npcId: Int,
|
||||
val dto: NPCConfigurationDTO
|
||||
) : Screen("gui.npc_editor.title".asTranslated()) {
|
||||
) : Screen("gui.npc_editor.title".asTranslated()), CobblemonRenderable {
|
||||
companion object {
|
||||
const val BASE_WIDTH = 331
|
||||
const val BASE_HEIGHT = 161
|
||||
const val BASE_WIDTH = 360
|
||||
const val BASE_HEIGHT = 220
|
||||
|
||||
val baseResource = cobblemonResource("textures/gui/npc/base.png")
|
||||
}
|
||||
|
||||
val middleX: Int
|
||||
@@ -41,53 +52,73 @@ class NPCEditorScreen(
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
addRenderableOnly(NPCRenderWidget(leftX + 6, topY + 22, dto.npcClass, dto.aspects))
|
||||
addRenderableOnly(NPCRenderWidget(leftX + 12, topY + 35, dto.npcClass, dto.aspects))
|
||||
addRenderableWidget(SimpleNPCTextInputWidget(
|
||||
texture = cobblemonResource("textures/gui/npc/basic_text_input.png"),
|
||||
getter = { dto.npcName.string },
|
||||
setter = { dto.npcName = it.text() },
|
||||
x = leftX + 6,
|
||||
y = topY + 80,
|
||||
width = 130,
|
||||
height = 22
|
||||
posX = leftX + 12,
|
||||
posY = topY + 9,
|
||||
width = 192,
|
||||
height = 22,
|
||||
maxLength = 32
|
||||
))
|
||||
|
||||
addRenderableWidget(SimpleNPCTextInputWidget(
|
||||
texture = cobblemonResource("textures/gui/npc/aspects_text_input.png"),
|
||||
getter = { dto.aspects.joinToString() },
|
||||
setter = {
|
||||
dto.aspects.clear()
|
||||
dto.aspects.addAll(it.split(",").map { it.trim() })
|
||||
},
|
||||
x = leftX + 6,
|
||||
y = topY + 100,
|
||||
width = 130,
|
||||
posX = leftX + 12,
|
||||
posY = topY + 155,
|
||||
width = 116,
|
||||
height = 40,
|
||||
maxLength = 75,
|
||||
maxLength = 72,
|
||||
wrap = true
|
||||
))
|
||||
|
||||
addRenderableWidget(
|
||||
Button
|
||||
.builder("Save".text()) {
|
||||
SaveNPCPacket(npcId, dto).sendToServer()
|
||||
this.minecraft!!.setScreen(null)
|
||||
}
|
||||
.pos(leftX + BASE_WIDTH - 42, topY + BASE_HEIGHT - 8)
|
||||
.size(40, 16)
|
||||
.build()
|
||||
NPCEditorButton(
|
||||
buttonX = leftX + 348F,
|
||||
buttonY = topY + 201F,
|
||||
label = lang("ui.generic.save"),
|
||||
alignRight = true
|
||||
) {
|
||||
SaveNPCPacket(npcId, dto).sendToServer()
|
||||
this.minecraft!!.setScreen(null)
|
||||
}
|
||||
)
|
||||
|
||||
addRenderableWidget(ConfigVariableList(leftX + 200, topY + 30, this))
|
||||
addRenderableWidget(ConfigVariableList(leftX + 134, topY + 35, this))
|
||||
}
|
||||
|
||||
override fun renderBlurredBackground(delta: Float) {}
|
||||
|
||||
override fun renderMenuBackground(context: GuiGraphics) {}
|
||||
|
||||
override fun isPauseScreen() = false
|
||||
|
||||
override fun render(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
// blitk(
|
||||
// matrixStack = context.pose(),
|
||||
// texture = baseResource,
|
||||
// x = leftX,
|
||||
// y = topY,
|
||||
// height = BASE_HEIGHT,
|
||||
// width = BASE_WIDTH
|
||||
// )
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = baseResource,
|
||||
x = leftX,
|
||||
y = topY,
|
||||
height = BASE_HEIGHT,
|
||||
width = BASE_WIDTH
|
||||
)
|
||||
|
||||
var extendedId = npcId.toString()
|
||||
while (extendedId.length < 12) extendedId = "0$extendedId"
|
||||
|
||||
drawScaledTextJustifiedRight(
|
||||
context = context,
|
||||
text = extendedId.text(),
|
||||
x = leftX + 348,
|
||||
y = topY + 9,
|
||||
shadow = true
|
||||
)
|
||||
|
||||
super.render(context, mouseX, mouseY, delta)
|
||||
}
|
||||
}
|
||||
+43
-55
@@ -8,16 +8,19 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.npc.widgets
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.npc.NPCClasses
|
||||
import com.cobblemon.mod.common.api.npc.configuration.NPCConfigVariable
|
||||
import com.cobblemon.mod.common.api.npc.configuration.NPCConfigVariable.NPCVariableType
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.npc.NPCEditorButton
|
||||
import com.cobblemon.mod.common.client.gui.npc.NPCEditorScreen
|
||||
import com.cobblemon.mod.common.client.gui.npc.widgets.ConfigVariableList.ConfigVariable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.ContainerObjectSelectionList
|
||||
import net.minecraft.client.gui.components.CycleButton
|
||||
import net.minecraft.client.gui.components.EditBox
|
||||
import net.minecraft.client.gui.components.Tooltip
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener
|
||||
@@ -25,7 +28,7 @@ import net.minecraft.client.gui.narration.NarratableEntry
|
||||
|
||||
class ConfigVariableList(
|
||||
val listX: Int,
|
||||
val listY: Int,
|
||||
var listY: Int,
|
||||
val parent: NPCEditorScreen
|
||||
) : ContainerObjectSelectionList<ConfigVariable>(
|
||||
Minecraft.getInstance(),
|
||||
@@ -33,13 +36,15 @@ class ConfigVariableList(
|
||||
HEIGHT, // height
|
||||
0, // top
|
||||
SLOT_HEIGHT + SLOT_SPACING
|
||||
) {
|
||||
), CobblemonRenderable {
|
||||
companion object {
|
||||
const val WIDTH = 200
|
||||
const val HEIGHT = 120
|
||||
const val SLOT_WIDTH = 160
|
||||
const val WIDTH = 211
|
||||
const val HEIGHT = 160
|
||||
const val SLOT_WIDTH = 196
|
||||
const val SLOT_HEIGHT = 33
|
||||
const val SLOT_SPACING = 0
|
||||
|
||||
val textInputBackground = cobblemonResource("textures/gui/npc/text_input_base.png")
|
||||
}
|
||||
|
||||
private var scrolling = false
|
||||
@@ -47,15 +52,16 @@ class ConfigVariableList(
|
||||
override fun getRowWidth() = SLOT_WIDTH
|
||||
|
||||
init {
|
||||
listY += 4
|
||||
this.x = listX
|
||||
this.y = listY
|
||||
correctSize()
|
||||
setRenderHeader(false, 0)
|
||||
val npcClass = NPCClasses.getByIdentifier(parent.dto.npcClass)
|
||||
if (npcClass != null) {
|
||||
npcClass.config.forEach { t ->
|
||||
val value = parent.dto.variables[t.variableName] ?: t.defaultValue
|
||||
addEntry(ConfigVariable(t, value, this))
|
||||
npcClass.config.forEach { variable ->
|
||||
val value = parent.dto.variables[variable.variableName] ?: variable.defaultValue
|
||||
addEntry(ConfigVariable(variable, value, this))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,20 +71,12 @@ class ConfigVariableList(
|
||||
public override fun addEntry(entry: ConfigVariable) = super.addEntry(entry)
|
||||
public override fun removeEntry(entry: ConfigVariable) = super.removeEntry(entry)
|
||||
|
||||
override fun renderListSeparators(guiGraphics: GuiGraphics) {}
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, partialTicks: Float) {
|
||||
correctSize()
|
||||
|
||||
super.renderWidget(context, mouseX, mouseY, partialTicks)
|
||||
|
||||
// Scroll Overlay
|
||||
// blitk(
|
||||
// matrixStack = context.pose(),
|
||||
// texture = scrollOverlayResource,
|
||||
// x = listX,
|
||||
// y = listY - 13,
|
||||
// height = 131,
|
||||
// width = WIDTH
|
||||
// )
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
@@ -114,7 +112,6 @@ class ConfigVariableList(
|
||||
|
||||
private fun correctSize() {
|
||||
setRectangle(WIDTH, HEIGHT, listX, (listY - 4))
|
||||
// setX(listX)
|
||||
}
|
||||
|
||||
fun isHovered(mouseX: Double, mouseY: Double) = mouseX.toFloat() in (x.toFloat()..(x.toFloat() + WIDTH)) && mouseY.toFloat() in (y.toFloat()..(y.toFloat() + HEIGHT))
|
||||
@@ -130,11 +127,12 @@ class ConfigVariableList(
|
||||
val editBox = EditBox(
|
||||
client.font,
|
||||
parent.listX,
|
||||
parent.listY + 4,
|
||||
if (variable.type == NPCVariableType.NUMBER) SLOT_WIDTH - 100 else SLOT_WIDTH,
|
||||
parent.listY + 8,
|
||||
SLOT_WIDTH - 8,
|
||||
SLOT_HEIGHT - 8,
|
||||
variable.displayName,
|
||||
).also {
|
||||
it.isBordered = false
|
||||
it.tooltip = Tooltip.create(variable.description)
|
||||
it.height = SLOT_HEIGHT - 16
|
||||
it.setMaxLength(250)
|
||||
@@ -147,18 +145,23 @@ class ConfigVariableList(
|
||||
it.setFilter { value -> value.toDoubleOrNull() != null || value.isBlank() || value == "." || value == "-" }
|
||||
}
|
||||
}
|
||||
val cycleButton = CycleButton.onOffBuilder(booleanValue).create(variable.displayName) { _, value ->
|
||||
booleanValue = value
|
||||
parent.parent.dto.variables[variable.variableName] = if (value) "1" else "0"
|
||||
val toggleButton = NPCEditorButton(
|
||||
parent.listX.toFloat(),
|
||||
parent.listY + 6F,
|
||||
variable.displayName.copy(),
|
||||
booleanValue,
|
||||
SLOT_WIDTH
|
||||
) {
|
||||
booleanValue = !booleanValue
|
||||
parent.parent.dto.variables[variable.variableName] = if (booleanValue) "1" else "0"
|
||||
(it as NPCEditorButton).cycleButtonState = booleanValue
|
||||
}.also {
|
||||
it.height = SLOT_HEIGHT - 14
|
||||
it.width = SLOT_WIDTH - 8
|
||||
it.tooltip = Tooltip.create(variable.description)
|
||||
}
|
||||
|
||||
init {
|
||||
if (variable.type == NPCVariableType.BOOLEAN) {
|
||||
children.add(cycleButton)
|
||||
children.add(toggleButton) // children.add(cycleButton)
|
||||
} else {
|
||||
children.add(editBox)
|
||||
}
|
||||
@@ -188,42 +191,27 @@ class ConfigVariableList(
|
||||
) {
|
||||
val x = rowLeft - 4
|
||||
val y = rowTop
|
||||
val matrixStack = context.pose()
|
||||
// blitk(
|
||||
// matrixStack = matrixStack,
|
||||
// texture = slotResource,
|
||||
// x = x,
|
||||
// y = y,
|
||||
// height = SLOT_HEIGHT,
|
||||
// width = rowWidth,
|
||||
// vOffset = if (isHovered) SLOT_HEIGHT else 0,
|
||||
// textureHeight = SLOT_HEIGHT * 2
|
||||
// )
|
||||
|
||||
if (variable.type == NPCVariableType.BOOLEAN) {
|
||||
cycleButton.x = x
|
||||
cycleButton.y = y + 6
|
||||
cycleButton.render(context, mouseX, mouseY, partialTicks)
|
||||
toggleButton.x = x
|
||||
toggleButton.y = y + 9
|
||||
toggleButton.render(context, mouseX, mouseY, partialTicks)
|
||||
} else {
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = variable.displayName.visualOrderText,
|
||||
x = x,
|
||||
y = y + 4
|
||||
y = y + 4,
|
||||
shadow = true
|
||||
)
|
||||
editBox.x = x
|
||||
editBox.y = y + 14
|
||||
|
||||
blitk(matrixStack = context.pose(), texture = textInputBackground, x = x, y = y + 16, height = 12, width = 1)
|
||||
blitk(matrixStack = context.pose(), texture = textInputBackground, x = x + 1, y = y + 15, height = 14, width = SLOT_WIDTH - 2)
|
||||
blitk(matrixStack = context.pose(), texture = textInputBackground, x = x + SLOT_WIDTH - 1, y = y + 16, height = 12, width = 1)
|
||||
|
||||
editBox.x = x + 4
|
||||
editBox.y = y + 18
|
||||
editBox.render(context, mouseX, mouseY, partialTicks)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// override fun mouseClicked(mouseX: Double, mouseY: Double, delta: Int): Boolean {
|
||||
// if (moveButton.isHovered(mouseX, mouseY) && canUnpasture()) {
|
||||
// moveButton.onPress()
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
}
|
||||
}
|
||||
+14
-16
@@ -8,11 +8,10 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.npc.widgets
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.gui.drawProfile
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.NPCModelRepository
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Renderable
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener
|
||||
@@ -23,41 +22,40 @@ class NPCRenderWidget(
|
||||
val y: Int,
|
||||
var identifier: ResourceLocation,
|
||||
val aspects: MutableSet<String>
|
||||
) : Renderable, GuiEventListener {
|
||||
) : CobblemonRenderable, GuiEventListener {
|
||||
val state = FloatingState().also {
|
||||
it.currentAspects = aspects
|
||||
}
|
||||
|
||||
companion object {
|
||||
val profileBackgroundResource = cobblemonResource("textures/gui/npc/profile_background.png")
|
||||
const val WIDTH = 66
|
||||
const val HEIGHT = 66
|
||||
const val WIDTH = 116
|
||||
const val HEIGHT = 112
|
||||
}
|
||||
|
||||
override fun isFocused() = false
|
||||
override fun setFocused(focused: Boolean) {}
|
||||
override fun render(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = profileBackgroundResource,
|
||||
x = x,
|
||||
y = y,
|
||||
width = WIDTH,
|
||||
height = HEIGHT
|
||||
)
|
||||
|
||||
context.enableScissor(
|
||||
x,
|
||||
y,
|
||||
x + WIDTH,
|
||||
y + HEIGHT
|
||||
)
|
||||
context.pose().pushPose()
|
||||
context.pose().translate(x + WIDTH / 2F, y + HEIGHT / 2F, 0F)
|
||||
// Decrease on Z-axis to prevent model from rendering above other components like tooltips
|
||||
context.pose().translate(x + (WIDTH / 2F), y + HEIGHT + (HEIGHT / 4F), -500F)
|
||||
|
||||
drawProfile(
|
||||
repository = NPCModelRepository,
|
||||
resourceIdentifier = identifier,
|
||||
matrixStack = context.pose(),
|
||||
partialTicks = delta,
|
||||
scale = 30F,
|
||||
scale = 120F,
|
||||
state = state
|
||||
)
|
||||
|
||||
context.pose().popPose()
|
||||
context.disableScissor()
|
||||
}
|
||||
}
|
||||
+99
-46
@@ -9,89 +9,142 @@
|
||||
package com.cobblemon.mod.common.client.gui.npc.widgets
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.gui.drawCenteredText
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import net.minecraft.Util
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.EditBox
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.network.chat.contents.PlainTextContents.LiteralContents
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.network.chat.Style
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import kotlin.math.floor
|
||||
|
||||
class SimpleNPCTextInputWidget(
|
||||
getter: () -> String,
|
||||
val texture: ResourceLocation,
|
||||
val texture: ResourceLocation? = null,
|
||||
private val setter: (String) -> Unit,
|
||||
x: Int,
|
||||
y: Int,
|
||||
posX: Int,
|
||||
posY: Int,
|
||||
width: Int,
|
||||
height: Int,
|
||||
maxLength: Int = 100,
|
||||
val shadow: Boolean = true,
|
||||
val wrap: Boolean = false
|
||||
) : EditBox(
|
||||
Minecraft.getInstance().font,
|
||||
x,
|
||||
y,
|
||||
posX + TEXT_PADDING,
|
||||
posY,
|
||||
width,
|
||||
height,
|
||||
"input".text()
|
||||
) {
|
||||
), CobblemonRenderable {
|
||||
companion object {
|
||||
const val TEXT_PADDING = 4
|
||||
}
|
||||
|
||||
var focusedTime: Long = 0
|
||||
|
||||
init {
|
||||
setMaxLength(maxLength)
|
||||
isFocused = true
|
||||
focusedTime = Util.getMillis()
|
||||
value = getter()
|
||||
this.setResponder { setter(it) }
|
||||
setResponder { setter(it) }
|
||||
setFocused(false)
|
||||
isBordered = false
|
||||
}
|
||||
|
||||
override fun setFocused(focused: Boolean) {
|
||||
if (focused) focusedTime = Util.getMillis()
|
||||
super.setFocused(focused)
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
return if (mouseX.toInt() in x..(x + width) && mouseY.toInt() in y..(y + height)) {
|
||||
isFocused = true
|
||||
true
|
||||
} else {
|
||||
false
|
||||
val clickedState = super.mouseClicked(mouseX, mouseY, button)
|
||||
|
||||
if (wrap) {
|
||||
val splitLines = Minecraft.getInstance().font.splitter.splitLines(value, width - 8, Style.EMPTY)
|
||||
val clickedLineIndex = floor((mouseY - y)/11).toInt()
|
||||
|
||||
if (clickedLineIndex >= 0 && splitLines.size > clickedLineIndex) {
|
||||
val lineAtIndex = splitLines.get(clickedLineIndex)
|
||||
var lineSubstring = ""
|
||||
for (char in lineAtIndex.string) {
|
||||
lineSubstring += char
|
||||
val startToLineWidth = Minecraft.getInstance().font.width(lineSubstring.text())
|
||||
if ((mouseX - x) <= startToLineWidth) break
|
||||
}
|
||||
var unwrappedLine = ""
|
||||
splitLines.forEachIndexed { index, line ->
|
||||
if (index == clickedLineIndex) {
|
||||
unwrappedLine += lineSubstring
|
||||
} else if (index < clickedLineIndex) {
|
||||
unwrappedLine += line.string
|
||||
}
|
||||
}
|
||||
|
||||
this.moveCursorTo(maxOf(0, unwrappedLine.length - 1), Screen.hasShiftDown())
|
||||
}
|
||||
}
|
||||
|
||||
return clickedState
|
||||
}
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
if (cursorPosition != value.length) {
|
||||
moveCursorToEnd(false)
|
||||
if (texture != null) {
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
x = x,
|
||||
y = y,
|
||||
width = width,
|
||||
height = height,
|
||||
texture = texture
|
||||
)
|
||||
}
|
||||
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
x = x,
|
||||
y = y,
|
||||
width = width,
|
||||
height = height,
|
||||
texture = texture
|
||||
)
|
||||
|
||||
context.pose().pushPose()
|
||||
val scale = 0.8F
|
||||
context.pose().scale(scale, scale, 1F)
|
||||
if (wrap) {
|
||||
val wrappedLines = Minecraft.getInstance().font.split(MutableComponent.create(LiteralContents(value)), ((width - 8) / scale).toInt())
|
||||
val showCursor = isFocused && ((Util.getMillis() - this.focusedTime) / 300L % 2L == 0L)
|
||||
val input = (if (isFocused) "${value}${if ((cursorPosition == value.length) && showCursor) "_" else ""}" else value)
|
||||
|
||||
var cursorLine = ""
|
||||
var cursorLineIndex = -1
|
||||
var cursorLinePos = 0
|
||||
var accumlatedLength = 0
|
||||
val wrappedLines = Minecraft.getInstance().font.splitter.splitLines(input, width - (TEXT_PADDING * 2), Style.EMPTY)
|
||||
|
||||
for ((index, line) in wrappedLines.withIndex()) {
|
||||
context.drawString(
|
||||
Minecraft.getInstance().font,
|
||||
line,
|
||||
((x + 4) / scale).toInt(),
|
||||
((y + index * 10 + 5) / scale).toInt(),
|
||||
0xFFFFFF,
|
||||
false
|
||||
accumlatedLength += line.string.length
|
||||
if (cursorLineIndex < 0 && accumlatedLength > cursorPosition) {
|
||||
cursorLineIndex = index
|
||||
cursorLine = line.string
|
||||
cursorLinePos = if (cursorLineIndex > 0) cursorPosition - (accumlatedLength - line.string.length) else cursorPosition
|
||||
}
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = line.string.text(),
|
||||
x = x,
|
||||
y = y + index * 10 + 1,
|
||||
colour = 0xDDDDDD,
|
||||
shadow = true
|
||||
)
|
||||
}
|
||||
|
||||
if (showCursor && !value.isEmpty() && cursorPosition != value.length) {
|
||||
val startToCursorWidth = Minecraft.getInstance().font.width((cursorLine.substring(0, cursorLinePos).text()))
|
||||
context.fill(
|
||||
RenderType.guiTextHighlight(),
|
||||
x + startToCursorWidth - 1,
|
||||
y + cursorLineIndex * 10 + 1,
|
||||
x + startToCursorWidth,
|
||||
y + (cursorLineIndex * 10 + 1) + 9,
|
||||
-3092272
|
||||
)
|
||||
}
|
||||
} else {
|
||||
drawCenteredText(
|
||||
context = context,
|
||||
text = value.text(),
|
||||
x = (x + width / 2F) / scale,
|
||||
y = (y + height / 2 - 4) / scale,
|
||||
shadow = true,
|
||||
colour = 0xFFFFFF
|
||||
)
|
||||
super.renderWidget(context, mouseX, mouseY, delta)
|
||||
}
|
||||
context.pose().popPose()
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
|
||||
import com.cobblemon.mod.common.client.gui.pc.StorageSlot
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.PartySlotWidget
|
||||
@@ -40,7 +41,7 @@ class PasturePokemonScrollList(
|
||||
HEIGHT, // height
|
||||
0, // top
|
||||
SLOT_HEIGHT + SLOT_SPACING
|
||||
) {
|
||||
), CobblemonRenderable {
|
||||
companion object {
|
||||
const val WIDTH = 70
|
||||
const val HEIGHT = 120
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.gui.pasture
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
@@ -18,7 +19,7 @@ import net.minecraft.network.chat.Component
|
||||
class PastureSlotIconButton(
|
||||
var xPos: Int, var yPos: Int,
|
||||
onPress: OnPress
|
||||
) : Button(xPos, yPos, (SIZE * SCALE).toInt(), (SIZE * SCALE).toInt(), Component.literal("Pasture Move"), onPress, DEFAULT_NARRATION) {
|
||||
) : Button(xPos, yPos, (SIZE * SCALE).toInt(), (SIZE * SCALE).toInt(), Component.literal("Pasture Move"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
const val SIZE = 14
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.pasture
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
@@ -22,7 +23,7 @@ import net.minecraft.network.chat.Component
|
||||
class RecallButton(
|
||||
x: Int, y: Int,
|
||||
onPress: OnPress
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("Retrieve"), onPress, DEFAULT_NARRATION) {
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("Retrieve"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private const val WIDTH = 70
|
||||
|
||||
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.client.gui.pc
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
@@ -21,7 +22,7 @@ class NavigationButton(
|
||||
pX: Int, pY: Int,
|
||||
private val forward: Boolean,
|
||||
onPress: OnPress
|
||||
): Button(pX, pY, (WIDTH * SCALE).toInt(), (HEIGHT * SCALE).toInt(), Component.literal("Navigation"), onPress, DEFAULT_NARRATION) {
|
||||
): Button(pX, pY, (WIDTH * SCALE).toInt(), (HEIGHT * SCALE).toInt(), Component.literal("Navigation"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private const val WIDTH = 8F
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
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
|
||||
@@ -40,7 +41,7 @@ class PCGUI(
|
||||
val pc: ClientPC,
|
||||
val party: ClientParty,
|
||||
val configuration: PCGUIConfiguration
|
||||
) : Screen(Component.translatable("cobblemon.ui.pc.title")) {
|
||||
) : Screen(Component.translatable("cobblemon.ui.pc.title")), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
const val BASE_WIDTH = 349
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.pc
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
@@ -23,7 +24,7 @@ class ReleaseButton(
|
||||
x: Int, y: Int,
|
||||
private val parent: StorageWidget,
|
||||
onPress: OnPress
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("Release"), onPress, DEFAULT_NARRATION) {
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("Release"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private const val WIDTH = 58
|
||||
|
||||
+2
-1
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.pc
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
@@ -24,7 +25,7 @@ class ReleaseConfirmButton(
|
||||
private val parent: StorageWidget,
|
||||
private val subKey: String,
|
||||
onPress: OnPress
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("ReleaseConfirm"), onPress, DEFAULT_NARRATION) {
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("ReleaseConfirm"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private const val WIDTH = 30
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.gui.pc
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
|
||||
import com.cobblemon.mod.common.client.gui.pasture.PasturePCGUIConfiguration
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
@@ -31,7 +32,7 @@ open class StorageSlot(
|
||||
x: Int, y: Int,
|
||||
private val parent: StorageWidget,
|
||||
onPress: OnPress
|
||||
) : Button(x, y, SIZE, SIZE, Component.literal("StorageSlot"), onPress, DEFAULT_NARRATION) {
|
||||
) : Button(x, y, SIZE, SIZE, Component.literal("StorageSlot"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
val state = FloatingState()
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.ClientMoLangFunctions.setupClient
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.BASE_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.BASE_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HEADER_BAR_HEIGHT
|
||||
@@ -75,7 +76,7 @@ class PokedexGUI private constructor(
|
||||
val type: PokedexType,
|
||||
val initSpecies: ResourceLocation?,
|
||||
val blockPos: BlockPos?
|
||||
): Screen(Component.translatable("cobblemon.ui.pokedex.title")) {
|
||||
): Screen(Component.translatable("cobblemon.ui.pokedex.title")), CobblemonRenderable {
|
||||
companion object {
|
||||
private val screenBackground = cobblemonResource("textures/gui/pokedex/pokedex_screen.png")
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.pokedex
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.gui.narration.NarrationElementOutput
|
||||
@@ -27,7 +28,7 @@ class ScaledButton(
|
||||
val scale: Float = 0.5F,
|
||||
val silent: Boolean = false,
|
||||
val clickAction: Button.OnPress
|
||||
): Button(buttonX.toInt(), buttonY.toInt(), buttonWidth.toInt(), buttonHeight.toInt(), "".text(), clickAction, DEFAULT_NARRATION) {
|
||||
): Button(buttonX.toInt(), buttonY.toInt(), buttonWidth.toInt(), buttonHeight.toInt(), "".text(), clickAction, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
var isWidgetActive = false
|
||||
|
||||
|
||||
+2
-1
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.font
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.SCALE
|
||||
@@ -33,7 +34,7 @@ class SearchWidget(
|
||||
height: Int,
|
||||
text: Component = "Search".text(),
|
||||
val update: () -> (Unit)
|
||||
): EditBox(Minecraft.getInstance().font, posX.toInt(), posY.toInt(), width, height, text) {
|
||||
): EditBox(Minecraft.getInstance().font, posX.toInt(), posY.toInt(), width, height, text), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private val backgroundOverlay = cobblemonResource("textures/gui/pokedex/pokedex_screen_search_overlay.png")
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.pokenav
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.summary.Summary
|
||||
import com.cobblemon.mod.common.client.keybind.boundKey
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.PokeNavigatorBinding
|
||||
@@ -28,7 +29,7 @@ import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class PokeNav : Screen(Component.translatable("cobblemon.ui.pokenav.title")) {
|
||||
class PokeNav : Screen(Component.translatable("cobblemon.ui.pokenav.title")), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
// Limiting
|
||||
|
||||
+2
-1
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.api.gui.ColourLibrary
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
@@ -31,7 +32,7 @@ open class PokeNavImageButton(
|
||||
private val text: MutableComponent,
|
||||
private val canClick: () -> Boolean = { true }
|
||||
// TODO: Make lang key per button
|
||||
): Button(pX, pY, pWidth, pHeight, "cobblemon.ui.pokenav.narrator.backbutton".asTranslated(), onPress, DEFAULT_NARRATION) {
|
||||
): Button(pX, pY, pWidth, pHeight, "cobblemon.ui.pokenav.narrator.backbutton".asTranslated(), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, pMouseX: Int, pMouseY: Int, pPartialTicks: Float) {
|
||||
// Render Button Image
|
||||
|
||||
+4
-2
@@ -17,6 +17,7 @@ import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.startselection.widgets.CategoryList
|
||||
import com.cobblemon.mod.common.client.gui.startselection.widgets.ExitButton
|
||||
import com.cobblemon.mod.common.client.gui.startselection.widgets.preview.ArrowButton
|
||||
@@ -47,7 +48,7 @@ import net.minecraft.network.chat.Component
|
||||
* @author Qu
|
||||
* @since 2022-06-18
|
||||
*/
|
||||
class StarterSelectionScreen(private val categories: List<RenderableStarterCategory>): Screen("cobblemon.ui.starter.title".asTranslated()) {
|
||||
class StarterSelectionScreen(private val categories: List<RenderableStarterCategory>): Screen("cobblemon.ui.starter.title".asTranslated()), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
// Size of UI at scale 1
|
||||
@@ -132,7 +133,8 @@ class StarterSelectionScreen(private val categories: List<RenderableStarterCateg
|
||||
pX = x + 85, pY = y + 50,
|
||||
pWidth = 102, pHeight = 100,
|
||||
pokemon = this,
|
||||
baseScale = 2.0f
|
||||
baseScale = 2.0f,
|
||||
playCryOnClick = true,
|
||||
)
|
||||
|
||||
typeWidget = typeWidget(this, x, y)
|
||||
|
||||
+2
-1
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.client.gui.startselection.widgets
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.startselection.StarterSelectionScreen
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.config.starter.RenderableStarterCategory
|
||||
@@ -37,7 +38,7 @@ class CategoryList(
|
||||
paneHeight,
|
||||
topOffset,
|
||||
entryHeight
|
||||
) {
|
||||
), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private const val CATEGORY_BUTTON_WIDTH = 51.5f
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.gui.startselection.widgets
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
@@ -20,7 +21,7 @@ class ExitButton(
|
||||
pWidth: Int, pHeight: Int,
|
||||
pXTexStart: Int, pYTexStart: Int, pYDiffText: Int,
|
||||
onPress: OnPress
|
||||
): Button(pX, pY, EXIT_BUTTON_WIDTH.toInt(), EXIT_BUTTON_HEIGHT.toInt(), "cobblemon.ui.starter.narrator.backbutton".asTranslated(), onPress, DEFAULT_NARRATION) {
|
||||
): Button(pX, pY, EXIT_BUTTON_WIDTH.toInt(), EXIT_BUTTON_HEIGHT.toInt(), "cobblemon.ui.starter.narrator.backbutton".asTranslated(), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private const val EXIT_BUTTON_WIDTH = 15.95F
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.gui.startselection.widgets.preview
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
@@ -22,7 +23,7 @@ class ArrowButton(
|
||||
right: Boolean,
|
||||
private val texture: ResourceLocation = if (right) RIGHT_ARROW_BUTTON_RESOURCE else LEFT_ARROW_BUTTON_RESOURCE,
|
||||
onPress: OnPress
|
||||
) : Button(pX, pY, pWidth, pHeight, Component.empty(), onPress, DEFAULT_NARRATION) {
|
||||
) : Button(pX, pY, pWidth, pHeight, Component.empty(), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private val RIGHT_ARROW_BUTTON_RESOURCE = cobblemonResource("textures/gui/starterselection/starterselection_arrow_right.png")
|
||||
|
||||
+2
-1
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.startselection.widgets.preview
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.ColourLibrary
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
@@ -25,7 +26,7 @@ class SelectionButton(
|
||||
pX: Int, pY: Int,
|
||||
pWidth: Int, pHeight: Int,
|
||||
onPress: OnPress
|
||||
): Button(pX, pY, pWidth, pHeight, Component.literal("SelectionButton"), onPress, DEFAULT_NARRATION) {
|
||||
): Button(pX, pY, pWidth, pHeight, Component.literal("SelectionButton"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private val buttonTexture = cobblemonResource("textures/gui/starterselection/starterselection_button.png")
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.ExitButton
|
||||
import com.cobblemon.mod.common.client.gui.TypeIcon
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.EvolutionSelectScreen
|
||||
@@ -63,7 +64,7 @@ import net.minecraft.sounds.SoundEvent
|
||||
* @param selection The index the [party] will have as the base [selectedPokemon].
|
||||
*/
|
||||
class Summary private constructor(party: Collection<Pokemon?>, private val editable: Boolean, private val selection: Int): Screen(
|
||||
Component.translatable("cobblemon.ui.summary.title")), Schedulable {
|
||||
Component.translatable("cobblemon.ui.summary.title")), Schedulable, CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
const val BASE_WIDTH = 331
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
@@ -38,7 +39,7 @@ class SummaryButton(
|
||||
private val boldText: Boolean = true,
|
||||
private val largeText: Boolean = true,
|
||||
private val textScale: Float = 1F
|
||||
): Button(buttonX.toInt(), buttonY.toInt(), buttonWidth.toInt(), buttonHeight.toInt(), text, clickAction, DEFAULT_NARRATION) {
|
||||
): Button(buttonX.toInt(), buttonY.toInt(), buttonWidth.toInt(), buttonHeight.toInt(), text, clickAction, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
const val TEXT_HEIGHT = 9
|
||||
|
||||
+12
-2
@@ -23,7 +23,8 @@ class ModelWidget(
|
||||
var pokemon: RenderablePokemon,
|
||||
val baseScale: Float = 2.7F,
|
||||
var rotationY: Float = 35F,
|
||||
var offsetY: Double = 0.0
|
||||
var offsetY: Double = 0.0,
|
||||
val playCryOnClick: Boolean = false,
|
||||
): SoundlessWidget(pX, pY, pWidth, pHeight, Component.literal("Summary - ModelWidget")) {
|
||||
|
||||
companion object {
|
||||
@@ -70,6 +71,15 @@ class ModelWidget(
|
||||
matrices.popPose()
|
||||
}
|
||||
|
||||
override fun onClick(pMouseX: Double, pMouseY: Double) {
|
||||
override fun mouseClicked(pMouseX: Double, pMouseY: Double, pButton: Int): Boolean {
|
||||
if (this.isHovered) playCry()
|
||||
return super.mouseClicked(pMouseX, pMouseY, pButton)
|
||||
}
|
||||
|
||||
private fun playCry() {
|
||||
if (playCryOnClick) {
|
||||
state.activeAnimations.clear()
|
||||
state.addFirstAnimation(setOf("cry"))
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.summary.widgets
|
||||
import com.cobblemon.mod.common.CobblemonNetwork
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetNicknamePacket
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetNicknameHandler.MAX_NAME_LENGTH
|
||||
@@ -28,7 +29,7 @@ class NicknameEntryWidget(
|
||||
): EditBox(
|
||||
Minecraft.getInstance().font,
|
||||
x, y, width, height, text
|
||||
) {
|
||||
), CobblemonRenderable {
|
||||
|
||||
var pokemonName = ""
|
||||
|
||||
|
||||
+2
-1
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.summary.widgets.common
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.Minecraft
|
||||
@@ -29,7 +30,7 @@ abstract class SummaryScrollList<T : ObjectSelectionList.Entry<T>>(
|
||||
HEIGHT, // height
|
||||
0, // top
|
||||
slotHeight
|
||||
) {
|
||||
), CobblemonRenderable {
|
||||
companion object {
|
||||
const val WIDTH = 108
|
||||
const val HEIGHT = 112
|
||||
|
||||
+2
-1
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.summary.widgets.screens
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
@@ -24,7 +25,7 @@ class SummaryTab(
|
||||
val label: MutableComponent? = null,
|
||||
val icon: ResourceLocation? = null,
|
||||
onPress: OnPress
|
||||
): Button(pX, pY, 50, 13, label, onPress, DEFAULT_NARRATION) {
|
||||
): Button(pX, pY, 50, 13, label, onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
private var isActive = false
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, pMouseX: Int, pMouseY: Int, pPartialTicks: Float) {
|
||||
|
||||
Loaded 100 of 1015 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user