Compare commits

...
Author SHA1 Message Date
MoeBoy76 d269270723 correct logical logic not being logical for LevelUpCriterion.kt by adding a separate "has_evolved" variable 2026-02-11 14:39:15 +11:00
Hiroku a7198fd324 Merge branch 'fossil_crash' into 'main'
Adjust fossil creation

Closes #1801

See merge request cable-mc/cobblemon!2150
2026-02-08 01:16:45 +00:00
aeroeng15 bc69ce91f3 Changelog 2026-02-07 16:00:00 -07:00
aeroeng15 1de1d8cdc3 Adjust ordering of party modification 2026-02-07 15:26:36 -07:00
Hiroku 087bf75500 Merge branch 'party-selection-toast' into 'main'
Party Selection Tutorial Toasts

See merge request cable-mc/cobblemon!2148
2026-02-02 05:58:58 +00:00
CeejayandHiroku bac435ba7b Party Selection Tutorial Toasts 2026-02-02 05:58:58 +00:00
Hiroku 74a6106eb6 Merge branch 'snack-stack-fix' into 'main'
Fixes odd stacking behavior with the poke_bait item.

See merge request cable-mc/cobblemon!2143
2026-02-01 03:29:20 +00:00
Neovitalism 5ec993ad3c Update CHANGELOG.md 2026-01-31 21:13:10 -06:00
Paul 73a03d90da Resnapshot 2026-01-31 13:22:11 +10:00
Neovitalism 246d00aa3f Fixes odd stacking behavior with the poke_bait item. 2026-01-27 21:45:05 -06:00
25 changed files with 295 additions and 68 deletions
+16 -13
View File
@@ -1,23 +1,26 @@
# Changelog
## [1.7.3 (January 31st, 2026)](#1-7-3)
## [1.7.4 (MONTH Xth, 2026)](#1-7-4)
### Additions
- Added a toast to notify players of how they can scroll through their party. Did you know you can hold R and scroll instead of using arrow keys??!
### New rideable Pokémon
### Pokémon Added
### Model updates for the following Pokémon
### Animation updates for the following Pokémon
### Changes
### Fixes
- Fixed mounted Pokémon not playing sounds.
- Fixed players failing to join servers randomly.
- Fixed some Pokémon having no stamina for flying.
- Fixed `/pctake` not respecting the actual size of the PC.
- Fixes https://gitlab.com/cable-mc/cobblemon/-/issues/1943
- Fix occasional crash on retrieving revived fossils
### Developer
- Poké Ball GUI textures now respect the ball's namespace, enabling proper texture loading for custom balls from other mods.
### Molang & Datapacks
- Added a `chance` requirement type for Pokémon interactions.
### Localization
- Updated translations for:
- French
- Canadian French
- Korean
- Portuguese
- Simplified Chinese
- Spanish
+23
View File
@@ -0,0 +1,23 @@
# Changelog
## [1.7.3 (January 31st, 2026)](#1-7-3)
### Fixes
- Fixed mounted Pokémon not playing sounds.
- Fixed players failing to join servers randomly.
- Fixed some Pokémon having no stamina for flying.
- Fixed `/pctake` not respecting the actual size of the PC.
### Developer
- Poké Ball GUI textures now respect the ball's namespace, enabling proper texture loading for custom balls from other mods.
### Molang & Datapacks
- Added a `chance` requirement type for Pokémon interactions.
### Localization
- Updated translations for:
- French
- Canadian French
- Korean
- Portuguese
- Simplified Chinese
- Spanish
@@ -35,6 +35,7 @@ import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.cobblemon.mod.common.client.gui.party.PartyTutorialToasts;
import static com.google.common.primitives.Floats.min;
import static net.minecraft.util.Mth.lerp;
@@ -85,11 +86,13 @@ public abstract class MouseHandlerMixin {
CobblemonClient.INSTANCE.getStorage().shiftSelected(false);
ci.cancel();
PartySendBinding.INSTANCE.actioned();
PartyTutorialToasts.INSTANCE.onHoldKeyScrollSwitchedSlot();
} else if (i < 0) {
accumulatedScrollY -= i;
CobblemonClient.INSTANCE.getStorage().shiftSelected(true);
ci.cancel();
PartySendBinding.INSTANCE.actioned();
PartyTutorialToasts.INSTANCE.onHoldKeyScrollSwitchedSlot();
}
}
}
@@ -65,7 +65,11 @@ 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.*
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.actor.PokemonBattleActor
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.block.dispenser.DispenserBehaviorRegistry
@@ -76,7 +80,12 @@ import com.cobblemon.mod.common.config.LastChangedVersion
import com.cobblemon.mod.common.config.constraint.IntConstraint
import com.cobblemon.mod.common.config.starter.StarterConfig
import com.cobblemon.mod.common.data.CobblemonDataProvider
import com.cobblemon.mod.common.events.*
import com.cobblemon.mod.common.events.AdvancementHandler
import com.cobblemon.mod.common.events.CallbackHandler
import com.cobblemon.mod.common.events.EntityCallbackHandler
import com.cobblemon.mod.common.events.PokedexHandler
import com.cobblemon.mod.common.events.ServerTickHandler
import com.cobblemon.mod.common.events.StatHandler
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
import com.cobblemon.mod.common.permission.LaxPermissionValidator
import com.cobblemon.mod.common.platform.events.PlatformEvents
@@ -90,11 +99,23 @@ import com.cobblemon.mod.common.pokemon.feature.SlowpokeTailRegrowthSpeciesFeatu
import com.cobblemon.mod.common.pokemon.feature.SlowpokeTailRegrowthSpeciesFeatureProvider
import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
import com.cobblemon.mod.common.pokemon.properties.*
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.LabelProperty
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.stat.CobblemonStatProvider
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
import com.cobblemon.mod.common.util.*
import com.cobblemon.mod.common.util.DataKeys
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.ifDedicatedServer
import com.cobblemon.mod.common.util.isLaterVersion
import com.cobblemon.mod.common.util.party
import com.cobblemon.mod.common.util.requestWallpapers
import com.cobblemon.mod.common.util.server
import com.cobblemon.mod.common.world.feature.CobblemonPlacedFeatures
import com.cobblemon.mod.common.world.feature.ore.CobblemonOrePlacedFeatures
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
@@ -102,6 +123,17 @@ 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 java.util.concurrent.TimeUnit
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
@@ -114,17 +146,6 @@ 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 java.util.concurrent.TimeUnit
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
@@ -451,7 +472,7 @@ object Cobblemon {
server()?.getLevel(dimension)
} else {
val mc = Minecraft.getInstance()
return mc.singleplayerServer?.getLevel(dimension) ?: mc.level
mc.singleplayerServer?.getLevel(dimension) ?: mc.level
}
}
@@ -140,13 +140,7 @@ import com.cobblemon.mod.common.net.messages.client.ui.ExpGainedDataPacket
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
import com.cobblemon.mod.common.net.messages.client.ui.PokedexUIPacket
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
import com.cobblemon.mod.common.net.messages.server.BattleChallengeResponsePacket
import com.cobblemon.mod.common.net.messages.server.BenchMovePacket
import com.cobblemon.mod.common.net.messages.server.RequestMoveSwapPacket
import com.cobblemon.mod.common.net.messages.server.RequestPlayerInteractionsPacket
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
import com.cobblemon.mod.common.net.messages.server.*
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamLeavePacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamRequestPacket
@@ -189,6 +183,7 @@ import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdateRide
import com.cobblemon.mod.common.net.messages.server.starter.RequestStarterScreenPacket
import com.cobblemon.mod.common.net.messages.server.storage.SwapPCPartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.party.PartyTutorialPacket
import com.cobblemon.mod.common.net.messages.server.storage.party.ReleasePartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.*
@@ -225,6 +220,7 @@ import com.cobblemon.mod.common.net.serverhandling.dialogue.InputToDialogueHandl
import com.cobblemon.mod.common.net.serverhandling.evolution.AcceptEvolutionHandler
import com.cobblemon.mod.common.net.serverhandling.npc.SaveNPCHandler
import com.cobblemon.mod.common.net.serverhandling.orientation.ServerboundUpdateOrientationHandler
import com.cobblemon.mod.common.net.serverhandling.storage.party.PartyTutorialPacketHandler
import com.cobblemon.mod.common.net.serverhandling.pasture.PasturePokemonHandler
import com.cobblemon.mod.common.net.serverhandling.pasture.SetPastureConflictHandler
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpastureAllPokemonHandler
@@ -529,7 +525,7 @@ 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(RequestRenamePCBoxPacket.ID, RequestRenamePCBoxPacket::decode, RequestRenamePCBoxHandler))
list.add(PacketRegisterInfo(PCBoxWallpapersPacket.ID, PCBoxWallpapersPacket::decode, PCBoxWallpapersHandler))
list.add(PacketRegisterInfo(RequestChangePCBoxWallpaperPacket.ID, RequestChangePCBoxWallpaperPacket::decode, RequestChangePCBoxWallpaperHandler))
list.add(PacketRegisterInfo(MarkPCBoxWallpapersSeenPacket.ID, MarkPCBoxWallpapersSeenPacket::decode, MarkPCBoxWallpapersSeenHandler))
@@ -587,6 +583,9 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(PartyPokemonMoveSelectedPacket.ID, PartyPokemonMoveSelectedPacket::decode, PartyPokemonMoveSelectedHandler))
list.add(PacketRegisterInfo(PartyMoveSelectCancelledPacket.ID, PartyMoveSelectCancelledPacket::decode, PartyMoveSelectCancelledHandler))
//Party move tutorial toasts packets
list.add(PacketRegisterInfo(PartyTutorialPacket.ID, PartyTutorialPacket::decode, PartyTutorialPacketHandler))
// Dialogue packets
list.add(PacketRegisterInfo(EscapeDialoguePacket.ID, EscapeDialoguePacket::decode, EscapeDialogueHandler))
list.add(PacketRegisterInfo(InputToDialoguePacket.ID, InputToDialoguePacket::decode, InputToDialogueHandler))
@@ -21,25 +21,27 @@ class LevelUpContext(val level: Int, val pokemon: Pokemon)
class LevelUpCriterion(
playerCtx: Optional<ContextAwarePredicate>,
val level: Int,
val evolved: Boolean
val hasEvolved: Boolean,
val canEvolve: Boolean
): SimpleCriterionCondition<LevelUpContext>(playerCtx) {
companion object {
val CODEC: Codec<LevelUpCriterion> = RecordCodecBuilder.create { it.group(
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(LevelUpCriterion::playerCtx),
Codec.INT.optionalFieldOf("level", 0).forGetter(LevelUpCriterion::level),
Codec.BOOL.optionalFieldOf("has_evolved", true).forGetter(LevelUpCriterion::evolved)
Codec.BOOL.optionalFieldOf("has_evolved", true).forGetter(LevelUpCriterion::hasEvolved),
Codec.BOOL.optionalFieldOf("can_evolve", true).forGetter(LevelUpCriterion::canEvolve)
).apply(it, ::LevelUpCriterion) }
}
override fun matches(player: ServerPlayer, context: LevelUpContext): Boolean {
val preEvo = context.pokemon.preEvolution != null
val hasEvolution = !context.pokemon.evolutions.none()
var evolutionCheck = true
/*var evolutionCheck = true
if (preEvo || hasEvolution) {
evolutionCheck = preEvo != hasEvolution
}
return level == context.level && evolutionCheck == evolved
}*/
return level == context.level && preEvo == hasEvolved && hasEvolution == canEvolve
}
}
@@ -28,6 +28,7 @@ data class GeneralPlayerData(
var starterUUID: UUID?,
var keyItems: MutableSet<ResourceLocation>,
var battleTheme: ResourceLocation?,
var partySelectTutorialDone: Boolean = false,
val extraData: MutableMap<String, PlayerDataExtension>,
) : InstancedPlayerData {
var advancementData: PlayerAdvancementData = PlayerAdvancementData()
@@ -53,7 +54,8 @@ data class GeneralPlayerData(
starterSelected,
starterUUID,
advancementData.totalBattleVictoryCount == 0,
battleTheme
battleTheme,
partySelectTutorialDone
)
}
@@ -36,7 +36,8 @@ class PlayerDataJsonBackend: JsonBackedPlayerDataStoreBackend<GeneralPlayerData>
starterUUID = null,
keyItems = Cobblemon.config.defaultKeyItems,
extraData = mutableMapOf(),
battleTheme = CobblemonSounds.PVP_BATTLE.location
battleTheme = CobblemonSounds.PVP_BATTLE.location,
partySelectTutorialDone = false
)}
override val gson = GsonBuilder()
@@ -37,7 +37,8 @@ class PlayerDataMongoBackend(mongoClient: MongoClient, databaseName: String, col
starterUUID = null,
keyItems = Cobblemon.config.defaultKeyItems,
extraData = mutableMapOf(),
battleTheme = CobblemonSounds.PVP_BATTLE.location
battleTheme = CobblemonSounds.PVP_BATTLE.location,
partySelectTutorialDone = false
)}
override val gson = GsonBuilder()
@@ -34,7 +34,8 @@ data class ClientGeneralPlayerData(
var starterSelected: Boolean = false,
var starterUUID: UUID? = null,
var showChallengeLabel: Boolean = true,
val battleTheme: ResourceLocation? = null
val battleTheme: ResourceLocation? = null,
var partySelectTutorialDone: Boolean = false
) : ClientInstancedPlayerData {
override fun encode(buf: RegistryFriendlyByteBuf) {
@@ -46,6 +47,7 @@ data class ClientGeneralPlayerData(
buf.writeNullable(starterUUID) { pb, value -> pb.writeString(value.toString()) }
buf.writeNullable(resetStarters) { pb, value -> pb.writeBoolean(value) }
buf.writeNullable(battleTheme) {pb, value -> pb.writeIdentifier(value)}
buf.writeBoolean(partySelectTutorialDone)
}
companion object {
fun decode(buffer: RegistryFriendlyByteBuf): SetClientPlayerDataPacket {
@@ -57,6 +59,7 @@ data class ClientGeneralPlayerData(
val starterUUID = buffer.readNullable { it.readString() }?.let { UUID.fromString(it) }
val resetStarterPrompt = buffer.readNullable { it.readBoolean() }
val battleTheme = buffer.readNullable { it.readIdentifier() }
val partySelectTutorialDone = buffer.readBoolean()
val data = ClientGeneralPlayerData(
resetStarterPrompt,
promptStarter,
@@ -64,7 +67,8 @@ data class ClientGeneralPlayerData(
starterSelected,
starterUUID,
showChallengeLabel,
battleTheme
battleTheme,
partySelectTutorialDone
)
//Weird to do this, but since the flag doesn't get passed to the decoded obj, do it here
//Should be fine, as long as decode doesn't get run on the server for some reason
@@ -128,11 +128,11 @@ class FossilMultiblockStructure (
if(pokemon != null) {
pokemon.caughtBall = ballType
player.party().add(pokemon)
this.fossilState.growthState = "Taken"
player.playSound(CobblemonSounds.FOSSIL_MACHINE_RETRIEVE_POKEMON, 1.0F, 1.0F)
CobblemonEvents.FOSSIL_REVIVED.post(FossilRevivedEvent(pokemon, player))
CobblemonCriteria.RESURRECT_POKEMON.trigger(player, pokemon)
player.party().add(pokemon)
}
// Turn the monitor off
@@ -27,6 +27,7 @@ import com.cobblemon.mod.common.client.gui.PartyOverlayDataControl
import com.cobblemon.mod.common.client.gui.RideControlsOverlay
import com.cobblemon.mod.common.client.gui.battle.BattleOverlay
import com.cobblemon.mod.common.client.gui.cookingpot.CookingPotScreen
import com.cobblemon.mod.common.client.gui.party.PartyTutorialToasts
import com.cobblemon.mod.common.client.particle.BedrockParticleOptionsRepository
import com.cobblemon.mod.common.client.render.ClientPlayerIcon
import com.cobblemon.mod.common.client.render.DeferredRenderer
@@ -128,6 +129,8 @@ object CobblemonClient {
battleOverlay.onLogout()
ClientTaskTracker.clear()
checkedStarterScreen = false
overlay.resetAttachedToast()
PartyTutorialToasts.reset()
// CobblemonDataProvider.canReload = true
DeferredRenderer.clearAll()
ClientPlayerIcon.clear()
@@ -165,13 +168,12 @@ object CobblemonClient {
PlatformEvents.CLIENT_TICK_POST.subscribe { event ->
val player = event.client.player
if (player != null) {
var selectedItem = player.inventory.getItem(player.inventory.selected)
val selectedItem = player.inventory.getItem(player.inventory.selected)
if (pokedexUsageContext.scanningGuiOpen &&
!(selectedItem.`is`(CobblemonItemTags.POKEDEX)) &&
!(player.offhandItem.`is`(CobblemonItemTags.POKEDEX) &&
player.isUsingItem == true &&
player.usedItemHand == InteractionHand.OFF_HAND
)
player.isUsingItem &&
player.usedItemHand == InteractionHand.OFF_HAND)
) {
// Stop using Pokédex in main hand if player switches to a different slot in hotbar
pokedexUsageContext.stopUsing(PokedexUsageContext.OPEN_SCANNER_BUFFER_TICKS + 1)
@@ -216,7 +218,7 @@ object CobblemonClient {
}
fun registerColors() {
this.implementation.registerBlockColors(BlockColor { blockState, view, blockPos, tintIndex ->
this.implementation.registerBlockColors(BlockColor { _, view, blockPos, _ ->
blockPos?.let { pos ->
view?.getBlockEntity(pos)?.let { blockEntity ->
if (blockEntity is TintBlockEntity) return@BlockColor blockEntity.getTint()
@@ -18,10 +18,10 @@ import com.cobblemon.mod.common.api.text.text
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.gui.battle.BattleGUI
import com.cobblemon.mod.common.client.gui.party.PartyTutorialToasts
import com.cobblemon.mod.common.client.gui.toast.CobblemonToast
import com.cobblemon.mod.common.client.keybind.boundKey
import com.cobblemon.mod.common.client.keybind.keybinds.HidePartyBinding
import com.cobblemon.mod.common.client.keybind.keybinds.SummaryBinding
import com.cobblemon.mod.common.client.keybind.keybinds.*
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
@@ -150,6 +150,9 @@ class PartyOverlay : Gui(Minecraft.getInstance()) {
val portraitFrameOffsetY = 2
val selectedSlot = CobblemonClient.storage.selectedSlot
val partySize = party.slots.count { it != null }
PartyTutorialToasts.onOverlayRender(partySize)
party.forEachIndexed { index, pokemon ->
if (pokemon != null) {
val selectedOffsetX = if (selectedSlot == index) 6 else 0
@@ -0,0 +1,99 @@
/*
* 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.party
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.api.text.darkGray
import com.cobblemon.mod.common.api.text.red
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.gui.toast.CobblemonToast
import com.cobblemon.mod.common.client.keybind.boundKey
import com.cobblemon.mod.common.client.keybind.keybinds.DownShiftPartyBinding
import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding
import com.cobblemon.mod.common.client.keybind.keybinds.UpShiftPartyBinding
import com.cobblemon.mod.common.net.messages.server.storage.party.PartyTutorialPacket
import com.cobblemon.mod.common.util.lang
import com.mojang.blaze3d.platform.InputConstants
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.components.toasts.Toast
import net.minecraft.client.gui.components.toasts.AdvancementToast
import net.minecraft.network.chat.Component
import net.minecraft.util.Mth
object PartyTutorialToasts {
private var toastAttached = false
val upKey = UpShiftPartyBinding.boundKey()
val downKey = DownShiftPartyBinding.boundKey()
val upDisplay =
if (upKey.type == InputConstants.Type.KEYSYM && upKey.value == InputConstants.KEY_UP)
Component.literal("↑")
else upKey.displayName
val downDisplay =
if (downKey.type == InputConstants.Type.KEYSYM && downKey.value == InputConstants.KEY_DOWN)
Component.literal("↓")
else downKey.displayName
private val toast = CobblemonToast(
Mth.createInsecureUUID(),
CobblemonItems.POKEDEX_RED.defaultInstance,
lang("ui.party.party_select_title").red(),
lang(
"ui.party.party_select_description",
upDisplay,
downDisplay,
PartySendBinding.boundKey().displayName
).darkGray(),
AdvancementToast.BACKGROUND_SPRITE,
-1F,
0
)
fun reset() {
toastAttached = false
}
fun onOverlayRender(partySize: Int) {
if (partySize <= 1) return
if (!CobblemonClient.clientPlayerData.partySelectTutorialDone) {
showToast()
}
}
fun onArrowKeySwitchedSlot() {
if (CobblemonClient.clientPlayerData.partySelectTutorialDone) return
if (CobblemonClient.storage.party.count { it != null } < 2) return
PartyTutorialPacket().sendToServer()
hideToast()
}
fun onHoldKeyScrollSwitchedSlot() {
if (CobblemonClient.clientPlayerData.partySelectTutorialDone) return
if (CobblemonClient.storage.party.count { it != null } < 2) return
PartyTutorialPacket().sendToServer()
hideToast()
}
private fun showToast() {
val minecraft = Minecraft.getInstance()
if (!toastAttached) {
toast.nextVisibility = Toast.Visibility.SHOW
minecraft.toasts.addToast(toast)
toastAttached = true
}
}
private fun hideToast() {
if (toastAttached) toast.nextVisibility = Toast.Visibility.HIDE
}
}
@@ -20,6 +20,8 @@ import net.minecraft.resources.ResourceLocation
import net.minecraft.util.Mth
import java.util.*
import kotlin.math.min
import net.minecraft.client.gui.Font
import net.minecraft.util.FormattedCharSequence
@Environment(EnvType.CLIENT)
class CobblemonToast(
@@ -38,11 +40,18 @@ class CobblemonToast(
private var lastTime = 0L
internal var nextVisibility: Toast.Visibility = Toast.Visibility.SHOW
fun getLines(font: Font, maxWidth: Int): List<FormattedCharSequence> {
return font.split(this.description, maxWidth)
}
override fun render(context: GuiGraphics, manager: ToastComponent, startTime: Long): Toast.Visibility {
context.blitSprite(this.frameTexture, 0, 0, this.width(), this.height())
val maxWidth = 125
val textRenderer = manager.minecraft.font
context.blitSprite(this.frameTexture, 0, 0, this.width(), this.height() + (getLines(textRenderer, maxWidth).size - 1) * 10)
context.drawString(textRenderer, this.title, 30, 7, this.title.style.color?.value ?: -1, false)
context.drawString(textRenderer, this.description, 30, 18, this.description.style.color?.value ?: -1, false)
context.drawWordWrap(textRenderer, this.description, 30, 18, maxWidth, this.description.style.color?.value ?: -1)
context.renderFakeItem(this.icon, 8, 8)
if (this.hasProgressBar()) {
context.fill(3, 28, 157, 29, -1)
@@ -9,6 +9,7 @@
package com.cobblemon.mod.common.client.keybind.keybinds
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.gui.party.PartyTutorialToasts
import com.cobblemon.mod.common.client.keybind.CobblemonKeyBinding
import com.cobblemon.mod.common.client.keybind.KeybindCategories
import com.mojang.blaze3d.platform.InputConstants
@@ -21,5 +22,6 @@ object DownShiftPartyBinding : CobblemonKeyBinding(
) {
override fun onPress() {
CobblemonClient.storage.shiftSelected(true)
PartyTutorialToasts.onArrowKeySwitchedSlot()
}
}
@@ -9,6 +9,7 @@
package com.cobblemon.mod.common.client.keybind.keybinds
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.gui.party.PartyTutorialToasts
import com.cobblemon.mod.common.client.keybind.CobblemonKeyBinding
import com.cobblemon.mod.common.client.keybind.KeybindCategories
import com.mojang.blaze3d.platform.InputConstants
@@ -21,5 +22,6 @@ object UpShiftPartyBinding : CobblemonKeyBinding(
) {
override fun onPress() {
CobblemonClient.storage.shiftSelected(false)
PartyTutorialToasts.onArrowKeySwitchedSlot()
}
}
@@ -31,7 +31,7 @@ class BaitEffectsComponent(
}
override fun equals(other: Any?): Boolean {
return other is BaitEffectsComponent && effects.size == other.effects.size && effects.all { it in other.effects }
return other is BaitEffectsComponent && effects == other.effects
}
override fun hashCode(): Int {
@@ -49,9 +49,7 @@ class FoodColourComponent(
}
override fun equals(other: Any?): Boolean {
return other is FoodColourComponent &&
colours.size == other.colours.size &&
colours.mapIndexed { index, value -> value == other.colours[index] }.all { it }
return other is FoodColourComponent && colours == other.colours // List == List in kotlin checks for element order and index.
}
fun getColoursAsARGB(): List<Int> {
@@ -0,0 +1,24 @@
/*
* 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.net.messages.server.storage.party
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.network.RegistryFriendlyByteBuf
class PartyTutorialPacket : NetworkPacket<PartyTutorialPacket> {
override val id = ID
override fun encode(buffer: RegistryFriendlyByteBuf) {}
companion object {
val ID = cobblemonResource("party_select_tutorial")
fun decode(buffer: RegistryFriendlyByteBuf): PartyTutorialPacket = PartyTutorialPacket()
}
}
@@ -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.net.serverhandling.storage.party
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreTypes
import com.cobblemon.mod.common.net.messages.server.storage.party.PartyTutorialPacket
import net.minecraft.server.MinecraftServer
import net.minecraft.server.level.ServerPlayer
object PartyTutorialPacketHandler : ServerNetworkPacketHandler<PartyTutorialPacket> {
override fun handle(packet: PartyTutorialPacket, server: MinecraftServer, player: ServerPlayer) {
val pd = Cobblemon.playerDataManager.getGenericData(player)
if (!pd.partySelectTutorialDone) {
pd.partySelectTutorialDone = true
Cobblemon.playerDataManager.saveSingle(pd, PlayerInstancedDataStoreTypes.GENERAL)
pd.sendToPlayer(player)
}
}
}
@@ -547,6 +547,8 @@
"cobblemon.trade.request_sent": "Offer'd to trade w'th %1$s",
"cobblemon.trade.offer": "%1$s offer'd to trade crewmates with ye.",
"cobblemon.ui.party": "Crew",
"cobblemon.ui.party.party_select_title": "Pick Yer Party Pal",
"cobblemon.ui.party.party_select_description": "Slam %1$s/%2$s...",
"cobblemon.ui.power": "Damage",
"cobblemon.ui.accuracy": "Shot rate",
"cobblemon.ui.effect": "Bonus",
@@ -824,10 +824,6 @@
"effect.cobblemon.cleanse_negative": "Negative Effect Cleanse",
"effect.cobblemon.mental_restoration": "Mental Restoration",
"effect.cobblemon.cleanse_all": "Effect Cleanse",
"effect.cobblemon.cleanse_negative": "Negative Effect Cleanse",
"effect.cobblemon.mental_restoration": "Mental Restoration",
"cobblemon.fossil.armor": "Armor",
"cobblemon.fossil.bird": "Bird",
"cobblemon.fossil.claw": "Claw",
@@ -1214,6 +1210,8 @@
"cobblemon.trade.error.duplicate": "You already sent a trade request to %1$s!",
"cobblemon.ui.party": "Party",
"cobblemon.ui.party.party_select_title": "Change Party Selection",
"cobblemon.ui.party.party_select_description": "Press %1$s/%2$s or hold %3$s and scroll.",
"cobblemon.ui.power": "Power",
"cobblemon.ui.accuracy": "Accuracy",
"cobblemon.ui.effect": "Effect",
@@ -20,7 +20,8 @@
"trigger": "cobblemon:level_up",
"conditions": {
"level": 100,
"has_evolved": false
"has_evolved": false,
"can_evolve": true
}
}
},
+2 -2
View File
@@ -13,7 +13,7 @@ parchment_version = 2024.07.28@zip
java_version = 21
mod_id=cobblemon
mod_version=1.7.3
snapshot=false
mod_version=1.7.4
snapshot=true
fabric.loom.multiProjectOptimisation=false