mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-22 07:06:23 -04:00
Compare commits
65
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86d48df9fe | ||
|
|
3401ba9cbb | ||
|
|
dac9ccb461 | ||
|
|
191a62f693 | ||
|
|
d8d410e539 | ||
|
|
b7c6e1ea77 | ||
|
|
0af4588a14 | ||
|
|
186812d6fd | ||
|
|
df9dc8c029 | ||
|
|
51dc606246 | ||
|
|
790f8347f8 | ||
|
|
09de901b35 | ||
|
|
1c0bdc766a | ||
|
|
c697bcd2e9 | ||
|
|
dcf321da8f | ||
|
|
c32bd4d014 | ||
|
|
ab4e2f2540 | ||
|
|
741bfb3316 | ||
|
|
9d6ff01d80 | ||
|
|
1691853a19 | ||
|
|
4e9a4e1e5a | ||
|
|
6450255a0b | ||
|
|
ce5df762f6 | ||
|
|
c5543cbd64 | ||
|
|
4929a4a567 | ||
|
|
e4591825c3 | ||
|
|
6d847e4b7d | ||
|
|
ac9d4f49d9 | ||
|
|
26e1145562 | ||
|
|
8417be3b89 | ||
|
|
53a7282c31 | ||
|
|
6349f12d8e | ||
|
|
052b01ff00 | ||
|
|
36f4e4fe1b | ||
|
|
06fe7568a5 | ||
|
|
dc03f26b20 | ||
|
|
b30ad68975 | ||
|
|
cc1f40a165 | ||
|
|
c1ce5491f1 | ||
|
|
588a5d4ce1 | ||
|
|
58bd15b3b2 | ||
|
|
88769ec1f2 | ||
|
|
aa790d0511 | ||
|
|
bd0b1bca3d | ||
|
|
2fa0204a20 | ||
|
|
d2d50a4c71 | ||
|
|
e07a5ca019 | ||
|
|
7bcd398438 | ||
|
|
830d30e0de | ||
|
|
21e279224d | ||
|
|
9b2d032c6a | ||
|
|
be76f8a180 | ||
|
|
6b6d9d9ecf | ||
|
|
2af0324ee5 | ||
|
|
8aa4f57a33 | ||
|
|
5f01e1a5d8 | ||
|
|
c43e6aba4a | ||
|
|
3599dc97cc | ||
|
|
8a5d895f03 | ||
|
|
26ef75fba7 | ||
|
|
dabc0ae859 | ||
|
|
6184bd850e | ||
|
|
01d2bcdfcf | ||
|
|
8d5e2f5773 | ||
|
|
73029800e4 |
@@ -0,0 +1,16 @@
|
||||
### Additions
|
||||
|
||||
- Added ability to rename PC Boxes by clicking on the name of a box
|
||||
- Added ability to set wallpapers per PC Box by clicking the button right to the box name
|
||||
- Added sorting by Name, Level and type by clicking the button left of the box name (shift reverses order)
|
||||
- Added filtering/search functionality in PC UI, which also supports pokemon properties (e.g. shiny=yes shows all shinies)
|
||||
- Added /changewallpaper <player> <boxNumber> <wallpaper> command to change a wallpaper through commands
|
||||
- Added /renamebox <player> <boxNumber> <name> command to rename a PC box through commands
|
||||
|
||||
### Developer
|
||||
|
||||
- Added RenamePCBoxEvent.Pre/Post events to prevent players from renaming a box or change their input
|
||||
- Added ChangePCBoxWallpaperEvent.Pre/Post to prevent players from changing to a wallpaper or change their selection
|
||||
- Added WallpaperCollectionEvent which gets called when clients connect to a server, allowing the server which of the clients found wallpapers it's allowed to move (collected wallpapers can be removed for example to make it "vanish" client-side)
|
||||
- Wallpapers are loaded from `assets/<namespace>/textures/gui/pc/wallpaper/` and all wallpapers in this folder are available to the client to choose by default
|
||||
- Renamed `SetPCBoxPokemonPacket` and the respective handler to `SetPCBoxPacket`
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
### Additions
|
||||
- Added support for NPCs to use Pokémon models and vice versa. This will require changes in addons that add fossil types due to naming conflicts between fossils and the Pokémon species.
|
||||
- Added `/changejointscale` command to change the scale of a joint in a model. Unbelievably funny.
|
||||
|
||||
### Developer
|
||||
- Removed all VaryingModelRepository subclasses into the parent class.
|
||||
|
||||
### Addons
|
||||
- Added `transformedParts` to the root of poser JSONs so it now exists in both poses and the model overall.
|
||||
@@ -1,14 +1,44 @@
|
||||
# Changelog
|
||||
## [1.7.0 (Month xth, 2025)](#1-7-0)
|
||||
|
||||
### Additions
|
||||
- Added an in-game configuration screen, allowing all settings from `main.json` to be edited directly in-game.
|
||||
- Added `/cobblemonconfig reload` command to reload `main.json` configuration. **Note:** Some settings require a server restart to take effect; use this command cautiously.
|
||||
- Added `blacklisted_items_to_hold` and `whitelisted_items_to_hold` tags to allow for controlling which items players can give to their Pokémon. If the whitelist is empty, it will consider all item as allowed (unless they are in the blacklist).
|
||||
- Pokémon now follow the mouse cursor on the Summary screen, with an option to disable this in the settings.
|
||||
|
||||
### Changes
|
||||
- Renamed `chargeGainedPerTick` config to `secondsToChargeHealingMachine`.
|
||||
|
||||
### Fixes
|
||||
- Fixed Particles sometimes facing the wrong direction (looking at you, Swords Dance)
|
||||
- Fixed PCs always opening at box 2 instead of box 1.
|
||||
- Fixed not being able to do complex item requirements aside from just NBT with evolution conditions, requirements and fossil items.
|
||||
- Fixed the usage `hiddenability` in `pokegive` or other spawn commands resulting in a forced hidden ability
|
||||
- Fixed the consumption of friendship berries (or EV berries) not making any noise
|
||||
- Fixed Instantly breaking and replacing a fossil analyzer with any block entity crashing the game in a complete multi-structure
|
||||
- Fixed players getting disconnected when sidemods update a Pokémon's teratype
|
||||
- Fixed fling not using Item Names for minecraft held items that substitute Pokémon items
|
||||
- Fixed evolutions sometimes preventing players from logging in to servers
|
||||
- Fixed rendering of shoulder-mounted Pokémon desyncing between clients
|
||||
|
||||
### Developer
|
||||
- A finished battle now has winners and losers set inside of `PokemonBattle` instead of them always being empty.
|
||||
- Dialogues are correctly removed from memory when they are stopped.
|
||||
- Dialogues with variably-set initial pages now properly start timeout tracking.
|
||||
- Added `EvGainedEvent.Pre` and `EvGainedEvent.Post`.
|
||||
- Deprecated `EVs#add(Stat, Int)`, you will not be able to compile against this code please migrate to the `EVs#add(Stat, Int, EvSource)` you most likely want to use `SidemodEvSource` but please check other implementations or make your own.
|
||||
- Removed the NbtItemPredicate class, all the mod usages now use the vanilla item predicate solution, this causes breaking changes on Fossil, HeldItemRequirement & ItemInteractionEvolution
|
||||
- Renamed Cobblemon's creative tabs to start with "Cobblemon: " to distinguish Cobblemon's tabs from tabs for other mods.
|
||||
- Various items now have a rarity value.
|
||||
|
||||
### Changes
|
||||
- When using the `cobblemon` or `generation_9` capture calculators a critical capture with a single shake will always play for successful captures when you've already registered the Pokémon as caught in your Pokédex.
|
||||
### MoLang & Datapacks
|
||||
- The following usages for item predicates can now use item conditions like advancements do, you can learn about them in the [Minecraft wiki](https://minecraft.wiki/w/Advancement_definition#minecraft:filled_bucket)
|
||||
- The `requiredContext` for an item interaction evolution
|
||||
- The `itemCondition` for a held item evolution requirement
|
||||
- The `fossils` for a fossil entry
|
||||
|
||||
## [1.6.1 (January 26th, 2025)](#1-6-1)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Cobblemon
|
||||
|
||||
An open-source Pokémon mod for Minecraft Java Edition, written in Kotlin for Fabric and Forge.
|
||||
An open-source Pokémon mod for Minecraft Java Edition, written in Kotlin for Fabric and NeoForge.
|
||||
|
||||
## Getting started
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ dependencies {
|
||||
|
||||
// Integrations
|
||||
compileOnlyApi(libs.jei.api)
|
||||
modCompileOnly(libs.bundles.fabric.integrations.compileOnly) {
|
||||
modCompileOnly(libs.bundles.common.integrations.compileOnly) {
|
||||
isTransitive = false
|
||||
}
|
||||
// Flywheel has no common dep so just pick one and don't use any platform specific code in common
|
||||
|
||||
@@ -62,11 +62,7 @@ import com.cobblemon.mod.common.api.storage.player.adapter.PlayerDataMongoBacken
|
||||
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
|
||||
import com.cobblemon.mod.common.battles.BagItems
|
||||
import com.cobblemon.mod.common.battles.BattleFormat
|
||||
import com.cobblemon.mod.common.battles.BattleRegistry
|
||||
import com.cobblemon.mod.common.battles.BattleSide
|
||||
import com.cobblemon.mod.common.battles.ShowdownThread
|
||||
import com.cobblemon.mod.common.battles.*
|
||||
import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.client.CobblemonPack
|
||||
@@ -89,22 +85,11 @@ import com.cobblemon.mod.common.pokemon.aspects.SHINY_ASPECT
|
||||
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.*
|
||||
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.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.util.*
|
||||
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
|
||||
@@ -112,25 +97,27 @@ import com.mongodb.ConnectionString
|
||||
import com.mongodb.MongoClientSettings
|
||||
import com.mongodb.client.MongoClient
|
||||
import com.mongodb.client.MongoClients
|
||||
import java.io.File
|
||||
import java.io.FileReader
|
||||
import java.io.FileWriter
|
||||
import java.io.PrintWriter
|
||||
import java.util.UUID
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.properties.Delegates
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import kotlin.reflect.jvm.javaField
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.commands.synchronization.SingletonArgumentInfo
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.world.item.NameTagItem
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.storage.LevelResource
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import org.apache.logging.log4j.Logger
|
||||
import java.io.File
|
||||
import java.io.FileReader
|
||||
import java.io.FileWriter
|
||||
import java.io.PrintWriter
|
||||
import java.util.*
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.properties.Delegates
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import kotlin.reflect.jvm.javaField
|
||||
|
||||
object Cobblemon {
|
||||
const val MODID = CobblemonBuildDetails.MOD_ID
|
||||
@@ -164,6 +151,7 @@ object Cobblemon {
|
||||
var permissionValidator: PermissionValidator by Delegates.observable(LaxPermissionValidator().also { it.initialize() }) { _, _, newValue -> newValue.initialize() }
|
||||
var statProvider: StatProvider = CobblemonStatProvider
|
||||
var seasonResolver: SeasonResolver = TagSeasonResolver
|
||||
var wallpapers = mapOf<UUID, List<ResourceLocation>>()
|
||||
|
||||
@JvmStatic
|
||||
val builtinPacks = listOf<CobblemonPack>(
|
||||
@@ -220,7 +208,8 @@ object Cobblemon {
|
||||
storage.onPlayerDataSync(it)
|
||||
playerDataManager.syncAllToPlayer(it)
|
||||
starterHandler.handleJoin(it)
|
||||
ServerSettingsPacket(this.config.preventCompletePartyDeposit, this.config.displayEntityLevelLabel, this.config.displayEntityNameLabel, this.config.maxPokemonLevel, this.config.maxPokemonFriendship, this.config.maxDynamaxLevel).sendToPlayer(it)
|
||||
it.requestWallpapers()
|
||||
sendServerSettingsPacketToPlayer(it)
|
||||
}
|
||||
PlatformEvents.SERVER_PLAYER_LOGOUT.subscribe {
|
||||
PCLinkManager.removeLink(it.player.uuid)
|
||||
@@ -268,8 +257,17 @@ object Cobblemon {
|
||||
}
|
||||
|
||||
HeldItemProvider.register(CobblemonHeldItemManager, Priority.LOWEST)
|
||||
}
|
||||
|
||||
|
||||
fun sendServerSettingsPacketToPlayer(player: ServerPlayer) {
|
||||
ServerSettingsPacket(
|
||||
this.config.preventCompletePartyDeposit,
|
||||
this.config.displayEntityLevelLabel,
|
||||
this.config.displayEntityNameLabel,
|
||||
this.config.maxPokemonLevel,
|
||||
this.config.maxPokemonFriendship,
|
||||
this.config.maxDynamaxLevel,
|
||||
).sendToPlayer(player)
|
||||
}
|
||||
|
||||
fun initialize() {
|
||||
@@ -429,7 +427,23 @@ object Cobblemon {
|
||||
}
|
||||
}
|
||||
|
||||
private fun initializeConfig() {
|
||||
loadCobblemonConfig()
|
||||
saveConfig(this.config)
|
||||
PokemonSpecies.observable.subscribe { starterConfig = this.loadStarterConfig() }
|
||||
}
|
||||
|
||||
fun loadConfig() {
|
||||
initializeConfig()
|
||||
bestSpawner.init()
|
||||
}
|
||||
|
||||
fun reloadConfig() {
|
||||
initializeConfig()
|
||||
bestSpawner.reloadConfig()
|
||||
}
|
||||
|
||||
private fun loadCobblemonConfig() {
|
||||
val configFile = File(CONFIG_PATH)
|
||||
configFile.parentFile.mkdirs()
|
||||
|
||||
@@ -472,12 +486,6 @@ object Cobblemon {
|
||||
} else {
|
||||
this.config = CobblemonConfig()
|
||||
}
|
||||
|
||||
config.lastSavedVersion = VERSION
|
||||
this.saveConfig()
|
||||
|
||||
bestSpawner.loadConfig()
|
||||
PokemonSpecies.observable.subscribe { starterConfig = this.loadStarterConfig() }
|
||||
}
|
||||
|
||||
fun loadStarterConfig(): StarterConfig {
|
||||
@@ -500,12 +508,14 @@ object Cobblemon {
|
||||
}
|
||||
}
|
||||
|
||||
fun saveConfig() {
|
||||
fun saveConfig(config: CobblemonConfig) {
|
||||
config.lastSavedVersion = VERSION
|
||||
|
||||
try {
|
||||
val configFile = File(CONFIG_PATH)
|
||||
val fileWriter = FileWriter(configFile)
|
||||
// Put the config to json then flush the writer to commence writing.
|
||||
CobblemonConfig.GSON.toJson(this.config, fileWriter)
|
||||
CobblemonConfig.GSON.toJson(config, fileWriter)
|
||||
fileWriter.flush()
|
||||
fileWriter.close()
|
||||
} catch (exception: Exception) {
|
||||
@@ -527,4 +537,4 @@ object Cobblemon {
|
||||
this.implementation.registerCommandArgument(cobblemonResource("npc_class"), NPCClassArgumentType::class, SingletonArgumentInfo.contextFree(NPCClassArgumentType::npcClass))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,9 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
|
||||
@JvmField
|
||||
val PC: BlockEntityType<PCBlockEntity> = this.create("pc", BlockEntityType.Builder.of(::PCBlockEntity, CobblemonBlocks.PC).build(null))
|
||||
|
||||
@JvmField
|
||||
val STADIUM: BlockEntityType<StadiumBlockEntity> = this.create("stadium_terminal", BlockEntityType.Builder.of(::StadiumBlockEntity, CobblemonBlocks.STADIUM).build(null))
|
||||
|
||||
@JvmField
|
||||
val LECTERN: BlockEntityType<LecternBlockEntity> = this.create("lectern", BlockEntityType.Builder.of(::LecternBlockEntity, CobblemonBlocks.LECTERN).build(null))
|
||||
|
||||
|
||||
@@ -354,6 +354,9 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val PC = create("pc", PCBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F).noOcclusion().lightLevel { if ((it.getValue(PCBlock.ON) as Boolean) && (it.getValue(PCBlock.PART) == PCBlock.PCPart.TOP)) 10 else 0 }))
|
||||
|
||||
@JvmField
|
||||
val STADIUM = create("stadium_terminal", StadiumBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F)))
|
||||
|
||||
@JvmField
|
||||
val LECTERN = create("lectern", LecternBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).sound(SoundType.WOOD).strength(2.5F).ignitedByLava()))
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ object CobblemonCommands {
|
||||
ChangeEyeHeight.register(dispatcher)
|
||||
ChangeScaleAndSize.register(dispatcher)
|
||||
ChangeWalkSpeed.register(dispatcher)
|
||||
ChangeJointScaleCommand.register(dispatcher)
|
||||
TestCommand.register(dispatcher)
|
||||
ReloadShowdownCommand.register(dispatcher)
|
||||
ClickTextCommand.register(dispatcher)
|
||||
@@ -56,7 +57,10 @@ object CobblemonCommands {
|
||||
AbandonMultiTeam.register(dispatcher)
|
||||
FreezePokemonCommand.register(dispatcher)
|
||||
ApplyPlayerTextureCommand.register(dispatcher)
|
||||
RenameBoxCommand.register(dispatcher)
|
||||
ChangeBoxWallpaperCommand.register(dispatcher)
|
||||
RunMolangScriptCommand.register(dispatcher)
|
||||
CobblemonConfigCommand.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
|
||||
|
||||
@@ -35,7 +35,6 @@ import com.cobblemon.mod.common.pokeball.PokeBall
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.core.component.DataComponents
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.network.chat.Component
|
||||
@@ -269,10 +268,12 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val MONITOR = blockItem("monitor", CobblemonBlocks.MONITOR)
|
||||
@JvmField
|
||||
val HEALING_MACHINE = blockItem("healing_machine", CobblemonBlocks.HEALING_MACHINE)
|
||||
val HEALING_MACHINE = blockItem("healing_machine", CobblemonBlocks.HEALING_MACHINE, Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val PC = blockItem("pc", CobblemonBlocks.PC)
|
||||
@JvmField
|
||||
val STADIUM = blockItem("stadium_terminal", CobblemonBlocks.STADIUM)
|
||||
@JvmField
|
||||
val PASTURE = blockItem("pasture", CobblemonBlocks.PASTURE)
|
||||
@JvmField
|
||||
val DISPLAY_CASE = blockItem("display_case", CobblemonBlocks.DISPLAY_CASE)
|
||||
@@ -398,7 +399,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
|
||||
// Medicine
|
||||
@JvmField
|
||||
val RARE_CANDY = candyItem("rare_candy") { _, pokemon -> pokemon.getExperienceToNextLevel() }
|
||||
val RARE_CANDY = candyItem("rare_candy", Rarity.RARE) { _, pokemon -> pokemon.getExperienceToNextLevel() }
|
||||
@JvmField
|
||||
val EXPERIENCE_CANDY_XS = candyItem("exp_candy_xs") { _, _ -> CandyItem.DEFAULT_XS_CANDY_YIELD }
|
||||
@JvmField
|
||||
@@ -883,48 +884,48 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
|
||||
// Archaeology
|
||||
@JvmField
|
||||
val ARMOR_FOSSIL = noSettingsItem("armor_fossil")
|
||||
val ARMOR_FOSSIL = itemWithRarity("armor_fossil", Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val FOSSILIZED_BIRD = noSettingsItem("fossilized_bird")
|
||||
val FOSSILIZED_BIRD = itemWithRarity("fossilized_bird", Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val CLAW_FOSSIL = noSettingsItem("claw_fossil")
|
||||
val CLAW_FOSSIL = itemWithRarity("claw_fossil", Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val COVER_FOSSIL = noSettingsItem("cover_fossil")
|
||||
val COVER_FOSSIL = itemWithRarity("cover_fossil", Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val FOSSILIZED_DINO = noSettingsItem("fossilized_dino")
|
||||
val FOSSILIZED_DINO = itemWithRarity("fossilized_dino", Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val DOME_FOSSIL = noSettingsItem("dome_fossil")
|
||||
val DOME_FOSSIL = itemWithRarity("dome_fossil", Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val FOSSILIZED_DRAKE = noSettingsItem("fossilized_drake")
|
||||
val FOSSILIZED_DRAKE = itemWithRarity("fossilized_drake", Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val FOSSILIZED_FISH = noSettingsItem("fossilized_fish")
|
||||
val FOSSILIZED_FISH = itemWithRarity("fossilized_fish", Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val HELIX_FOSSIL = noSettingsItem("helix_fossil")
|
||||
val HELIX_FOSSIL = itemWithRarity("helix_fossil", Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val JAW_FOSSIL = noSettingsItem("jaw_fossil")
|
||||
val JAW_FOSSIL = itemWithRarity("jaw_fossil", Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val OLD_AMBER_FOSSIL = noSettingsItem("old_amber_fossil")
|
||||
val OLD_AMBER_FOSSIL = itemWithRarity("old_amber_fossil", Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val PLUME_FOSSIL = noSettingsItem("plume_fossil")
|
||||
val PLUME_FOSSIL = itemWithRarity("plume_fossil", Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val ROOT_FOSSIL = noSettingsItem("root_fossil")
|
||||
val ROOT_FOSSIL = itemWithRarity("root_fossil", Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val SAIL_FOSSIL = noSettingsItem("sail_fossil")
|
||||
val SAIL_FOSSIL = itemWithRarity("sail_fossil", Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val SKULL_FOSSIL = noSettingsItem("skull_fossil")
|
||||
val SKULL_FOSSIL = itemWithRarity("skull_fossil", Rarity.UNCOMMON)
|
||||
|
||||
@JvmField
|
||||
val BYGONE_SHERD = noSettingsItem("bygone_sherd")
|
||||
val BYGONE_SHERD = itemWithRarity("bygone_sherd", Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val CAPTURE_SHERD = noSettingsItem("capture_sherd")
|
||||
val CAPTURE_SHERD = itemWithRarity("capture_sherd",Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val DOME_SHERD = noSettingsItem("dome_sherd")
|
||||
val DOME_SHERD = itemWithRarity("dome_sherd", Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val HELIX_SHERD = noSettingsItem("helix_sherd")
|
||||
val HELIX_SHERD = itemWithRarity("helix_sherd", Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val NOSTALGIC_SHERD = noSettingsItem("nostalgic_sherd")
|
||||
val NOSTALGIC_SHERD = itemWithRarity("nostalgic_sherd",Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val SUSPICIOUS_SHERD = noSettingsItem("suspicious_sherd")
|
||||
val SUSPICIOUS_SHERD = itemWithRarity("suspicious_sherd", Rarity.UNCOMMON)
|
||||
|
||||
@JvmField
|
||||
val TUMBLESTONE = this.create("tumblestone", TumblestoneItem(Item.Properties(), CobblemonBlocks.SMALL_BUDDING_TUMBLESTONE))
|
||||
@@ -1144,11 +1145,11 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val DREAM_ROD = pokerodItem(cobblemonResource("dream_rod"))
|
||||
@JvmField
|
||||
val BEAST_ROD = pokerodItem(cobblemonResource("beast_rod"))
|
||||
val BEAST_ROD = pokerodItem(cobblemonResource("beast_rod"), Rarity.RARE)
|
||||
@JvmField
|
||||
val MASTER_ROD = pokerodItem(cobblemonResource("master_rod"))
|
||||
val MASTER_ROD = pokerodItem(cobblemonResource("master_rod"), Rarity.EPIC)
|
||||
@JvmField
|
||||
val CHERISH_ROD = pokerodItem(cobblemonResource("cherish_rod"))
|
||||
val CHERISH_ROD = pokerodItem(cobblemonResource("cherish_rod"), Rarity.EPIC)
|
||||
@JvmField
|
||||
val ANCIENT_POKE_ROD = pokerodItem(cobblemonResource("ancient_poke_rod"))
|
||||
@JvmField
|
||||
@@ -1180,7 +1181,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val ANCIENT_GIGATON_ROD = pokerodItem(cobblemonResource("ancient_gigaton_rod"))
|
||||
@JvmField
|
||||
val ANCIENT_ORIGIN_ROD = pokerodItem(cobblemonResource("ancient_origin_rod"))
|
||||
val ANCIENT_ORIGIN_ROD = pokerodItem(cobblemonResource("ancient_origin_rod"), Rarity.EPIC)
|
||||
|
||||
// Misc
|
||||
@JvmField
|
||||
@@ -1232,10 +1233,12 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
//@JvmField
|
||||
//val BINDING_SOIL = blockItem("binding_soil", CobblemonBlocks.BINDING_SOIL)
|
||||
|
||||
private fun blockItem(name: String, block: Block): BlockItem = this.create(name, BlockItem(block, Item.Properties()))
|
||||
private fun blockItem(name: String, block: Block, rarity: Rarity = Rarity.COMMON): BlockItem = this.create(name, BlockItem(block, Item.Properties().rarity(rarity)))
|
||||
|
||||
private fun noSettingsItem(name: String): CobblemonItem = this.create(name, CobblemonItem(Item.Properties()))
|
||||
|
||||
private fun itemWithRarity(name: String, rarity: Rarity): CobblemonItem = this.create(name, CobblemonItem(Item.Properties().rarity(rarity)))
|
||||
|
||||
fun berries() = this.berries.toMap()
|
||||
|
||||
private fun mulchItem(name: String, mulchVariant: MulchVariant): MulchItem = this.create(name, MulchItem(mulchVariant))
|
||||
@@ -1247,10 +1250,10 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
return item
|
||||
}
|
||||
|
||||
private fun candyItem(name: String, calculator: CandyItem.Calculator): CandyItem = this.create(name, CandyItem(calculator))
|
||||
private fun candyItem(name: String, rarity: Rarity = Rarity.COMMON, calculator: CandyItem.Calculator): CandyItem = this.create(name, CandyItem(rarity, calculator))
|
||||
|
||||
private fun pokerodItem(pokeRodId: ResourceLocation): PokerodItem {
|
||||
val settings = Item.Properties().stacksTo(1).durability(256)
|
||||
private fun pokerodItem(pokeRodId: ResourceLocation, rarity: Rarity = Rarity.COMMON): PokerodItem {
|
||||
val settings = Item.Properties().stacksTo(1).durability(256).rarity(rarity)
|
||||
val item = create(pokeRodId.path, PokerodItem(pokeRodId, settings))
|
||||
pokeRods.add(item)
|
||||
return item
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.cobblemon.mod.common.client.net.pasture.PokemonPasturedHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.PokemonUnpasturedHandler
|
||||
import com.cobblemon.mod.common.client.net.pokedex.ServerConfirmedRegisterHandler
|
||||
import com.cobblemon.mod.common.client.net.pokemon.update.PokemonUpdatePacketHandler
|
||||
import com.cobblemon.mod.common.client.net.settings.OpenCobblemonConfigEditorHandler
|
||||
import com.cobblemon.mod.common.client.net.settings.ServerSettingsPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.sound.UnvalidatedPlaySoundS2CPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.spawn.SpawnExtraDataEntityHandler
|
||||
@@ -44,12 +45,7 @@ import com.cobblemon.mod.common.client.net.storage.party.InitializePartyHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.party.MoveClientPartyPokemonHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.party.SetPartyPokemonHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.party.SetPartyReferenceHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.pc.ClosePCHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.pc.InitializePCHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.pc.MoveClientPCPokemonHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.pc.OpenPCHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.pc.SetPCBoxPokemonHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.pc.SetPCPokemonHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.pc.*
|
||||
import com.cobblemon.mod.common.client.net.toast.ToastPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.*
|
||||
import com.cobblemon.mod.common.net.PacketRegisterInfo
|
||||
@@ -66,9 +62,6 @@ import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueOpenedPacke
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.fishing.FishingBaitRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.fossil.FossilRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.fossil.NaturalMaterialRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.npc.CloseNPCEditorPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.npc.OpenNPCEditorPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.ClosePasturePacket
|
||||
@@ -80,6 +73,7 @@ import com.cobblemon.mod.common.net.messages.client.pokemon.update.*
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.AddEvolutionPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.ClearEvolutionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.RemoveEvolutionPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.settings.OpenCobblemonConfigScreenPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnGenericBedrockPacket
|
||||
@@ -94,6 +88,9 @@ import com.cobblemon.mod.common.net.messages.client.storage.party.MoveClientPart
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyReferencePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.ChangePCBoxWallpaperPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.RequestPCBoxWallpapersPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.SetPCBoxWallpapersPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.toast.ToastPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.*
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
|
||||
@@ -127,7 +124,11 @@ import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokem
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePCPokemonToPartyPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePartyPokemonToPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.PCBoxWallpapersPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.ReleasePCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.RequestChangePCBoxWallpaperPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.RequestRenamePCBoxPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.SortPCBoxPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.SwapPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.UnlinkPlayerFromPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.*
|
||||
@@ -160,12 +161,7 @@ import com.cobblemon.mod.common.net.serverhandling.storage.SwapPCPartyPokemonHan
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.party.MovePartyPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.party.ReleasePCPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.party.SwapPartyPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.pc.MovePCPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.pc.MovePCPokemonToPartyHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.pc.MovePartyPokemonToPCHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.pc.ReleasePartyPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.pc.SwapPCPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.pc.UnlinkPlayerFromPCHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.*
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
@@ -221,6 +217,9 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(SpeciesFeatureUpdatePacket.ID, SpeciesFeatureUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(OriginalTrainerUpdatePacket.ID, OriginalTrainerUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(FormUpdatePacket.ID, FormUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(TeraTypeUpdatePacket.ID, TeraTypeUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(DmaxLevelUpdatePacket.ID, DmaxLevelUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(GmaxFactorUpdatePacket.ID, GmaxFactorUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
|
||||
// Evolution start
|
||||
list.add(PacketRegisterInfo(AddEvolutionPacket.ID, AddEvolutionPacket::decode, PokemonUpdatePacketHandler()))
|
||||
@@ -235,13 +234,18 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(SetPartyReferencePacket.ID, SetPartyReferencePacket::decode, SetPartyReferenceHandler))
|
||||
list.add(PacketRegisterInfo(InitializePCPacket.ID, InitializePCPacket::decode, InitializePCHandler))
|
||||
list.add(PacketRegisterInfo(MoveClientPCPokemonPacket.ID, MoveClientPCPokemonPacket::decode, MoveClientPCPokemonHandler))
|
||||
list.add(PacketRegisterInfo(SetPCBoxPokemonPacket.ID, SetPCBoxPokemonPacket::decode, SetPCBoxPokemonHandler))
|
||||
list.add(PacketRegisterInfo(SetPCBoxPacket.ID, SetPCBoxPacket::decode, SetPCBoxHandler))
|
||||
list.add(PacketRegisterInfo(SetPCPokemonPacket.ID, SetPCPokemonPacket::decode, SetPCPokemonHandler))
|
||||
list.add(PacketRegisterInfo(OpenPCPacket.ID, OpenPCPacket::decode, OpenPCHandler))
|
||||
list.add(PacketRegisterInfo(ClosePCPacket.ID, ClosePCPacket::decode, ClosePCHandler))
|
||||
list.add(PacketRegisterInfo(SwapClientPokemonPacket.ID, SwapClientPokemonPacket::decode, SwapClientPokemonHandler))
|
||||
list.add(PacketRegisterInfo(RemoveClientPokemonPacket.ID, RemoveClientPokemonPacket::decode, RemoveClientPokemonHandler))
|
||||
|
||||
list.add(PacketRegisterInfo(RenamePCBoxPacket.ID, RenamePCBoxPacket::decode, RenamePCBoxHandler))
|
||||
list.add(PacketRegisterInfo(RequestPCBoxWallpapersPacket.ID, RequestPCBoxWallpapersPacket::decode, RequestPCBoxWallpapersHandler))
|
||||
list.add(PacketRegisterInfo(SetPCBoxWallpapersPacket.ID, SetPCBoxWallpapersPacket::decode, SetPCBoxWallpapersHandler))
|
||||
list.add(PacketRegisterInfo(ChangePCBoxWallpaperPacket.ID, ChangePCBoxWallpaperPacket::decode, ChangePCBoxWallpaperHandler))
|
||||
|
||||
// UI Packets
|
||||
list.add(PacketRegisterInfo(SummaryUIPacket.ID, SummaryUIPacket::decode, SummaryUIPacketHandler))
|
||||
list.add(PacketRegisterInfo(InteractPokemonUIPacket.ID, InteractPokemonUIPacket::decode, InteractPokemonUIPacketHandler))
|
||||
@@ -279,11 +283,13 @@ object CobblemonNetwork {
|
||||
// MultiBattleTeam Packets
|
||||
list.add(PacketRegisterInfo(TeamRequestNotificationPacket.ID, TeamRequestNotificationPacket::decode, TeamRequestNotificationHandler))
|
||||
list.add(PacketRegisterInfo(TeamRequestExpiredPacket.ID, TeamRequestExpiredPacket::decode, TeamRequestExpiredHandler))
|
||||
list.add(PacketRegisterInfo(TeamMemberAddNotificationPacket.ID, TeamMemberAddNotificationPacket::decode, TeamMemberAddNotificationHandler))
|
||||
list.add(PacketRegisterInfo(TeamMemberRemoveNotificationPacket.ID, TeamMemberRemoveNotificationPacket::decode, TeamMemberRemoveNotificationHandler))
|
||||
list.add(PacketRegisterInfo(TeamJoinNotificationPacket.ID, TeamJoinNotificationPacket::decode, TeamJoinNotificationHandler))
|
||||
|
||||
// Settings packets
|
||||
list.add(PacketRegisterInfo(ServerSettingsPacket.ID, ServerSettingsPacket::decode, ServerSettingsPacketHandler))
|
||||
list.add(PacketRegisterInfo(OpenCobblemonConfigScreenPacket.ID, OpenCobblemonConfigScreenPacket::decode, OpenCobblemonConfigEditorHandler))
|
||||
|
||||
// Data registries
|
||||
list.add(PacketRegisterInfo(AbilityRegistrySyncPacket.ID, AbilityRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
@@ -387,6 +393,10 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(ReleasePCPokemonPacket.ID, ReleasePCPokemonPacket::decode, ReleasePCPokemonHandler))
|
||||
list.add(PacketRegisterInfo(UnlinkPlayerFromPCPacket.ID, UnlinkPlayerFromPCPacket::decode, UnlinkPlayerFromPCHandler))
|
||||
|
||||
list.add(PacketRegisterInfo(RequestRenamePCBoxPacket.Companion.ID, RequestRenamePCBoxPacket.Companion::decode, RequestRenamePCBoxHandler))
|
||||
list.add(PacketRegisterInfo(PCBoxWallpapersPacket.ID, PCBoxWallpapersPacket::decode, PCBoxWallpapersHandler))
|
||||
list.add(PacketRegisterInfo(RequestChangePCBoxWallpaperPacket.ID, RequestChangePCBoxWallpaperPacket::decode, RequestChangePCBoxWallpaperHandler))
|
||||
|
||||
// Starter packets
|
||||
list.add(PacketRegisterInfo(SelectStarterPacket.ID, SelectStarterPacket::decode, SelectStarterPacketHandler))
|
||||
list.add(PacketRegisterInfo(RequestStarterScreenPacket.ID, RequestStarterScreenPacket::decode, RequestStarterScreenHandler))
|
||||
@@ -399,6 +409,8 @@ object CobblemonNetwork {
|
||||
|
||||
list.add(PacketRegisterInfo(SwapPCPartyPokemonPacket.ID, SwapPCPartyPokemonPacket::decode, SwapPCPartyPokemonHandler))
|
||||
|
||||
list.add(PacketRegisterInfo(SortPCBoxPacket.ID, SortPCBoxPacket::decode, SortPCBoxHandler))
|
||||
|
||||
// Battle packets
|
||||
list.add(PacketRegisterInfo(BattleSelectActionsPacket.ID, BattleSelectActionsPacket::decode, BattleSelectActionsHandler))
|
||||
list.add(PacketRegisterInfo(SpectateBattlePacket.ID, SpectateBattlePacket::decode, SpectateBattleHandler))
|
||||
|
||||
@@ -43,7 +43,8 @@ interface SleepDepth {
|
||||
"comatose" to comatose,
|
||||
"normal" to normal
|
||||
)
|
||||
val adapter = StringIdentifiedObjectAdapter { depths[it] ?: throw IllegalArgumentException("Unknown sleep depth: $it") }
|
||||
|
||||
val adapter = StringIdentifiedObjectAdapter({ depths[it] ?: throw IllegalArgumentException("Unknown sleep depth: $it") })
|
||||
}
|
||||
|
||||
fun canSleep(pokemonEntity: PokemonEntity): Boolean
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleFledEvent
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.BattleEvSource
|
||||
import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
@@ -272,7 +273,7 @@ open class PokemonBattle(
|
||||
opponent.awardExperience(opponentPokemon, experience)
|
||||
}
|
||||
Cobblemon.evYieldCalculator.calculate(opponentPokemon, faintedPokemon).forEach { (stat, amount) ->
|
||||
pokemon.evs.add(stat, amount)
|
||||
pokemon.evs.add(stat, amount, BattleEvSource(this, opponentPokemon.facedOpponents.toList(), pokemon))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.drop
|
||||
|
||||
import com.cobblemon.mod.common.api.serialization.StringIdentifiedObjectAdapter
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
/**
|
||||
* The way an item will be dropped.
|
||||
@@ -28,6 +29,9 @@ enum class ItemDropMethod(val methodName: String) {
|
||||
TO_INVENTORY("to-inventory");
|
||||
|
||||
companion object {
|
||||
val adapter = StringIdentifiedObjectAdapter { str -> values().firstOrNull { it.methodName == str } }
|
||||
val adapter = StringIdentifiedObjectAdapter(
|
||||
{ str -> ItemDropMethod.entries.firstOrNull { it.methodName == str } },
|
||||
{ value -> (value ?: ON_ENTITY).methodName },
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,10 @@ import com.cobblemon.mod.common.api.events.pokemon.healing.PokemonHealedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.interaction.ExperienceCandyUseEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.interaction.PokemonInteractionGUICreationEvent
|
||||
import com.cobblemon.mod.common.api.events.starter.StarterChosenEvent
|
||||
import com.cobblemon.mod.common.api.events.storage.ChangePCBoxWallpaperEvent
|
||||
import com.cobblemon.mod.common.api.events.storage.ReleasePokemonEvent
|
||||
import com.cobblemon.mod.common.api.events.storage.RenamePCBoxEvent
|
||||
import com.cobblemon.mod.common.api.events.storage.WallpaperCollectionEvent
|
||||
import com.cobblemon.mod.common.api.events.world.BigRootPropagatedEvent
|
||||
import com.cobblemon.mod.common.api.reactive.CancelableObservable
|
||||
import com.cobblemon.mod.common.api.reactive.EventObservable
|
||||
@@ -158,11 +161,29 @@ object CobblemonEvents {
|
||||
@JvmField
|
||||
val EXPERIENCE_CANDY_USE_POST = EventObservable<ExperienceCandyUseEvent.Post>()
|
||||
|
||||
@JvmField
|
||||
val EV_GAINED_EVENT_PRE = CancelableObservable<EvGainedEvent.Pre>()
|
||||
@JvmField
|
||||
val EV_GAINED_EVENT_POST = EventObservable<EvGainedEvent.Post>()
|
||||
|
||||
@JvmField
|
||||
val POKEMON_RELEASED_EVENT_PRE = CancelableObservable<ReleasePokemonEvent.Pre>()
|
||||
@JvmField
|
||||
val POKEMON_RELEASED_EVENT_POST = EventObservable<ReleasePokemonEvent.Post>()
|
||||
|
||||
@JvmField
|
||||
val RENAME_PC_BOX_EVENT_PRE = CancelableObservable<RenamePCBoxEvent.Pre>()
|
||||
@JvmField
|
||||
val RENAME_PC_BOX_EVENT_POST = EventObservable<RenamePCBoxEvent.Post>()
|
||||
|
||||
@JvmField
|
||||
val WALLPAPER_COLLECTION_EVENT = EventObservable<WallpaperCollectionEvent>()
|
||||
|
||||
@JvmField
|
||||
val CHANGE_PC_BOX_WALLPAPER_EVENT_PRE = CancelableObservable<ChangePCBoxWallpaperEvent.Pre>()
|
||||
@JvmField
|
||||
val CHANGE_PC_BOX_WALLPAPER_EVENT_POST = EventObservable<ChangePCBoxWallpaperEvent.Post>()
|
||||
|
||||
@JvmField
|
||||
val LOOT_DROPPED = CancelableObservable<LootDroppedEvent>()
|
||||
@JvmField
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.EvSource
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
/**
|
||||
* Fired during EV mutation.
|
||||
*
|
||||
* @see [Pre]
|
||||
* @see [Post]
|
||||
*/
|
||||
interface EvGainedEvent {
|
||||
|
||||
/**
|
||||
* The [Stat] having EVs added to itself.
|
||||
*/
|
||||
val stat: Stat
|
||||
|
||||
/**
|
||||
* @see EvSource.pokemon
|
||||
*/
|
||||
val pokemon: Pokemon get() = this.source.pokemon
|
||||
|
||||
/**
|
||||
* The [EvSource] that fired this event.
|
||||
*/
|
||||
val source: EvSource
|
||||
|
||||
/**
|
||||
* Fired before EV mutation occurs, cancelling will cause the mutation to be flagged as not successful (returns 0).
|
||||
*
|
||||
* @property stat See [EvGainedEvent.stat].
|
||||
* @property amount The amount of EVs that will be gained.
|
||||
* @property source See [EvGainedEvent.source].
|
||||
*/
|
||||
class Pre(override val stat: Stat, var amount: Int, override val source: EvSource) : EvGainedEvent, Cancelable()
|
||||
|
||||
/**
|
||||
* Fired after EV mutation occurs, this is purely for notification purposes.
|
||||
*
|
||||
* @property stat See [EvGainedEvent.stat].
|
||||
* @property amount The final amount of EVs gained.
|
||||
* @property source See [EvGainedEvent.source].
|
||||
*/
|
||||
class Post(override val stat: Stat, val amount: Int, override val source: EvSource) : EvGainedEvent
|
||||
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.storage
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.storage.pc.PCBox
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
/**
|
||||
* Events fired whenever a player changes their PC Wallpaper.
|
||||
* Has a cancelable [Pre] event and a [Post] which gets fired after the change.
|
||||
*
|
||||
* @author JustAHuman-xD
|
||||
* @since February 14th, 2025
|
||||
*/
|
||||
interface ChangePCBoxWallpaperEvent {
|
||||
|
||||
/**
|
||||
* The [ServerPlayer] who is changing their wallpaper
|
||||
*/
|
||||
val player: ServerPlayer
|
||||
|
||||
/**
|
||||
* The [PCBox] whose wallpaper is being changed
|
||||
*/
|
||||
val box: PCBox
|
||||
|
||||
/**
|
||||
* The location of the wallpaper that is being changed to. Can be modified in the [Pre] event.
|
||||
* NOTE: Changing this to a wallpaper that does not exist on the client, will result in a purple/black fallback texture being displayed.
|
||||
*/
|
||||
val wallpaper: ResourceLocation
|
||||
|
||||
class Pre(
|
||||
override val player: ServerPlayer,
|
||||
override val box: PCBox,
|
||||
override var wallpaper: ResourceLocation
|
||||
) : ChangePCBoxWallpaperEvent, Cancelable()
|
||||
|
||||
class Post(
|
||||
override val player: ServerPlayer,
|
||||
override val box: PCBox,
|
||||
override val wallpaper: ResourceLocation
|
||||
) : ChangePCBoxWallpaperEvent
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.storage
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.storage.pc.PCBox
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
/**
|
||||
* Events fired whenever a player renames one of their PC boxes.
|
||||
* Has a cancelable [Pre] event and a [Post] which gets fired after the change.
|
||||
*
|
||||
* @author JustAHuman-xD
|
||||
* @since February 14th, 2025
|
||||
*/
|
||||
interface RenamePCBoxEvent {
|
||||
|
||||
/**
|
||||
* The [ServerPlayer] who is changing their wallpaper
|
||||
*/
|
||||
val player: ServerPlayer
|
||||
|
||||
/**
|
||||
* The [PCBox] whose wallpaper is being changed
|
||||
*/
|
||||
val box: PCBox
|
||||
|
||||
/**
|
||||
* The new box name being used. This can be modified in the [Pre] event.
|
||||
*/
|
||||
val name: String
|
||||
|
||||
class Pre(
|
||||
override val player: ServerPlayer,
|
||||
override val box: PCBox,
|
||||
override var name: String
|
||||
) : RenamePCBoxEvent, Cancelable()
|
||||
|
||||
class Post(
|
||||
override val player: ServerPlayer,
|
||||
override val box: PCBox,
|
||||
override val name: String
|
||||
) : RenamePCBoxEvent
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.storage
|
||||
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
/**
|
||||
* Event being fired whenever the client connects to a server and "requests" what wallpapers are available for it to choose from.
|
||||
* Mods can listen to this event and remove available options from the client when they connect, essentially causing them to not exist client-side
|
||||
*
|
||||
* NOTE: Adding wallpapers here that do not exist on the client, will result in the purple/black fallback texture being displayed client-side.
|
||||
*
|
||||
* @author JustAHuman-xD
|
||||
* @since February 14th, 2025
|
||||
*/
|
||||
data class WallpaperCollectionEvent(
|
||||
val player: ServerPlayer,
|
||||
val wallpapers: MutableList<ResourceLocation>
|
||||
)
|
||||
@@ -11,7 +11,7 @@ package com.cobblemon.mod.common.api.fishing
|
||||
import com.cobblemon.mod.common.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.net.messages.client.fishing.FishingBaitRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.data.FishingBaitRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.Gson
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.fossil
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.pokemon.evolution.predicate.NbtItemPredicate
|
||||
import net.minecraft.advancements.critereon.ItemPredicate
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
@@ -19,7 +19,7 @@ import net.minecraft.world.item.ItemStack
|
||||
class Fossil(
|
||||
identifier: ResourceLocation,
|
||||
val result: PokemonProperties,
|
||||
val fossils: List<NbtItemPredicate>
|
||||
val fossils: List<ItemPredicate>
|
||||
): StringRepresentable {
|
||||
|
||||
@Transient
|
||||
|
||||
@@ -13,15 +13,15 @@ import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.net.messages.client.fossil.FossilRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.pokemon.evolution.adapters.NbtItemPredicateAdapter
|
||||
import com.cobblemon.mod.common.pokemon.evolution.predicate.NbtItemPredicate
|
||||
import com.cobblemon.mod.common.net.messages.client.data.FossilRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.pokemon.evolution.adapters.LegacyItemConditionWrapperAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ItemLikeConditionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.pokemonPropertiesShortAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.advancements.critereon.ItemPredicate
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
@@ -40,7 +40,7 @@ object Fossils: JsonDataRegistry<Fossil> {
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
|
||||
.registerTypeAdapter(NbtItemPredicate::class.java, NbtItemPredicateAdapter)
|
||||
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter)
|
||||
.create()
|
||||
|
||||
override val typeToken: TypeToken<Fossil> = TypeToken.get(Fossil::class.java)
|
||||
|
||||
@@ -10,7 +10,7 @@ package com.cobblemon.mod.common.api.fossil
|
||||
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.net.messages.client.fossil.NaturalMaterialRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.data.NaturalMaterialRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.registry.ItemTagCondition
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ItemLikeConditionAdapter
|
||||
|
||||
@@ -12,12 +12,10 @@ import com.cobblemon.mod.common.api.text.font
|
||||
import com.cobblemon.mod.common.client.gui.battle.BattleOverlay.Companion.PORTRAIT_DIAMETER
|
||||
import com.cobblemon.mod.common.client.render.SpriteType
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.util.toHex
|
||||
import com.mojang.authlib.minecraft.client.MinecraftClient
|
||||
import com.mojang.blaze3d.platform.GlStateManager
|
||||
import com.mojang.blaze3d.platform.Lighting
|
||||
import com.mojang.blaze3d.systems.RenderSystem
|
||||
@@ -209,7 +207,6 @@ fun drawPosablePortrait(
|
||||
contextScale: Float = 1F,
|
||||
reversed: Boolean = false,
|
||||
state: PosableState,
|
||||
repository: VaryingModelRepository<*>,
|
||||
partialTicks: Float,
|
||||
limbSwing: Float = 0F,
|
||||
limbSwingAmount: Float = 0F,
|
||||
@@ -227,16 +224,16 @@ fun drawPosablePortrait(
|
||||
matrixStack.scale(scale, scale, -scale)
|
||||
matrixStack.translate(0.0, -PORTRAIT_DIAMETER / 18.0, 0.0)
|
||||
|
||||
val sprite = repository.getSprite(identifier, state, SpriteType.PORTRAIT);
|
||||
val sprite = VaryingModelRepository.getSprite(identifier, state, SpriteType.PORTRAIT);
|
||||
|
||||
if (sprite == null) {
|
||||
val model = repository.getPoser(identifier, state)
|
||||
val model = VaryingModelRepository.getPoser(identifier, state)
|
||||
state.currentModel = model
|
||||
val texture = repository.getTexture(identifier, state)
|
||||
val texture = VaryingModelRepository.getTexture(identifier, state)
|
||||
|
||||
val context = RenderContext()
|
||||
model.context = context
|
||||
repository.getTextureNoSubstitute(identifier, state).let { context.put(RenderContext.TEXTURE, it) }
|
||||
VaryingModelRepository.getTextureNoSubstitute(identifier, state).let { context.put(RenderContext.TEXTURE, it) }
|
||||
context.put(RenderContext.SCALE, contextScale)
|
||||
context.put(RenderContext.SPECIES, identifier)
|
||||
context.put(RenderContext.ASPECTS, state.currentAspects)
|
||||
@@ -255,7 +252,7 @@ fun drawPosablePortrait(
|
||||
|
||||
matrixStack.translate(
|
||||
model.portraitTranslation.x * if (reversed) -1F else 1F,
|
||||
model.portraitTranslation.y,
|
||||
model.portraitTranslation.y + 1.5 * model.portraitScale,
|
||||
model.portraitTranslation.z - 4
|
||||
)
|
||||
matrixStack.scale(model.portraitScale, model.portraitScale, 1 / model.portraitScale)
|
||||
@@ -272,7 +269,7 @@ fun drawPosablePortrait(
|
||||
val packedLight = LightTexture.pack(11, 7)
|
||||
|
||||
val colour = toHex(r, g, b, a)
|
||||
model.withLayerContext(immediate, state, repository.getLayers(identifier, state)) {
|
||||
model.withLayerContext(immediate, state, VaryingModelRepository.getLayers(identifier, state)) {
|
||||
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, colour)
|
||||
immediate.endBatch()
|
||||
}
|
||||
@@ -288,7 +285,6 @@ fun drawPosablePortrait(
|
||||
}
|
||||
|
||||
fun drawProfile(
|
||||
repository: VaryingModelRepository<*>,
|
||||
resourceIdentifier: ResourceLocation,
|
||||
matrixStack: PoseStack,
|
||||
state: PosableState,
|
||||
@@ -298,16 +294,16 @@ fun drawProfile(
|
||||
RenderSystem.applyModelViewMatrix()
|
||||
matrixStack.scale(scale, scale, -scale)
|
||||
|
||||
val sprite = repository.getSprite(resourceIdentifier, state, SpriteType.PROFILE)
|
||||
val sprite = VaryingModelRepository.getSprite(resourceIdentifier, state, SpriteType.PROFILE)
|
||||
|
||||
if (sprite == null) {
|
||||
|
||||
val model = repository.getPoser(resourceIdentifier, state)
|
||||
val texture = repository.getTexture(resourceIdentifier, state)
|
||||
val model = VaryingModelRepository.getPoser(resourceIdentifier, state)
|
||||
val texture = VaryingModelRepository.getTexture(resourceIdentifier, state)
|
||||
|
||||
val context = RenderContext()
|
||||
model.context = context
|
||||
repository.getTextureNoSubstitute(resourceIdentifier, state).let { context.put(RenderContext.TEXTURE, it) }
|
||||
VaryingModelRepository.getTextureNoSubstitute(resourceIdentifier, state).let { context.put(RenderContext.TEXTURE, it) }
|
||||
context.put(RenderContext.SCALE, 1F)
|
||||
context.put(RenderContext.SPECIES, resourceIdentifier)
|
||||
context.put(RenderContext.ASPECTS, state.currentAspects)
|
||||
@@ -319,7 +315,11 @@ fun drawProfile(
|
||||
state.setPoseToFirstSuitable(PoseType.PORTRAIT)
|
||||
state.updatePartialTicks(partialTicks)
|
||||
model.applyAnimations(null, state, 0F, 0F, 0F, 0F, 0F)
|
||||
matrixStack.translate(model.profileTranslation.x, model.profileTranslation.y, model.profileTranslation.z - 4.0)
|
||||
matrixStack.translate(
|
||||
model.profileTranslation.x,
|
||||
model.profileTranslation.y + 1.5 * model.profileScale,
|
||||
model.profileTranslation.z - 4.0
|
||||
)
|
||||
matrixStack.scale(model.profileScale, model.profileScale, 1 / model.profileScale)
|
||||
// matrixStack.multiply(rotation)
|
||||
val quaternion1 = Axis.YP.rotationDegrees(-32F * if (false) -1F else 1F)
|
||||
@@ -337,7 +337,7 @@ fun drawProfile(
|
||||
RenderSystem.setShaderLights(light1, light2)
|
||||
val packedLight = LightTexture.pack(11, 7)
|
||||
|
||||
model.withLayerContext(bufferSource, state, repository.getLayers(resourceIdentifier, state)) {
|
||||
model.withLayerContext(bufferSource, state, VaryingModelRepository.getLayers(resourceIdentifier, state)) {
|
||||
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
bufferSource.endBatch()
|
||||
}
|
||||
|
||||
+6
-2
@@ -8,8 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.permission
|
||||
|
||||
import com.cobblemon.mod.common.command.AbandonMultiTeam
|
||||
|
||||
object CobblemonPermissions {
|
||||
|
||||
private const val COMMAND_PREFIX = "command."
|
||||
@@ -18,6 +16,7 @@ object CobblemonPermissions {
|
||||
val CHANGE_EYE_HEIGHT = this.create("${COMMAND_PREFIX}changeeyeheight", PermissionLevel.ALL_COMMANDS)
|
||||
val CHANGE_SCALE_AND_SIZE = this.create("${COMMAND_PREFIX}changescaleandsize", PermissionLevel.ALL_COMMANDS)
|
||||
val CHANGE_WALK_SPEED = this.create("${COMMAND_PREFIX}changewalkspeed", PermissionLevel.ALL_COMMANDS)
|
||||
val CHANGE_JOINT_SCALE = this.create("${COMMAND_PREFIX}changejointscale", PermissionLevel.ALL_COMMANDS)
|
||||
val CHECKSPAWNS = this.create("${COMMAND_PREFIX}checkspawns", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
val GET_NBT = this.create("${COMMAND_PREFIX}getnbt", PermissionLevel.ALL_COMMANDS)
|
||||
@@ -64,6 +63,9 @@ object CobblemonPermissions {
|
||||
|
||||
val POKEBOX = this.create("${COMMAND_PREFIX}pokebox", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
val RENAMEBOX = this.create("${COMMAND_PREFIX}renamebox", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
val CHANGE_WALLPAPER = this.create("${COMMAND_PREFIX}changewallpaper", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
val TEST_STORE = this.create("${COMMAND_PREFIX}teststore", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
val QUERY_LEARNSET = this.create("${COMMAND_PREFIX}querylearnset", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
@@ -84,6 +86,8 @@ object CobblemonPermissions {
|
||||
|
||||
val RUN_MOLANG_SCRIPT = this.create("${COMMAND_PREFIX}runmolangscript", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
val COBBLEMON_CONFIG_RELOAD = this.create("${COMMAND_PREFIX}cobblemonconfig.reload", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
fun all(): Iterable<Permission> = this.permissions
|
||||
|
||||
private fun create(node: String, level: PermissionLevel): Permission {
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokeball.catching.calculators
|
||||
|
||||
import com.cobblemon.mod.common.api.pokeball.catching.CaptureContext
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.pokedex
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
/**
|
||||
* An influencer on capture results based on Pokedex data.
|
||||
*/
|
||||
interface PokedexStatusCaptureInfluencer {
|
||||
|
||||
/**
|
||||
* Attempts to influence the [context] of a capture.
|
||||
*
|
||||
* @param thrower The [LivingEntity] that threw the Pokeball
|
||||
* @param target The [PokemonEntity] attempting to capture.
|
||||
* @param context The calculated [CaptureContext].
|
||||
* @return The final [CaptureContext].
|
||||
*/
|
||||
fun influence(thrower: LivingEntity, target: PokemonEntity, context: CaptureContext): CaptureContext {
|
||||
if (!context.isSuccessfulCapture) {
|
||||
return context
|
||||
}
|
||||
val player = thrower as? ServerPlayer ?: return context
|
||||
val pokedex = player.pokedex()
|
||||
val speciesId = target.pokemon.species.resourceIdentifier
|
||||
val formName = target.pokemon.form.name
|
||||
val hasCaughtStatus = pokedex.getOrCreateSpeciesRecord(speciesId)
|
||||
.getOrCreateFormRecord(formName)
|
||||
.knowledge == PokedexEntryProgress.CAUGHT
|
||||
// In modern games when the catch is a success and the Pokémon has already been registered to the Pokédex
|
||||
// the catch becomes a critical capture and only requires one shake
|
||||
return if (hasCaughtStatus) {
|
||||
CaptureContext(
|
||||
numberOfShakes = 1,
|
||||
isSuccessfulCapture = true,
|
||||
isCriticalCapture = true
|
||||
)
|
||||
} else context
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
enum class PokemonSortMode(val comparator: Comparator<Pokemon?>, val reverseComparator: Comparator<Pokemon?>) {
|
||||
NAME( { it?.getDisplayName()?.string } ),
|
||||
LEVEL( { it?.level } ),
|
||||
TYPE( { it?.primaryType?.name } );
|
||||
|
||||
constructor(mapper: (Pokemon?) -> Comparable<*>?) : this(compareBy({ it == null }, mapper),
|
||||
compareBy<Pokemon?> { it == null }.thenComparing(compareBy(mapper).reversed()))
|
||||
|
||||
fun comparator(descending: Boolean) = if (descending) reverseComparator else comparator
|
||||
}
|
||||
@@ -42,8 +42,7 @@ import com.cobblemon.mod.common.pokemon.SpeciesAdditions
|
||||
import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonEvolutionAdapter
|
||||
import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonPreEvolutionAdapter
|
||||
import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonRequirementAdapter
|
||||
import com.cobblemon.mod.common.pokemon.evolution.adapters.NbtItemPredicateAdapter
|
||||
import com.cobblemon.mod.common.pokemon.evolution.predicate.NbtItemPredicate
|
||||
import com.cobblemon.mod.common.pokemon.evolution.adapters.LegacyItemConditionWrapperAdapter
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.util.adapters.*
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
@@ -51,6 +50,7 @@ import com.google.common.collect.HashBasedTable
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.advancements.critereon.ItemPredicate
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
@@ -99,7 +99,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Structure::class.java).type, StructureLikeConditionAdapter)
|
||||
.registerTypeAdapter(EggGroup::class.java, EggGroupAdapter)
|
||||
.registerTypeAdapter(MobEffect::class.java, RegistryElementAdapter<MobEffect>(BuiltInRegistries::MOB_EFFECT))
|
||||
.registerTypeAdapter(NbtItemPredicate::class.java, NbtItemPredicateAdapter)
|
||||
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter)
|
||||
.disableHtmlEscaping()
|
||||
.enableComplexMapKeySerialization()
|
||||
.create()
|
||||
|
||||
@@ -105,6 +105,9 @@ interface Evolution : EvolutionLike {
|
||||
* @param pokemon The [Pokemon] being evolved.
|
||||
*/
|
||||
fun evolve(pokemon: Pokemon): Boolean {
|
||||
if (this.consumeHeldItem) {
|
||||
pokemon.swapHeldItem(ItemStack.EMPTY)
|
||||
}
|
||||
if (this.optional) {
|
||||
// All the networking is handled under the hood, see EvolutionController.
|
||||
return pokemon.evolutionProxy.server().add(this)
|
||||
@@ -220,10 +223,6 @@ interface Evolution : EvolutionLike {
|
||||
|
||||
this.shed(pokemon)
|
||||
|
||||
if (this.consumeHeldItem) {
|
||||
pokemon.swapHeldItem(ItemStack.EMPTY)
|
||||
}
|
||||
|
||||
val ownerPlayer = pokemon.getOwnerPlayer()
|
||||
if (ownerPlayer != null && ownerPlayer.level().gameRules.getBoolean(CobblemonGameRules.DO_POKEMON_LOOT)) {
|
||||
drops.drop(
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokemon.stats
|
||||
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
interface EvSource {
|
||||
|
||||
/**
|
||||
* The [Pokemon] being affected.
|
||||
*/
|
||||
val pokemon: Pokemon
|
||||
|
||||
/**
|
||||
* Utility function that checks if the source is an implementation of [BattleEvSource].
|
||||
*/
|
||||
fun isBattle() = this is BattleEvSource
|
||||
|
||||
/**
|
||||
* Utility function that checks if the source is an implementation of [ItemEvSource].
|
||||
*/
|
||||
fun isInteraction() = this is ItemEvSource
|
||||
|
||||
/**
|
||||
* Utility function that checks if the source is an implementation of [SidemodEvSource].
|
||||
*/
|
||||
fun isSidemod() = this is SidemodEvSource
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered by sidemods.
|
||||
*
|
||||
* @property sidemodId The mod ID of the sidemod triggering this source.
|
||||
* @property pokemon See [EvSource.pokemon].
|
||||
*/
|
||||
open class SidemodEvSource(
|
||||
val sidemodId: String,
|
||||
override val pokemon: Pokemon
|
||||
) : EvSource
|
||||
|
||||
/**
|
||||
* An Ev source fired when using Ev mutating items.
|
||||
*
|
||||
* @property player The [ServerPlayer] using the item.
|
||||
* @property stack The [ItemStack] being consumed.
|
||||
* @property pokemon See [EvSource.pokemon].
|
||||
*/
|
||||
open class ItemEvSource(
|
||||
val player: ServerPlayer,
|
||||
val stack: ItemStack,
|
||||
override val pokemon: Pokemon
|
||||
) : EvSource
|
||||
|
||||
/**
|
||||
* An Ev source fired in battles.
|
||||
*
|
||||
* @property battle The associated [PokemonBattle].
|
||||
* @property facedPokemon The [BattlePokemon]s that the [pokemon] faced.
|
||||
* @property pokemon See [EvSource.pokemon], comes from the original [BattlePokemon.effectedPokemon].
|
||||
*/
|
||||
open class BattleEvSource(
|
||||
val battle: PokemonBattle,
|
||||
val facedPokemon: List<BattlePokemon>,
|
||||
override val pokemon: Pokemon
|
||||
) : EvSource
|
||||
@@ -45,4 +45,15 @@ open class CancelableObservable<T : Cancelable> : EventObservable<T>() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline fun postThenFinally(event: T, ifCanceled: (T) -> Unit = {}, finally: (T) -> Unit = {},ifSucceeded: (T) -> Unit) {
|
||||
post(event) {
|
||||
if (it.isCanceled) {
|
||||
ifCanceled(it)
|
||||
} else {
|
||||
ifSucceeded(it)
|
||||
}
|
||||
finally(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
-1
@@ -11,6 +11,9 @@ package com.cobblemon.mod.common.api.serialization
|
||||
import com.google.gson.JsonDeserializationContext
|
||||
import com.google.gson.JsonDeserializer
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonPrimitive
|
||||
import com.google.gson.JsonSerializationContext
|
||||
import com.google.gson.JsonSerializer
|
||||
import java.lang.reflect.Type
|
||||
|
||||
/**
|
||||
@@ -19,6 +22,13 @@ import java.lang.reflect.Type
|
||||
* @author Hiroku
|
||||
* @since July 18th, 2022
|
||||
*/
|
||||
class StringIdentifiedObjectAdapter<T>(val fromString: (String) -> T) : JsonDeserializer<T> {
|
||||
class StringIdentifiedObjectAdapter<T>(
|
||||
val fromString: (String) -> T,
|
||||
val toString: ((T) -> String)? = null,
|
||||
) : JsonDeserializer<T>, JsonSerializer<T> {
|
||||
override fun deserialize(json: JsonElement, type: Type, ctx: JsonDeserializationContext) = fromString(json.asString)
|
||||
override fun serialize(src: T, type: Type?, ctx: JsonSerializationContext?): JsonElement? {
|
||||
val stringValue = toString?.invoke(src) ?: throw IllegalStateException("No toString function provided for serialization.")
|
||||
return JsonPrimitive(stringValue)
|
||||
}
|
||||
}
|
||||
@@ -83,8 +83,9 @@ object BestSpawner {
|
||||
var defaultPokemonDespawner: Despawner<PokemonEntity> = CobblemonAgingDespawner(getAgeTicks = { it.ticksLived })
|
||||
lateinit var fishingSpawner: FishingSpawner
|
||||
|
||||
fun loadConfig() {
|
||||
fun init() {
|
||||
LOGGER.info("Starting the Best Spawner...")
|
||||
|
||||
SpawningCondition.register(BasicSpawningCondition.NAME, BasicSpawningCondition::class.java)
|
||||
SpawningCondition.register(AreaSpawningCondition.NAME, AreaSpawningCondition::class.java)
|
||||
SpawningCondition.register(SubmergedSpawningCondition.NAME, SubmergedSpawningCondition::class.java)
|
||||
@@ -94,6 +95,7 @@ object BestSpawner {
|
||||
SpawningCondition.register(FishingSpawningCondition.NAME, FishingSpawningCondition::class.java)
|
||||
|
||||
LOGGER.info("Loaded ${SpawningCondition.conditionTypes.size} spawning condition types.")
|
||||
|
||||
SpawningContextCalculator.register(GroundedSpawningContextCalculator)
|
||||
SpawningContextCalculator.register(SeafloorSpawningContextCalculator)
|
||||
SpawningContextCalculator.register(LavafloorSpawningContextCalculator)
|
||||
@@ -113,14 +115,23 @@ object BestSpawner {
|
||||
SpawnDetail.registerSpawnType(name = NPCSpawnDetail.TYPE, NPCSpawnDetail::class.java)
|
||||
LOGGER.info("Loaded ${SpawnDetail.spawnDetailTypes.size} spawn detail types.")
|
||||
|
||||
config = BestSpawnerConfig.load()
|
||||
loadConfig()
|
||||
|
||||
SpawnDetailPresets.registerPresetType(BasicSpawnDetailPreset.NAME, BasicSpawnDetailPreset::class.java)
|
||||
SpawnDetailPresets.registerPresetType(PokemonSpawnDetailPreset.NAME, PokemonSpawnDetailPreset::class.java)
|
||||
}
|
||||
|
||||
fun loadConfig() {
|
||||
config = BestSpawnerConfig.load()
|
||||
}
|
||||
|
||||
fun reloadConfig() {
|
||||
loadConfig()
|
||||
spawnerManagers.forEach(SpawnerManager::onConfigReload)
|
||||
}
|
||||
|
||||
fun onServerStarted() {
|
||||
spawnerManagers.forEach(SpawnerManager::onServerStarted)
|
||||
fishingSpawner = FishingSpawner()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,4 +96,4 @@ object SpawnDetailPresets : JsonDataRegistry<SpawnDetailPreset> {
|
||||
this.presets = data.toMutableMap()
|
||||
Cobblemon.LOGGER.info("Loaded ${presets.size} spawn detail presets.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.api.spawning
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.spawning.influence.SpawningInfluence
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.PlayerSpawner
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.Spawner
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.TickingSpawner
|
||||
import com.cobblemon.mod.common.util.server
|
||||
@@ -58,6 +59,12 @@ open class SpawnerManager {
|
||||
}
|
||||
}
|
||||
|
||||
open fun onConfigReload() {
|
||||
spawners.filterIsInstance<PlayerSpawner>().forEach {
|
||||
it.ticksBetweenSpawns = Cobblemon.config.ticksBetweenSpawnAttempts
|
||||
}
|
||||
}
|
||||
|
||||
open fun onServerStarted() {
|
||||
spawners.clear()
|
||||
}
|
||||
|
||||
+1
-1
@@ -161,4 +161,4 @@ abstract class SpawningCondition<T : SpawningContext> {
|
||||
return false
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -221,4 +221,4 @@ abstract class SpawningContext {
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -64,4 +64,4 @@ open class SpawningContextInput(
|
||||
val cause: SpawnCause,
|
||||
/** The [Level] the spawning context exists in. */
|
||||
val world: ServerLevel
|
||||
)
|
||||
)
|
||||
|
||||
@@ -103,4 +103,4 @@ abstract class SpawnDetail : ModDependant {
|
||||
}
|
||||
|
||||
abstract fun doSpawn(ctx: SpawningContext): SpawnAction<*>
|
||||
}
|
||||
}
|
||||
|
||||
+7
-4
@@ -167,10 +167,10 @@ open class PlayerPartyStore(
|
||||
}
|
||||
|
||||
// Shoulder validation code
|
||||
if (player.shoulderEntityLeft.isPokemonEntity() && !validateShoulder(player.shoulderEntityLeft, true)) {
|
||||
if (player.shoulderEntityLeft.isPokemonEntity() && !validateShoulder(player, true)) {
|
||||
player.respawnEntityOnShoulder(player.shoulderEntityLeft)
|
||||
}
|
||||
if (player.shoulderEntityRight.isPokemonEntity() && !validateShoulder(player.shoulderEntityRight, false)) {
|
||||
if (player.shoulderEntityRight.isPokemonEntity() && !validateShoulder(player, false)) {
|
||||
player.respawnEntityOnShoulder(player.shoulderEntityRight)
|
||||
}
|
||||
|
||||
@@ -182,11 +182,14 @@ open class PlayerPartyStore(
|
||||
}
|
||||
}
|
||||
|
||||
fun validateShoulder(shoulderEntity: CompoundTag, isLeft: Boolean): Boolean {
|
||||
private fun validateShoulder(player: ServerPlayer, isLeft: Boolean): Boolean {
|
||||
val shoulderEntity = if(isLeft) player.shoulderEntityLeft else player.shoulderEntityRight
|
||||
val pokemon = find { it.uuid == shoulderEntity.getCompound("Pokemon").getUUID(DataKeys.POKEMON_UUID) }
|
||||
if (pokemon == null || (pokemon.state as? ShoulderedState)?.isLeftShoulder != isLeft) {
|
||||
// No longer valid if (in order): not in party, not the correct shoulder, no longer shoulder mountable
|
||||
if (pokemon == null || (pokemon.state as? ShoulderedState)?.isLeftShoulder != isLeft || !pokemon.form.shoulderMountable) {
|
||||
return false
|
||||
}
|
||||
player.updateShoulderNbt(pokemon)
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -8,16 +8,19 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.storage.pc
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSortMode
|
||||
import com.cobblemon.mod.common.api.reactive.Observable.Companion.stopAfter
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.storage.InvalidSpeciesException
|
||||
import com.cobblemon.mod.common.api.storage.StoreCoordinates
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.JsonObject
|
||||
import net.minecraft.core.RegistryAccess
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
/**
|
||||
@@ -34,6 +37,18 @@ open class PCBox(val pc: PCStore) : Iterable<Pokemon> {
|
||||
|
||||
protected var emit = true
|
||||
|
||||
var name : String? = null
|
||||
set(value) {
|
||||
field = value
|
||||
if (emit) boxChangeEmitter.emit(Unit)
|
||||
}
|
||||
|
||||
var wallpaper : ResourceLocation = cobblemonResource("textures/gui/pc/pc_screen_overlay.png")
|
||||
set(value) {
|
||||
field = value
|
||||
if (emit) boxChangeEmitter.emit(Unit)
|
||||
}
|
||||
|
||||
protected val pokemon = Array<Pokemon?>(POKEMON_PER_BOX) { null }
|
||||
|
||||
open operator fun get(index: Int): Pokemon? {
|
||||
@@ -88,6 +103,13 @@ open class PCBox(val pc: PCStore) : Iterable<Pokemon> {
|
||||
boxChangeEmitter.subscribe { pc.pcChangeObservable.emit(Unit) }
|
||||
}
|
||||
|
||||
fun sort(sortMode: PokemonSortMode, descending: Boolean) {
|
||||
pokemon.sortWith(sortMode.comparator(descending))
|
||||
pokemon.forEachIndexed { slot, pokemon ->
|
||||
pokemon?.storeCoordinates?.set(StoreCoordinates(pc, PCPosition(boxNumber, slot)))
|
||||
}
|
||||
}
|
||||
|
||||
fun trackPokemon(pokemon: Pokemon) {
|
||||
pokemon.getChangeObservable()
|
||||
.pipe(
|
||||
@@ -100,10 +122,14 @@ open class PCBox(val pc: PCStore) : Iterable<Pokemon> {
|
||||
}
|
||||
|
||||
fun sendTo(player: ServerPlayer) {
|
||||
SetPCBoxPokemonPacket(this).sendToPlayer(player)
|
||||
SetPCBoxPacket(this).sendToPlayer(player)
|
||||
}
|
||||
|
||||
open fun saveToNBT(nbt: CompoundTag, registryAccess: RegistryAccess): CompoundTag {
|
||||
name?.let {
|
||||
nbt.putString(DataKeys.STORE_BOX_NAME, it)
|
||||
}
|
||||
nbt.putString(DataKeys.STORE_BOX_WALLPAPER, wallpaper.toString())
|
||||
for (slot in 0 until POKEMON_PER_BOX) {
|
||||
val pokemon = pokemon[slot] ?: continue
|
||||
nbt.put(DataKeys.STORE_SLOT + slot, pokemon.saveToNBT(registryAccess))
|
||||
@@ -112,6 +138,10 @@ open class PCBox(val pc: PCStore) : Iterable<Pokemon> {
|
||||
}
|
||||
|
||||
open fun saveToJSON(json: JsonObject, registryAccess: RegistryAccess): JsonObject {
|
||||
name?.let {
|
||||
json.addProperty(DataKeys.STORE_BOX_NAME, it)
|
||||
}
|
||||
json.addProperty(DataKeys.STORE_BOX_WALLPAPER, wallpaper.toString())
|
||||
for (slot in 0 until POKEMON_PER_BOX) {
|
||||
val pokemon = pokemon[slot] ?: continue
|
||||
json.add(DataKeys.STORE_SLOT + slot, pokemon.saveToJSON(registryAccess))
|
||||
@@ -119,7 +149,16 @@ open class PCBox(val pc: PCStore) : Iterable<Pokemon> {
|
||||
return json
|
||||
}
|
||||
|
||||
|
||||
open fun loadFromJSON(json: JsonObject, registryAccess: RegistryAccess): PCBox {
|
||||
if (json.has(DataKeys.STORE_BOX_NAME)) {
|
||||
name = json.getAsJsonPrimitive(DataKeys.STORE_BOX_NAME).asString
|
||||
}
|
||||
|
||||
if (json.has(DataKeys.STORE_BOX_WALLPAPER)) {
|
||||
wallpaper = ResourceLocation.parse(json.getAsJsonPrimitive(DataKeys.STORE_BOX_WALLPAPER).asString)
|
||||
}
|
||||
|
||||
for (slot in 0 until POKEMON_PER_BOX) {
|
||||
if (json.has(DataKeys.STORE_SLOT + slot)) {
|
||||
val pokemonJson = json.getAsJsonObject(DataKeys.STORE_SLOT + slot)
|
||||
@@ -134,6 +173,14 @@ open class PCBox(val pc: PCStore) : Iterable<Pokemon> {
|
||||
}
|
||||
|
||||
open fun loadFromNBT(nbt: CompoundTag, registryAccess: RegistryAccess): PCBox {
|
||||
if (nbt.contains(DataKeys.STORE_BOX_NAME)) {
|
||||
name = nbt.getString(DataKeys.STORE_BOX_NAME)
|
||||
}
|
||||
|
||||
if (nbt.contains(DataKeys.STORE_BOX_WALLPAPER)) {
|
||||
wallpaper = ResourceLocation.parse(nbt.getString(DataKeys.STORE_BOX_WALLPAPER))
|
||||
}
|
||||
|
||||
for (slot in 0 until POKEMON_PER_BOX) {
|
||||
if (nbt.contains(DataKeys.STORE_SLOT + slot)) {
|
||||
val pokemonNBT = nbt.getCompound(DataKeys.STORE_SLOT + slot)
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.storage.pc.search
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
/**
|
||||
* Functional interface used in [Search]es
|
||||
*/
|
||||
fun interface PokemonFilter {
|
||||
fun test(pokemon: Pokemon): Boolean
|
||||
|
||||
fun inverted(): PokemonFilter {
|
||||
return PokemonFilter { pokemon -> !this.test(pokemon) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.storage.pc.search
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import java.util.HashSet
|
||||
import java.util.Locale
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* Client-side class containing currently applied filters, and cached results of which Pokémon pass or fail those filters.
|
||||
* Used in [com.cobblemon.mod.common.client.gui.pc.PCGUI]
|
||||
*/
|
||||
class Search(
|
||||
private val filters: Set<PokemonFilter>,
|
||||
private val passed: MutableSet<UUID> = HashSet(),
|
||||
private val failed: MutableSet<UUID> = HashSet()
|
||||
) {
|
||||
companion object {
|
||||
val DEFAULT = Search(setOf())
|
||||
fun of(search: String): Search {
|
||||
if (search.isBlank()) return DEFAULT
|
||||
|
||||
val split = search.lowercase(Locale.ROOT).trim().split(" ")
|
||||
val filters = HashSet<PokemonFilter>()
|
||||
|
||||
for (piece in split) {
|
||||
var filter = piece
|
||||
val inverted = filter.startsWith("!")
|
||||
if (inverted) {
|
||||
filter = filter.substring(1)
|
||||
}
|
||||
|
||||
val pokemonFilter: PokemonFilter = when (filter) {
|
||||
"holding" -> PokemonFilter { pokemon -> !pokemon.heldItem().isEmpty }
|
||||
"fainted" -> PokemonFilter { pokemon -> pokemon.isFainted() }
|
||||
"legendary" -> PokemonFilter { pokemon -> pokemon.isLegendary() }
|
||||
"mythical" -> PokemonFilter { pokemon -> pokemon.isMythical() }
|
||||
"ultrabeast", "ultra_beast" -> PokemonFilter { pokemon -> pokemon.isUltraBeast() }
|
||||
else -> PokemonFilter { pokemon -> PokemonProperties.parse(filter).matches(pokemon) }
|
||||
}
|
||||
|
||||
if (inverted) {
|
||||
filters.add(pokemonFilter.inverted())
|
||||
} else {
|
||||
filters.add(pokemonFilter)
|
||||
}
|
||||
}
|
||||
|
||||
return Search(filters)
|
||||
}
|
||||
}
|
||||
|
||||
fun passes(pokemon: Pokemon?): Boolean {
|
||||
if (pokemon == null) return false
|
||||
val uuid = pokemon.uuid
|
||||
if (passed.contains(uuid)) return true
|
||||
if (failed.contains(uuid)) return false
|
||||
val passes = filters.all { it.test(pokemon) }
|
||||
val set = if (passes) passed else failed
|
||||
set.add(uuid)
|
||||
return passes
|
||||
}
|
||||
}
|
||||
@@ -111,6 +111,9 @@ object CobblemonItemTags {
|
||||
@JvmField val EXPERIENCE_SHARE = create("held/experience_share")
|
||||
@JvmField val IS_FRIENDSHIP_BOOSTER = create("is_friendship_booster")
|
||||
@JvmField val ANY_HELD_ITEM = create("held/is_held_item")
|
||||
@JvmField val BLACKLISTED_ITEMS_TO_HOLD = create("held/blacklisted_items_to_hold")
|
||||
@JvmField val WHITELISTED_ITEMS_TO_HOLD = create("held/whitelisted_items_to_hold")
|
||||
|
||||
/** Tag that flags items as being able to "create" [CobblemonItems.LEFTOVERS]. */
|
||||
@JvmField val LEAVES_LEFTOVERS = create("held/leaves_leftovers")
|
||||
@JvmField val LUCKY_EGG = create("held/lucky_egg")
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.block
|
||||
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.block.entity.StadiumBlockEntity
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.context.BlockPlaceContext
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.BaseEntityBlock
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock
|
||||
import net.minecraft.world.level.block.Mirror
|
||||
import net.minecraft.world.level.block.RenderShape
|
||||
import net.minecraft.world.level.block.Rotation
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateDefinition
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
|
||||
class StadiumBlock(properties: Properties): BaseEntityBlock(properties) {
|
||||
companion object {
|
||||
val CODEC = simpleCodec(::StadiumBlock)
|
||||
}
|
||||
|
||||
init {
|
||||
registerDefaultState(stateDefinition.any().setValue(HorizontalDirectionalBlock.FACING, Direction.NORTH))
|
||||
}
|
||||
|
||||
override fun codec() = CODEC
|
||||
|
||||
override fun newBlockEntity(pos: BlockPos, state: BlockState): BlockEntity {
|
||||
return StadiumBlockEntity(pos, state)
|
||||
}
|
||||
|
||||
override fun getStateForPlacement(blockPlaceContext: BlockPlaceContext): BlockState {
|
||||
return this.defaultBlockState().setValue(HorizontalDirectionalBlock.FACING, blockPlaceContext.horizontalDirection)
|
||||
}
|
||||
|
||||
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
builder.add(HorizontalDirectionalBlock.FACING)
|
||||
}
|
||||
|
||||
override fun rotate(blockState: BlockState, rotation: Rotation): BlockState {
|
||||
return blockState.setValue(
|
||||
HorizontalDirectionalBlock.FACING, rotation.rotate(blockState.getValue(
|
||||
HorizontalDirectionalBlock.FACING)))
|
||||
}
|
||||
|
||||
override fun mirror(blockState: BlockState, mirror: Mirror): BlockState {
|
||||
return blockState.rotate(mirror.getRotation(blockState.getValue(HorizontalDirectionalBlock.FACING)))
|
||||
}
|
||||
|
||||
override fun onRemove(state: BlockState, world: Level, pos: BlockPos, newState: BlockState, moved: Boolean) {
|
||||
if (!state.`is`(newState.block)) super.onRemove(state, world, pos, newState, moved)
|
||||
}
|
||||
|
||||
//TODO: override getTicker
|
||||
|
||||
override fun getRenderShape(state: BlockState) = RenderShape.MODEL
|
||||
|
||||
override fun useWithoutItem(
|
||||
blockState: BlockState,
|
||||
world: Level,
|
||||
blockPos: BlockPos,
|
||||
player: Player,
|
||||
blockHitResult: BlockHitResult
|
||||
): InteractionResult {
|
||||
if (player !is ServerPlayer) return InteractionResult.SUCCESS
|
||||
|
||||
val blockEntity = world.getBlockEntity(blockPos)
|
||||
if (blockEntity !is StadiumBlockEntity) return InteractionResult.SUCCESS
|
||||
|
||||
// Toggle isInUse state
|
||||
blockEntity.isInUse = !blockEntity.isInUse
|
||||
|
||||
// debug
|
||||
val activateMessage = if (blockEntity.isInUse) "Stadium Activated!" else "Stadium Deactivated!"
|
||||
player.sendSystemMessage(text(activateMessage).red())
|
||||
|
||||
if (blockEntity.isInUse) {
|
||||
// Generate flight path when activated
|
||||
blockEntity.generateFlightPath(world, radiusX = 5.0, radiusZ = 3.0, height = 10.0, steps = 20)
|
||||
|
||||
} else {
|
||||
// Clear path when deactivated
|
||||
blockEntity.pathPoints.clear()
|
||||
}
|
||||
|
||||
val message = "Stadium Pos: " + blockEntity.blockPos +
|
||||
"\nPlayer 1 Pos: " + blockEntity.getPlayer1Pos() +
|
||||
"\nPoke 1 Pos: " + blockEntity.getPoke1Pos() +
|
||||
"\nPlayer 2 Pos: " + blockEntity.getPlayer2Pos() +
|
||||
"\nPoke 2 Pos: " + blockEntity.getPoke2Pos()
|
||||
player.sendSystemMessage(text(message).red())
|
||||
|
||||
blockEntity.setChanged()
|
||||
world.sendBlockUpdated(blockPos, blockState, blockState, Block.UPDATE_CLIENTS)
|
||||
|
||||
return InteractionResult.SUCCESS
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -42,7 +42,7 @@ open class FossilMultiblockEntity(
|
||||
if(masterBlockPos != null && masterBlockPos != blockPos) {
|
||||
val chunkPos = ChunkPos(masterBlockPos)
|
||||
if (level?.chunkSource?.hasChunk(chunkPos.x, chunkPos.z) == true) {
|
||||
val entity: FossilMultiblockEntity? = level?.getBlockEntity(masterBlockPos) as FossilMultiblockEntity?
|
||||
val entity: FossilMultiblockEntity? = level?.getBlockEntity(masterBlockPos) as? FossilMultiblockEntity?
|
||||
field = entity?.multiblockStructure
|
||||
}
|
||||
}
|
||||
|
||||
+5
-2
@@ -308,9 +308,12 @@ class HealingMachineBlockEntity(
|
||||
} else {
|
||||
// Recharging
|
||||
if (blockEntity.healingCharge < blockEntity.maxCharge) {
|
||||
val chargePerTick = (Cobblemon.config.chargeGainedPerTick).coerceAtLeast(0F)
|
||||
val secondsToChargeHealingMachine = (Cobblemon.config.secondsToChargeHealingMachine).coerceAtLeast(0.0)
|
||||
val totalTicks = secondsToChargeHealingMachine * 20
|
||||
val chargePerTick = if (totalTicks > 0) blockEntity.maxCharge / totalTicks else 0.0
|
||||
|
||||
blockEntity.healingCharge =
|
||||
(blockEntity.healingCharge + chargePerTick).coerceIn(0F..blockEntity.maxCharge)
|
||||
(blockEntity.healingCharge + chargePerTick.toFloat()).coerceIn(0F..blockEntity.maxCharge)
|
||||
blockEntity.updateBlockChargeLevel()
|
||||
blockEntity.updateRedstoneSignal()
|
||||
blockEntity.markUpdated()
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
package com.cobblemon.mod.common.block.entity
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.drone.DroneState
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.network.protocol.Packet
|
||||
import net.minecraft.network.protocol.game.ClientGamePacketListener
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerLookAtPacket
|
||||
import net.minecraft.network.protocol.game.ClientboundSetCarriedItemPacket
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class StadiumBlockEntity(
|
||||
pos: BlockPos,
|
||||
blockState: BlockState
|
||||
): BlockEntity(
|
||||
CobblemonBlockEntities.STADIUM,
|
||||
pos,
|
||||
blockState
|
||||
) {
|
||||
var isInUse = false
|
||||
|
||||
val droneState = DroneState()
|
||||
|
||||
val pathPoints: MutableList<Vec3> = mutableListOf()
|
||||
|
||||
fun generateFlightPath(world: Level, radiusX: Double, radiusZ: Double, height: Double, steps: Int) {
|
||||
pathPoints.clear()
|
||||
|
||||
for (i in 0 until steps) {
|
||||
val angle = (i.toDouble() / steps) * Math.PI * 2
|
||||
val xOffset = radiusX * Math.cos(angle)
|
||||
val zOffset = radiusZ * Math.sin(angle)
|
||||
|
||||
val basePos = Vec3(blockPos.x + xOffset, blockPos.y + height, blockPos.z + zOffset)
|
||||
val adjustedPos = getValidPoint(world, basePos)
|
||||
|
||||
pathPoints.add(adjustedPos)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getValidPoint(world: Level, start: Vec3): Vec3 {
|
||||
val maxHeight = 40 // Max height for drone path
|
||||
val stepHeight = 1.0 // Step size for raycast
|
||||
|
||||
var adjustedHeight = start.y
|
||||
for (h in 0..maxHeight step stepHeight.toInt()) {
|
||||
val checkPos = BlockPos(start.x.toInt(), start.y.toInt() - h, start.z.toInt()) // Convert to BlockPos
|
||||
if (!world.getBlockState(checkPos).isAir) { // Check if block is solid
|
||||
return Vec3(start.x, start.y - h - 1, start.z) // Adjust position
|
||||
}
|
||||
}
|
||||
return start // No obstruction found
|
||||
}
|
||||
|
||||
|
||||
fun getPlayer1Pos(): BlockPos {
|
||||
return blockPos.north(10)
|
||||
}
|
||||
fun getPlayer2Pos(): BlockPos {
|
||||
return blockPos.south(10)
|
||||
}
|
||||
fun getPoke1Pos(): BlockPos {
|
||||
return blockPos.north(5)
|
||||
}
|
||||
fun getPoke2Pos(): BlockPos {
|
||||
return blockPos.south(5)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Saves data to NBT.
|
||||
*/
|
||||
override fun saveAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
|
||||
super.saveAdditional(tag, registries)
|
||||
|
||||
// Save the isInUse state
|
||||
tag.putBoolean("IsInUse", isInUse)
|
||||
|
||||
// Save path points
|
||||
val pathTag = ListTag()
|
||||
for (point in pathPoints) {
|
||||
val pointTag = CompoundTag()
|
||||
pointTag.putDouble("x", point.x)
|
||||
pointTag.putDouble("y", point.y)
|
||||
pointTag.putDouble("z", point.z)
|
||||
pathTag.add(pointTag)
|
||||
}
|
||||
tag.put("PathPoints", pathTag)
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads data from NBT.
|
||||
*/
|
||||
override fun loadAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
|
||||
super.loadAdditional(tag, registries)
|
||||
|
||||
// Load the isInUse state
|
||||
isInUse = tag.getBoolean("IsInUse")
|
||||
|
||||
// Load path points
|
||||
pathPoints.clear()
|
||||
val pathTag = tag.getList("PathPoints", 10) // 10 is the ID for CompoundTag
|
||||
for (i in 0 until pathTag.size) {
|
||||
val pointTag = pathTag.getCompound(i)
|
||||
val point = Vec3(pointTag.getDouble("x"), pointTag.getDouble("y"), pointTag.getDouble("z"))
|
||||
pathPoints.add(point)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getUpdatePacket(): Packet<ClientGamePacketListener>? {
|
||||
//println("getUpdatePacket called for NestBlockEntity at $blockPos with egg: $eggComponent")
|
||||
return ClientboundBlockEntityDataPacket.create(this)
|
||||
}
|
||||
|
||||
override fun getUpdateTag(registryLookup: HolderLookup.Provider): CompoundTag {
|
||||
val tag = saveWithoutMetadata(registryLookup)
|
||||
//println("getUpdateTag called for NestBlockEntity at $blockPos with tag: $tag")
|
||||
return tag
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -25,13 +25,7 @@ import com.cobblemon.mod.common.client.gui.battle.BattleOverlay
|
||||
import com.cobblemon.mod.common.client.particle.BedrockParticleOptionsRepository
|
||||
import com.cobblemon.mod.common.client.render.ClientPlayerIcon
|
||||
import com.cobblemon.mod.common.client.render.DeferredRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.BerryBlockRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.DisplayCaseRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.FossilAnalyzerRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.GildedChestBlockRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.HealingMachineRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.LecternBlockEntityRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.RestorationTankRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.*
|
||||
import com.cobblemon.mod.common.client.render.boat.CobblemonBoatRenderer
|
||||
import com.cobblemon.mod.common.client.render.entity.PokeBobberEntityRenderer
|
||||
import com.cobblemon.mod.common.client.render.generic.GenericBedrockRenderer
|
||||
@@ -40,13 +34,8 @@ import com.cobblemon.mod.common.client.render.item.PokemonItemRenderer
|
||||
import com.cobblemon.mod.common.client.render.layer.PokemonOnShoulderRenderer
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.bedrock.animation.BedrockAnimationRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.BerryModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.BlockEntityModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.FossilModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.GenericBedrockEntityModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.MiscModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.NPCModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokeBallModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.client.render.npc.NPCRenderer
|
||||
import com.cobblemon.mod.common.client.render.pokeball.PokeBallRenderer
|
||||
import com.cobblemon.mod.common.client.render.pokemon.PokemonRenderer
|
||||
@@ -77,10 +66,12 @@ import net.minecraft.client.renderer.blockentity.SignRenderer
|
||||
import net.minecraft.client.renderer.entity.EntityRenderer
|
||||
import net.minecraft.client.renderer.entity.LivingEntityRenderer
|
||||
import net.minecraft.client.resources.PlayerSkin
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.packs.resources.ResourceManager
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.AABB
|
||||
import java.util.UUID
|
||||
|
||||
object CobblemonClient {
|
||||
|
||||
@@ -94,15 +85,6 @@ object CobblemonClient {
|
||||
var checkedStarterScreen = false
|
||||
var requests = ClientPlayerActionRequests()
|
||||
var teamData = ClientPlayerTeamData()
|
||||
var posableModelRepositories = listOf(
|
||||
PokemonModelRepository,
|
||||
PokeBallModelRepository,
|
||||
NPCModelRepository,
|
||||
FossilModelRepository,
|
||||
BlockEntityModelRepository,
|
||||
GenericBedrockEntityModelRepository
|
||||
)
|
||||
|
||||
val overlay: PartyOverlay by lazy { PartyOverlay() }
|
||||
val battleOverlay: BattleOverlay by lazy { BattleOverlay() }
|
||||
val pokedexUsageContext: PokedexUsageContext by lazy { PokedexUsageContext() }
|
||||
@@ -268,7 +250,8 @@ object CobblemonClient {
|
||||
CobblemonBlocks.SKY_TUMBLESTONE_CLUSTER,
|
||||
CobblemonBlocks.GIMMIGHOUL_CHEST,
|
||||
CobblemonBlocks.DISPLAY_CASE,
|
||||
CobblemonBlocks.LECTERN
|
||||
CobblemonBlocks.LECTERN,
|
||||
CobblemonBlocks.STADIUM
|
||||
)
|
||||
|
||||
this.createBoatModelLayers()
|
||||
@@ -302,6 +285,7 @@ object CobblemonClient {
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.GILDED_CHEST, ::GildedChestBlockRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.DISPLAY_CASE, ::DisplayCaseRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.LECTERN, ::LecternBlockEntityRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.STADIUM, ::StadiumBlockRenderer)
|
||||
}
|
||||
|
||||
private fun registerEntityRenderers() {
|
||||
@@ -330,9 +314,9 @@ object CobblemonClient {
|
||||
// Animations come next because models need them.
|
||||
BedrockAnimationRepository.loadAnimations(
|
||||
resourceManager = resourceManager,
|
||||
directories = posableModelRepositories.flatMap { it.animationDirectories }
|
||||
directories = VaryingModelRepository.animationDirectories
|
||||
)
|
||||
posableModelRepositories.forEach { it.reload(resourceManager) }
|
||||
VaryingModelRepository.reload(resourceManager)
|
||||
|
||||
BerryModelRepository.reload(resourceManager)
|
||||
MiscModelRepository.reload(resourceManager)
|
||||
|
||||
+2
-3
@@ -10,8 +10,7 @@ package com.cobblemon.mod.common.client.entity
|
||||
|
||||
import com.cobblemon.mod.common.api.entity.EntitySideDelegate
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.GenericBedrockEntityModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.entity.generic.GenericBedrockEntity
|
||||
|
||||
class GenericBedrockClientDelegate : EntitySideDelegate<GenericBedrockEntity>, PosableState() {
|
||||
@@ -24,7 +23,7 @@ class GenericBedrockClientDelegate : EntitySideDelegate<GenericBedrockEntity>, P
|
||||
super.initialize(entity)
|
||||
this.currentEntity = entity
|
||||
this.age = entity.tickCount
|
||||
this.currentModel = GenericBedrockEntityModelRepository.getPoser(entity.category, entity.delegate as GenericBedrockClientDelegate)
|
||||
this.currentModel = VaryingModelRepository.getPoser(entity.category, entity.delegate as GenericBedrockClientDelegate)
|
||||
currentModel!!.updateLocators(entity, this)
|
||||
updateLocatorPosition(entity.position())
|
||||
|
||||
|
||||
+2
-2
@@ -29,7 +29,7 @@ import com.cobblemon.mod.common.client.render.MatrixWrapper
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.ActiveAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.PrimaryAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.client.render.pokemon.PokemonRenderer.Companion.ease
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
@@ -99,7 +99,7 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
currentPose = null
|
||||
currentEntity.pokemon.species = PokemonSpecies.getByIdentifier(identifier)!! // TODO exception handling
|
||||
// force a model update - handles edge case where the PosableState's tracked PosableModel isn't updated until the LivingEntityRenderer render is run
|
||||
currentModel = PokemonModelRepository.getPoser(identifier, this)
|
||||
currentModel = VaryingModelRepository.getPoser(identifier, this)
|
||||
} else if (data == PokemonEntity.ASPECTS) {
|
||||
currentAspects = currentEntity.entityData.get(PokemonEntity.ASPECTS)
|
||||
currentEntity.pokemon.shiny = currentAspects.contains("shiny")
|
||||
|
||||
@@ -24,7 +24,6 @@ import com.cobblemon.mod.common.client.keybind.keybinds.SummaryBinding
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.getDepletableRedGreen
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.client.render.renderScaledGuiItemIcon
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
@@ -161,7 +160,6 @@ class PartyOverlay : Gui(Minecraft.getInstance()) {
|
||||
matrixStack = matrices,
|
||||
partialTicks = 0F, // partialDeltaTicks, //Before you get any funny ideas about party animated pokemon, make sure they each get their own state instead of sharing.
|
||||
contextScale = pokemon.form.baseScale,
|
||||
repository = PokemonModelRepository,
|
||||
state = state
|
||||
)
|
||||
matrices.popPose()
|
||||
|
||||
@@ -12,10 +12,11 @@ import com.cobblemon.mod.common.api.gui.renderSprite
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.client.render.SpriteType
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.pokemon.RenderablePokemon
|
||||
import com.cobblemon.mod.common.util.math.toEulerXYZDegrees
|
||||
import com.cobblemon.mod.common.util.toHex
|
||||
import com.mojang.blaze3d.platform.Lighting
|
||||
import com.mojang.blaze3d.systems.RenderSystem
|
||||
@@ -25,8 +26,10 @@ import net.minecraft.client.renderer.LightTexture
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.Mth
|
||||
import org.joml.Quaternionf
|
||||
import org.joml.Vector3f
|
||||
import kotlin.math.atan
|
||||
|
||||
fun drawProfilePokemon(
|
||||
renderablePokemon: RenderablePokemon,
|
||||
@@ -41,7 +44,9 @@ fun drawProfilePokemon(
|
||||
r: Float = 1F,
|
||||
g: Float = 1F,
|
||||
b: Float = 1F,
|
||||
a: Float = 1F
|
||||
a: Float = 1F,
|
||||
headYaw: Float = 0f,
|
||||
headPitch: Float = 0f,
|
||||
) = drawProfilePokemon(
|
||||
species = renderablePokemon.species.resourceIdentifier,
|
||||
matrixStack = matrixStack,
|
||||
@@ -56,6 +61,8 @@ fun drawProfilePokemon(
|
||||
g = g,
|
||||
b = b,
|
||||
a = a,
|
||||
headYaw = headYaw,
|
||||
headPitch = headPitch,
|
||||
)
|
||||
|
||||
fun drawProfilePokemon(
|
||||
@@ -71,21 +78,23 @@ fun drawProfilePokemon(
|
||||
r: Float = 1F,
|
||||
g: Float = 1F,
|
||||
b: Float = 1F,
|
||||
a: Float = 1F
|
||||
a: Float = 1F,
|
||||
headYaw: Float = 0f,
|
||||
headPitch: Float = 0f,
|
||||
) {
|
||||
RenderSystem.applyModelViewMatrix()
|
||||
matrixStack.scale(scale, scale, -scale)
|
||||
|
||||
val sprite = PokemonModelRepository.getSprite(species, state, SpriteType.PROFILE)
|
||||
val sprite = VaryingModelRepository.getSprite(species, state, SpriteType.PROFILE)
|
||||
|
||||
if (sprite == null) {
|
||||
|
||||
val model = PokemonModelRepository.getPoser(species, state)
|
||||
val texture = PokemonModelRepository.getTexture(species, state)
|
||||
val model = VaryingModelRepository.getPoser(species, state)
|
||||
val texture = VaryingModelRepository.getTexture(species, state)
|
||||
|
||||
val context = RenderContext()
|
||||
model.context = context
|
||||
PokemonModelRepository.getTextureNoSubstitute(species, state).let { context.put(RenderContext.TEXTURE, it) }
|
||||
VaryingModelRepository.getTextureNoSubstitute(species, state).let { context.put(RenderContext.TEXTURE, it) }
|
||||
val baseScale = PokemonSpecies.getByIdentifier(species)!!.getForm(state.currentAspects).baseScale
|
||||
context.put(RenderContext.SCALE, baseScale)
|
||||
context.put(RenderContext.SPECIES, species)
|
||||
@@ -100,9 +109,13 @@ fun drawProfilePokemon(
|
||||
|
||||
state.setPoseToFirstSuitable(poseType)
|
||||
state.updatePartialTicks(partialTicks)
|
||||
model.applyAnimations(null, state, 0F, 0F, 0F, 0F, 0F)
|
||||
|
||||
if (applyProfileTransform) {
|
||||
matrixStack.translate(model.profileTranslation.x, model.profileTranslation.y, model.profileTranslation.z - 4.0)
|
||||
matrixStack.translate(
|
||||
model.profileTranslation.x,
|
||||
model.profileTranslation.y + 1.5 * model.profileScale,
|
||||
model.profileTranslation.z - 4.0
|
||||
)
|
||||
matrixStack.scale(model.profileScale, model.profileScale, 1 / model.profileScale)} else {
|
||||
matrixStack.translate(0F, 0F, -4.0F)
|
||||
if (applyBaseScale) {
|
||||
@@ -110,6 +123,9 @@ fun drawProfilePokemon(
|
||||
}
|
||||
}
|
||||
matrixStack.mulPose(rotation)
|
||||
|
||||
model.applyAnimations(null, state, 0F, 0F, 0F, headYaw, headPitch)
|
||||
|
||||
Lighting.setupForEntityInInventory()
|
||||
val entityRenderDispatcher = Minecraft.getInstance().entityRenderDispatcher
|
||||
rotation.conjugate()
|
||||
@@ -124,7 +140,7 @@ fun drawProfilePokemon(
|
||||
val packedLight = LightTexture.pack(11, 7)
|
||||
|
||||
val colour = toHex(r, g, b, a)
|
||||
model.withLayerContext(bufferSource, state, PokemonModelRepository.getLayers(species, state)) {
|
||||
model.withLayerContext(bufferSource, state, VaryingModelRepository.getLayers(species, state)) {
|
||||
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, colour)
|
||||
bufferSource.endBatch()
|
||||
}
|
||||
@@ -136,3 +152,29 @@ fun drawProfilePokemon(
|
||||
}
|
||||
}
|
||||
|
||||
const val HEAD_YAW_FACTOR = 40f
|
||||
const val HEAD_PITCH_FACTOR = 20f
|
||||
const val SMOOTHING_FACTOR = 0.05f
|
||||
|
||||
fun calculateHeadYawAndPitch(
|
||||
xCoordinate: Float,
|
||||
yCoordinate: Float,
|
||||
rotation: Quaternionf,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
currentYaw: Float,
|
||||
currentPitch: Float,
|
||||
resetToCenter: Boolean,
|
||||
): Pair<Float, Float> {
|
||||
val horizontalAngle = atan(((xCoordinate - mouseX) / 40.0f).toDouble()).toFloat()
|
||||
val verticalAngle = atan(((yCoordinate - mouseY) / 40.0f).toDouble()).toFloat()
|
||||
|
||||
val eulerXYZRotationDegrees = rotation.toEulerXYZDegrees()
|
||||
val targetYaw = if (!resetToCenter) horizontalAngle * HEAD_YAW_FACTOR - eulerXYZRotationDegrees.y else 0f
|
||||
val targetPitch = if (!resetToCenter) -verticalAngle * HEAD_PITCH_FACTOR - eulerXYZRotationDegrees.x else 0f
|
||||
|
||||
val newYaw = Mth.rotLerp(SMOOTHING_FACTOR, currentYaw, targetYaw)
|
||||
val newPitch = Mth.rotLerp(SMOOTHING_FACTOR, currentPitch, targetPitch)
|
||||
|
||||
return Pair(newYaw, newPitch)
|
||||
}
|
||||
@@ -26,9 +26,8 @@ import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.drawScaledTextJustifiedRight
|
||||
import com.cobblemon.mod.common.client.render.getDepletableRedGreen
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokeBallModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.sineFunction
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
|
||||
@@ -321,7 +320,6 @@ class BattleOverlay : Gui(Minecraft.getInstance()), Schedulable {
|
||||
matrixStack = matrixStack,
|
||||
scale = 18F * (ballState?.scale ?: 1F) * if (isCompact) 0.65F else 1.0f,
|
||||
contextScale = species.getForm(state.currentAspects).baseScale,
|
||||
repository = PokemonModelRepository,
|
||||
reversed = reversed,
|
||||
state = state,
|
||||
partialTicks = partialTicks
|
||||
@@ -490,8 +488,8 @@ class BattleOverlay : Gui(Minecraft.getInstance()), Schedulable {
|
||||
reversed: Boolean = false
|
||||
) {
|
||||
val context = RenderContext()
|
||||
val model = PokeBallModelRepository.getPoser(state.pokeBall.name, state)
|
||||
val texture = PokeBallModelRepository.getTexture(state.pokeBall.name, state)
|
||||
val model = VaryingModelRepository.getPoser(state.pokeBall.name, state)
|
||||
val texture = VaryingModelRepository.getTexture(state.pokeBall.name, state)
|
||||
val renderType = RenderType.entityCutout(texture)//model.getLayer(texture)
|
||||
|
||||
RenderSystem.applyModelViewMatrix()
|
||||
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.config
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.gui.components.EditBox
|
||||
import net.minecraft.client.gui.components.StringWidget
|
||||
import net.minecraft.client.gui.layouts.HeaderAndFooterLayout
|
||||
import net.minecraft.client.gui.layouts.LinearLayout
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.network.chat.CommonComponents
|
||||
|
||||
class CobblemonConfigScreen(
|
||||
private val previousScreen: Screen?,
|
||||
) : Screen("gui.cobblemon_config.title".asTranslated()), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
const val HEIGHT = 240
|
||||
const val HEADER_HEIGHT = 45
|
||||
const val FOOTER_HEIGHT = 33
|
||||
const val PADDING = 4
|
||||
const val SLOT_WIDTH = 340
|
||||
const val SLOT_HEIGHT = 22
|
||||
const val HALF_SLOT_WIDTH = SLOT_WIDTH / 2
|
||||
const val RESET_SLOT_WIDTH = 40
|
||||
const val WIDGET_WIDTH = 110 - RESET_SLOT_WIDTH - PADDING
|
||||
const val WIDGET_HEIGHT = SLOT_HEIGHT - PADDING
|
||||
const val LABEL_Y_OFFSET = 4
|
||||
const val WIDGET_Y_OFFSET = 0
|
||||
}
|
||||
|
||||
val clonedConfig = Cobblemon.config.clone()
|
||||
val defaultConfig = CobblemonConfig()
|
||||
|
||||
private lateinit var layout: HeaderAndFooterLayout
|
||||
private lateinit var searchEdit: EditBox
|
||||
private lateinit var variableList: CobblemonConfigVariableList
|
||||
private lateinit var doneButton: Button
|
||||
|
||||
private var searchString: String = ""
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
|
||||
if (::layout.isInitialized) layout.visitWidgets { removeWidget(it) }
|
||||
layout = HeaderAndFooterLayout(this, HEADER_HEIGHT, FOOTER_HEIGHT)
|
||||
|
||||
if (::variableList.isInitialized) removeWidget(variableList)
|
||||
variableList = CobblemonConfigVariableList(this)
|
||||
variableList.filterConfigurations(searchString)
|
||||
addRenderableWidget(variableList)
|
||||
|
||||
searchEdit = EditBox(
|
||||
Minecraft.getInstance().font,
|
||||
width / 2 - HALF_SLOT_WIDTH / 2,
|
||||
variableList.y,
|
||||
HALF_SLOT_WIDTH,
|
||||
SLOT_HEIGHT,
|
||||
lang("config.ui.search_configurations"),
|
||||
).also {
|
||||
it.height = WIDGET_HEIGHT
|
||||
it.setMaxLength(250)
|
||||
|
||||
it.value = searchString
|
||||
it.setResponder { text ->
|
||||
variableList.filterConfigurations(text)
|
||||
searchString = text
|
||||
}
|
||||
}
|
||||
|
||||
val linearLayout = layout.addToHeader(LinearLayout.vertical())
|
||||
linearLayout.addChild(StringWidget(lang("config.ui.search_configurations"), this.font))
|
||||
linearLayout.addChild(searchEdit)
|
||||
layout.addToHeader(linearLayout)
|
||||
|
||||
doneButton = Button.builder(CommonComponents.GUI_DONE) { doneButtonClick() }
|
||||
.pos(width / 2 - HALF_SLOT_WIDTH / 2, variableList.y + variableList.height + PADDING)
|
||||
.width(HALF_SLOT_WIDTH).build()
|
||||
layout.addToFooter(doneButton)
|
||||
|
||||
layout.visitWidgets { widget ->
|
||||
addRenderableWidget(widget)
|
||||
}
|
||||
arrangeLayoutElements()
|
||||
}
|
||||
|
||||
private fun arrangeLayoutElements() {
|
||||
layout.arrangeElements()
|
||||
variableList.updateSize(this.width, this.layout)
|
||||
}
|
||||
|
||||
private fun doneButtonClick() {
|
||||
Cobblemon.saveConfig(clonedConfig)
|
||||
Cobblemon.reloadConfig()
|
||||
onClose()
|
||||
}
|
||||
|
||||
override fun onClose() {
|
||||
minecraft?.setScreen(previousScreen)
|
||||
}
|
||||
}
|
||||
+190
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* 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.config
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.text.yellow
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.LABEL_Y_OFFSET
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.PADDING
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.SLOT_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.SLOT_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigVariableList.CobblemonConfigVariableListEntry
|
||||
import com.cobblemon.mod.common.client.gui.config.variable.*
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.config.Category
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import com.cobblemon.mod.common.config.CobblemonConfigField
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import net.minecraft.SharedConstants
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.ContainerObjectSelectionList
|
||||
import net.minecraft.client.gui.components.Tooltip
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener
|
||||
import net.minecraft.client.gui.narration.NarratableEntry
|
||||
import kotlin.math.min
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KMutableProperty1
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.jvm.javaField
|
||||
|
||||
class CobblemonConfigVariableList(
|
||||
val parent: CobblemonConfigScreen,
|
||||
) : ContainerObjectSelectionList<CobblemonConfigVariableListEntry>(
|
||||
Minecraft.getInstance(),
|
||||
Minecraft.getInstance().window.guiScaledWidth,
|
||||
HEIGHT,
|
||||
0,
|
||||
SLOT_HEIGHT
|
||||
) {
|
||||
|
||||
val entries = mutableListOf<CobblemonConfigCategory>()
|
||||
|
||||
init {
|
||||
this.x = 0
|
||||
this.y = minecraft.window.guiScaledHeight / 2 - HEIGHT / 2
|
||||
|
||||
setRenderHeader(false, 0)
|
||||
addEntries()
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun addEntries() {
|
||||
parent.clonedConfig::class.memberProperties.map { property ->
|
||||
if (!property.javaField!!.isAnnotationPresent(CobblemonConfigField::class.java)) {
|
||||
return@map null
|
||||
}
|
||||
|
||||
val entry: CobblemonConfigVariable? =
|
||||
when (val classifier = property.returnType.classifier) {
|
||||
String::class -> CobblemonConfigStringVariable(this, property as KMutableProperty1<out CobblemonConfig, String>)
|
||||
Int::class -> CobblemonConfigIntVariable(this, property as KMutableProperty1<out CobblemonConfig, Int>)
|
||||
Float::class -> CobblemonConfigFloatVariable(this, property as KMutableProperty1<out CobblemonConfig, Float>)
|
||||
Double::class -> CobblemonConfigDoubleVariable(this, property as KMutableProperty1<out CobblemonConfig, Double>)
|
||||
Boolean::class -> CobblemonConfigBooleanVariable(this, property as KMutableProperty1<out CobblemonConfig, Boolean>)
|
||||
is KClass<*> -> if (classifier.java.isEnum) {
|
||||
CobblemonConfigEnumVariable(this, property as KMutableProperty1<out CobblemonConfig, Enum<*>>)
|
||||
} else null
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (entry == null) {
|
||||
if (SharedConstants.IS_RUNNING_IN_IDE) {
|
||||
Cobblemon.LOGGER.warn("Widget for variable type: ${property.returnType.classifier} not registered: ${property.name}")
|
||||
}
|
||||
|
||||
return@map null
|
||||
}
|
||||
|
||||
return@map entry
|
||||
}
|
||||
.filterNotNull()
|
||||
.groupBy { it.cobblemonConfigFieldAnnotation.category }
|
||||
.toSortedMap(compareBy { it.ordinal })
|
||||
.forEach { category, variables ->
|
||||
val categoryEntry = CobblemonConfigCategory(this, category, variables)
|
||||
entries.add(categoryEntry)
|
||||
}
|
||||
|
||||
entries.forEach { entry -> entry.add() }
|
||||
}
|
||||
|
||||
override fun renderWidget(guiGraphics: GuiGraphics, mouseX: Int, mouseY: Int, partialTick: Float) {
|
||||
super.renderWidget(guiGraphics, mouseX, mouseY, partialTick)
|
||||
|
||||
val hoveredVariableTooltip = this.hovered?.tooltip
|
||||
if (isMouseInsideScrollList(mouseX, mouseY) && hoveredVariableTooltip != null) {
|
||||
guiGraphics.renderTooltip(minecraft.font, hoveredVariableTooltip.toCharSequence(minecraft), mouseX, mouseY)
|
||||
}
|
||||
}
|
||||
|
||||
fun isMouseInsideScrollList(mouseX: Int, mouseY: Int): Boolean {
|
||||
val bottomX = parent.width / 2 - SLOT_WIDTH / 2
|
||||
val upperX = parent.width / 2 + SLOT_WIDTH / 2
|
||||
|
||||
return mouseX >= bottomX && mouseX <= upperX && mouseY >= y && mouseY <= bottom
|
||||
}
|
||||
|
||||
override fun getRowWidth(): Int = width
|
||||
override fun getScrollbarPosition(): Int = width / 2 - SLOT_WIDTH / 2 + SLOT_WIDTH + PADDING
|
||||
|
||||
fun filterConfigurations(text: String) {
|
||||
for (entry in entries) {
|
||||
entry.remove()
|
||||
}
|
||||
|
||||
for (entry in entries) {
|
||||
if (text.isBlank() || entry.filter(text)) {
|
||||
entry.add(text)
|
||||
}
|
||||
}
|
||||
|
||||
scrollAmount = min(maxScroll.toDouble(), scrollAmount)
|
||||
}
|
||||
|
||||
abstract class CobblemonConfigVariableListEntry(
|
||||
val parent: CobblemonConfigVariableList,
|
||||
) : Entry<CobblemonConfigVariableListEntry>() {
|
||||
val children = mutableListOf<GuiEventListener>()
|
||||
var tooltip: Tooltip? = null
|
||||
|
||||
fun getX(left: Int) = parent.width / 2 - SLOT_WIDTH / 2
|
||||
fun getY(top: Int) = top
|
||||
|
||||
abstract fun filter(text: String): Boolean
|
||||
|
||||
override fun children(): MutableList<out GuiEventListener> = children
|
||||
override fun narratables(): MutableList<out NarratableEntry> = children.filterIsInstance<NarratableEntry>().toMutableList()
|
||||
}
|
||||
|
||||
class CobblemonConfigCategory(
|
||||
parent: CobblemonConfigVariableList,
|
||||
val category: Category,
|
||||
val configVariables: List<CobblemonConfigVariable>
|
||||
) : CobblemonConfigVariableListEntry(parent) {
|
||||
override fun render(
|
||||
context: GuiGraphics,
|
||||
index: Int,
|
||||
top: Int,
|
||||
left: Int,
|
||||
width: Int,
|
||||
height: Int,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
hovering: Boolean,
|
||||
partialTick: Float
|
||||
) {
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = "cobblemon.config.ui.category.${category.lang}".asTranslated().yellow(),
|
||||
x = parent.width / 2,
|
||||
y = getY(top) + LABEL_Y_OFFSET,
|
||||
shadow = true,
|
||||
centered = true,
|
||||
)
|
||||
}
|
||||
|
||||
fun add(filter: String? = null) {
|
||||
parent.addEntry(this)
|
||||
configVariables.forEach { variable ->
|
||||
if (filter == null || variable.filter(filter)) {
|
||||
parent.addEntry(variable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun remove() {
|
||||
parent.removeEntry(this)
|
||||
configVariables.forEach { variable -> parent.removeEntry(variable) }
|
||||
}
|
||||
|
||||
override fun filter(text: String): Boolean = configVariables.any { it.filter(text) }
|
||||
}
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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.config.variable
|
||||
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.PADDING
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.WIDGET_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.WIDGET_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.WIDGET_Y_OFFSET
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigVariableList
|
||||
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
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.components.Tooltip
|
||||
import net.minecraft.network.chat.CommonComponents
|
||||
import net.minecraft.network.chat.Component
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KMutableProperty1
|
||||
|
||||
abstract class CobblemonConfigButtonVariable(
|
||||
parent: CobblemonConfigVariableList,
|
||||
config: KMutableProperty1<out CobblemonConfig, *>,
|
||||
) : CobblemonConfigVariable(parent, config) {
|
||||
val button: Button =
|
||||
Button.builder(labelLang) { onButtonClick() }
|
||||
.size(WIDGET_WIDTH, WIDGET_HEIGHT)
|
||||
.build()
|
||||
|
||||
init {
|
||||
children.addFirst(button)
|
||||
}
|
||||
|
||||
abstract fun onButtonClick()
|
||||
|
||||
override fun updateConfigValueDisplay() {
|
||||
button.message = Component.literal(getConfigValueAsString())
|
||||
}
|
||||
|
||||
override fun render(
|
||||
context: GuiGraphics,
|
||||
index: Int,
|
||||
top: Int,
|
||||
left: Int,
|
||||
width: Int,
|
||||
height: Int,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
hovering: Boolean,
|
||||
partialTick: Float
|
||||
) {
|
||||
super.render(context, index, top, left, width, height, mouseX, mouseY, hovering, partialTick)
|
||||
|
||||
button.x = resetButton.x - button.width - PADDING
|
||||
button.y = getY(top) + WIDGET_Y_OFFSET
|
||||
button.render(context, mouseX, mouseY, partialTick)
|
||||
}
|
||||
}
|
||||
|
||||
class CobblemonConfigBooleanVariable(
|
||||
parent: CobblemonConfigVariableList,
|
||||
config: KMutableProperty1<out CobblemonConfig, Boolean>,
|
||||
) : CobblemonConfigButtonVariable(parent, config) {
|
||||
|
||||
init {
|
||||
updateConfigValueDisplay()
|
||||
}
|
||||
|
||||
override fun getConfigValueAsString(): String = (if (isSelected()) CommonComponents.GUI_YES else CommonComponents.GUI_NO).string
|
||||
override fun onButtonClick() = setConfigValue(!isSelected())
|
||||
|
||||
private fun isSelected() = (config.getter.call(parent.parent.clonedConfig) as Boolean?) ?: false
|
||||
}
|
||||
|
||||
class CobblemonConfigEnumVariable(
|
||||
parent: CobblemonConfigVariableList,
|
||||
config: KMutableProperty1<out CobblemonConfig, Enum<*>>,
|
||||
) : CobblemonConfigButtonVariable(parent, config) {
|
||||
|
||||
private var enumIndex = 0
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private val enumValues: Array<Enum<*>> = config.returnType.classifier
|
||||
.let { it as? KClass<Enum<*>> }
|
||||
?.java?.enumConstants ?: emptyArray()
|
||||
|
||||
init {
|
||||
val currentEnumValue = getCurrentEnumValue()
|
||||
enumValues.firstOrNull { it.name == currentEnumValue?.name }?.let {
|
||||
enumIndex = it.ordinal
|
||||
}
|
||||
updateConfigValueDisplay()
|
||||
}
|
||||
|
||||
override fun getConfigValueAsString(): String {
|
||||
return getCurrentEnumValue()?.name?.let {
|
||||
lang("$labelEntry.${it.lowercase()}").string
|
||||
} ?: ""
|
||||
}
|
||||
|
||||
private fun getConfigValueTooltipString(): String {
|
||||
return getCurrentEnumValue()?.name?.let {
|
||||
lang("$labelEntry.${it.lowercase()}.tooltip").string
|
||||
} ?: ""
|
||||
}
|
||||
|
||||
override fun onButtonClick() {
|
||||
enumIndex = (enumIndex + 1) % enumValues.size
|
||||
val newEnumValue = enumValues[enumIndex]
|
||||
|
||||
setConfigValue(newEnumValue)
|
||||
}
|
||||
|
||||
override fun updateConfigValueDisplay() {
|
||||
super.updateConfigValueDisplay()
|
||||
tooltip = Tooltip.create(Component.literal(getConfigValueTooltipString()))
|
||||
}
|
||||
|
||||
private fun getCurrentEnumValue(): Enum<*>? = (config.getter.call(parent.parent.clonedConfig) as Enum<*>?)
|
||||
}
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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.config.variable
|
||||
|
||||
import com.cobblemon.mod.common.api.text.add
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.PADDING
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.SLOT_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.WIDGET_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.WIDGET_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.WIDGET_Y_OFFSET
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigVariableList
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import com.cobblemon.mod.common.config.constraint.IntConstraint
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.EditBox
|
||||
import net.minecraft.client.gui.components.EditBox.DEFAULT_TEXT_COLOR
|
||||
import net.minecraft.client.gui.components.Tooltip
|
||||
import net.minecraft.network.chat.Component
|
||||
import kotlin.reflect.KMutableProperty1
|
||||
import kotlin.reflect.jvm.javaField
|
||||
|
||||
abstract class CobblemonConfigEditBoxVariable(
|
||||
parent: CobblemonConfigVariableList,
|
||||
config: KMutableProperty1<out CobblemonConfig, *>,
|
||||
) : CobblemonConfigVariable(parent, config) {
|
||||
val editBox = EditBox(
|
||||
Minecraft.getInstance().font,
|
||||
parent.x,
|
||||
parent.y,
|
||||
WIDGET_WIDTH,
|
||||
SLOT_HEIGHT,
|
||||
labelLang,
|
||||
).also {
|
||||
it.height = WIDGET_HEIGHT
|
||||
it.setMaxLength(250)
|
||||
|
||||
it.value = getConfigValueAsString()
|
||||
}
|
||||
|
||||
init {
|
||||
children.addFirst(editBox)
|
||||
}
|
||||
|
||||
override fun updateConfigValueDisplay() {
|
||||
editBox.value = getConfigValueAsString()
|
||||
}
|
||||
|
||||
override fun render(
|
||||
context: GuiGraphics,
|
||||
index: Int,
|
||||
top: Int,
|
||||
left: Int,
|
||||
width: Int,
|
||||
height: Int,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
hovering: Boolean,
|
||||
partialTick: Float
|
||||
) {
|
||||
super.render(context, index, top, left, width, height, mouseX, mouseY, hovering, partialTick)
|
||||
|
||||
editBox.x = resetButton.x - editBox.width - PADDING
|
||||
editBox.y = getY(top) + WIDGET_Y_OFFSET
|
||||
editBox.render(context, mouseX, mouseY, partialTick)
|
||||
}
|
||||
}
|
||||
|
||||
class CobblemonConfigStringVariable(
|
||||
parent: CobblemonConfigVariableList,
|
||||
config: KMutableProperty1<out CobblemonConfig, String>,
|
||||
) : CobblemonConfigEditBoxVariable(parent, config) {
|
||||
override fun getConfigValueAsString(): String = (config.getter.call(parent.parent.clonedConfig) as String?) ?: ""
|
||||
|
||||
init {
|
||||
editBox.setResponder { value ->
|
||||
setConfigValue(value, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CobblemonConfigIntVariable(
|
||||
parent: CobblemonConfigVariableList,
|
||||
config: KMutableProperty1<out CobblemonConfig, Int>,
|
||||
) : CobblemonConfigEditBoxVariable(parent, config) {
|
||||
private val intConstraintAnnotation: IntConstraint? =
|
||||
config.javaField!!.annotations.firstOrNull{ it is IntConstraint } as IntConstraint?
|
||||
|
||||
override fun getConfigValueAsString(): String = (config.getter.call(parent.parent.clonedConfig) as Int?).toString()
|
||||
|
||||
init {
|
||||
editBox.setFilter { value -> value.toIntOrNull() != null || value.isBlank() }
|
||||
editBox.setResponder { value ->
|
||||
if (value.isBlank()) {
|
||||
return@setResponder
|
||||
}
|
||||
|
||||
val intValue = value.toInt()
|
||||
setConfigValue(intValue, false)
|
||||
|
||||
if (intConstraintAnnotation != null) {
|
||||
val isBetweenIntConstraint = intValue >= intConstraintAnnotation.min && intValue <= intConstraintAnnotation.max
|
||||
if (isBetweenIntConstraint) {
|
||||
tooltip = originalTooltip
|
||||
editBox.setTextColor(DEFAULT_TEXT_COLOR)
|
||||
} else {
|
||||
val errorLang = lang("config.ui.error.int_constraint", intConstraintAnnotation.min, intConstraintAnnotation.max).red()
|
||||
tooltip = Tooltip.create(tooltipLang.plainCopy().add(Component.literal("\n")).add(errorLang))
|
||||
ChatFormatting.RED.color?.let { editBox.setTextColor(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CobblemonConfigFloatVariable(
|
||||
parent: CobblemonConfigVariableList,
|
||||
config: KMutableProperty1<out CobblemonConfig, Float>,
|
||||
) : CobblemonConfigEditBoxVariable(parent, config) {
|
||||
override fun getConfigValueAsString(): String = (config.getter.call(parent.parent.clonedConfig) as Float?).toString()
|
||||
|
||||
init {
|
||||
editBox.setFilter { value -> value.toFloatOrNull() != null || value.isBlank() }
|
||||
editBox.setResponder { value ->
|
||||
if (value.toFloatOrNull() != null) {
|
||||
setConfigValue(value.toFloat(), false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CobblemonConfigDoubleVariable(
|
||||
parent: CobblemonConfigVariableList,
|
||||
config: KMutableProperty1<out CobblemonConfig, Double>,
|
||||
) : CobblemonConfigEditBoxVariable(parent, config) {
|
||||
override fun getConfigValueAsString(): String = (config.getter.call(parent.parent.clonedConfig) as Double?).toString()
|
||||
|
||||
init {
|
||||
editBox.setFilter { value -> value.toDoubleOrNull() != null || value.isBlank() }
|
||||
editBox.setResponder { value ->
|
||||
if (value.toDoubleOrNull() != null) {
|
||||
setConfigValue(value.toDouble(), false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.config.variable
|
||||
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.LABEL_Y_OFFSET
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.RESET_SLOT_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.SLOT_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.WIDGET_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.WIDGET_Y_OFFSET
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigVariableList
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigVariableList.CobblemonConfigVariableListEntry
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import com.cobblemon.mod.common.config.CobblemonConfigField
|
||||
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.components.Tooltip
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import java.text.Normalizer
|
||||
import kotlin.reflect.KMutableProperty1
|
||||
import kotlin.reflect.jvm.javaField
|
||||
|
||||
abstract class CobblemonConfigVariable(
|
||||
parent: CobblemonConfigVariableList,
|
||||
val config: KMutableProperty1<out CobblemonConfig, *>,
|
||||
) : CobblemonConfigVariableListEntry(parent) {
|
||||
val cobblemonConfigFieldAnnotation: CobblemonConfigField =
|
||||
config.javaField!!.annotations.firstOrNull{ it is CobblemonConfigField } as CobblemonConfigField
|
||||
|
||||
val labelEntry = "config.ui.${cobblemonConfigFieldAnnotation.lang}"
|
||||
val tooltipEntry = "$labelEntry.tooltip"
|
||||
val labelLang: MutableComponent = lang(labelEntry)
|
||||
val tooltipLang: MutableComponent = lang(tooltipEntry)
|
||||
val originalTooltip: Tooltip? = if (!tooltipLang.string.endsWith(tooltipEntry)) Tooltip.create(tooltipLang) else null
|
||||
|
||||
val resetButton: Button =
|
||||
Button.builder(lang("config.ui.reset")) {
|
||||
val defaultValue = config.getter.call(parent.parent.defaultConfig)
|
||||
setConfigValue(defaultValue)
|
||||
}
|
||||
.size(RESET_SLOT_WIDTH, WIDGET_HEIGHT)
|
||||
.build()
|
||||
|
||||
init {
|
||||
tooltip = originalTooltip
|
||||
children.add(resetButton)
|
||||
updateResetButton()
|
||||
}
|
||||
|
||||
abstract fun getConfigValueAsString(): String
|
||||
abstract fun updateConfigValueDisplay()
|
||||
|
||||
fun setConfigValue(value: Any?, updateConfigValueDisplay: Boolean = true) {
|
||||
config.setter.call(parent.parent.clonedConfig, value)
|
||||
|
||||
if (updateConfigValueDisplay) {
|
||||
updateConfigValueDisplay()
|
||||
}
|
||||
|
||||
updateResetButton()
|
||||
}
|
||||
|
||||
private fun updateResetButton() {
|
||||
resetButton.active = config.getter.call(parent.parent.clonedConfig) != config.getter.call(parent.parent.defaultConfig)
|
||||
}
|
||||
|
||||
override fun filter(text: String): Boolean {
|
||||
val normalizedLabel = Normalizer.normalize(labelLang.string, Normalizer.Form.NFD).replace("\\p{M}+".toRegex(), "")
|
||||
return normalizedLabel.contains(text, ignoreCase = true)
|
||||
}
|
||||
|
||||
override fun render(
|
||||
context: GuiGraphics,
|
||||
index: Int,
|
||||
top: Int,
|
||||
left: Int,
|
||||
width: Int,
|
||||
height: Int,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
hovering: Boolean,
|
||||
partialTick: Float
|
||||
) {
|
||||
val x = getX(left)
|
||||
val y = getY(top)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = labelLang,
|
||||
x = getX(left),
|
||||
y = getY(top) + LABEL_Y_OFFSET,
|
||||
shadow = true
|
||||
)
|
||||
|
||||
resetButton.x = x + SLOT_WIDTH - RESET_SLOT_WIDTH
|
||||
resetButton.y = y + WIDGET_Y_OFFSET
|
||||
resetButton.render(context, mouseX, mouseY, partialTick)
|
||||
}
|
||||
}
|
||||
@@ -15,8 +15,6 @@ import com.cobblemon.mod.common.client.entity.NPCClientDelegate
|
||||
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.NPCModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import java.util.UUID
|
||||
@@ -82,7 +80,6 @@ class ReferenceRenderableFace(val entity: PosableEntity, override val isLeftSide
|
||||
state.currentAspects = state.currentEntity.pokemon.aspects
|
||||
drawPosablePortrait(
|
||||
identifier = state.currentEntity.pokemon.species.resourceIdentifier,
|
||||
repository = PokemonModelRepository,
|
||||
contextScale = state.currentEntity.pokemon.form.baseScale,
|
||||
matrixStack = GuiGraphics.pose(),
|
||||
state = state,
|
||||
@@ -96,7 +93,6 @@ class ReferenceRenderableFace(val entity: PosableEntity, override val isLeftSide
|
||||
val limbSwingAmount = entity.walkAnimation.speed(partialTicks)
|
||||
drawPosablePortrait(
|
||||
identifier = state.npcEntity.npc.resourceIdentifier,
|
||||
repository = NPCModelRepository,
|
||||
matrixStack = GuiGraphics.pose(),
|
||||
state = state,
|
||||
reversed = !isLeftSide,
|
||||
@@ -131,7 +127,6 @@ class ArtificialRenderableFace(
|
||||
contextScale = species.getForm(aspects).baseScale,
|
||||
state = state,
|
||||
reversed = !isLeftSide,
|
||||
repository = PokemonModelRepository,
|
||||
partialTicks = partialTicks
|
||||
)
|
||||
} else if (modelType == "npc") {
|
||||
@@ -140,7 +135,6 @@ class ArtificialRenderableFace(
|
||||
matrixStack = GuiGraphics.pose(),
|
||||
state = state,
|
||||
reversed = !isLeftSide,
|
||||
repository = NPCModelRepository,
|
||||
partialTicks = partialTicks
|
||||
)
|
||||
}
|
||||
|
||||
-3
@@ -11,9 +11,7 @@ package com.cobblemon.mod.common.client.gui.npc.widgets
|
||||
import com.cobblemon.mod.common.api.gui.drawProfile
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.NPCModelRepository
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Renderable
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
@@ -47,7 +45,6 @@ class NPCRenderWidget(
|
||||
context.pose().translate(x + (WIDTH / 2F), y + HEIGHT + (HEIGHT / 4F), -500F)
|
||||
|
||||
drawProfile(
|
||||
repository = NPCModelRepository,
|
||||
resourceIdentifier = identifier,
|
||||
matrixStack = context.pose(),
|
||||
partialTicks = delta,
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.pc
|
||||
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.font
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.storage.ClientBox
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.RequestRenamePCBoxPacket
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.EditBox
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
|
||||
class BoxNameWidget(
|
||||
private val pX: Int,
|
||||
pY: Int,
|
||||
text: Component = "BoxNameWidget".text(),
|
||||
private val pcGui: PCGUI,
|
||||
private val storageWidget: StorageWidget,
|
||||
): EditBox(Minecraft.getInstance().font, pX, pY, 0, HEIGHT, text) {
|
||||
|
||||
companion object {
|
||||
const val HEIGHT = 14
|
||||
}
|
||||
|
||||
init {
|
||||
setMaxLength(21)
|
||||
update()
|
||||
setResponder { update() }
|
||||
}
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
if (cursorPosition != value.length) moveCursorToEnd(false)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = text(),
|
||||
x = x,
|
||||
y = y
|
||||
)
|
||||
}
|
||||
|
||||
override fun setFocused(focused: Boolean) {
|
||||
super.setFocused(focused)
|
||||
update()
|
||||
if (!focused) {
|
||||
RequestRenamePCBoxPacket(pcGui.pc.uuid, storageWidget.box, value).sendToServer()
|
||||
pcGui.pc.boxes[storageWidget.box].name = if (value.isBlank()) null else Component.literal(value).bold()
|
||||
value = ""
|
||||
}
|
||||
}
|
||||
|
||||
private fun text(): MutableComponent {
|
||||
return (if (isFocused) {
|
||||
"${value}_".text()
|
||||
} else if (value.isEmpty()) {
|
||||
getBox().name?: Component.translatable("cobblemon.ui.pc.box.title", storageWidget.box + 1)
|
||||
} else {
|
||||
value.text()
|
||||
}).bold().font(CobblemonResources.DEFAULT_LARGE)
|
||||
}
|
||||
|
||||
fun getBox(): ClientBox {
|
||||
return pcGui.pc.boxes[storageWidget.box]
|
||||
}
|
||||
|
||||
fun update() {
|
||||
width = Minecraft.getInstance().font.width(text())
|
||||
x = pX - width / 2
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,8 @@ class BoxStorageSlot(
|
||||
}
|
||||
|
||||
override fun shouldRender(): Boolean {
|
||||
if (!super.shouldRender()) return false
|
||||
|
||||
val grabbedSlot = parent.grabbedSlot
|
||||
return if (grabbedSlot == null) {
|
||||
true
|
||||
|
||||
@@ -30,4 +30,6 @@ class GrabbedStorageSlot(
|
||||
override fun getPokemon() = pokemon
|
||||
|
||||
override fun isHoveredOrFocused() = true
|
||||
|
||||
override fun shouldRender() = true
|
||||
}
|
||||
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.client.gui.pc
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.storage.pc.search.Search
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
@@ -22,6 +23,7 @@ import com.cobblemon.mod.common.client.gui.summary.widgets.common.reformatNature
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.storage.ClientPC
|
||||
import com.cobblemon.mod.common.client.storage.ClientParty
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.SortPCBoxPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.UnlinkPlayerFromPCPacket
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
@@ -36,6 +38,7 @@ import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import kotlin.isInitialized
|
||||
|
||||
class PCGUI(
|
||||
val pc: ClientPC,
|
||||
@@ -67,9 +70,13 @@ class PCGUI(
|
||||
}
|
||||
|
||||
private lateinit var storageWidget: StorageWidget
|
||||
private lateinit var boxNameWidget: BoxNameWidget
|
||||
private lateinit var searchWidget: SearchWidget
|
||||
private lateinit var wallpaperWidget: WallpapersScrollingWidget
|
||||
private var modelWidget: ModelWidget? = null
|
||||
internal var previewPokemon: Pokemon? = null
|
||||
|
||||
var search: Search = Search.DEFAULT
|
||||
var ticksElapsed = 0
|
||||
var selectPointerOffsetY = 0
|
||||
var selectPointerOffsetIncrement = false
|
||||
@@ -91,7 +98,9 @@ class PCGUI(
|
||||
pX = x + 221,
|
||||
pY = y + 17,
|
||||
forward = true
|
||||
) { storageWidget.box += 1 }
|
||||
) {
|
||||
storageWidget.box += 1
|
||||
}
|
||||
)
|
||||
|
||||
// Add Backwards Button
|
||||
@@ -100,7 +109,20 @@ class PCGUI(
|
||||
pX = x + 119,
|
||||
pY = y + 17,
|
||||
forward = false
|
||||
) { storageWidget.box -= 1 }
|
||||
) {
|
||||
storageWidget.box -= 1
|
||||
}
|
||||
)
|
||||
|
||||
// Add Sort Button
|
||||
addRenderableWidget(
|
||||
SortButton(
|
||||
pX = x + 85,
|
||||
pY = y + 12,
|
||||
onPress = { it as SortButton
|
||||
SortPCBoxPacket(pc.uuid, storageWidget.box, it.sortMode, hasShiftDown()).sendToServer()
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
// Add Storage
|
||||
@@ -113,8 +135,47 @@ class PCGUI(
|
||||
)
|
||||
this.storageWidget.box = openOnBox
|
||||
|
||||
// Add Box Name
|
||||
this.boxNameWidget = BoxNameWidget(
|
||||
pX = x + 172,
|
||||
pY = y + 15,
|
||||
pcGui = this,
|
||||
storageWidget = storageWidget
|
||||
)
|
||||
|
||||
// Add Search Widget
|
||||
this.searchWidget = SearchWidget(
|
||||
pX = x + 117,
|
||||
pY = y + 183,
|
||||
update = { search = Search.of(searchWidget.value) }
|
||||
)
|
||||
|
||||
// Add Wallpaper Button
|
||||
this.addRenderableWidget(
|
||||
WallpaperButton(
|
||||
pX = x + 235,
|
||||
pY = y + 12,
|
||||
onPress = {
|
||||
configuration.showParty = wallpaperWidget.visible
|
||||
wallpaperWidget.visible = !wallpaperWidget.visible
|
||||
},
|
||||
pcGui = this
|
||||
)
|
||||
)
|
||||
|
||||
// Add Wallpaper Widget
|
||||
this.wallpaperWidget = WallpapersScrollingWidget(
|
||||
pX = x + 275,
|
||||
pY = y + 30,
|
||||
pcGui = this,
|
||||
storageWidget = storageWidget
|
||||
)
|
||||
|
||||
this.setPreviewPokemon(null)
|
||||
this.addRenderableWidget(storageWidget)
|
||||
this.addRenderableWidget(boxNameWidget)
|
||||
this.addRenderableWidget(searchWidget)
|
||||
this.addRenderableWidget(wallpaperWidget)
|
||||
super.init()
|
||||
}
|
||||
|
||||
@@ -136,7 +197,9 @@ class PCGUI(
|
||||
)
|
||||
|
||||
// Render Model Portrait
|
||||
modelWidget?.render(context, mouseX, mouseY, delta)
|
||||
if (search.passes(previewPokemon)) {
|
||||
modelWidget?.render(context, mouseX, mouseY, delta)
|
||||
}
|
||||
|
||||
// Render Base Resource
|
||||
blitk(
|
||||
@@ -177,7 +240,7 @@ class PCGUI(
|
||||
|
||||
// Render Pokemon Info
|
||||
val pokemon = previewPokemon
|
||||
if (pokemon != null) {
|
||||
if (pokemon != null && search.passes(pokemon)) {
|
||||
// Status
|
||||
val status = pokemon.status?.status
|
||||
if (pokemon.isFainted() || status != null) {
|
||||
@@ -367,16 +430,6 @@ class PCGUI(
|
||||
)
|
||||
}
|
||||
|
||||
// Box Label
|
||||
drawScaledText(
|
||||
context = context,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
text = Component.translatable("cobblemon.ui.pc.box.title", (this.storageWidget.box + 1).toString()).bold(),
|
||||
x = x + 172,
|
||||
y = y + 15,
|
||||
centered = true
|
||||
)
|
||||
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = topSpacerResource,
|
||||
@@ -454,27 +507,36 @@ class PCGUI(
|
||||
}
|
||||
|
||||
override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
|
||||
if (isInventoryKeyPressed(minecraft, keyCode, scanCode)) {
|
||||
val boxNameSelected = this::boxNameWidget.isInitialized && boxNameWidget.isFocused
|
||||
val searchSelected = this::searchWidget.isInitialized && searchWidget.isFocused
|
||||
if (isInventoryKeyPressed(minecraft, keyCode, scanCode) && !boxNameSelected && !searchSelected) {
|
||||
playSound(CobblemonSounds.PC_OFF)
|
||||
UnlinkPlayerFromPCPacket().sendToServer()
|
||||
Minecraft.getInstance().setScreen(null)
|
||||
return true
|
||||
}
|
||||
|
||||
if ((keyCode == InputConstants.KEY_RETURN || keyCode == InputConstants.KEY_NUMPADENTER)
|
||||
&& (boxNameSelected || searchSelected)) {
|
||||
this.focused = null
|
||||
}
|
||||
|
||||
when (keyCode) {
|
||||
InputConstants.KEY_ESCAPE -> {
|
||||
playSound(CobblemonSounds.PC_OFF)
|
||||
UnlinkPlayerFromPCPacket().sendToServer()
|
||||
onClose()
|
||||
return true
|
||||
}
|
||||
InputConstants.KEY_RIGHT -> {
|
||||
playSound(CobblemonSounds.PC_CLICK)
|
||||
this.storageWidget.box += 1
|
||||
return true
|
||||
}
|
||||
|
||||
InputConstants.KEY_LEFT -> {
|
||||
playSound(CobblemonSounds.PC_CLICK)
|
||||
this.storageWidget.box -= 1
|
||||
return true
|
||||
}
|
||||
}
|
||||
return super.keyPressed(keyCode, scanCode, modifiers)
|
||||
@@ -483,9 +545,7 @@ class PCGUI(
|
||||
/**
|
||||
* Whether this Screen should pause the Game in SinglePlayer
|
||||
*/
|
||||
override fun isPauseScreen(): Boolean {
|
||||
return false
|
||||
}
|
||||
override fun isPauseScreen() = false
|
||||
|
||||
override fun tick() {
|
||||
ticksElapsed++
|
||||
@@ -521,4 +581,10 @@ class PCGUI(
|
||||
modelWidget = null
|
||||
}
|
||||
}
|
||||
|
||||
fun updateBoxName() {
|
||||
if (this::boxNameWidget.isInitialized) {
|
||||
boxNameWidget.update()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,6 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
open class PCGUIConfiguration(
|
||||
val exitFunction: (PCGUI) -> Unit = { it.closeNormally(unlink = true) },
|
||||
val selectOverride: ((PCGUI, StorePosition, Pokemon?) -> Unit)? = null,
|
||||
val showParty: Boolean = true,
|
||||
var showParty: Boolean = true,
|
||||
val canSelect: (Pokemon) -> Boolean = { true }
|
||||
)
|
||||
@@ -25,6 +25,8 @@ class PartyStorageSlot(
|
||||
}
|
||||
|
||||
override fun shouldRender(): Boolean {
|
||||
if (!super.shouldRender()) return false
|
||||
|
||||
val grabbedSlot = parent.grabbedSlot
|
||||
return if (grabbedSlot == null) {
|
||||
true
|
||||
@@ -32,4 +34,8 @@ class PartyStorageSlot(
|
||||
grabbedSlot.getPokemon() != getPokemon()
|
||||
}
|
||||
}
|
||||
|
||||
override fun clickable(): Boolean {
|
||||
return parent.pcGui.configuration.showParty && super.clickable()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.pc
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.EditBox
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
class SearchWidget(
|
||||
private var pX: Int,
|
||||
private var pY: Int,
|
||||
text: Component = "SearchWidget".text(),
|
||||
update: () -> (Unit)
|
||||
): EditBox(Minecraft.getInstance().font, pX, pY, WIDTH, HEIGHT, text) {
|
||||
|
||||
companion object {
|
||||
const val WIDTH = 110
|
||||
const val HEIGHT = 14
|
||||
const val HINT_COLOUR = 0x8D8D8D
|
||||
private val hint = Component.translatable("cobblemon.ui.pc.search")
|
||||
private val searchIcon = cobblemonResource("textures/gui/pc/pc_search_icon.png")
|
||||
}
|
||||
|
||||
init {
|
||||
setMaxLength(21)
|
||||
setResponder { update() }
|
||||
}
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
if (cursorPosition != value.length) moveCursorToEnd(false)
|
||||
val input = if (isFocused) "${value}_".text() else value.text()
|
||||
val useHint = !isFocused && value.isEmpty()
|
||||
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = searchIcon,
|
||||
x = pX + 1,
|
||||
y = pY + 3,
|
||||
width = 8,
|
||||
height = 8
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
text = if (useHint) hint.bold() else input.bold(),
|
||||
x = pX + if (useHint) 55 else 14,
|
||||
y = pY + 2,
|
||||
colour = if (useHint) HINT_COLOUR else 0xFFFFFF,
|
||||
centered = useHint
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.pc
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSortMode
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.client.sounds.SoundManager
|
||||
import net.minecraft.network.chat.Component
|
||||
import kotlin.math.abs
|
||||
|
||||
class SortButton(
|
||||
pX: Int, pY: Int,
|
||||
onPress: OnPress,
|
||||
) : Button(pX, pY, WIDTH, HEIGHT, Component.literal("SortButton"), onPress, DEFAULT_NARRATION) {
|
||||
|
||||
var sortMode = PokemonSortMode.NAME
|
||||
|
||||
companion object {
|
||||
const val WIDTH = 24
|
||||
const val HEIGHT = 11
|
||||
|
||||
private val modeResources = PokemonSortMode.entries.map { cobblemonResource("textures/gui/pc/pc_sort_${it.name.lowercase()}.png") }
|
||||
private val buttonResource = cobblemonResource("textures/gui/pc/pc_sort_button.png")
|
||||
}
|
||||
|
||||
override fun renderWidget(context: net.minecraft.client.gui.GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = buttonResource,
|
||||
x = x,
|
||||
y = y,
|
||||
width = WIDTH,
|
||||
height = HEIGHT,
|
||||
vOffset = if (isHovered()) HEIGHT else 0,
|
||||
textureHeight = HEIGHT * 2
|
||||
)
|
||||
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = modeResources[sortMode.ordinal],
|
||||
x = x,
|
||||
y = y,
|
||||
width = WIDTH,
|
||||
height = HEIGHT
|
||||
)
|
||||
}
|
||||
|
||||
override fun mouseScrolled(
|
||||
mouseX: Double,
|
||||
mouseY: Double,
|
||||
scrollX: Double,
|
||||
scrollY: Double
|
||||
): Boolean {
|
||||
if (abs(scrollY) >= .5 && isMouseOver(mouseX, mouseY)) {
|
||||
val modes = PokemonSortMode.entries
|
||||
var mode = sortMode.ordinal + if (scrollY > 0) 1 else -1
|
||||
if (mode < 0) mode = modes.size - 1
|
||||
if (mode >= modes.size) mode = 0
|
||||
sortMode = modes[mode]
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun playDownSound(soundManager: SoundManager) {
|
||||
soundManager.play(SimpleSoundInstance.forUI(CobblemonSounds.PC_CLICK, 1.0F))
|
||||
}
|
||||
}
|
||||
@@ -212,7 +212,15 @@ open class StorageSlot(
|
||||
}
|
||||
|
||||
open fun shouldRender(): Boolean {
|
||||
return true
|
||||
return parent.pcGui.search.passes(getPokemon())
|
||||
}
|
||||
|
||||
open fun clickable(): Boolean {
|
||||
return getPokemon() == null || parent.pcGui.search.passes(getPokemon())
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
return if (clickable()) super.mouseClicked(mouseX, mouseY, button) else false
|
||||
}
|
||||
|
||||
fun isHovered(mouseX: Int, mouseY: Int) = mouseX.toFloat() in (x.toFloat()..(x.toFloat() + SIZE)) && mouseY.toFloat() in (y.toFloat()..(y.toFloat() + SIZE))
|
||||
|
||||
@@ -57,7 +57,6 @@ class StorageWidget(
|
||||
const val PARTY_SLOT_PADDING = 6
|
||||
|
||||
private val partyPanelResource = cobblemonResource("textures/gui/pc/party_panel.png")
|
||||
private val screenOverlayResource = cobblemonResource("textures/gui/pc/pc_screen_overlay.png")
|
||||
}
|
||||
|
||||
private val partySlots = arrayListOf<PartyStorageSlot>()
|
||||
@@ -82,6 +81,7 @@ class StorageWidget(
|
||||
// Else it's greater than max, wrap around to start
|
||||
else 0
|
||||
this.setupStorageSlots()
|
||||
this.pcGui.updateBoxName()
|
||||
}
|
||||
|
||||
init {
|
||||
@@ -255,7 +255,7 @@ class StorageWidget(
|
||||
// Screen Overlay
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = screenOverlayResource,
|
||||
texture = pc.boxes[box].wallpaper,
|
||||
x = x - 17,
|
||||
y = y - 17,
|
||||
width = 208,
|
||||
@@ -348,7 +348,7 @@ class StorageWidget(
|
||||
}
|
||||
|
||||
if (grabbedSlot == null) {
|
||||
if (clickedPokemon != null) {
|
||||
if (clickedPokemon != null && pcGui.search.passes(clickedPokemon)) {
|
||||
val shiftClicked = Screen.hasShiftDown()
|
||||
if (shiftClicked) {
|
||||
if (clickedPosition is PCPosition) {
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.pc
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.client.sounds.SoundManager
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
class WallpaperButton(
|
||||
pX: Int, pY: Int,
|
||||
onPress: OnPress,
|
||||
private val pcGui: PCGUI
|
||||
) : Button(pX, pY, WIDTH, HEIGHT, Component.literal("WallpaperButton"), onPress, DEFAULT_NARRATION) {
|
||||
|
||||
companion object {
|
||||
const val WIDTH = 24
|
||||
const val HEIGHT = 11
|
||||
|
||||
private val buttonResource = cobblemonResource("textures/gui/pc/pc_wallpaper_button.png")
|
||||
}
|
||||
|
||||
override fun renderWidget(context: net.minecraft.client.gui.GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = buttonResource,
|
||||
x = x,
|
||||
y = y,
|
||||
width = WIDTH,
|
||||
height = HEIGHT,
|
||||
vOffset = if (isHovered() || !pcGui.configuration.showParty) HEIGHT else 0,
|
||||
textureHeight = HEIGHT * 2
|
||||
)
|
||||
}
|
||||
|
||||
override fun playDownSound(soundManager: SoundManager) {
|
||||
soundManager.play(SimpleSoundInstance.forUI(CobblemonSounds.PC_CLICK, 1.0F))
|
||||
}
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.pc
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.ScrollingWidget
|
||||
import com.cobblemon.mod.common.client.gui.pc.WallpapersScrollingWidget.WallpaperEntry
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.gui.PCBoxWallpaperRepository
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.RequestChangePCBoxWallpaperPacket
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class WallpapersScrollingWidget(
|
||||
pX: Int, val pY: Int,
|
||||
val pcGui: PCGUI,
|
||||
val storageWidget: StorageWidget
|
||||
) : ScrollingWidget<WallpaperEntry>(
|
||||
width = WIDTH,
|
||||
height = HEIGHT,
|
||||
left = pX,
|
||||
top = 0,
|
||||
slotHeight = SLOT_HEIGHT + SLOT_PADDING,
|
||||
scrollBarWidth = SCROLL_BAR_WIDTH
|
||||
) {
|
||||
companion object {
|
||||
const val WIDTH = 67
|
||||
const val HEIGHT = 147
|
||||
const val SLOT_WIDTH = 58
|
||||
const val SLOT_HEIGHT = 53
|
||||
const val SLOT_PADDING = 3
|
||||
const val SCROLL_BAR_WIDTH = 3
|
||||
val ENTRY_HOVERED = cobblemonResource("textures/gui/pc/wallpaper_entry_hover.png")
|
||||
val BACKGROUND = cobblemonResource("textures/gui/pc/wallpaper_widget_background.png")
|
||||
}
|
||||
|
||||
init {
|
||||
this.visible = false
|
||||
this.y = pY
|
||||
createEntries()
|
||||
}
|
||||
|
||||
override fun renderWidget(
|
||||
context: GuiGraphics,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
delta: Float
|
||||
) {
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = BACKGROUND,
|
||||
x = x - 1,
|
||||
y = y - 1,
|
||||
width = width + 1,
|
||||
height = height + 2
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
text = lang("ui.wallpapers").bold(),
|
||||
x = x + 23,
|
||||
y = y - 18.5,
|
||||
centered = true,
|
||||
shadow = true
|
||||
)
|
||||
|
||||
super.renderWidget(context, mouseX, mouseY, delta)
|
||||
}
|
||||
|
||||
private fun createEntries() {
|
||||
clearEntries()
|
||||
for (wallpaper in PCBoxWallpaperRepository.wallpapers) {
|
||||
addEntry(WallpaperEntry(wallpaper))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRowLeft(): Int {
|
||||
return this.left + SLOT_PADDING
|
||||
}
|
||||
|
||||
override fun getRowWidth(): Int {
|
||||
return SLOT_WIDTH
|
||||
}
|
||||
|
||||
override fun getRowRight(): Int {
|
||||
return this.rowLeft + SLOT_WIDTH
|
||||
}
|
||||
|
||||
inner class WallpaperEntry(val wallpaper: ResourceLocation) : Slot<WallpaperEntry>() {
|
||||
override fun render(
|
||||
guiGraphics: GuiGraphics,
|
||||
index: Int,
|
||||
top: Int,
|
||||
left: Int,
|
||||
width: Int,
|
||||
height: Int,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
hovering: Boolean,
|
||||
partialTick: Float
|
||||
) {
|
||||
val matrices = guiGraphics.pose()
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = wallpaper,
|
||||
x = left,
|
||||
y = top,
|
||||
width = width,
|
||||
height = height,
|
||||
)
|
||||
|
||||
if (hovering) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = ENTRY_HOVERED,
|
||||
x = left,
|
||||
y = top,
|
||||
width = width,
|
||||
height = height
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
if (this@WallpapersScrollingWidget.visible && isMouseOver(mouseX, mouseY)) {
|
||||
RequestChangePCBoxWallpaperPacket(pcGui.pc.uuid, storageWidget.box, wallpaper).sendToServer()
|
||||
pcGui.pc.boxes[storageWidget.box].wallpaper = wallpaper
|
||||
minecraft.soundManager.play(SimpleSoundInstance.forUI(CobblemonSounds.PC_CLICK, 1.0F))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getNarration(): Component? {
|
||||
return wallpaper.toString().text()
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -38,7 +38,7 @@ import com.cobblemon.mod.common.client.gui.summary.widgets.SoundlessWidget
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.drawScaledTextJustifiedRight
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.pokemon.FormData
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
@@ -655,7 +655,7 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
|
||||
fun recalculatePoses(renderablePokemon: RenderablePokemon) {
|
||||
val state = FloatingState()
|
||||
state.currentAspects = renderablePokemon.aspects
|
||||
val poser = PokemonModelRepository.getPoser(renderablePokemon.species.resourceIdentifier, state)
|
||||
val poser = VaryingModelRepository.getPoser(renderablePokemon.species.resourceIdentifier, state)
|
||||
state.currentModel = poser
|
||||
this.poseList = poser.poses
|
||||
.map { it.value.poseTypes.minBy { it.ordinal } }
|
||||
|
||||
+1
-1
@@ -80,7 +80,7 @@ class SizeWidget(val pX: Int, val pY: Int) : SoundlessWidget(
|
||||
matrices.pushPose()
|
||||
matrices.translate(
|
||||
pX.toDouble() + 50,
|
||||
pY.toDouble() + (POKEMON_DESCRIPTION_HEIGHT / 2) + 18.5 - baseScale * modelScale * 1.5,
|
||||
pY.toDouble() + (POKEMON_DESCRIPTION_HEIGHT / 2) + 18.5,
|
||||
0.0
|
||||
)
|
||||
drawProfilePokemon(
|
||||
|
||||
+3
-3
@@ -161,7 +161,7 @@ class StarterSelectionScreen(private val categories: List<RenderableStarterCateg
|
||||
pX = x + 119, pY = height / 2 + 84,
|
||||
pWidth = StarterRoundabout.MODEL_WIDTH, pHeight = StarterRoundabout.MODEL_HEIGHT,
|
||||
pokemon = currentPokemon,
|
||||
rotationVector = this.modelWidget.rotVec
|
||||
rotationVector = this.modelWidget.rotationVector
|
||||
)
|
||||
|
||||
starterRoundaboutLeft = StarterRoundabout(
|
||||
@@ -169,7 +169,7 @@ class StarterSelectionScreen(private val categories: List<RenderableStarterCateg
|
||||
pWidth = StarterRoundabout.MODEL_WIDTH, pHeight = StarterRoundabout.MODEL_HEIGHT,
|
||||
pokemon = currentCategory.pokemon[leftOfCurrentSelection()],
|
||||
clickAction = { _, _ -> this.left() },
|
||||
rotationVector = this.modelWidget.rotVec
|
||||
rotationVector = this.modelWidget.rotationVector
|
||||
)
|
||||
|
||||
starterRoundaboutRight = StarterRoundabout(
|
||||
@@ -177,7 +177,7 @@ class StarterSelectionScreen(private val categories: List<RenderableStarterCateg
|
||||
pWidth = StarterRoundabout.MODEL_WIDTH, pHeight = StarterRoundabout.MODEL_HEIGHT,
|
||||
pokemon = currentCategory.pokemon[rightOfCurrentSelection()],
|
||||
clickAction = { _, _ -> this.right() },
|
||||
rotationVector = this.modelWidget.rotVec
|
||||
rotationVector = this.modelWidget.rotationVector
|
||||
)
|
||||
|
||||
addRenderableWidget(starterRoundaboutLeft)
|
||||
|
||||
@@ -35,7 +35,7 @@ import com.cobblemon.mod.common.client.gui.summary.widgets.screens.moves.MoveSwa
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.screens.moves.MovesWidget
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.screens.stats.StatWidget
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
@@ -235,7 +235,8 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
|
||||
pokemon = selectedPokemon.asRenderablePokemon(),
|
||||
baseScale = 2F,
|
||||
rotationY = 325F,
|
||||
offsetY = -10.0
|
||||
offsetY = -10.0,
|
||||
shouldFollowCursor = true,
|
||||
)
|
||||
addRenderableOnly(this.modelWidget)
|
||||
}
|
||||
@@ -274,9 +275,11 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
|
||||
listenToMoveSet()
|
||||
displayMainScreen(mainScreenIndex)
|
||||
children().find { it is EvolutionSelectScreen }?.let(this::removeWidget)
|
||||
if (this::modelWidget.isInitialized) {
|
||||
this.modelWidget.pokemon = selectedPokemon.asRenderablePokemon()
|
||||
|
||||
if (::modelWidget.isInitialized) {
|
||||
modelWidget.pokemon = selectedPokemon.asRenderablePokemon()
|
||||
}
|
||||
|
||||
if (this::nicknameEntryWidget.isInitialized) {
|
||||
this.nicknameEntryWidget.setSelectedPokemon(selectedPokemon)
|
||||
}
|
||||
@@ -592,12 +595,6 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
|
||||
return children().any { it.mouseScrolled(mouseX, mouseY, amount, verticalAmount) }
|
||||
}
|
||||
|
||||
/*
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
return children().any { it.mouseClicked(mouseX, mouseY, button) }
|
||||
}
|
||||
*/
|
||||
|
||||
override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean {
|
||||
if (sideScreenIndex == MOVE_SWAP || sideScreenIndex == EVOLVE) sideScreen.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
|
||||
if (mainScreenIndex == MOVES) mainScreen.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
|
||||
@@ -619,7 +616,7 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
|
||||
this.focused = null
|
||||
}
|
||||
if (Cobblemon.config.enableDebugKeys) {
|
||||
val model = PokemonModelRepository.getPoser(selectedPokemon.species.resourceIdentifier, modelWidget.state)
|
||||
val model = VaryingModelRepository.getPoser(selectedPokemon.species.resourceIdentifier, modelWidget.state)
|
||||
if (keyCode == InputConstants.KEY_UP) {
|
||||
model.profileTranslation = model.profileTranslation.add(0.0, -0.01, 0.0)
|
||||
}
|
||||
@@ -648,7 +645,7 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
|
||||
|
||||
override fun onClose() {
|
||||
if (Cobblemon.config.enableDebugKeys) {
|
||||
val model = PokemonModelRepository.getPoser(selectedPokemon.species.resourceIdentifier, modelWidget.state)
|
||||
val model = VaryingModelRepository.getPoser(selectedPokemon.species.resourceIdentifier, modelWidget.state)
|
||||
Minecraft.getInstance().player?.sendSystemMessage(Component.literal("Profile Translation: ${model.profileTranslation}"))
|
||||
Minecraft.getInstance().player?.sendSystemMessage(Component.literal("Profile Scale: ${model.profileScale}"))
|
||||
Cobblemon.LOGGER.info("override var profileTranslation = Vec3d(${model.profileTranslation.x}, ${model.profileTranslation.y}, ${model.profileTranslation.z})")
|
||||
|
||||
+52
-8
@@ -8,7 +8,9 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.summary.widgets
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
|
||||
import com.cobblemon.mod.common.client.gui.calculateHeadYawAndPitch
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.pokemon.RenderablePokemon
|
||||
import com.cobblemon.mod.common.util.math.fromEulerXYZDegrees
|
||||
@@ -20,29 +22,39 @@ import org.joml.Vector3f
|
||||
class ModelWidget(
|
||||
pX: Int, pY: Int,
|
||||
pWidth: Int, pHeight: Int,
|
||||
var pokemon: RenderablePokemon,
|
||||
pokemon: RenderablePokemon,
|
||||
val baseScale: Float = 2.7F,
|
||||
var rotationY: Float = 35F,
|
||||
var offsetY: Double = 0.0,
|
||||
val playCryOnClick: Boolean = false,
|
||||
val shouldFollowCursor: Boolean = false,
|
||||
): SoundlessWidget(pX, pY, pWidth, pHeight, Component.literal("Summary - ModelWidget")) {
|
||||
|
||||
companion object {
|
||||
var render = true
|
||||
const val MAX_SECONDS_LOOKING = 6L
|
||||
}
|
||||
|
||||
var pokemon: RenderablePokemon = pokemon
|
||||
set (value) {
|
||||
field = value
|
||||
currentYawAndPitch = Pair(0f, 0f)
|
||||
}
|
||||
|
||||
var state = FloatingState()
|
||||
val rotVec = Vector3f(13F, rotationY, 0F)
|
||||
var lookStartTime: Long? = null
|
||||
var currentYawAndPitch: Pair<Float, Float> = Pair(0f, 0f)
|
||||
val rotationVector = Vector3f(13F, rotationY, 0F)
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, pMouseX: Int, pMouseY: Int, partialTicks: Float) {
|
||||
if (!render) {
|
||||
return
|
||||
}
|
||||
isHovered = pMouseX >= x && pMouseY >= y && pMouseX < x + width && pMouseY < y + height
|
||||
renderPKM(context, partialTicks)
|
||||
renderPKM(context, partialTicks, pMouseX, pMouseY)
|
||||
}
|
||||
|
||||
private fun renderPKM(context: GuiGraphics, partialTicks: Float) {
|
||||
private fun renderPKM(context: GuiGraphics, partialTicks: Float, mouseX: Int, mouseY: Int) {
|
||||
val matrices = context.pose()
|
||||
matrices.pushPose()
|
||||
|
||||
@@ -50,19 +62,48 @@ class ModelWidget(
|
||||
x,
|
||||
y,
|
||||
x + width,
|
||||
y + height
|
||||
y + height
|
||||
)
|
||||
|
||||
matrices.translate(x + width * 0.5, y.toDouble() + offsetY, 0.0)
|
||||
matrices.scale(baseScale, baseScale, baseScale)
|
||||
matrices.pushPose()
|
||||
|
||||
if (isHovered) {
|
||||
lookStartTime = System.currentTimeMillis()
|
||||
}
|
||||
|
||||
val timeLooking = lookStartTime?.let { (System.currentTimeMillis() - it) / 1000 } ?: MAX_SECONDS_LOOKING
|
||||
val lookedTooMuch = timeLooking >= MAX_SECONDS_LOOKING
|
||||
val resetToCenter = (!isHovered && lookedTooMuch) || !shouldFollowCursor || !Cobblemon.config.summaryPokemonFollowCursor
|
||||
|
||||
if (resetToCenter) {
|
||||
lookStartTime = null
|
||||
}
|
||||
|
||||
val rotation = Quaternionf().fromEulerXYZDegrees(rotationVector)
|
||||
|
||||
if (shouldFollowCursor) {
|
||||
currentYawAndPitch = calculateHeadYawAndPitch(
|
||||
x + width / 2f,
|
||||
y + height / 2f,
|
||||
rotation,
|
||||
mouseX,
|
||||
mouseY,
|
||||
currentYawAndPitch.first,
|
||||
currentYawAndPitch.second,
|
||||
resetToCenter
|
||||
)
|
||||
}
|
||||
|
||||
drawProfilePokemon(
|
||||
renderablePokemon = pokemon,
|
||||
matrixStack = matrices,
|
||||
rotation = Quaternionf().fromEulerXYZDegrees(rotVec),
|
||||
rotation = rotation,
|
||||
state = state,
|
||||
partialTicks = partialTicks
|
||||
partialTicks = partialTicks,
|
||||
headYaw = currentYawAndPitch.first,
|
||||
headPitch = currentYawAndPitch.second,
|
||||
)
|
||||
|
||||
matrices.popPose()
|
||||
@@ -72,7 +113,10 @@ class ModelWidget(
|
||||
}
|
||||
|
||||
override fun mouseClicked(pMouseX: Double, pMouseY: Double, pButton: Int): Boolean {
|
||||
if (this.isHovered) playCry()
|
||||
if (this.isHovered) {
|
||||
playCry()
|
||||
}
|
||||
|
||||
return super.mouseClicked(pMouseX, pMouseY, pButton)
|
||||
}
|
||||
|
||||
|
||||
+8
-8
@@ -13,7 +13,7 @@ import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.keybind.CobblemonKeyBinding
|
||||
import com.cobblemon.mod.common.client.keybind.KeybindCategories
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.mojang.blaze3d.platform.InputConstants
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.chat.Component
|
||||
@@ -38,7 +38,7 @@ object DebugKeybindings {
|
||||
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
|
||||
if (currentlySelectedPokemon != null) {
|
||||
val state = FloatingState().also { it.currentAspects = currentlySelectedPokemon.aspects }
|
||||
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
|
||||
val model = VaryingModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
|
||||
model.portraitScale += 0.01F
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ object DebugKeybindings {
|
||||
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
|
||||
if (currentlySelectedPokemon != null) {
|
||||
val state = FloatingState().also { it.currentAspects = currentlySelectedPokemon.aspects }
|
||||
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
|
||||
val model = VaryingModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
|
||||
model.portraitScale -= 0.01F
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ object DebugKeybindings {
|
||||
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
|
||||
if (currentlySelectedPokemon != null) {
|
||||
val state = FloatingState().also { it.currentAspects = currentlySelectedPokemon.aspects }
|
||||
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
|
||||
val model = VaryingModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
|
||||
model.portraitTranslation = model.portraitTranslation.add(0.0, -0.01, 0.0)
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ object DebugKeybindings {
|
||||
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
|
||||
if (currentlySelectedPokemon != null) {
|
||||
val state = FloatingState().also { it.currentAspects = currentlySelectedPokemon.aspects }
|
||||
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
|
||||
val model = VaryingModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
|
||||
model.portraitTranslation = model.portraitTranslation.add(0.0, 0.01, 0.0)
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ object DebugKeybindings {
|
||||
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
|
||||
if (currentlySelectedPokemon != null) {
|
||||
val state = FloatingState().also { it.currentAspects = currentlySelectedPokemon.aspects }
|
||||
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
|
||||
val model = VaryingModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
|
||||
model.portraitTranslation = model.portraitTranslation.add(-0.01, 0.0, 0.0)
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ object DebugKeybindings {
|
||||
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
|
||||
if (currentlySelectedPokemon != null) {
|
||||
val state = FloatingState().also { it.currentAspects = currentlySelectedPokemon.aspects }
|
||||
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
|
||||
val model = VaryingModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
|
||||
model.portraitTranslation = model.portraitTranslation.add(0.01, 0.0, 0.0)
|
||||
}
|
||||
}
|
||||
@@ -137,7 +137,7 @@ object DebugKeybindings {
|
||||
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
|
||||
if (currentlySelectedPokemon != null) {
|
||||
val state = FloatingState().also { it.currentAspects = currentlySelectedPokemon.aspects }
|
||||
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
|
||||
val model = VaryingModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, state)
|
||||
Minecraft.getInstance().player?.sendSystemMessage(Component.literal("Portrait Translation: ${model.portraitTranslation}"))
|
||||
Minecraft.getInstance().player?.sendSystemMessage(Component.literal("Portrait Scale: ${model.portraitScale}"))
|
||||
Cobblemon.LOGGER.info("override var portraitTranslation = Vec3d(${model.portraitTranslation.x}, ${model.portraitTranslation.y}, ${model.portraitTranslation.z})")
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.net.battle
|
||||
|
||||
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.api.text.aqua
|
||||
import com.cobblemon.mod.common.api.text.green
|
||||
import com.cobblemon.mod.common.client.ClientMultiBattleTeamMember
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.render.ClientPlayerIcon
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.TeamMemberAddNotificationPacket
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.Minecraft
|
||||
|
||||
object TeamMemberAddNotificationHandler : ClientNetworkPacketHandler<TeamMemberAddNotificationPacket> {
|
||||
override fun handle(packet: TeamMemberAddNotificationPacket, client: Minecraft) {
|
||||
|
||||
if (CobblemonClient.teamData.multiBattleTeamMembers.any { it.uuid == packet.teamMemberUUID }) {
|
||||
return //already knows about the new member
|
||||
}
|
||||
var newMember = ClientMultiBattleTeamMember(packet.teamMemberUUID, packet.teamMemberName)
|
||||
CobblemonClient.teamData.multiBattleTeamMembers.add(newMember)
|
||||
ClientPlayerIcon.update(newMember.uuid)
|
||||
|
||||
client.player?.sendSystemMessage(
|
||||
lang(
|
||||
"team.join.other",
|
||||
newMember.name.copy().aqua(),
|
||||
).green()
|
||||
)
|
||||
}
|
||||
}
|
||||
-3
@@ -9,14 +9,11 @@
|
||||
package com.cobblemon.mod.common.client.net.pokemon.update
|
||||
|
||||
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.client.render.layer.PokemonOnShoulderRenderer
|
||||
import com.cobblemon.mod.common.net.messages.client.PokemonUpdatePacket
|
||||
import net.minecraft.client.Minecraft
|
||||
|
||||
class PokemonUpdatePacketHandler<T : PokemonUpdatePacket<T>> : ClientNetworkPacketHandler<T> {
|
||||
override fun handle(packet: T, client: Minecraft) {
|
||||
packet.applyToPokemon()
|
||||
val player = client.player ?: return
|
||||
PokemonOnShoulderRenderer.clearCache(player)
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.net.settings
|
||||
|
||||
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen
|
||||
import com.cobblemon.mod.common.net.messages.client.settings.OpenCobblemonConfigScreenPacket
|
||||
import net.minecraft.client.Minecraft
|
||||
|
||||
object OpenCobblemonConfigEditorHandler : ClientNetworkPacketHandler<OpenCobblemonConfigScreenPacket> {
|
||||
override fun handle(packet: OpenCobblemonConfigScreenPacket, client: Minecraft) {
|
||||
client.setScreen(CobblemonConfigScreen(Minecraft.getInstance().screen))
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.net.storage.pc
|
||||
|
||||
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.ChangePCBoxWallpaperPacket
|
||||
import net.minecraft.client.Minecraft
|
||||
|
||||
object ChangePCBoxWallpaperHandler : ClientNetworkPacketHandler<ChangePCBoxWallpaperPacket> {
|
||||
override fun handle(packet: ChangePCBoxWallpaperPacket, client: Minecraft) {
|
||||
CobblemonClient.storage.changeBoxWallpaper(packet.storeID, packet.boxNumber, packet.wallpaper)
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.net.storage.pc
|
||||
|
||||
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.RenamePCBoxPacket
|
||||
import net.minecraft.client.Minecraft
|
||||
|
||||
object RenamePCBoxHandler : ClientNetworkPacketHandler<RenamePCBoxPacket> {
|
||||
override fun handle(packet: RenamePCBoxPacket, client: Minecraft) {
|
||||
CobblemonClient.storage.renameBox(packet.storeID, packet.boxNumber, packet.name)
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.net.storage.pc
|
||||
|
||||
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.client.render.gui.PCBoxWallpaperRepository
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.PCBoxWallpapersPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.RequestPCBoxWallpapersPacket
|
||||
import net.minecraft.client.Minecraft
|
||||
|
||||
object RequestPCBoxWallpapersHandler : ClientNetworkPacketHandler<RequestPCBoxWallpapersPacket> {
|
||||
override fun handle(packet: RequestPCBoxWallpapersPacket, client: Minecraft) {
|
||||
PCBoxWallpaperRepository.findWallpapers(client.resourceManager)
|
||||
PCBoxWallpapersPacket(PCBoxWallpaperRepository.wallpapers).sendToServer()
|
||||
}
|
||||
}
|
||||
+5
-4
@@ -11,15 +11,16 @@ package com.cobblemon.mod.common.client.net.storage.pc
|
||||
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.storage.ClientBox
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPacket
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
object SetPCBoxPokemonHandler : ClientNetworkPacketHandler<SetPCBoxPokemonPacket> {
|
||||
override fun handle(packet: SetPCBoxPokemonPacket, client: Minecraft) {
|
||||
object SetPCBoxHandler : ClientNetworkPacketHandler<SetPCBoxPacket> {
|
||||
override fun handle(packet: SetPCBoxPacket, client: Minecraft) {
|
||||
CobblemonClient.storage.pcStores[packet.storeID]?.let { pc ->
|
||||
val boxNumber = packet.boxNumber
|
||||
while (pc.boxes.size <= boxNumber) { pc.boxes.add(ClientBox()) }
|
||||
pc.boxes[boxNumber] = ClientBox()
|
||||
pc.boxes[boxNumber] = ClientBox(if (packet.name.isBlank()) null else Component.literal(packet.name), packet.wallpaper)
|
||||
packet.pokemon.forEach { (slot, pokemon) -> pc.boxes[packet.boxNumber].slots[slot] = pokemon(client.level!!.registryAccess()) }
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.net.storage.pc
|
||||
|
||||
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.client.render.gui.PCBoxWallpaperRepository
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.SetPCBoxWallpapersPacket
|
||||
import net.minecraft.client.Minecraft
|
||||
|
||||
object SetPCBoxWallpapersHandler : ClientNetworkPacketHandler<SetPCBoxWallpapersPacket> {
|
||||
override fun handle(packet: SetPCBoxWallpapersPacket, client: Minecraft) {
|
||||
PCBoxWallpaperRepository.wallpapers = packet.wallpapers
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -30,12 +30,12 @@ import org.joml.Vector4f
|
||||
* @author Hiroku
|
||||
* @since May 14th, 2022
|
||||
*/
|
||||
class VaryingRenderableResolver<T : PosableModel>(
|
||||
class VaryingRenderableResolver(
|
||||
val name: ResourceLocation,
|
||||
val variations: MutableList<ModelAssetVariation>
|
||||
) {
|
||||
lateinit var repository: VaryingModelRepository<T>
|
||||
val posers = mutableMapOf<Pair<ResourceLocation, ResourceLocation>, T>()
|
||||
lateinit var repository: VaryingModelRepository
|
||||
val posers = mutableMapOf<Pair<ResourceLocation, ResourceLocation>, PosableModel>()
|
||||
val models = mutableMapOf<ResourceLocation, Bone>()
|
||||
|
||||
fun getResolvedPoser(state: PosableState): ResourceLocation {
|
||||
@@ -98,19 +98,19 @@ class VaryingRenderableResolver<T : PosableModel>(
|
||||
.create()
|
||||
}
|
||||
|
||||
fun initialize(repository: VaryingModelRepository<T>) {
|
||||
fun initialize(repository: VaryingModelRepository) {
|
||||
this.repository = repository
|
||||
posers.clear()
|
||||
getAllModels().forEach { identifier ->
|
||||
try {
|
||||
models[identifier] = repository.texturedModels[identifier]!!.invoke(repository.isForLivingEntityRenderer)
|
||||
models[identifier] = repository.texturedModels[identifier]!!
|
||||
} catch (e: Exception) {
|
||||
throw IllegalStateException("Unable to load model $identifier for $name", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getPoser(state: PosableState): T {
|
||||
fun getPoser(state: PosableState): PosableModel {
|
||||
val poserName = getResolvedPoser(state)
|
||||
val poserSupplier = repository.posers[poserName] ?: throw IllegalStateException("No poser found for name: $poserName for $name")
|
||||
val modelName = getResolvedModel(state)
|
||||
|
||||
+5
-4
@@ -9,8 +9,9 @@
|
||||
package com.cobblemon.mod.common.client.render.block
|
||||
|
||||
import com.cobblemon.mod.common.block.entity.GildedChestBlockEntity
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.BlockEntityModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.blockentity.BlockEntityModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.math.Axis
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
@@ -40,9 +41,9 @@ class GildedChestBlockRenderer(context: BlockEntityRendererProvider.Context) : B
|
||||
|
||||
val poserId = entity.type.poserId
|
||||
|
||||
val model = BlockEntityModelRepository.getPoser(poserId, state)
|
||||
val model = VaryingModelRepository.getPoser(poserId, state) as BlockEntityModel
|
||||
model.context = context
|
||||
val texture = BlockEntityModelRepository.getTexture(poserId, state)
|
||||
val texture = VaryingModelRepository.getTexture(poserId, state)
|
||||
val vertexConsumer = vertexConsumers.getBuffer(RenderType.entityCutout(texture))
|
||||
model.bufferProvider = vertexConsumers
|
||||
state.currentModel = model
|
||||
@@ -67,7 +68,7 @@ class GildedChestBlockRenderer(context: BlockEntityRendererProvider.Context) : B
|
||||
ageInTicks = state.animationSeconds * 20
|
||||
)
|
||||
model.render(context, matrices, vertexConsumer, light, overlay, -0x1)
|
||||
model.withLayerContext(vertexConsumers, state, BlockEntityModelRepository.getLayers(poserId, state)) {
|
||||
model.withLayerContext(vertexConsumers, state, VaryingModelRepository.getLayers(poserId, state)) {
|
||||
model.render(context, matrices, vertexConsumer, light, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
}
|
||||
model.setDefault()
|
||||
|
||||
+23
-16
@@ -12,23 +12,24 @@ import com.cobblemon.mod.common.CobblemonBlocks
|
||||
import com.cobblemon.mod.common.block.entity.RestorationTankBlockEntity
|
||||
import com.cobblemon.mod.common.block.multiblock.FossilMultiblockStructure
|
||||
import com.cobblemon.mod.common.client.CobblemonBakingOverrides
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.FossilModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.fossil.FossilModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.WaveFunction
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.parabolaFunction
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.rerange
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.timeDilate
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import kotlin.math.pow
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.math.Axis
|
||||
import kotlin.math.pow
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock
|
||||
|
||||
class RestorationTankRenderer(ctx: BlockEntityRendererProvider.Context) : BlockEntityRenderer<RestorationTankBlockEntity> {
|
||||
val context = RenderContext().also {
|
||||
@@ -114,8 +115,14 @@ class RestorationTankRenderer(ctx: BlockEntityRendererProvider.Context) : BlockE
|
||||
state.updatePartialTicks(tickDelta)
|
||||
state.currentAspects = aspects
|
||||
|
||||
var fossilPoserId = fossil.identifier.withPath("${fossil.identifier.path}_fetus")
|
||||
|
||||
val completionPercentage = (1 - timeRemaining / FossilMultiblockStructure.TIME_TO_TAKE.toFloat()).coerceIn(0F, 1F)
|
||||
val fossilFetusModel = FossilModelRepository.getPoser(fossil.identifier, state)
|
||||
val fossilFetusModel = VaryingModelRepository.getPoser(fossilPoserId, state) as? FossilModel ?: let {
|
||||
fossilPoserId = cobblemonResource("fossil_fetus")
|
||||
VaryingModelRepository.getPoser(fossilPoserId, state) as FossilModel
|
||||
}
|
||||
|
||||
fossilFetusModel.context = context
|
||||
|
||||
val embryo1Scale = EMBRYO_CURVE_1(completionPercentage)
|
||||
@@ -124,15 +131,15 @@ class RestorationTankRenderer(ctx: BlockEntityRendererProvider.Context) : BlockE
|
||||
val fossilScale = FOSSIL_CURVE(completionPercentage)
|
||||
|
||||
val identifiersAndScales = listOf(
|
||||
Pair(EMBRYO_IDENTIFIERS[0], embryo1Scale),
|
||||
Pair(EMBRYO_IDENTIFIERS[1], embryo2Scale),
|
||||
Pair(EMBRYO_IDENTIFIERS[2], embryo3Scale),
|
||||
Pair(fossil.identifier, fossilScale)
|
||||
Pair(EMBRYO_IDENTIFIERS[0], embryo1Scale),
|
||||
Pair(EMBRYO_IDENTIFIERS[1], embryo2Scale),
|
||||
Pair(EMBRYO_IDENTIFIERS[2], embryo3Scale),
|
||||
Pair(fossilPoserId, fossilScale)
|
||||
)
|
||||
|
||||
identifiersAndScales.forEach { (identifier, scale) ->
|
||||
val model = FossilModelRepository.getPoser(identifier, state)
|
||||
val texture = FossilModelRepository.getTexture(identifier, state)
|
||||
val model = VaryingModelRepository.getPoser(identifier, state) as FossilModel
|
||||
val texture = VaryingModelRepository.getTexture(identifier, state)
|
||||
|
||||
if (scale > 0F) {
|
||||
val vertexConsumer = vertexConsumers.getBuffer(RenderType.entityCutout(texture))
|
||||
@@ -175,7 +182,7 @@ class RestorationTankRenderer(ctx: BlockEntityRendererProvider.Context) : BlockE
|
||||
ageInTicks = state.animationSeconds * 20
|
||||
)
|
||||
model.render(context, matrices, vertexConsumer, light, overlay, -0x1)
|
||||
model.withLayerContext(vertexConsumers, state, FossilModelRepository.getLayers(fossil.identifier, state)) {
|
||||
model.withLayerContext(vertexConsumers, state, VaryingModelRepository.getLayers(fossilPoserId, state)) {
|
||||
model.render(context, matrices, vertexConsumer, light, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
}
|
||||
model.setDefault()
|
||||
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.block
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBlocks
|
||||
import com.cobblemon.mod.common.block.entity.StadiumBlockEntity
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.drone.DroneModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.drone.DroneState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.math.Axis
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
|
||||
class StadiumBlockRenderer(ctx: BlockEntityRendererProvider.Context) : BlockEntityRenderer<StadiumBlockEntity> {
|
||||
val context = RenderContext().also {
|
||||
it.put(RenderContext.DO_QUIRKS, false)
|
||||
it.put(RenderContext.RENDER_STATE, RenderContext.RenderState.BLOCK)
|
||||
}
|
||||
|
||||
private var pathIndex = 0
|
||||
private var animationTime = 0.0
|
||||
private val droneSpeed = 0.10
|
||||
|
||||
override fun render(
|
||||
blockEntity: StadiumBlockEntity,
|
||||
tickDelta: Float,
|
||||
poseStack: PoseStack,
|
||||
multiBufferSource: MultiBufferSource,
|
||||
light: Int,
|
||||
overlay: Int
|
||||
) {
|
||||
val blockState = blockEntity.blockState
|
||||
val yRot = blockState.getValue(HorizontalDirectionalBlock.FACING).toYRot()
|
||||
|
||||
val isClientSide = blockEntity.level?.isClientSide == true
|
||||
if (!isClientSide) return
|
||||
|
||||
val stadiumBlockState = blockEntity.level?.getBlockState(blockEntity.blockPos) ?: return
|
||||
if (stadiumBlockState.block != CobblemonBlocks.STADIUM) {
|
||||
return
|
||||
}
|
||||
|
||||
val droneState = blockEntity.droneState
|
||||
|
||||
|
||||
poseStack.pushPose()
|
||||
if (blockEntity.isInUse) {
|
||||
if (blockEntity.pathPoints.isEmpty()) {
|
||||
|
||||
poseStack.popPose()
|
||||
return
|
||||
}
|
||||
|
||||
spawnDebugParticles(blockEntity) // debug particles
|
||||
|
||||
// Center the drone at the block's center
|
||||
poseStack.translate(0.5, -3.0, 0.5)
|
||||
//poseStack.mulPose(Axis.XP.rotationDegrees(180F))
|
||||
//poseStack.mulPose(Axis.YP.rotationDegrees(180F))
|
||||
|
||||
val points = blockEntity.pathPoints
|
||||
val nextIndex = (pathIndex + 1) % points.size
|
||||
|
||||
val currentPoint = points[pathIndex]
|
||||
val nextPoint = points[nextIndex]
|
||||
|
||||
animationTime += tickDelta * droneSpeed
|
||||
if (animationTime >= 1.0) {
|
||||
animationTime = 0.0
|
||||
pathIndex = nextIndex
|
||||
}
|
||||
|
||||
val interpolatedPos = currentPoint.lerp(nextPoint, animationTime.toDouble())
|
||||
|
||||
println("DEBUG: Drone moving between points:")
|
||||
println(" - Current Point: ${currentPoint}")
|
||||
println(" - Next Point: ${nextPoint}")
|
||||
println(" - Interpolated Position: $interpolatedPos")
|
||||
|
||||
poseStack.translate(interpolatedPos.x - blockEntity.blockPos.x,
|
||||
interpolatedPos.y - blockEntity.blockPos.y,
|
||||
interpolatedPos.z - blockEntity.blockPos.z)
|
||||
|
||||
println("DEBUG: Drone position interpolated to: $interpolatedPos")
|
||||
|
||||
poseStack.mulPose(Axis.YP.rotationDegrees(-yRot))
|
||||
poseStack.mulPose(Axis.ZP.rotationDegrees(180F)) // flip the drone right side up
|
||||
|
||||
renderDrone(droneState, "sleep", tickDelta, poseStack, 1.0F, multiBufferSource, light)
|
||||
} else {
|
||||
val yRot = blockState.getValue(HorizontalDirectionalBlock.FACING).toYRot()
|
||||
|
||||
val poseEntry = poseStack.last()
|
||||
val matrix = poseEntry.pose()
|
||||
|
||||
poseStack.translate(0.5, 0.0, 0.5)
|
||||
poseStack.mulPose(Axis.YP.rotationDegrees(yRot))
|
||||
|
||||
val posX = matrix.m03()
|
||||
val posY = matrix.m13()
|
||||
val posZ = matrix.m23()
|
||||
|
||||
println("DEBUG: Drone is NOT in use. Rendering default position at: x=$posX, y=$posY, z=$posZ")
|
||||
|
||||
poseStack.mulPose(Axis.ZP.rotationDegrees(180F))
|
||||
renderDrone(droneState, "sleep", tickDelta, poseStack, 1.0F, multiBufferSource, light)
|
||||
}
|
||||
|
||||
poseStack.popPose()
|
||||
}
|
||||
|
||||
fun renderDrone(
|
||||
state: DroneState,
|
||||
pose: String,
|
||||
tickDelta: Float,
|
||||
poseStack: PoseStack,
|
||||
scale: Float = 1F,
|
||||
multiBufferSource: MultiBufferSource,
|
||||
light: Int,
|
||||
) {
|
||||
state.updatePartialTicks(tickDelta)
|
||||
|
||||
val droneResource: ResourceLocation = cobblemonResource("rotom_drone")
|
||||
|
||||
val model = VaryingModelRepository.getPoser(droneResource, state) as DroneModel
|
||||
val texture = VaryingModelRepository.getTexture(droneResource, state)
|
||||
|
||||
val buffer = multiBufferSource.getBuffer(RenderType.entityCutout(texture))
|
||||
model.bufferProvider = multiBufferSource
|
||||
|
||||
state.currentModel = model
|
||||
state.setPose(pose)
|
||||
|
||||
model.context = context
|
||||
context.put(RenderContext.TEXTURE, texture)
|
||||
context.put(RenderContext.RENDER_STATE, RenderContext.RenderState.BLOCK)
|
||||
context.put(RenderContext.POSABLE_STATE, state)
|
||||
|
||||
model.applyAnimations(
|
||||
entity = null,
|
||||
state = state,
|
||||
headYaw = 0F,
|
||||
headPitch = 0F,
|
||||
limbSwing = 0F,
|
||||
limbSwingAmount = 0F,
|
||||
ageInTicks = state.animationSeconds * 20
|
||||
)
|
||||
|
||||
poseStack.scale(scale, scale, scale)
|
||||
|
||||
// TODO: Make drone lighting dynamic (simply using the light arg makes the drone always appear dark)
|
||||
model.withLayerContext(multiBufferSource, state, VaryingModelRepository.getLayers(droneResource, state)) {
|
||||
model.render(context, poseStack, buffer, 200, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
}
|
||||
model.setDefault()
|
||||
}
|
||||
|
||||
private fun spawnDebugParticles(blockEntity: StadiumBlockEntity) {
|
||||
val world = blockEntity.level ?: return
|
||||
if (!world.isClientSide) return // Only run on the client-side
|
||||
|
||||
for (point in blockEntity.pathPoints) {
|
||||
world.addParticle(
|
||||
net.minecraft.core.particles.ParticleTypes.FLAME, // Test particle (changeable)
|
||||
point.x, point.y, point.z, // Position of the particle
|
||||
0.0, 0.02, 0.0 // Slight upward motion
|
||||
)
|
||||
}
|
||||
|
||||
// Spawn a special particle at the next interpolation point
|
||||
if (blockEntity.pathPoints.isNotEmpty()) {
|
||||
val nextPoint = blockEntity.pathPoints[(pathIndex + 1) % blockEntity.pathPoints.size]
|
||||
world.addParticle(
|
||||
net.minecraft.core.particles.ParticleTypes.END_ROD, // Different effect for next point
|
||||
nextPoint.x, nextPoint.y, nextPoint.z,
|
||||
0.0, 0.05, 0.0
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-6
@@ -10,8 +10,7 @@ package com.cobblemon.mod.common.client.render.generic
|
||||
|
||||
import com.cobblemon.mod.common.client.entity.GenericBedrockClientDelegate
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.generic.PosableGenericEntityModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.GenericBedrockEntityModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.entity.generic.GenericBedrockEntity
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.math.Axis
|
||||
@@ -20,11 +19,10 @@ import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.client.renderer.entity.EntityRenderer
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class GenericBedrockRenderer(context: EntityRendererProvider.Context) : EntityRenderer<GenericBedrockEntity>(context) {
|
||||
val model = PosableGenericEntityModel()
|
||||
override fun getTextureLocation(entity: GenericBedrockEntity) = GenericBedrockEntityModelRepository.getTexture(entity.category, (entity.delegate as GenericBedrockClientDelegate))
|
||||
override fun getTextureLocation(entity: GenericBedrockEntity) = VaryingModelRepository.getTexture(entity.category, (entity.delegate as GenericBedrockClientDelegate))
|
||||
override fun render(entity: GenericBedrockEntity, yaw: Float, partialTicks: Float, poseStack: PoseStack, buffer: MultiBufferSource, packedLight: Int) {
|
||||
if (entity.isInvisible) {
|
||||
return
|
||||
@@ -32,7 +30,7 @@ class GenericBedrockRenderer(context: EntityRendererProvider.Context) : EntityRe
|
||||
|
||||
val state = entity.delegate as GenericBedrockClientDelegate
|
||||
state.currentAspects = entity.aspects
|
||||
val model = GenericBedrockEntityModelRepository.getPoser(entity.category, state)
|
||||
val model = VaryingModelRepository.getPoser(entity.category, state)
|
||||
this.model.posableModel = model
|
||||
model.context = this.model.context
|
||||
this.model.setupEntityTypeContext(entity)
|
||||
@@ -43,7 +41,7 @@ class GenericBedrockRenderer(context: EntityRendererProvider.Context) : EntityRe
|
||||
val vertexConsumer = buffer.getBuffer(RenderType.entityCutout(getTextureLocation(entity)))
|
||||
|
||||
state.updatePartialTicks(partialTicks)
|
||||
model.setLayerContext(buffer, state, PokemonModelRepository.getLayers(entity.category, state))
|
||||
model.setLayerContext(buffer, state, VaryingModelRepository.getLayers(entity.category, state))
|
||||
this.model.setupAnim(entity, 0f, 0f, entity.tickCount + partialTicks, 0F, 0F)
|
||||
this.model.renderToBuffer(poseStack, vertexConsumer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.gui
|
||||
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.endsWith
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.packs.resources.ResourceManager
|
||||
|
||||
object PCBoxWallpaperRepository {
|
||||
lateinit var wallpapers: List<ResourceLocation>
|
||||
var defaultWallpaper = cobblemonResource("textures/gui/pc/pc_screen_overlay.png")
|
||||
|
||||
fun findWallpapers(resourceManager: ResourceManager): List<ResourceLocation> {
|
||||
val wallpapers = mutableListOf<ResourceLocation>(defaultWallpaper)
|
||||
resourceManager.listResources("textures/gui/pc/wallpaper") { path -> path?.endsWith(".png") == true }.keys.forEach { key ->
|
||||
wallpapers.add(key)
|
||||
}
|
||||
this.wallpapers = wallpapers
|
||||
return wallpapers
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -9,8 +9,8 @@
|
||||
package com.cobblemon.mod.common.client.render.item
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.item.PokemonItem
|
||||
import com.cobblemon.mod.common.util.math.fromEulerXYZDegrees
|
||||
@@ -38,7 +38,7 @@ class PokemonItemRenderer : CobblemonBuiltinItemRenderer {
|
||||
val state = FloatingState()
|
||||
state.currentAspects = aspects
|
||||
matrices.pushPose()
|
||||
val model = PokemonModelRepository.getPoser(species.resourceIdentifier, state)
|
||||
val model = VaryingModelRepository.getPoser(species.resourceIdentifier, state)
|
||||
model.context = context
|
||||
context.put(RenderContext.RENDER_STATE, RenderContext.RenderState.PROFILE)
|
||||
context.put(RenderContext.SPECIES, species.resourceIdentifier)
|
||||
@@ -46,7 +46,7 @@ class PokemonItemRenderer : CobblemonBuiltinItemRenderer {
|
||||
context.put(RenderContext.POSABLE_STATE, state)
|
||||
state.currentModel = model
|
||||
|
||||
val renderLayer = RenderType.entityCutout(PokemonModelRepository.getTexture(species.resourceIdentifier, state))
|
||||
val renderLayer = RenderType.entityCutout(VaryingModelRepository.getTexture(species.resourceIdentifier, state))
|
||||
|
||||
val transformations = positions[mode]!!
|
||||
|
||||
@@ -75,7 +75,7 @@ class PokemonItemRenderer : CobblemonBuiltinItemRenderer {
|
||||
|
||||
// x = red, y = green, z = blue, w = alpha
|
||||
val tint = pokemonItem.tint(stack)
|
||||
model.withLayerContext(vertexConsumers, state, PokemonModelRepository.getLayers(species.resourceIdentifier, state)) {
|
||||
model.withLayerContext(vertexConsumers, state, VaryingModelRepository.getLayers(species.resourceIdentifier, state)) {
|
||||
val tintRed = (tint.x * 255).toInt()
|
||||
val tintGreen = (tint.y * 255).toInt()
|
||||
val tintBlue = (tint.z * 255).toInt()
|
||||
|
||||
+16
-27
@@ -11,8 +11,8 @@ package com.cobblemon.mod.common.client.render.layer
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.pokemon.FormData
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
@@ -87,27 +87,21 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
|
||||
) {
|
||||
val compoundTag = if (pLeftShoulder) livingEntity.shoulderEntityLeft else livingEntity.shoulderEntityRight
|
||||
if (compoundTag.isPokemonEntity()) {
|
||||
matrixStack.pushPose()
|
||||
livingEntity.level().profiler.push("shoulder_render_".plus(if(pLeftShoulder) "left" else "right"))
|
||||
val uuid = this.extractUuid(compoundTag)
|
||||
val cache = playerCache.getOrPut(livingEntity.uuid) { ShoulderCache() }
|
||||
var shoulderData: ShoulderData? = null
|
||||
if (pLeftShoulder && cache.lastKnownLeft?.uuid != uuid) {
|
||||
shoulderData = this.extractData(compoundTag, uuid)
|
||||
cache.lastKnownLeft = shoulderData
|
||||
}
|
||||
else if (!pLeftShoulder && cache.lastKnownRight?.uuid != uuid) {
|
||||
shoulderData = this.extractData(compoundTag, uuid)
|
||||
cache.lastKnownRight = shoulderData
|
||||
}
|
||||
val shoulderData = this.extractData(compoundTag, uuid)
|
||||
if (pLeftShoulder) cache.lastKnownLeft = shoulderData else cache.lastKnownRight = shoulderData
|
||||
|
||||
if (shoulderData == null){
|
||||
// Could be null
|
||||
shoulderData = (if (pLeftShoulder) cache.lastKnownLeft else cache.lastKnownRight) ?: return
|
||||
// Nothing to do
|
||||
return
|
||||
}
|
||||
|
||||
matrixStack.pushPose()
|
||||
var state = FloatingState()
|
||||
state.currentAspects = shoulderData.aspects
|
||||
val model = PokemonModelRepository.getPoser(shoulderData.species.resourceIdentifier, state)
|
||||
val model = VaryingModelRepository.getPoser(shoulderData.species.resourceIdentifier, state)
|
||||
model.context = context
|
||||
context.put(RenderContext.SPECIES, shoulderData.species.resourceIdentifier)
|
||||
context.put(RenderContext.ASPECTS, shoulderData.aspects)
|
||||
@@ -129,6 +123,7 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
|
||||
)
|
||||
|
||||
matrixStack.scale(scale, scale, scale)
|
||||
matrixStack.translate(0f, 1.5f, 0f)
|
||||
|
||||
state = if (pLeftShoulder && shoulderData != lastRenderedLeft) {
|
||||
leftState = configureState(state, model, true)
|
||||
@@ -144,7 +139,7 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
|
||||
state.updatePartialTicks(partialTicks)
|
||||
context.put(RenderContext.POSABLE_STATE, state)
|
||||
state.currentModel = model
|
||||
val vertexConsumer = buffer.getBuffer(RenderType.entityCutout(PokemonModelRepository.getTexture(shoulderData.species.resourceIdentifier, state)))
|
||||
val vertexConsumer = buffer.getBuffer(RenderType.entityCutout(VaryingModelRepository.getTexture(shoulderData.species.resourceIdentifier, state)))
|
||||
val i = LivingEntityRenderer.getOverlayCoords(livingEntity, 0.0f)
|
||||
|
||||
model.applyAnimations(
|
||||
@@ -157,11 +152,16 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
|
||||
ageInTicks = livingEntity.tickCount.toFloat()
|
||||
)
|
||||
model.render(context, matrixStack, vertexConsumer, packedLight, i, -0x1)
|
||||
model.withLayerContext(buffer, state, PokemonModelRepository.getLayers(shoulderData.species.resourceIdentifier, state)) {
|
||||
model.withLayerContext(buffer, state, VaryingModelRepository.getLayers(shoulderData.species.resourceIdentifier, state)) {
|
||||
model.render(context, matrixStack, vertexConsumer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
}
|
||||
model.setDefault()
|
||||
matrixStack.popPose()
|
||||
livingEntity.level().profiler.pop()
|
||||
}
|
||||
else {
|
||||
val entry = playerCache.getOrPut(livingEntity.uuid) { ShoulderCache() }
|
||||
if (pLeftShoulder) entry.lastKnownLeft = null else entry.lastKnownRight = null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,16 +217,5 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
|
||||
return Pair(cache.lastKnownLeft, cache.lastKnownRight)
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the cache for the respective player.
|
||||
* This is required to be done whenever a Pokémon changes in any way (form, evolution, etc.)
|
||||
*
|
||||
* @param player The player whose cache to clear
|
||||
*/
|
||||
@JvmStatic
|
||||
fun clearCache(player: Player) {
|
||||
playerCache.remove(player.uuid)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -20,8 +20,10 @@ import java.lang.reflect.Type
|
||||
* @since October 18th, 2022
|
||||
*/
|
||||
class JsonModelAdapter<T : PosableModel>(private val constructor: (Bone) -> T) : InstanceCreator<T> {
|
||||
var modelPart: Bone? = null
|
||||
var model: T? = null
|
||||
companion object {
|
||||
var modelPart: Bone? = null
|
||||
var model: PosableModel? = null
|
||||
}
|
||||
override fun createInstance(type: Type): T {
|
||||
val rootBone = modelPart!!
|
||||
return constructor(rootBone).also {
|
||||
|
||||
+3
-9
@@ -71,9 +71,6 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
@Transient
|
||||
lateinit var context: RenderContext
|
||||
|
||||
/** Whether the renderer that will process this is going to do the weird -1.5 Y offset bullshit that the living entity renderer does. */
|
||||
@Transient
|
||||
open var isForLivingEntityRenderer = true
|
||||
|
||||
var poses = mutableMapOf<String, Pose>()
|
||||
|
||||
@@ -81,6 +78,8 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
@Transient
|
||||
lateinit var locatorAccess: LocatorAccess
|
||||
|
||||
open var transformedParts = arrayOf<ModelPartTransformation>()
|
||||
|
||||
open var portraitScale = 1F
|
||||
open var portraitTranslation = Vec3(0.0, 0.0, 0.0)
|
||||
|
||||
@@ -485,7 +484,7 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
|
||||
|
||||
/** Applies the given pose's [ModelPartTransformation]s to the model, if there is a matching pose. */
|
||||
fun applyPose(state: PosableState, pose: Pose, intensity: Float) = pose.transformedParts.forEach { it.apply(state, intensity) }
|
||||
fun applyPose(state: PosableState, pose: Pose, intensity: Float) = (pose.transformedParts + transformedParts).forEach { it.apply(state, intensity) }
|
||||
/** Gets the first pose of this model that matches the given [PoseType]. */
|
||||
fun getPose(pose: PoseType) = poses.values.firstOrNull { pose in it.poseTypes }
|
||||
fun getPose(name: String) = poses[name]
|
||||
@@ -697,11 +696,6 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
matrixStack.scale(-1F, -1F, 1F)
|
||||
}
|
||||
|
||||
if (isForLivingEntityRenderer) {
|
||||
// Standard living entity offset, only God knows why Mojang did this.
|
||||
matrixStack.translate(0.0, -1.5, 0.0)
|
||||
}
|
||||
|
||||
locatorAccess.update(matrixStack, entity, scale, state.locatorStates, isRoot = true)
|
||||
}
|
||||
|
||||
|
||||
+6
-2
@@ -10,9 +10,11 @@ package com.cobblemon.mod.common.client.render.models.blockbench
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.ActiveAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.isBattling
|
||||
import com.cobblemon.mod.common.util.isDusk
|
||||
import com.cobblemon.mod.common.util.isStandingOnRedSand
|
||||
import com.cobblemon.mod.common.util.isStandingOnSand
|
||||
@@ -31,7 +33,6 @@ import java.lang.reflect.Type
|
||||
* @since October 18th, 2022
|
||||
*/
|
||||
class PoseAdapter(
|
||||
val poseConditionReader: (JsonObject) -> List<(PosableState) -> Boolean>,
|
||||
val modelFinder: () -> PosableModel
|
||||
) : JsonDeserializer<Pose> {
|
||||
companion object {
|
||||
@@ -62,7 +63,10 @@ class PoseAdapter(
|
||||
|
||||
addCondition("isDusk") { entity, expectedValue -> entity.isDusk() == expectedValue }
|
||||
|
||||
conditionsList.addAll(poseConditionReader(json))
|
||||
val mustBeInBattle = json.get("isBattle")?.asBoolean
|
||||
if (mustBeInBattle != null) {
|
||||
conditionsList.add { mustBeInBattle == it.isBattling }
|
||||
}
|
||||
|
||||
if (json.has("conditions")) {
|
||||
val conditionSet = json.get("conditions").asJsonArray.map { it.asString.asExpressionLike() }
|
||||
|
||||
+6
@@ -8,8 +8,10 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench
|
||||
|
||||
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer
|
||||
@@ -46,6 +48,10 @@ abstract class PosableEntityModel<T : Entity>(
|
||||
) {
|
||||
val entity = context.request(RenderContext.ENTITY)
|
||||
val overlay = getOverlayTexture(entity) ?: packedOverlay
|
||||
if (entity is LivingEntity) {
|
||||
// We're using the living entity renderer, ergo we need to apply a Y offset of 24 model units (1.5 blocks) for reasons only God can tell us.
|
||||
stack.translate(0.0, 1.5, 0.0)
|
||||
}
|
||||
posableModel.render(context, stack, buffer, packedLight, overlay, color)
|
||||
}
|
||||
|
||||
|
||||
+4
-5
@@ -27,8 +27,8 @@ class TexturedModel {
|
||||
@SerializedName("minecraft:geometry")
|
||||
val geometry: List<ModelGeometry>? = null
|
||||
|
||||
fun create(isForLivingEntityRenderer: Boolean) : LayerDefinition {
|
||||
return createWithUvOverride(isForLivingEntityRenderer, 0, 0, null, null)
|
||||
fun create() : LayerDefinition {
|
||||
return createWithUvOverride(0, 0, null, null)
|
||||
}
|
||||
|
||||
fun resolveParentsFromRoot(boneMap: MutableMap<String, ModelBone>, bone: ModelBone): Set<ModelBone> {
|
||||
@@ -147,7 +147,7 @@ class TexturedModel {
|
||||
// return modelBuilder.build()
|
||||
// }
|
||||
|
||||
fun createWithUvOverride(isForLivingEntityRenderer: Boolean, u: Int, v: Int, textureWidth: Int?, textureHeight: Int?) : LayerDefinition {
|
||||
fun createWithUvOverride(u: Int, v: Int, textureWidth: Int?, textureHeight: Int?) : LayerDefinition {
|
||||
val modelData = MeshDefinition()
|
||||
val parts = HashMap<String, PartDefinition>()
|
||||
val bones = HashMap<String, ModelBone>()
|
||||
@@ -184,8 +184,7 @@ class TexturedModel {
|
||||
val modelTransform : PartPose
|
||||
when {
|
||||
bone.parent == null -> {
|
||||
// The root part always has a 24 Y offset. One of life's great mysteries.
|
||||
modelTransform = PartPose.offset(0F, if (isForLivingEntityRenderer) 24F else 0F, 0F)
|
||||
modelTransform = PartPose.offset(0F, 0F, 0F)
|
||||
}
|
||||
boneRotation != null -> {
|
||||
modelTransform = PartPose.offsetAndRotation(
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user