Compare commits

..
Author SHA1 Message Date
Guilherme Pereira 96079065b6 more armors 2025-12-05 11:38:38 -03:00
Guilherme Pereira 86f91ed77a add malicious armor armor material 2025-12-03 20:41:32 -03:00
115 changed files with 685 additions and 1219 deletions

No files matched your search

-20
View File
@@ -2,39 +2,19 @@
## [1.7.2 (MONTH Xth, YEAR)](#1-7-2)
### Additions
- Added riding statistics: `Distance by Pokémon on Land`, `Distance by Pokémon in Air` and `Distance by Pokémon in Liquid`.
- Added the Partner Mark, which party Pokémon have a very small chance to earn as the player walks, provided they have enough friendship.
- Added trades for Saccharine Saplings, Hearty Grains, Chipped Pot, and Masterpiece Teacup to the Wandering Trader.
- Added brewing recipe for Throat Spray.
- Added mood particles! Pokémon now visually react to certain actions:
- Angry particles when attacking a mob.
- Annoyed particles when a player tries to feed them while they’re already full.
- Sweat droplets when they run out of stamina while being ridden.
### Changes
- Ride sounds have been separated into stereo for passengers and mono for other players. Riding will now sound more spacious.
### Fixes
- Fixed orientation not getting reset after crashing while flying and getting back on the Pokémon.
- Fixed Furfrou not being trimmable on NeoForge.
- Fixed shiny Pokémon not respecting the silent flag on spawn.
- Fixed honey from Saccharine Leaves being harvestable at less than the max age.
- Items given from interacting with Saccharine Leaves are placed in the active hotbar slot if possible.
- Fix all Pokémon being saved to chunks and never despawning.
- Fixed PokeSnacks crashing if there was no available spawn.
- Fixed Pokémon spawn influences not being specific to regional forms
- Fixed crashing when viewing another player in spectator mode
- Fixed missing apricorn textures for Adorn blocks
- Fixed crashing when riding due to malformed json file, instead resetting it
- Fixed mochi items consuming two items at a time
- Fix item interaction sometimes not working properly when playing on servers.
### Developer
- Changed the `owner` parameter in the `OwnerQueryRequirement` interface from `ServerPlayer` to `Player`. This method is now also called on the client to verify whether a Pokémon interaction succeeded, so make sure to update your implementations to handle both server and client contexts.
### Molang & Datapacks
- Ride sounds can now be set as exclusive to passengers
- Ride sounds no longer play when submerged unless specified with a new setting
### Particles
@@ -11,15 +11,11 @@ package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.Cobblemon;
import com.cobblemon.mod.common.OrientationControllable;
import com.cobblemon.mod.common.PlayerSpawnerAccessor;
import com.cobblemon.mod.common.api.riding.RidingStyle;
import com.cobblemon.mod.common.api.spawning.spawner.PlayerSpawner;
import com.cobblemon.mod.common.api.spawning.spawner.PlayerSpawnerFactory;
import com.cobblemon.mod.common.api.stats.CobblemonStats;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
@@ -93,32 +89,4 @@ public abstract class ServerPlayerMixin implements PlayerSpawnerAccessor {
private boolean cobblemon$cancelSavingPokemonMounts(boolean original, @Local(ordinal=0) Entity entity) {
return original && !(entity instanceof PokemonEntity);
}
@WrapOperation(method = "checkRidingStatistics", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;getVehicle()Lnet/minecraft/world/entity/Entity;"))
public Entity cobblemon$checkRidingStatistics(ServerPlayer player, Operation<Entity> original, @Local int distance) {
var entity = original.call(player);
if (!(entity instanceof PokemonEntity pokemonEntity)) {
return entity;
}
var ridingController = pokemonEntity.getRidingController();
if (ridingController == null) return entity;
var activeContext = ridingController.getContext();
if (activeContext == null) return entity;
var ridingStyle = activeContext.getStyle();
CobblemonStats.CobblemonStat stat = switch (ridingStyle) {
case RidingStyle.LAND -> CobblemonStats.RIDING_LAND;
case RidingStyle.AIR -> CobblemonStats.RIDING_AIR;
case RidingStyle.LIQUID -> CobblemonStats.RIDING_LIQUID;
default -> null;
};
if (stat != null) {
player.awardStat(CobblemonStats.getStat(stat), distance);
}
return entity;
}
}
@@ -33,7 +33,7 @@ public class AbstractClientPlayerMixin {
cir.setReturnValue(usageContext.getFovMultiplier());
} else {
// Only modify fov through riding if the pokedex is not open
AbstractClientPlayer player = (AbstractClientPlayer) (Object) this;
LocalPlayer player = (LocalPlayer) (Object) this;
// Only modify fov for the driver and not the passengers
if (player != null && player.isPassenger() && player.getVehicle() instanceof PokemonEntity && player.getVehicle().getControllingPassenger() == player) {
PokemonEntity ride = (PokemonEntity) player.getVehicle();
@@ -42,8 +42,8 @@ import com.cobblemon.mod.common.api.scheduling.ServerRealTimeTaskTracker
import com.cobblemon.mod.common.api.scheduling.ServerTaskTracker
import com.cobblemon.mod.common.api.spawning.BestSpawner
import com.cobblemon.mod.common.api.spawning.CobblemonSpawningZoneGenerator
import com.cobblemon.mod.common.api.spawning.SpawningZoneGenerator
import com.cobblemon.mod.common.api.spawning.position.AreaSpawnablePositionResolver
import com.cobblemon.mod.common.api.spawning.SpawningZoneGenerator
import com.cobblemon.mod.common.api.starter.StarterHandler
import com.cobblemon.mod.common.api.stats.CobblemonStats
import com.cobblemon.mod.common.api.storage.PokemonStoreManager
@@ -76,7 +76,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.EntityCallbackHandler
import com.cobblemon.mod.common.events.CallbackHandler
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
@@ -189,6 +194,7 @@ object Cobblemon {
implementation.registerSoundEvents()
implementation.registerDataComponents()
implementation.registerBlocks()
implementation.registerArmorMaterials()
implementation.registerItems()
implementation.registerEntityTypes()
implementation.registerEntityAttributes()
@@ -0,0 +1,53 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.platform.PlatformRegistry
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.core.Registry
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.core.registries.Registries
import net.minecraft.resources.ResourceKey
import net.minecraft.sounds.SoundEvents
import net.minecraft.world.item.ArmorItem
import net.minecraft.world.item.ArmorMaterial
import net.minecraft.world.item.Items
import net.minecraft.world.item.crafting.Ingredient
@Suppress("unused")
object CobblemonArmorMaterials :
PlatformRegistry<Registry<ArmorMaterial>, ResourceKey<Registry<ArmorMaterial>>, ArmorMaterial>() {
override val registry: Registry<ArmorMaterial> = BuiltInRegistries.ARMOR_MATERIAL
override val resourceKey: ResourceKey<Registry<ArmorMaterial>> = Registries.ARMOR_MATERIAL
@JvmField
val MALICIOUS_ARMOR = cosmeticMaterial("malicious_armor")
@JvmField
val HEAVY_DUTY_BOOTS = cosmeticMaterial("heavy_duty_boots")
@JvmField
val PROTECTIVE_PADS = cosmeticMaterial("protective_pads")
@JvmField
val ASSAULT_VEST = cosmeticMaterial("assault_vest")
@JvmField
val MYSTIC_WATER = cosmeticMaterial("mystic_water")
@JvmField
val BLACK_BELT = cosmeticMaterial("black_belt")
private fun cosmeticMaterial(name: String): ArmorMaterial {
val armorMaterial = ArmorMaterial(
mapOf(
ArmorItem.Type.HELMET to 0,
ArmorItem.Type.CHESTPLATE to 0,
ArmorItem.Type.LEGGINGS to 0,
ArmorItem.Type.BOOTS to 0,
),
0,
SoundEvents.ARMOR_EQUIP_GENERIC,
{ Ingredient.EMPTY },
listOf(ArmorMaterial.Layer(cobblemonResource(name), "", true)),
0.0f,
0.0f,
)
return create(name, armorMaterial)
}
}
@@ -64,6 +64,8 @@ interface CobblemonImplementation {
fun registerEntityDataSerializers()
fun registerArmorMaterials()
/**
* TODO
*
@@ -44,16 +44,21 @@ import com.cobblemon.mod.common.pokeball.PokeBall
import com.cobblemon.mod.common.pokemon.IVs
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.core.Holder
import net.minecraft.core.Registry
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.core.registries.Registries
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
import net.minecraft.sounds.SoundEvents
import net.minecraft.world.effect.MobEffectInstance
import net.minecraft.world.effect.MobEffects
import net.minecraft.world.entity.EquipmentSlot
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.food.FoodProperties
import net.minecraft.world.item.ArmorItem
import net.minecraft.world.item.ArmorMaterial
import net.minecraft.world.item.BlockItem
import net.minecraft.world.item.HangingSignItem
import net.minecraft.world.item.Item
@@ -501,8 +506,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField val RAZOR_CLAW = noSettingsItem("razor_claw")
@JvmField val RAZOR_FANG = noSettingsItem("razor_fang")
@JvmField val AUSPICIOUS_ARMOR = heldItem("auspicious_armor")
@JvmField val MALICIOUS_ARMOR = heldItem("malicious_armor")
@JvmField val SHELL_HELMET = heldItem("shell_helmet")
@JvmField val METAL_ALLOY = noSettingsItem("metal_alloy")
@JvmField val SCROLL_OF_DARKNESS = noSettingsItem("scroll_of_darkness")
@JvmField val SCROLL_OF_WATERS = noSettingsItem("scroll_of_waters")
@@ -892,7 +895,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
val WATER_STONE = noSettingsItem("water_stone")
val wearables = mutableListOf<WearableItem>()
//Wearable items (these items should have a corresponding 3D model)
// Wearable items (these items should have a corresponding 3D model)
@JvmField val BLACK_GLASSES = wearableItem("black_glasses")
@JvmField val CHOICE_BAND = wearableItem("choice_band")
@JvmField val CHOICE_SPECS = wearableItem("choice_specs")
@@ -903,6 +907,20 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField val ROCKY_HELMET = wearableItem("rocky_helmet")
@JvmField val SAFETY_GOGGLES = wearableItem("safety_goggles")
@JvmField val WISE_GLASSES = wearableItem("wise_glasses")
@JvmField val SHELL_HELMET = wearableItem("shell_helmet")
@JvmField
val MALICIOUS_ARMOR = armorItem("malicious_armor", CobblemonArmorMaterials.MALICIOUS_ARMOR, ArmorItem.Type.CHESTPLATE)
@JvmField
val HEAVY_DUTY_BOOTS = armorItem("heavy_duty_boots", CobblemonArmorMaterials.HEAVY_DUTY_BOOTS, ArmorItem.Type.BOOTS)
@JvmField
val PROTECTIVE_PADS = armorItem("protective_pads", CobblemonArmorMaterials.PROTECTIVE_PADS, ArmorItem.Type.CHESTPLATE)
@JvmField
val ASSAULT_VEST = armorItem("assault_vest", CobblemonArmorMaterials.ASSAULT_VEST, ArmorItem.Type.CHESTPLATE)
@JvmField
val MYSTIC_WATER = armorItem("mystic_water", CobblemonArmorMaterials.MYSTIC_WATER, ArmorItem.Type.CHESTPLATE)
@JvmField
val BLACK_BELT = armorItem("black_belt", CobblemonArmorMaterials.BLACK_BELT, ArmorItem.Type.CHESTPLATE)
// Held Items
@JvmField
@@ -912,14 +930,10 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val AIR_BALLOON = heldItem("air_balloon")
@JvmField
val ASSAULT_VEST = heldItem("assault_vest")
@JvmField
val BIG_ROOT = compostableBlockItem("big_root", CobblemonBlocks.BIG_ROOT, 0.30f)
@JvmField
val BINDING_BAND = heldItem("binding_band")
@JvmField
val BLACK_BELT = heldItem("black_belt")
@JvmField
val BLACK_SLUDGE = heldItem("black_sludge")
@JvmField
val BLUNDER_POLICY = heldItem("blunder_policy")
@@ -966,8 +980,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val HARD_STONE = heldItem("hard_stone")
@JvmField
val HEAVY_DUTY_BOOTS = heldItem("heavy_duty_boots")
@JvmField
val IRON_BALL = heldItem("iron_ball")
@JvmField
val LAGGING_TAIL = heldItem("lagging_tail")
@@ -992,8 +1004,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val MIRACLE_SEED = heldItem("miracle_seed")
@JvmField
val MYSTIC_WATER = heldItem("mystic_water")
@JvmField
val NEVER_MELT_ICE = heldItem("never_melt_ice")
@JvmField
val POISON_BARB = heldItem("poison_barb")
@@ -1012,8 +1022,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val PSYCHIC_SEED = heldItem("psychic_seed")
@JvmField
val PROTECTIVE_PADS = heldItem("protective_pads")
@JvmField
val PUNCHING_GLOVE = heldItem("punching_glove")
@JvmField
val QUICK_CLAW = heldItem("quick_claw")
@@ -1491,9 +1499,13 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
return item
}
private fun wearableItem(name: String, heldItemRemappedName: String? = null): CobblemonItem = create(
private fun wearableItem(
name: String,
heldItemRemappedName: String? = null,
equipmentSlot: EquipmentSlot = EquipmentSlot.HEAD,
): CobblemonItem = create(
name,
WearableItem(name).also {
WearableItem(name, equipmentSlot).also {
wearables.add(it)
if (heldItemRemappedName != null) {
CobblemonHeldItemManager.registerRemap(it, heldItemRemappedName)
@@ -1501,6 +1513,21 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
}
)
private fun armorItem(
name: String,
armorMaterial: ArmorMaterial,
armorType: ArmorItem.Type,
durability: Int? = null,
): ArmorItem {
var properties = Properties()
if (durability != null) properties = properties.durability(durability)
val armorMaterialHolder = BuiltInRegistries.ARMOR_MATERIAL.wrapAsHolder(armorMaterial)
val armorItem = ArmorItem(armorMaterialHolder, armorType, properties)
return create(name, armorItem)
}
private fun campfirePotItem(block: Block, color: CampfirePotColor): CampfirePotItem {
val item = create("campfire_pot_${color.suffix}", CampfirePotItem(block, color))
campfire_pots.add(item)
@@ -21,12 +21,15 @@ import com.cobblemon.mod.common.client.net.callback.partymove.OpenPartyMoveCallb
import com.cobblemon.mod.common.client.net.cooking.ToggleCookingPotLidHandler
import com.cobblemon.mod.common.client.net.data.CobblemonMechanicsSyncHandler
import com.cobblemon.mod.common.client.net.data.DataRegistrySyncPacketHandler
import com.cobblemon.mod.common.client.net.data.PokemonInteractionsSyncHandler
import com.cobblemon.mod.common.client.net.data.RideSettingsSyncHandler
import com.cobblemon.mod.common.client.net.debug.OpenRidingStatsDebugGUIHandler
import com.cobblemon.mod.common.client.net.dialogue.DialogueClosedHandler
import com.cobblemon.mod.common.client.net.dialogue.DialogueOpenedHandler
import com.cobblemon.mod.common.client.net.effect.*
import com.cobblemon.mod.common.client.net.effect.PokeSnackBlockParticlesHandler
import com.cobblemon.mod.common.client.net.effect.RunPosableMoLangHandler
import com.cobblemon.mod.common.client.net.effect.SaccharineLogBlockParticlesHandler
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormEntityParticleHandler
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormParticleHandler
import com.cobblemon.mod.common.client.net.gui.ExpGainedDataPacketHandler
import com.cobblemon.mod.common.client.net.gui.InteractPokemonUIPacketHandler
import com.cobblemon.mod.common.client.net.gui.PokedexUIPacketHandler
@@ -34,7 +37,11 @@ import com.cobblemon.mod.common.client.net.gui.SummaryUIPacketHandler
import com.cobblemon.mod.common.client.net.npc.CloseNPCEditorHandler
import com.cobblemon.mod.common.client.net.npc.OpenNPCEditorHandler
import com.cobblemon.mod.common.client.net.orientation.ClientboundUpdateOrientationHandler
import com.cobblemon.mod.common.client.net.pasture.*
import com.cobblemon.mod.common.client.net.pasture.ClosePastureHandler
import com.cobblemon.mod.common.client.net.pasture.OpenPastureHandler
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.pasture.UpdatePastureConflictFlagHandler
import com.cobblemon.mod.common.client.net.pokedex.ServerConfirmedRegisterHandler
import com.cobblemon.mod.common.client.net.pokemon.update.ClientboundUpdateRidingStateHandler
import com.cobblemon.mod.common.client.net.pokemon.update.PokemonUpdatePacketHandler
@@ -52,7 +59,14 @@ 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.*
import com.cobblemon.mod.common.client.net.toast.ToastPacketHandler
import com.cobblemon.mod.common.client.net.trade.*
import com.cobblemon.mod.common.client.net.trade.TradeAcceptanceChangedHandler
import com.cobblemon.mod.common.client.net.trade.TradeCancelledHandler
import com.cobblemon.mod.common.client.net.trade.TradeCompletedHandler
import com.cobblemon.mod.common.client.net.trade.TradeOfferExpiredHandler
import com.cobblemon.mod.common.client.net.trade.TradeOfferNotificationHandler
import com.cobblemon.mod.common.client.net.trade.TradeProcessStartedHandler
import com.cobblemon.mod.common.client.net.trade.TradeStartedHandler
import com.cobblemon.mod.common.client.net.trade.TradeUpdatedHandler
import com.cobblemon.mod.common.net.PacketRegisterInfo
import com.cobblemon.mod.common.net.messages.client.CalculateSeatPositionsPacket
import com.cobblemon.mod.common.net.messages.client.OpenBehaviourEditorPacket
@@ -69,12 +83,20 @@ import com.cobblemon.mod.common.net.messages.client.data.*
import com.cobblemon.mod.common.net.messages.client.debug.RequestOpenRidingStatsDebugGUIPacket
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueClosedPacket
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueOpenedPacket
import com.cobblemon.mod.common.net.messages.client.effect.*
import com.cobblemon.mod.common.net.messages.client.effect.PokeSnackBlockParticlesPacket
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
import com.cobblemon.mod.common.net.messages.client.effect.SaccharineLogBlockParticlesPacket
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.npc.CloseNPCEditorPacket
import com.cobblemon.mod.common.net.messages.client.npc.OpenNPCEditorPacket
import com.cobblemon.mod.common.net.messages.client.orientation.ClientboundUpdateDriverInputPacket
import com.cobblemon.mod.common.net.messages.client.orientation.ClientboundUpdateOrientationPacket
import com.cobblemon.mod.common.net.messages.client.pasture.*
import com.cobblemon.mod.common.net.messages.client.pasture.ClosePasturePacket
import com.cobblemon.mod.common.net.messages.client.pasture.OpenPasturePacket
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonPasturedPacket
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonUnpasturedPacket
import com.cobblemon.mod.common.net.messages.client.pasture.UpdatePastureConflictFlagPacket
import com.cobblemon.mod.common.net.messages.client.pokedex.ServerConfirmedRegisterPacket
import com.cobblemon.mod.common.net.messages.client.pokemon.update.*
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.AddEvolutionPacket
@@ -94,19 +116,43 @@ import com.cobblemon.mod.common.net.messages.client.storage.party.InitializePart
import com.cobblemon.mod.common.net.messages.client.storage.party.MoveClientPartyPokemonPacket
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.ClosePCPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.InitializePCPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.MoveClientPCPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.OpenPCPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.RenamePCBoxPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCPokemonPacket
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.storage.pc.wallpaper.UnlockPCBoxWallpaperPacket
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.trade.TradeAcceptanceChangedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeCancelledPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeCompletedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferExpiredPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferNotificationPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeProcessStartedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
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.*
import com.cobblemon.mod.common.net.messages.server.battle.*
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.battle.BattleSelectActionsPacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamLeavePacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamRequestPacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamResponsePacket
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
import com.cobblemon.mod.common.net.messages.server.behaviour.DamageOnCollisionPacket
import com.cobblemon.mod.common.net.messages.server.behaviour.SetEntityBehaviourPacket
import com.cobblemon.mod.common.net.messages.server.block.AdjustBlockEntityViewerCountPacket
@@ -131,7 +177,11 @@ import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPack
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.FinishScanningPacket
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.StartScanningPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.interact.InteractPokemonPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.*
import com.cobblemon.mod.common.net.messages.server.pokemon.update.ServerboundUpdateRidingStatePacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetActiveMarkPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetItemHiddenPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetMarkingsPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetNicknamePacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.evolution.AcceptEvolutionPacket
import com.cobblemon.mod.common.net.messages.server.riding.DismountPokemonPacket
import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdateDriverInputPacket
@@ -142,11 +192,21 @@ import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokem
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.*
import com.cobblemon.mod.common.net.messages.server.trade.*
import com.cobblemon.mod.common.net.messages.server.trade.AcceptTradeRequestPacket
import com.cobblemon.mod.common.net.messages.server.trade.CancelTradePacket
import com.cobblemon.mod.common.net.messages.server.trade.ChangeTradeAcceptancePacket
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
import com.cobblemon.mod.common.net.messages.server.trade.PerformTradePacket
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket
import com.cobblemon.mod.common.net.serverhandling.ChallengeHandler
import com.cobblemon.mod.common.net.serverhandling.ChallengeResponseHandler
import com.cobblemon.mod.common.net.serverhandling.RequestInteractionsHandler
import com.cobblemon.mod.common.net.serverhandling.battle.*
import com.cobblemon.mod.common.net.serverhandling.battle.BattleSelectActionsHandler
import com.cobblemon.mod.common.net.serverhandling.battle.RemoveSpectatorHandler
import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
import com.cobblemon.mod.common.net.serverhandling.battle.TeamLeaveHandler
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestHandler
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestResponseHandler
import com.cobblemon.mod.common.net.serverhandling.behaviour.DamageOnCollisionPacketHandler
import com.cobblemon.mod.common.net.serverhandling.behaviour.SetEntityBehaviourHandler
import com.cobblemon.mod.common.net.serverhandling.block.AdjustBlockEntityViewerCountHandler
@@ -172,7 +232,11 @@ import com.cobblemon.mod.common.net.serverhandling.pasture.UnpasturePokemonHandl
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.FinishScanningHandler
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.StartScanningHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.interact.InteractPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.*
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.ServerboundUpdateRidingStateHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetActiveMarkHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetItemHiddenHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetMarkingsHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetNicknameHandler
import com.cobblemon.mod.common.net.serverhandling.riding.DismountPokemonPacketHandler
import com.cobblemon.mod.common.net.serverhandling.riding.DriverInputPacketHandler
import com.cobblemon.mod.common.net.serverhandling.riding.ServerboundUpdateRiderRotationHandler
@@ -186,7 +250,12 @@ import com.cobblemon.mod.common.net.serverhandling.storage.party.MovePartyPokemo
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.*
import com.cobblemon.mod.common.net.serverhandling.trade.*
import com.cobblemon.mod.common.net.serverhandling.trade.AcceptTradeRequestHandler
import com.cobblemon.mod.common.net.serverhandling.trade.CancelTradeHandler
import com.cobblemon.mod.common.net.serverhandling.trade.ChangeTradeAcceptanceHandler
import com.cobblemon.mod.common.net.serverhandling.trade.OfferTradeHandler
import com.cobblemon.mod.common.net.serverhandling.trade.PerformTradeHandler
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler
import com.cobblemon.mod.common.util.server
import net.minecraft.server.level.ServerPlayer
@@ -332,7 +401,6 @@ object CobblemonNetwork {
// Data registries
list.add(PacketRegisterInfo(AbilityRegistrySyncPacket.ID, AbilityRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(CobblemonMechanicsSyncPacket.ID, CobblemonMechanicsSyncPacket::decode, CobblemonMechanicsSyncHandler))
list.add(PacketRegisterInfo(PokemonInteractionsSyncPacket.ID, PokemonInteractionsSyncPacket::decode, PokemonInteractionsSyncHandler))
list.add(PacketRegisterInfo(MovesRegistrySyncPacket.ID, MovesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(BerryRegistrySyncPacket.ID, BerryRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(SpeciesRegistrySyncPacket.ID, SpeciesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
@@ -12,10 +12,10 @@ import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.pokemon.requirement.OwnerQueryRequirement
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.net.messages.client.data.PokemonInteractionsSyncPacket
import com.cobblemon.mod.common.pokemon.adapters.CobblemonRequirementAdapter
import com.cobblemon.mod.common.pokemon.evolution.adapters.LegacyItemConditionWrapperAdapter
import com.cobblemon.mod.common.pokemon.requirements.PokemonPropertiesRequirement
@@ -51,12 +51,7 @@ object PokemonInteractions : JsonDataRegistry<PokemonInteractionSet> {
val speciesInteractions = mutableListOf<PokemonInteractionSet>()
val generalInteractions = mutableListOf<PokemonInteractionSet>()
override fun sync(player: ServerPlayer) {
PokemonInteractionsSyncPacket(
speciesInteractions,
generalInteractions,
).sendToPlayer(player)
}
override fun sync(player: ServerPlayer) {}
override fun reload(data: Map<ResourceLocation, PokemonInteractionSet>) {
speciesInteractions.clear()
@@ -15,10 +15,11 @@ import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
import com.cobblemon.mod.common.pokemon.adapters.CobblemonRequirementAdapter
import com.cobblemon.mod.common.util.*
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.giveOrDropItemStack
import com.cobblemon.mod.common.util.withPlayerValue
import com.cobblemon.mod.common.util.withQueryValue
import net.minecraft.core.registries.Registries
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.sounds.SoundSource
@@ -27,83 +28,30 @@ import net.minecraft.world.entity.EquipmentSlot
import net.minecraft.world.entity.item.ItemEntity
import net.minecraft.world.item.ItemStack
/**
* A
*/
data class PokemonInteractionSet(
val requirements: List<Requirement> = listOf(),
val interactions: List<PokemonInteraction> = listOf(),
) {
fun encode(buffer: FriendlyByteBuf) {
buffer.writeCollection(requirements) { it, requirement ->
CobblemonRequirementAdapter.encode(requirement, it)
}
buffer.writeCollection(interactions) { it, interaction ->
interaction.encode(it)
}
}
companion object {
fun decode(buffer: FriendlyByteBuf): PokemonInteractionSet {
val requirements = buffer.readList { it ->
CobblemonRequirementAdapter.decode(it)
}
val interactions = buffer.readList { it ->
PokemonInteraction.decode(it)
}
return PokemonInteractionSet(
requirements,
interactions,
)
}
}
}
val interactions: List<PokemonInteraction> = listOf()
)
data class PokemonInteraction(
val grouping: ResourceLocation,
val requirements: List<Requirement> = listOf(),
val effects: List<InteractionEffect> = listOf(),
val cooldown: ExpressionLike = "0".asExpressionLike()
) {
fun encode(buffer: FriendlyByteBuf) {
buffer.writeResourceLocation(grouping)
buffer.writeCollection(requirements) { it, requirement ->
CobblemonRequirementAdapter.encode(requirement, it)
}
buffer.writeExpressionLike(cooldown)
}
companion object {
fun decode(buffer: FriendlyByteBuf): PokemonInteraction {
val grouping = buffer.readResourceLocation()
val requirements = buffer.readList { it ->
CobblemonRequirementAdapter.decode(it)
}
// No need to sync these for now
val effects = emptyList<InteractionEffect>()
val cooldown = buffer.readExpressionLike()
return PokemonInteraction(
grouping,
requirements,
effects,
cooldown,
)
}
}
}
)
interface InteractionEffect {
fun applyEffect(pokemon: PokemonEntity, player: ServerPlayer)
}
class DropItemEffect(val item: ResourceLocation, val amount: IntRange?) : InteractionEffect {
class DropItemEffect(val item: ResourceLocation, val amount: IntRange?): InteractionEffect {
override fun applyEffect(
pokemon: PokemonEntity,
player: ServerPlayer
) {
val item = player.registryAccess().registryOrThrow(Registries.ITEM).get(item) ?: throw IllegalArgumentException(
"Cannot load item with id: $item"
)
val item = player.registryAccess().registryOrThrow(Registries.ITEM).get(item) ?: throw IllegalArgumentException("Cannot load item with id: $item")
val stack = ItemStack(item)
stack.count = amount?.randomOrNull() ?: 1
if (stack.isEmpty)
@@ -120,14 +68,12 @@ class DropItemEffect(val item: ResourceLocation, val amount: IntRange?) : Intera
}
}
class GiveItemEffect(val item: ResourceLocation, val amount: IntRange?) : InteractionEffect {
class GiveItemEffect(val item: ResourceLocation, val amount: IntRange?): InteractionEffect {
override fun applyEffect(
pokemon: PokemonEntity,
player: ServerPlayer
) {
val item = player.registryAccess().registryOrThrow(Registries.ITEM).get(item) ?: throw IllegalArgumentException(
"Cannot load item with id: $item"
)
val item = player.registryAccess().registryOrThrow(Registries.ITEM).get(item) ?: throw IllegalArgumentException("Cannot load item with id: $item")
val stack = ItemStack(item)
stack.count = amount?.randomOrNull() ?: 1
if (stack.isEmpty)
@@ -140,29 +86,14 @@ class GiveItemEffect(val item: ResourceLocation, val amount: IntRange?) : Intera
}
}
class PlaySoundEffect(
val sound: ResourceLocation,
val soundSource: SoundSource?,
val playAround: Boolean = true,
val distance: Double = 64.0,
val volume: Float = 1.0F,
val pitch: Float = 1.0F
) : InteractionEffect {
class PlaySoundEffect(val sound: ResourceLocation, val soundSource: SoundSource?, val playAround: Boolean = true, val distance: Double = 64.0, val volume: Float = 1.0F, val pitch: Float = 1.0F): InteractionEffect {
override fun applyEffect(
pokemon: PokemonEntity,
player: ServerPlayer
) {
val packet = UnvalidatedPlaySoundS2CPacket(
sound,
soundSource ?: SoundSource.NEUTRAL,
pokemon.x,
pokemon.y,
pokemon.z,
volume,
pitch
)
val packet = UnvalidatedPlaySoundS2CPacket(sound, soundSource ?: SoundSource.NEUTRAL, pokemon.x, pokemon.y, pokemon.z, volume, pitch)
if (playAround) {
packet.sendToPlayersAround(pokemon.x, pokemon.y, pokemon.z, distance, pokemon.level().dimension())
packet.sendToPlayersAround( pokemon.x, pokemon.y, pokemon.z, distance, pokemon.level().dimension())
} else {
packet.sendToPlayer(player)
}
@@ -173,7 +104,7 @@ class PlaySoundEffect(
}
}
class ShrinkItemEffect(val amount: Int = 1) : InteractionEffect {
class ShrinkItemEffect(val amount: Int = 1): InteractionEffect {
override fun applyEffect(
pokemon: PokemonEntity,
player: ServerPlayer
@@ -189,7 +120,7 @@ class ShrinkItemEffect(val amount: Int = 1) : InteractionEffect {
}
}
class ScriptEffect(val script: ExpressionLike) : InteractionEffect {
class ScriptEffect(val script: ExpressionLike): InteractionEffect {
override fun applyEffect(
pokemon: PokemonEntity,
player: ServerPlayer
@@ -92,17 +92,13 @@ interface PokemonAndMoveSelectingItem {
}
fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon): Boolean {
if (pokemon.entity == null && stack.`is`(CobblemonItemTags.POKE_FOOD) && pokemon.isFull()) {
return false
if (stack.`is`(CobblemonItemTags.POKE_FOOD)) {
return !pokemon.isFull()
}
return true
}
fun canUseOnBattlePokemon(stack: ItemStack, battlePokemon: BattlePokemon): Boolean {
return bagItem!!.canUse(stack, battlePokemon.actor.battle, battlePokemon)
}
fun canUseOnBattlePokemon(stack: ItemStack, battlePokemon: BattlePokemon): Boolean = bagItem!!.canUse(stack, battlePokemon.actor.battle, battlePokemon)
fun canUseOnMove(stack: ItemStack, pokemon: Pokemon, move: Move): Boolean = canUseOnMove(stack, move)
fun canUseOnMove(stack: ItemStack, move: Move): Boolean
@@ -107,16 +107,13 @@ interface PokemonSelectingItem {
}
fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon): Boolean {
if (pokemon.entity == null && stack.`is`(CobblemonItemTags.POKE_FOOD) && pokemon.isFull()) {
return false
if (stack.`is`(CobblemonItemTags.POKE_FOOD)) {
return !pokemon.isFull()
}
return true
}
fun canUseOnBattlePokemon(stack: ItemStack, battlePokemon: BattlePokemon): Boolean {
return bagItem!!.canUse(stack, battlePokemon.actor.battle, battlePokemon)
}
fun canUseOnBattlePokemon(stack: ItemStack, battlePokemon: BattlePokemon): Boolean = bagItem!!.canUse(stack, battlePokemon.actor.battle, battlePokemon)
fun interactWithSpecificBattle(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon): InteractionResultHolder<ItemStack> {
return if (canUseOnBattlePokemon(stack, battlePokemon)) {
@@ -779,20 +779,6 @@ object MoLangFunctions {
battleStartResult.ifSuccessful { returnValue = it.struct }
return@put returnValue
}
map.put("get_custom_stat") { params ->
val statName = params.getString(0)
val resourceLocation = ResourceLocation.tryParse(statName) ?: return@put DoubleValue.ZERO
val statResourceLocation = BuiltInRegistries.CUSTOM_STAT.get(resourceLocation) ?: return@put DoubleValue.ZERO
val exists = net.minecraft.stats.Stats.CUSTOM.contains(statResourceLocation)
if (!exists) return@put DoubleValue.ZERO
val stat = net.minecraft.stats.Stats.CUSTOM.get(statResourceLocation)
val value = player.stats.getValue(stat)
DoubleValue(value)
}
}
map
}
@@ -1566,9 +1552,8 @@ object MoLangFunctions {
}
map.put("feed_pokemon") { params ->
val amount = params.getDouble(0)
val playSound = params.getBooleanOrNull(1) != false
val playMoodParticles = params.getBooleanOrNull(2) != false
return@put DoubleValue(pokemon.feedPokemon(amount.toInt(), playSound, playMoodParticles))
val playSound = params.getBooleanOrNull(1) ?: true
pokemon.feedPokemon(amount.toInt(), playSound)
}
map.put("behaviour") { pokemon.form.behaviour.struct }
map.put("behavior") { pokemon.form.behaviour.struct } // Inferior
@@ -1754,35 +1739,22 @@ object MoLangFunctions {
pokemon.removeCosmeticItem()
}
map.put("add_marks") { params ->
var appliedMark = false
for (param in params.params) {
val identifier = param.asString().asIdentifierDefaultingNamespace()
val mark = Marks.getByIdentifier(identifier)
if (mark != null) {
pokemon.exchangeMark(mark, true)
appliedMark = true
}
if (mark != null) pokemon.exchangeMark(mark, true)
}
DoubleValue(appliedMark)
}
map.put("add_marks_with_chance") { params ->
var appliedMark = false
for (param in params.params) {
val identifier = param.asString().asIdentifierDefaultingNamespace()
val mark = Marks.getByIdentifier(identifier)
mark?.let {
val probability = it.chance.coerceIn(0F, 1F) * 100
val randomValue = Random.nextDouble(0.0, 100.0)
if (randomValue < probability) {
pokemon.exchangeMark(it, true)
appliedMark = true
}
if (randomValue < probability) pokemon.exchangeMark(it, true)
}
}
DoubleValue(appliedMark)
}
map.put("add_potential_marks") { params ->
for (param in params.params) {
@@ -12,7 +12,6 @@ import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.pokemon.Pokemon
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
/**
* A [Requirement] that expects a [LivingEntity] to be attached to the [Pokemon].
@@ -27,7 +26,7 @@ interface OwnerQueryRequirement : Requirement {
override fun check(pokemon: Pokemon): Boolean {
val owner = pokemon.getOwnerEntity() ?: return false
return when (owner) {
is Player -> {
is ServerPlayer -> {
this.checkPlayer(pokemon, owner)
}
is NPCEntity -> {
@@ -38,13 +37,13 @@ interface OwnerQueryRequirement : Requirement {
}
/**
* Checks if the given [Pokemon] & [Player] satisfies the requirement.
* Checks if the given [Pokemon] & [ServerPlayer] satisfies the requirement.
*
* @param pokemon The [Pokemon] being queried.
* @param owner The [Player] that owns this [Pokemon].
* @param owner The [ServerPlayer] that owns this [Pokemon].
* @return If the requirement was satisfied.
*/
fun checkPlayer(pokemon: Pokemon, owner: Player): Boolean
fun checkPlayer(pokemon: Pokemon, owner: ServerPlayer): Boolean
/**
* Checks if the given [Pokemon] & [NPCEntity] satisfies the requirement.
@@ -12,7 +12,6 @@ package com.cobblemon.mod.common.api.riding.sound
import com.cobblemon.mod.common.api.riding.behaviour.types.composite.CompositeBehaviour
import com.cobblemon.mod.common.api.riding.behaviour.types.composite.CompositeState
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.getIsSubmerged
import com.cobblemon.mod.common.util.resolveDouble
import net.minecraft.client.Minecraft
import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance
@@ -66,21 +65,6 @@ class RideLoopSound(val ride: PokemonEntity, val soundSettings: RideSoundSetting
return
}
// Mute the sound if it's not meant to play for the passenger
if (this.isPassenger && !this.soundSettings.playForPassengers) {
this.volume = 0.0f
return
}
// Mute sounds when submerged unless they support underwater sounds, underwater sounds don't play above water
if (this.ride.getIsSubmerged() && !this.soundSettings.submerged) {
this.volume = 0.0f
return
} else if (!this.ride.getIsSubmerged() && this.soundSettings.submerged) {
this.volume = 0.0f
return
}
// Perform data driven pitch and volume calculation
this.volume = ((soundSettings.volumeExpr.let { ride.runtime.resolveDouble(it) })).toFloat()
this.volume *= this.fade
@@ -27,9 +27,7 @@ data class RideSoundSettings(
val soundLocation: ResourceLocation,
@SerializedName("volumeExpr") private val _volumeExpr: Expression? = "1.0".asExpression(),
@SerializedName("pitchExpr") private val _pitchExpr: Expression? = "1.0".asExpression(),
val playForPassengers: Boolean = true,
val playForNonPassengers: Boolean = false,
val submerged: Boolean = false,
val muffleEnabled: Boolean = false,
@SerializedName("attenuationModel") private val _attenuationModel: RideAttenuationModel? = RideAttenuationModel.NONE
): Encodable {
@@ -48,9 +46,7 @@ data class RideSoundSettings(
buffer.writeResourceLocation(soundLocation)
buffer.writeExpression(volumeExpr)
buffer.writeExpression(pitchExpr)
buffer.writeBoolean(playForPassengers)
buffer.writeBoolean(playForNonPassengers)
buffer.writeBoolean(submerged)
buffer.writeBoolean(muffleEnabled)
buffer.writeEnum(attenuationModel)
}
@@ -61,9 +57,7 @@ data class RideSoundSettings(
val soundLocation = buffer.readResourceLocation()
val volumeExpr = buffer.readExpression()
val pitchExpr = buffer.readExpression()
val playForPassengers = buffer.readBoolean()
val playForNonPassengers = buffer.readBoolean()
val submerged = buffer.readBoolean()
val muffleEnabled = buffer.readBoolean()
val attenuationModel = buffer.readEnum(RideAttenuationModel::class.java)
@@ -71,9 +65,7 @@ data class RideSoundSettings(
soundLocation,
volumeExpr,
pitchExpr,
playForPassengers,
playForNonPassengers,
submerged,
muffleEnabled,
attenuationModel
)
@@ -44,7 +44,11 @@ abstract class SpawnAction<R>(
spawnablePosition.applyInfluences { it.affectAction(this) }
val result = run()
future.complete(result)
if (result != null) {
future.complete(result)
} else {
future.completeExceptionally(Exception("Nothing was spawned."))
}
return result
}
@@ -61,9 +61,7 @@ open class SpawnBaitInfluence(val effects: List<SpawnBait.Effect>, val onUsed: (
val baitEVStat = effects.firstOrNull { it.type == Effects.EV }?.subcategory?.path?.let { Stats.getStat(it) }
if (detailSpecies != null && baitEVStat != null) {
val detailAspects = detail.pokemon.aspects
val formData = detailSpecies.getForm(detailAspects)
val evYieldValue = formData.evYield[baitEVStat]?.toFloat() ?: 0f
val evYieldValue = detailSpecies.evYield[baitEVStat]?.toFloat() ?: 0f
return when {
evYieldValue > 0 -> {
markUsed()
@@ -85,9 +83,7 @@ open class SpawnBaitInfluence(val effects: List<SpawnBait.Effect>, val onUsed: (
val baitTypingEffect = baitEffect?.subcategory?.path?.let { ElementalTypes.get(it) }
if (detailSpecies != null && baitTypingEffect != null) {
val detailAspects = detail.pokemon.aspects
val formData = detailSpecies.getForm(detailAspects)
val isMatchingType = formData.types.contains(baitTypingEffect)
val isMatchingType = detailSpecies.types.contains(baitTypingEffect)
return when {
isMatchingType -> {
markUsed()
@@ -104,9 +100,6 @@ open class SpawnBaitInfluence(val effects: List<SpawnBait.Effect>, val onUsed: (
val detailSpecies = detail.pokemon.species?.let { PokemonSpecies.getByName(it) }
if (detailSpecies != null) {
val detailAspects = detail.pokemon.aspects
val formData = detailSpecies.getForm(detailAspects)
// Collect all the egg group effects
val eggGroupEffects = effects.filter { it.type == Effects.EGG_GROUP }
@@ -118,7 +111,7 @@ open class SpawnBaitInfluence(val effects: List<SpawnBait.Effect>, val onUsed: (
LOGGER.warn("Unknown egg group identifier: $effectEggGroupKey")
return@firstOrNull false
}
formData.eggGroups.contains(eggGroup)
detailSpecies.eggGroups.contains(eggGroup)
}
if (matchingEffect != null) {
@@ -8,58 +8,30 @@
package com.cobblemon.mod.common.api.stats
import com.cobblemon.mod.common.Cobblemon
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.resources.ResourceLocation
import net.minecraft.stats.StatFormatter
object CobblemonStats {
val stats = mutableMapOf<String, CobblemonStat>()
val stats = mutableMapOf<String, ResourceLocation>()
@JvmField
var CAPTURED: CobblemonStat = CobblemonStat("captured")
@JvmField
val SHINIES_CAPTURED: CobblemonStat = CobblemonStat("shinies_captured")
@JvmField
val RELEASED: CobblemonStat = CobblemonStat("released")
@JvmField
val EVOLVED: CobblemonStat = CobblemonStat("evolved")
@JvmField
val LEVEL_UP: CobblemonStat = CobblemonStat("level_up")
@JvmField
val BATTLES_WON: CobblemonStat = CobblemonStat("battles_won")
@JvmField
val BATTLES_LOST: CobblemonStat = CobblemonStat("battles_lost")
@JvmField
val BATTLES_FLED: CobblemonStat = CobblemonStat("battles_fled")
@JvmField
val BATTLES_TOTAL: CobblemonStat = CobblemonStat("battles_total")
@JvmField
val DEX_ENTRIES: CobblemonStat = CobblemonStat("dex_entries")
@JvmField
val EGGS_COLLECTED: CobblemonStat = CobblemonStat("eggs_collected")
@JvmField
val EGGS_HATCHED: CobblemonStat = CobblemonStat("eggs_hatched")
@JvmField
val TRADED: CobblemonStat = CobblemonStat("traded")
@JvmField
val FOSSILS_REVIVED: CobblemonStat = CobblemonStat("fossils_revived")
@JvmField
val TIMES_RIDDEN: CobblemonStat = CobblemonStat("times_ridden")
@JvmField
val ROD_CASTS: CobblemonStat = CobblemonStat("rod_casts")
@JvmField
val REEL_INS: CobblemonStat = CobblemonStat("reel_ins")
@JvmField
val POKEMON_INTERACTED_WITH: CobblemonStat = CobblemonStat("pokemon_interacted_with")
@JvmField
val RIDING_LAND: CobblemonStat = CobblemonStat("riding_land", StatFormatter.DISTANCE)
@JvmField
val RIDING_AIR: CobblemonStat = CobblemonStat("riding_air", StatFormatter.DISTANCE)
@JvmField
val RIDING_LIQUID: CobblemonStat = CobblemonStat("riding_liquid", StatFormatter.DISTANCE)
//TODO block, stats (interact, gimmi)
var CAPTURED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "captured") //makeCustomStat("captured", StatFormatter.DEFAULT)
val SHINIES_CAPTURED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "shinies_captured") //makeCustomStat("shinies_captured", StatFormatter.DEFAULT)
val RELEASED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "released") //makeCustomStat("released", StatFormatter.DEFAULT)
val EVOLVED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "evolved") //makeCustomStat("evolved", StatFormatter.DEFAULT)
val LEVEL_UP: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "level_up") //makeCustomStat("level_up", StatFormatter.DEFAULT)
val BATTLES_WON: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "battles_won") //makeCustomStat("battles_won", StatFormatter.DEFAULT)
val BATTLES_LOST: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "battles_lost") //makeCustomStat("battles_lost", StatFormatter.DEFAULT)
val BATTLES_FLED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "battles_fled") //makeCustomStat("battles_fled", StatFormatter.DEFAULT)
val BATTLES_TOTAL: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "battles_total") //makeCustomStat("battles_total", StatFormatter.DEFAULT)
val DEX_ENTRIES: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "dex_entries") //makeCustomStat("dex_entries", StatFormatter.DEFAULT)
val EGGS_COLLECTED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "eggs_collected") //makeCustomStat("eggs_collected", StatFormatter.DEFAULT)
val EGGS_HATCHED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "eggs_hatched") //makeCustomStat("eggs_hatched", StatFormatter.DEFAULT)
val TRADED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "traded") //makeCustomStat("traded", StatFormatter.DEFAULT)
val FOSSILS_REVIVED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "fossils_revived") //makeCustomStat("fossils_revived", StatFormatter.DEFAULT)
val TIMES_RIDDEN: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "times_ridden")
val ROD_CASTS: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "rod_casts")
val REEL_INS: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "reel_ins")
val POKEMON_INTERACTED_WITH: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "pokemon_interacted_with") //makeCustomStat("pokemon_interacted_with", StatFormatter.DEFAULT)
//TODO block, stats (interact, gimmi), riding (styles?)
fun registerStats() {
stats["captured"] = CAPTURED
@@ -80,22 +52,5 @@ object CobblemonStats {
stats["rod_casts"] = ROD_CASTS
stats["reel_ins"] = REEL_INS
stats["pokemon_interacted_with"] = POKEMON_INTERACTED_WITH
stats["riding_land"] = RIDING_LAND
stats["riding_air"] = RIDING_AIR
stats["riding_liquid"] = RIDING_LIQUID
}
@JvmStatic
fun getStat(cobblemonStat: CobblemonStat) : ResourceLocation {
val resourceLocation = cobblemonStat.resourceLocation
val stat = BuiltInRegistries.CUSTOM_STAT.get(resourceLocation)
if (stat == null) {
Cobblemon.LOGGER.error("Could not find stat with id {}", resourceLocation)
}
return stat ?: throw NullPointerException("Could not find stat with id $resourceLocation")
}
data class CobblemonStat(val path: String, val formatter: StatFormatter = StatFormatter.DEFAULT) {
val resourceLocation: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", path);
}
}
@@ -1,27 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.net.data
import com.cobblemon.mod.common.api.interaction.PokemonInteractions
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.net.messages.client.data.PokemonInteractionsSyncPacket
import net.minecraft.client.Minecraft
object PokemonInteractionsSyncHandler : ClientNetworkPacketHandler<PokemonInteractionsSyncPacket> {
override fun handle(
packet: PokemonInteractionsSyncPacket,
client: Minecraft,
) {
PokemonInteractions.speciesInteractions.clear()
PokemonInteractions.speciesInteractions.addAll(packet.speciesInteractions)
PokemonInteractions.generalInteractions.clear()
PokemonInteractions.generalInteractions.addAll(packet.generalInteractions)
}
}
@@ -8,8 +8,6 @@
package com.cobblemon.mod.common.client.persisted
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.Cobblemon.LOGGER
import com.cobblemon.mod.common.config.CobblemonConfig
import java.io.BufferedReader
import java.io.BufferedWriter
@@ -33,14 +31,7 @@ object ClientPersistedData {
fun readSnapshotsData() : SnapshotAcknowledgementData? {
if (snapshotsPath.exists()) {
BufferedReader(InputStreamReader(FileInputStream(snapshotsPath.toFile()))).use { reader ->
try {
return gson.fromJson(reader, SnapshotAcknowledgementData::class.java)
} catch (exception: Exception) {
LOGGER.error("Failed to load snapshots.json... Resetting File")
val data = SnapshotAcknowledgementData(Cobblemon.VERSION, false)
writeSnapshotsData(data)
return data
}
return gson.fromJson(reader, SnapshotAcknowledgementData::class.java)
}
}
@@ -55,23 +46,16 @@ object ClientPersistedData {
fun readRidingPerspectivesData() : RidingPerspectiveData? {
if (ridingPerspectivesPath.exists()) {
BufferedReader(InputStreamReader(FileInputStream(ridingPerspectivesPath.toFile()))).use { reader ->
try {
return gson.fromJson(reader, RidingPerspectiveData::class.java)
} catch (exception: Exception) {
LOGGER.error("Failed to load riding_perspectives.json... Resetting File")
val data = RidingPerspectiveData()
saveRidingPerspectivesData(data)
return data
}
return gson.fromJson(reader, RidingPerspectiveData::class.java)
}
}
return null
}
fun saveRidingPerspectivesData(data: RidingPerspectiveData) {
fun saveRidingPerspectivesData() {
ridingPerspectivesPath.toFile().parentFile.mkdirs()
BufferedWriter(FileWriter(ridingPerspectivesPath.toFile())).use { writer -> gson.toJson(data, writer) }
BufferedWriter(FileWriter(ridingPerspectivesPath.toFile())).use { writer -> gson.toJson(ridingPerspectives, writer) }
}
data class SnapshotAcknowledgementData(val version: String, val dontShowAgain: Boolean)
@@ -80,7 +64,7 @@ object ClientPersistedData {
) {
fun updatePerspective(key: ResourceLocation, cameraType: CameraType) {
perspectives[key] = cameraType
saveRidingPerspectivesData(this)
saveRidingPerspectivesData()
}
}
}
@@ -9,10 +9,7 @@
package com.cobblemon.mod.common.entity.ai
import com.bedrockk.molang.Expression
import com.cobblemon.mod.common.CobblemonMemories
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.getMemorySafely
import com.cobblemon.mod.common.util.mainThreadRuntime
import com.cobblemon.mod.common.util.resolveInt
import com.cobblemon.mod.common.util.withQueryValue
@@ -32,23 +29,12 @@ object FleeFromAttackerTask {
Trigger { _, entity, _ ->
val hurtByEntity = it.get(hurtByEntity)
val avoidTarget = it.tryGet(avoidTarget).orElse(null)
if (avoidTarget != null && avoidTarget == hurtByEntity) {
if (avoidTarget != null && avoidTarget == hurtByEntity.uuid) {
return@Trigger false
}
mainThreadRuntime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
val avoidDurationTicks = mainThreadRuntime.resolveInt(avoidDurationTicks)
val pokemonEntity = entity as? PokemonEntity
pokemonEntity?.let {
it.after(1.0f) {
it.playMoodParticle("mood_stress")
}
}
entity.brain.setMemoryWithExpiry(MemoryModuleType.AVOID_TARGET, hurtByEntity, avoidDurationTicks.toLong())
return@Trigger true
}
}
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common.entity.ai
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.ai.behavior.OneShot
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
@@ -25,10 +24,6 @@ object GetAngryAtAttackerTask {
Trigger { _, entity, _ ->
val hurtByEntity = it.get(hurtByEntity)
val angryAt = it.tryGet(angryAt).orElse(null)
if (angryAt == null && hurtByEntity != null) {
(entity as PokemonEntity?)?.playMoodParticle("mood_anger_steam")
}
if (angryAt != null && angryAt == hurtByEntity.uuid) {
return@Trigger false
}
@@ -802,14 +802,13 @@ class PokeRodFishingBobberEntity(type: EntityType<out PokeRodFishingBobberEntity
spawnAction.complete()
val result = spawnAction.future
val resultingSpawn = result.get()
if (resultingSpawn == null) {
if (result.isCompletedExceptionally) {
noBite(player)
return false
}
var spawnedPokemon: PokemonEntity? = null
val resultingSpawn = result.get()
if (resultingSpawn is EntitySpawnResult) {
for (entity in resultingSpawn.entities) {
@@ -82,7 +82,6 @@ import com.cobblemon.mod.common.entity.pokemon.effects.EffectTracker
import com.cobblemon.mod.common.entity.pokemon.effects.IllusionEffect
import com.cobblemon.mod.common.net.messages.client.OpenBehaviourEditorPacket
import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimationPacket
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokemonPacket
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
@@ -420,9 +419,6 @@ open class PokemonEntity(
var occupiedSeats = arrayOfNulls<Entity>(seats.size)
var moodParticleLock = false
var playedZeroStaminaParticle = false
init {
delegate.initialize(this)
delegate.changePokemon(pokemon)
@@ -837,28 +833,6 @@ open class PokemonEntity(
return future
}
fun playMoodParticle(particleName: String) {
if (moodParticleLock) return
cry()
SpawnSnowstormEntityParticlePacket(
cobblemonResource(particleName),
id,
listOf("head", "top")
).sendToPlayersAround(
x,
y,
z,
64.0,
level().dimension()
)
moodParticleLock = true
after(5.0f) {
moodParticleLock = false
}
}
override fun saveWithoutId(nbt: CompoundTag): CompoundTag {
val tethering = this.tethering
if (tethering != null) {
@@ -1234,13 +1208,14 @@ open class PokemonEntity(
}
}
if (hand == InteractionHand.MAIN_HAND) {
if (player.isShiftKeyDown && player is ServerPlayer) {
if (hand == InteractionHand.MAIN_HAND && player is ServerPlayer) {
if (player.isShiftKeyDown) {
showInteractionWheel(player, itemStack)
return InteractionResult.sidedSuccess(level().isClientSide)
}
else if (this.ownerUUID == player.uuid && this.attemptItemInteraction(player, player.getItemInHand(hand))) {
return InteractionResult.sidedSuccess(level().isClientSide)
else if (pokemon.getOwnerPlayer() == player) {
// TODO #105
if (this.attemptItemInteraction(player, player.getItemInHand(hand))) return InteractionResult.SUCCESS
}
}
@@ -1307,7 +1282,7 @@ open class PokemonEntity(
}
override fun shouldBeSaved(): Boolean {
if (ownerUUID == null && !pokemon.isNPCOwned() && (Cobblemon.config.savePokemonToWorld || isPersistenceRequired)) {
if (ownerUUID == null && !pokemon.isNPCOwned() && (Cobblemon.config.savePokemonToWorld || isPersistenceRequired || this.pokemon.canDropHeldItem)) {
CobblemonEvents.POKEMON_ENTITY_SAVE_TO_WORLD.postThen(PokemonEntitySaveToWorldEvent(this)) {
return true
}
@@ -1416,24 +1391,18 @@ open class PokemonEntity(
return bagItemLike.handleInteraction(player, battlePokemon, stack)
}
if (this.isBusy) {
if (player !is ServerPlayer || this.isBusy) {
return false
}
val interaction = PokemonInteractions.findInteraction(this)
if (interaction != null && !pokemon.isOnInteractionCooldown(interaction.grouping)) {
if (player is ServerPlayer) {
interaction.effects.forEach { it.applyEffect(this, player) }
pokemon.interactionCooldowns.put(interaction.grouping, runtime.resolveInt(interaction.cooldown))
}
interaction.effects.forEach { it.applyEffect(this, player) }
pokemon.interactionCooldowns.put(interaction.grouping, runtime.resolveInt(interaction.cooldown))
return true
}
if (player !is ServerPlayer) {
return false
}
// Evolution item logic
if (pokemon.getOwnerPlayer() == player) {
val context = ItemInteractionEvolution.ItemInteractionContext(stack, player.level())
@@ -2239,8 +2208,6 @@ open class PokemonEntity(
ifRidingAvailable { _, _, state ->
state.stamina.set(entityData.get(RIDE_STAMINA))
}
playedZeroStaminaParticle = false
}
}
@@ -2269,26 +2236,12 @@ open class PokemonEntity(
override fun tickRidden(driver: Player, movementInput: Vec3) {
super.tickRidden(driver, movementInput)
ifRidingAvailable { behaviour, settings, state ->
behaviour.tick(settings, state, this, driver, movementInput)
if (entityData.get(RIDE_STAMINA) == -1F) {
state.stamina.set(1F, forced = true)
}
if (!level().isClientSide) {
val stamina = state.stamina.get()
if (stamina <= 0f) {
if (!playedZeroStaminaParticle) {
playMoodParticle("mood_stress")
playedZeroStaminaParticle = true
}
} else {
playedZeroStaminaParticle = false
}
}
if (!this.level().isClientSide) {
val pose = behaviour.pose(settings, state, this)
if (pose != this.entityData.get(POSE_TYPE)) {
@@ -44,11 +44,6 @@ class DefendOwnerSensor : Sensor<PokemonEntity>(10) {
return@findClosest false
}.map { mob -> mob as LivingEntity }
val previousAttacker = entity.brain.getMemorySafely(CobblemonMemories.NEAREST_VISIBLE_ATTACKER)
if (nearestAttacker.isPresent && previousAttacker.isEmpty) {
entity.playMoodParticle("mood_anger_steam")
}
entity.brain.setMemory(CobblemonMemories.NEAREST_VISIBLE_ATTACKER, nearestAttacker)
}
}
@@ -9,7 +9,6 @@
package com.cobblemon.mod.common.entity.pokemon.ai.tasks
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.getMemorySafely
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.Mob
import net.minecraft.world.entity.ai.behavior.OneShot
@@ -61,12 +60,7 @@ object AttackHostileMobsTask {
}
if (hostile != null) {
if (currentTarget == null) {
(entity as? PokemonEntity)?.playMoodParticle("mood_anger_steam")
}
entity.brain.setMemory(MemoryModuleType.ATTACK_TARGET, hostile)
true
} else {
false
@@ -91,7 +91,7 @@ class EatHeldItemTask(entity: PokemonEntity) : Behavior<PokemonEntity>(
}
this.timelastEaten = time
if (itemConfig != null && itemConfig.fullnessValue > 0) {
entity.pokemon.feedPokemon(itemConfig.fullnessValue, false, false)
entity.pokemon.feedPokemon(itemConfig.fullnessValue, false)
}
// Check if the result item is something that should be dropped
resultItemStack = entity.pokemon.heldItem()
@@ -30,13 +30,21 @@ import com.cobblemon.mod.common.api.events.battles.BattleStartedEvent
import com.cobblemon.mod.common.api.events.battles.BattleVictoryEvent
import com.cobblemon.mod.common.api.events.fishing.PokerodCastEvent
import com.cobblemon.mod.common.api.events.fishing.PokerodReelEvent
import com.cobblemon.mod.common.api.events.pokemon.*
import com.cobblemon.mod.common.api.events.pokemon.CollectEggEvent
import com.cobblemon.mod.common.api.events.pokemon.FossilRevivedEvent
import com.cobblemon.mod.common.api.events.pokemon.HatchEggEvent
import com.cobblemon.mod.common.api.events.pokemon.LevelUpEvent
import com.cobblemon.mod.common.api.events.pokemon.PokemonCapturedEvent
import com.cobblemon.mod.common.api.events.pokemon.PokemonGainedEvent
import com.cobblemon.mod.common.api.events.pokemon.RidePokemonEvent
import com.cobblemon.mod.common.api.events.pokemon.TradeEvent
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEvent
import com.cobblemon.mod.common.api.events.storage.ReleasePokemonEvent
import com.cobblemon.mod.common.api.stats.CobblemonStats.getStat
import com.cobblemon.mod.common.util.getPlayer
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import java.util.*
import java.util.UUID
object StatHandler : EventHandler {
override fun registerListeners() {
@@ -92,13 +100,13 @@ object StatHandler : EventHandler {
fun onBattleStart(event : BattleStartedEvent) {
event.battle.players.forEach { player ->
player.awardStat(getStat(Cobblemon.statistics.BATTLES_TOTAL))
player.awardStat(this.getStat(getStat(Cobblemon.statistics.BATTLES_TOTAL)))
}
}
fun onDexEntryGain(event : PokemonGainedEvent) {
val player = event.pokemon.getOwnerPlayer()
player?.awardStat(getStat(Cobblemon.statistics.DEX_ENTRIES))
player?.awardStat(getStat(getStat(Cobblemon.statistics.DEX_ENTRIES)))
}
fun onCollectEgg(event : CollectEggEvent) {
@@ -131,4 +139,12 @@ object StatHandler : EventHandler {
fun onReelIn(event : PokerodReelEvent) {
event.player.awardStat(getStat(Cobblemon.statistics.REEL_INS))
}
fun getStat(resourceLocation: ResourceLocation) : ResourceLocation {
val stat = BuiltInRegistries.CUSTOM_STAT.get(resourceLocation)
if (stat == null) {
Cobblemon.LOGGER.error("Could not find stat with id {}", resourceLocation)
}
return stat ?: throw NullPointerException("Could not find stat with id $resourceLocation")
}
}
@@ -13,9 +13,7 @@ import com.cobblemon.mod.common.api.apricorn.Apricorn
import com.cobblemon.mod.common.api.item.PokemonSelectingItem
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.client.pot.CookingQuality
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.network.chat.Component
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
@@ -93,9 +91,7 @@ class AprijuiceItem(val type: Apricorn): CobblemonItem(Properties().stacksTo(16)
return InteractionResultHolder.fail(stack)
}
if (!pokemon.feedPokemon(1)) {
return InteractionResultHolder.fail(stack)
}
pokemon.feedPokemon(1)
val boosts = getBoosts(stack)
pokemon.addRideBoosts(boosts.mapValues { it.value.toFloat() })
@@ -96,9 +96,8 @@ class PokePuffItem : Item(Properties().stacksTo(64)), PokemonSelectingItem {
return InteractionResultHolder.fail(stack)
}
if (!pokemon.feedPokemon(4)) {
return InteractionResultHolder.fail(stack)
}
// Feed the Pokémon 4 fullness points
pokemon.feedPokemon(4)
val friendshipChange = PokePuffUtils.calculateFriendshipChange(stack, pokemon.nature)
@@ -13,7 +13,10 @@ import net.minecraft.resources.ResourceLocation
import net.minecraft.world.entity.EquipmentSlot
import net.minecraft.world.item.Equipable
class WearableItem(val name: String): CobblemonItem(Properties()), Equipable {
class WearableItem(
val name: String,
val armorEquipmentSlot: EquipmentSlot = EquipmentSlot.HEAD,
): CobblemonItem(Properties()), Equipable {
companion object {
const val MODEL_PATH = "item/wearable"
}
@@ -21,5 +24,7 @@ class WearableItem(val name: String): CobblemonItem(Properties()), Equipable {
fun getModel3d(): ResourceLocation = cobblemonResource("${MODEL_PATH}/${this.name}")
fun getModel2d(): ResourceLocation = cobblemonResource(this.name)
override fun getEquipmentSlot(): EquipmentSlot { return EquipmentSlot.HEAD }
override fun getEquipmentSlot(): EquipmentSlot {
return armorEquipmentSlot
}
}
@@ -54,16 +54,14 @@ class FriendshipRaisingBerryItem(block: BerryBlock, val stat: Stat) : BerryItem(
val evLowerAmount = max(genericRuntime.resolveInt(CobblemonMechanics.berries.evLowerAmount), 0)
val decreasedEVs = pokemon.evs.add(stat, -evLowerAmount, ItemEvSource(player, stack, pokemon)) != 0
if (!increasedFriendship && !decreasedEVs) {
return InteractionResultHolder.pass(stack)
}
return if (increasedFriendship || decreasedEVs) {
pokemon.feedPokemon(1)
if (!pokemon.feedPokemon(1)) {
return InteractionResultHolder.fail(stack)
stack.consume(1, player)
InteractionResultHolder.success(stack)
} else {
InteractionResultHolder.pass(stack)
}
stack.consume(1, player)
return InteractionResultHolder.success(stack)
}
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
@@ -54,10 +54,7 @@ class HealingBerryItem(block: BerryBlock, val amount: () -> ExpressionLike): Ber
return InteractionResultHolder.fail(stack)
}
if (!pokemon.feedPokemon(1)) {
return InteractionResultHolder.fail(stack)
}
pokemon.feedPokemon(1)
pokemon.currentHealth = Integer.min(pokemon.currentHealth + genericRuntime.resolveInt(amount(), pokemon), pokemon.maxHealth)
stack.consume(1, player)
return InteractionResultHolder.success(stack)
@@ -65,7 +62,7 @@ class HealingBerryItem(block: BerryBlock, val amount: () -> ExpressionLike): Ber
override fun applyToBattlePokemon(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon) {
super.applyToBattlePokemon(player, stack, battlePokemon)
battlePokemon.originalPokemon.feedPokemon(1, playMoodParticle = false)
battlePokemon.originalPokemon.feedPokemon(1)
}
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
@@ -48,26 +48,21 @@ class PPRestoringBerryItem(block: BerryBlock, val amount: () -> ExpressionLike):
&& super.canUseOnPokemon(stack, pokemon)
override fun applyToPokemon(player: ServerPlayer, stack: ItemStack, pokemon: Pokemon, move: Move) {
if (!canUseOnPokemon(stack, pokemon) && canUseOnMove(stack, move)) {
return
}
if (canUseOnPokemon(stack, pokemon) && canUseOnMove(stack, move)) {
pokemon.feedPokemon(1)
val moveToRecover = pokemon.moveSet.find { it.template == move.template }
if (moveToRecover != null && moveToRecover.currentPp < moveToRecover.maxPp) {
moveToRecover.currentPp =
min(moveToRecover.maxPp, moveToRecover.currentPp + genericRuntime.resolveInt(amount(), pokemon))
if (!pokemon.feedPokemon(1)) {
return
}
val moveToRecover = pokemon.moveSet.find { it.template == move.template }
if (moveToRecover != null && moveToRecover.currentPp < moveToRecover.maxPp) {
moveToRecover.currentPp =
min(moveToRecover.maxPp, moveToRecover.currentPp + genericRuntime.resolveInt(amount(), pokemon))
stack.consume(1, player)
stack.consume(1, player)
}
}
}
override fun applyToBattlePokemon(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon, move: Move) {
super.applyToBattlePokemon(player, stack, battlePokemon, move)
battlePokemon.originalPokemon.feedPokemon(1, playMoodParticle = false)
battlePokemon.originalPokemon.feedPokemon(1)
}
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
@@ -59,9 +59,7 @@ class PortionHealingBerryItem(block: BerryBlock, val canCauseConfusion: Boolean,
}
// count these berries as multiple feedings due to the amount they heal
if (!pokemon.feedPokemon(5)) {
return InteractionResultHolder.fail(stack)
}
pokemon.feedPokemon(5)
var amount = Integer.min(pokemon.currentHealth + (genericRuntime.resolveFloat(portion(), pokemon) * pokemon.maxHealth).toInt(), pokemon.maxHealth)
CobblemonEvents.POKEMON_HEALED.postThen(PokemonHealedEvent(pokemon, amount, this), { cancelledEvent -> return InteractionResultHolder.fail(stack)}) { event ->
@@ -75,7 +73,7 @@ class PortionHealingBerryItem(block: BerryBlock, val canCauseConfusion: Boolean,
override fun applyToBattlePokemon(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon) {
super.applyToBattlePokemon(player, stack, battlePokemon)
battlePokemon.originalPokemon.feedPokemon(5, playMoodParticle = false)
battlePokemon.originalPokemon.feedPokemon(5)
}
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
@@ -58,23 +58,19 @@ class StatusCuringBerryItem(block: BerryBlock, vararg val status: Status): Berry
stack: ItemStack,
pokemon: Pokemon
): InteractionResultHolder<ItemStack>? {
if (!canUseOnPokemon(stack, pokemon)) {
return InteractionResultHolder.fail(stack)
return if (canUseOnPokemon(stack, pokemon)) {
pokemon.feedPokemon(1)
pokemon.status = null
stack.consume(1, player)
InteractionResultHolder.success(stack)
} else {
InteractionResultHolder.fail(stack)
}
if (!pokemon.feedPokemon(1)) {
return InteractionResultHolder.fail(stack)
}
pokemon.status = null
stack.consume(1, player)
return InteractionResultHolder.success(stack)
}
override fun applyToBattlePokemon(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon) {
super.applyToBattlePokemon(player, stack, battlePokemon)
battlePokemon.originalPokemon.feedPokemon(1, playMoodParticle = false)
battlePokemon.originalPokemon.feedPokemon(1)
}
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
@@ -53,10 +53,7 @@ class BerryJuiceItem : CobblemonItem(Properties()), PokemonSelectingItem, Healin
if (!canUseOnPokemon(stack, pokemon)) {
return InteractionResultHolder.fail(stack)
}
if (!pokemon.feedPokemon(1)) {
return InteractionResultHolder.fail(stack)
}
pokemon.feedPokemon(1)
var amount = Integer.min(pokemon.currentHealth + 20, pokemon.maxHealth)
CobblemonEvents.POKEMON_HEALED.postThen(PokemonHealedEvent(pokemon, amount, this), { cancelledEvent -> return InteractionResultHolder.fail(stack)}) { event ->
@@ -77,9 +74,7 @@ class BerryJuiceItem : CobblemonItem(Properties()), PokemonSelectingItem, Healin
override fun applyToBattlePokemon(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon) {
super.applyToBattlePokemon(player, stack, battlePokemon)
battlePokemon.originalPokemon.feedPokemon(1, playMoodParticle = false)
battlePokemon.originalPokemon.feedPokemon(1)
if (!player.hasInfiniteMaterials()) {
val woodenBowlItemStack = ItemStack(Items.BOWL)
if (!player.inventory.add(woodenBowlItemStack)) {
@@ -33,10 +33,7 @@ class FreshStartMochiItem : CobblemonItem(Properties()), PokemonSelectingItem {
return InteractionResultHolder.fail(stack)
}
if (!pokemon.feedPokemon(1)) {
return InteractionResultHolder.fail(stack)
}
pokemon.feedPokemon(1)
pokemon.evs.forEach {
pokemon.evs[it.key] = 0
}
@@ -24,10 +24,10 @@ class MochiItem(stat: Stats): EVIncreaseItem(stat, 4) {
return InteractionResultHolder.fail(stack)
}
if (!pokemon.feedPokemon(1)) {
return InteractionResultHolder.fail(stack)
}
pokemon.feedPokemon(1)
stack.consume(1, player)
return super.applyToPokemon(player, stack, pokemon)
}
}
@@ -1,48 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.net.messages.client.data
import com.cobblemon.mod.common.api.interaction.PokemonInteractionSet
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.network.RegistryFriendlyByteBuf
class PokemonInteractionsSyncPacket(
val speciesInteractions: List<PokemonInteractionSet>,
val generalInteractions: List<PokemonInteractionSet>,
) : NetworkPacket<PokemonInteractionsSyncPacket> {
override val id = ID
override fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeCollection(speciesInteractions) { it, speciesInteraction ->
speciesInteraction.encode(it)
}
buffer.writeCollection(generalInteractions) { it, generalInteraction ->
generalInteraction.encode(it)
}
}
companion object {
val ID = cobblemonResource("pokemon_interactions_sync")
fun decode(buffer: RegistryFriendlyByteBuf): PokemonInteractionsSyncPacket {
val speciesInteractions = buffer.readList { it ->
PokemonInteractionSet.decode(it)
}
val generalInteractions = buffer.readList { it ->
PokemonInteractionSet.decode(it)
}
return PokemonInteractionsSyncPacket(
speciesInteractions,
generalInteractions,
)
}
}
}
@@ -21,9 +21,7 @@ class PokemonStateUpdatePacket(pokemon: () -> Pokemon?, value: PokemonState): Si
value.writeToBuffer(buffer)
}
override fun set(pokemon: Pokemon, value: PokemonState) {
pokemon.state = value
}
override fun set(pokemon: Pokemon, value: PokemonState) { pokemon.state = value }
companion object {
val ID = cobblemonResource("state_update")
@@ -13,24 +13,30 @@ import com.cobblemon.mod.common.api.mark.Marks
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.entity.PlatformType
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.pokemon.Gender
import com.cobblemon.mod.common.util.*
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.readEnumConstant
import com.cobblemon.mod.common.util.readIdentifier
import com.cobblemon.mod.common.util.readString
import com.cobblemon.mod.common.util.readText
import com.cobblemon.mod.common.util.writeEnumConstant
import com.cobblemon.mod.common.util.writeIdentifier
import com.cobblemon.mod.common.util.writeString
import com.cobblemon.mod.common.util.writeText
import java.util.UUID
import net.minecraft.client.multiplayer.ClientLevel
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.network.chat.MutableComponent
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.entity.Entity
import java.util.*
class SpawnPokemonPacket(
var ownerId: UUID?,
var pokemonUUID: UUID,
var storageUUID: UUID?,
var scaleModifier: Float,
var speciesId: ResourceLocation,
var gender: Gender,
@@ -55,7 +61,6 @@ class SpawnPokemonPacket(
var tickSpawned: Int,
var rideBoosts: Map<RidingStat, Float>,
var rideStamina: Float,
var silent: Boolean,
vanillaSpawnPacket: ClientboundAddEntityPacket,
) : SpawnExtraDataEntityPacket<SpawnPokemonPacket, PokemonEntity>(vanillaSpawnPacket) {
@@ -64,7 +69,6 @@ class SpawnPokemonPacket(
constructor(entity: PokemonEntity, vanillaSpawnPacket: ClientboundAddEntityPacket) : this(
entity.ownerUUID,
entity.pokemon.uuid,
entity.pokemon.storeCoordinates.get()?.store?.uuid,
entity.pokemon.scaleModifier,
entity.exposedSpecies.resourceIdentifier,
entity.pokemon.gender,
@@ -89,14 +93,12 @@ class SpawnPokemonPacket(
entity.tickCount,
entity.entityData.get(PokemonEntity.RIDE_BOOSTS),
entity.entityData.get(PokemonEntity.RIDE_STAMINA),
entity.isSilent,
vanillaSpawnPacket
)
override fun encodeEntityData(buffer: RegistryFriendlyByteBuf) {
buffer.writeNullable(ownerId) { _, v -> buffer.writeUUID(v) }
buffer.writeUUID(this.pokemonUUID)
buffer.writeNullable(this.storageUUID) { pb, value -> pb.writeUUID(value) }
buffer.writeFloat(this.scaleModifier)
buffer.writeIdentifier(this.speciesId)
buffer.writeEnumConstant(this.gender)
@@ -125,21 +127,10 @@ class SpawnPokemonPacket(
{ _, value -> buffer.writeFloat(value) }
)
buffer.writeFloat(rideStamina)
buffer.writeBoolean(silent)
}
override fun applyData(entity: PokemonEntity, level: ClientLevel) {
entity.ownerUUID = ownerId
// Reuse the stored Pokémon instance to avoid creating a duplicate,
// preventing client/entity desync issues.
this@SpawnPokemonPacket.storageUUID?.let {
val storedPokemon = CobblemonClient.storage.locatePokemon(it, this@SpawnPokemonPacket.pokemonUUID)
if (storedPokemon != null) {
entity.pokemon = storedPokemon
}
}
entity.pokemon.apply {
uuid = this@SpawnPokemonPacket.pokemonUUID
scaleModifier = this@SpawnPokemonPacket.scaleModifier
@@ -171,7 +162,6 @@ class SpawnPokemonPacket(
entity.entityData.set(PokemonEntity.RIDE_BOOSTS, rideBoosts)
entity.entityData.set(PokemonEntity.RIDE_STAMINA, rideStamina)
entity.entityData.set(PokemonEntity.SCALE_MODIFIER, scaleModifier)
entity.isSilent = silent
entity.ejectPassengers()
passengers.forEach {
@@ -189,7 +179,6 @@ class SpawnPokemonPacket(
fun decode(buffer: RegistryFriendlyByteBuf): SpawnPokemonPacket {
val ownerId = buffer.readNullable { buffer.readUUID() }
val pokemonUUID = buffer.readUUID()
val storageUUID = buffer.readNullable { buffer.readUUID() }
val scaleModifier = buffer.readFloat()
val speciesId = buffer.readIdentifier()
val gender = buffer.readEnumConstant(Gender::class.java)
@@ -217,13 +206,11 @@ class SpawnPokemonPacket(
{ buffer.readFloat() }
)
val rideStamina = buffer.readFloat()
val silent = buffer.readBoolean()
val vanillaPacket = decodeVanillaPacket(buffer)
return SpawnPokemonPacket(
ownerId,
pokemonUUID,
storageUUID,
scaleModifier,
speciesId,
gender,
@@ -248,7 +235,6 @@ class SpawnPokemonPacket(
tickSpawned,
rideBoosts,
rideStamina,
silent,
vanillaPacket
)
}
@@ -673,7 +673,7 @@ open class Pokemon : ShowdownIdentifiable {
* Whether this Pokémon's held item can be dropped by its AI.
*/
internal var canDropHeldItem: Boolean = false
get() = field || heldItem.isEmpty
get() = field && !heldItem.isEmpty
val riding: RidingProperties
get() = this.form.riding
@@ -897,10 +897,6 @@ open class Pokemon : ShowdownIdentifiable {
this.recall()
}
fun playMoodParticle(particleName: String) {
entity?.playMoodParticle(particleName)
}
fun heal() {
CobblemonEvents.POKEMON_HEALED.postThen(PokemonHealedEvent(this)) { event ->
this.currentHealth = maxHealth
@@ -968,13 +964,23 @@ open class Pokemon : ShowdownIdentifiable {
else -> 0 // For weights less than 0.1
}
fun feedPokemon(feedCount: Int, playSound: Boolean = true, playMoodParticle: Boolean = true): Boolean {
playFullnessEffects(playSound, playMoodParticle)
fun feedPokemon(feedCount: Int, playSound: Boolean = true) {
// play sounds from the entity first (itemstack is consumed outside of this function)
if (this.entity != null && playSound) {
val fullnessPercent = ((this.currentFullness).toFloat() / (this.getMaxFullness()).toFloat()) * (.5f)
if (this.currentFullness >= this.getMaxFullness()) {
this.entity?.playSound(CobblemonSounds.BERRY_EAT_FULL, 1F, 1F)
}
else {
this.entity?.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F + fullnessPercent)
}
}
// if it is already full we don't need to do anything
// TODO this can happen when feeding in battle since we are temporarily ignoring fullness checks for pp/hp/status berries
if (isFull()) {
return false
return
}
this.currentFullness = (this.currentFullness + feedCount).coerceIn(0, this.getMaxFullness())
@@ -983,31 +989,6 @@ open class Pokemon : ShowdownIdentifiable {
if (this.currentFullness == 1) {
this.resetMetabolismCycle()
}
return true
}
private fun playFullnessEffects(playSound: Boolean = true, playMoodParticle: Boolean = true) {
if (!playSound && !playMoodParticle) return
val pokemonEntity = entity ?: return
val fullnessPercent = ((this.currentFullness).toFloat() / (this.getMaxFullness()).toFloat()) * (.5f)
if (!isFull()) {
if (playSound) {
pokemonEntity.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F + fullnessPercent)
}
return
}
if (playSound) {
pokemonEntity.playSound(CobblemonSounds.BERRY_EAT_FULL, 1F, 1F)
if (playMoodParticle) {
pokemonEntity.playMoodParticle("mood_annoyed")
}
}
}
// decrease a pokemon's Fullness value by a certain amount
@@ -1456,11 +1437,6 @@ open class Pokemon : ShowdownIdentifiable {
}
fun getOwnerEntity(): LivingEntity? {
if (isClient) {
val ownerUUID = entity?.ownerUUID ?: return null
return entity?.level()?.getPlayerByUUID(ownerUUID)
}
return storeCoordinates.get()?.let {
if (isPlayerOwned()) {
server()?.playerList?.getPlayer(it.store.uuid)
@@ -8,22 +8,13 @@
package com.cobblemon.mod.common.pokemon.adapters
import com.cobblemon.mod.common.api.interaction.InteractionEffect
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.pokemon.adapters.RequirementAdapter
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
import com.cobblemon.mod.common.pokemon.evolution.adapters.LegacyItemConditionWrapperAdapter
import com.cobblemon.mod.common.pokemon.requirements.*
import com.cobblemon.mod.common.util.adapters.*
import com.cobblemon.mod.common.util.readString
import com.cobblemon.mod.common.util.writeString
import com.google.common.collect.HashBiMap
import com.google.gson.*
import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.util.LowerCaseEnumTypeAdapterFactory
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonElement
import com.google.gson.JsonSerializationContext
import java.lang.reflect.Type
import kotlin.reflect.KClass
@@ -69,60 +60,21 @@ object CobblemonRequirementAdapter : RequirementAdapter {
this.registerType(OwnerHoldsItemRequirement.ADAPTER_VARIANT, OwnerHoldsItemRequirement::class)
}
val gson: Gson by lazy {
GsonBuilder()
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
.registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter)
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter)
.registerTypeAdapter(Requirement::class.java, CobblemonRequirementAdapter)
.registerTypeAdapter(InteractionEffect::class.java, InteractionEffectAdapter)
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
.registerTypeAdapter(IntRange::class.java, IntRangeAdapter)
.registerTypeAdapterFactory(LowerCaseEnumTypeAdapterFactory())
.setPrettyPrinting()
.create()
}
override fun <T : Requirement> registerType(id: String, type: KClass<T>) {
this.types[id.lowercase()] = type
}
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Requirement {
val variant = json.asJsonObject.get(VARIANT).asString.lowercase()
val type = getRequirementType(variant)
val type = this.types[variant] ?: throw IllegalArgumentException("Cannot resolve evolution requirement type for variant $variant")
return context.deserialize(json, type.java)
}
override fun serialize(requirement: Requirement, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
val json = context.serialize(requirement, requirement::class.java).asJsonObject
val variant = getVariant(requirement)
override fun serialize(src: Requirement, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
val json = context.serialize(src, src::class.java).asJsonObject
val variant = this.types.inverse()[src::class] ?: throw IllegalArgumentException("Cannot resolve evolution requirement for type ${src::class.qualifiedName}")
json.addProperty(VARIANT, variant)
return json
}
fun encode(requirement: Requirement, buffer: FriendlyByteBuf) {
buffer.writeString(gson.toJson(requirement, Requirement::class.java))
}
fun decode(buffer: FriendlyByteBuf): Requirement {
return gson.fromJson(buffer.readString(), Requirement::class.java)
}
private fun getVariant(requirement: Requirement): String {
val variant = this.types.inverse()[requirement::class]
if (variant == null) {
throw IllegalArgumentException("Cannot resolve evolution requirement for type ${requirement::class.qualifiedName}")
}
return variant
}
private fun getRequirementType(variant: String): KClass<out Requirement> {
val requirementType = this.types[variant]
if (requirementType == null) {
throw IllegalArgumentException("Cannot resolve evolution requirement type for variant $variant")
}
return requirementType
}
}
@@ -11,9 +11,9 @@ package com.cobblemon.mod.common.pokemon.requirements
import com.cobblemon.mod.common.api.pokemon.requirement.OwnerQueryRequirement
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.pokemon.Pokemon
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.player.Player
import net.minecraft.resources.ResourceLocation
import kotlin.collections.iterator
/**
* An [com.cobblemon.mod.common.api.pokemon.requirement.Requirement] that checks if the player has a certain [net.minecraft.advancements.Advancement]
@@ -26,16 +26,13 @@ class AdvancementRequirement(val requiredAdvancement: ResourceLocation) : OwnerQ
override fun checkPlayer(
pokemon: Pokemon,
owner: Player
owner: ServerPlayer
): Boolean {
val serverPlayer = owner as? ServerPlayer ?: return false
for (entry in serverPlayer.advancements.progress) {
for (entry in owner.advancements.progress) {
if (entry.key.id == requiredAdvancement && entry.value.isDone) {
return true
}
}
return false
}
@@ -12,9 +12,11 @@ import com.cobblemon.mod.common.api.pokemon.requirement.OwnerQueryRequirement
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.pokemon.Pokemon
import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.server.level.ServerPlayer
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.InteractionHand
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
import kotlin.collections.iterator
/**
* An [OwnerQueryRequirement] that checks if the player/npc is holding a certain [ItemPredicate]
@@ -28,7 +30,7 @@ class OwnerHoldsItemRequirement(val itemCondition: ItemPredicate)
override fun checkPlayer(
pokemon: Pokemon,
owner: Player
owner: ServerPlayer
): Boolean {
return checkItem(owner)
}
@@ -8,22 +8,22 @@
package com.cobblemon.mod.common.util.adapters
import com.google.gson.*
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import com.google.gson.JsonSerializationContext
import com.google.gson.JsonSerializer
import com.mojang.serialization.Codec
import com.mojang.serialization.JsonOps
import java.lang.reflect.Type
class CodecBackedAdapter<T>(val codec: Codec<T>) : JsonDeserializer<T>, JsonSerializer<T> {
override fun deserialize(
jElement: JsonElement,
typeOfT: Type,
context: JsonDeserializationContext
): T {
val ops = RegistryOpsProvider.getOpsWithDefaultFallback()
val result = ops.withDecoder(codec).apply(jElement)
return result.result().orElseThrow {
IllegalStateException("Failed to deserialize $jElement: ${result.error().orElse(null)}")
}.first
return JsonOps.INSTANCE.withDecoder(codec).apply(jElement).result().get().first as T
}
override fun serialize(
@@ -31,10 +31,6 @@ class CodecBackedAdapter<T>(val codec: Codec<T>) : JsonDeserializer<T>, JsonSeri
typeOfSrc: Type?,
context: JsonSerializationContext?
): JsonElement {
val ops = RegistryOpsProvider.getOpsWithDefaultFallback()
val result = ops.withEncoder(codec).apply(src)
return result.result().orElseThrow {
IllegalStateException("Failed to serialize $src: ${result.error().orElse(null)}")
}
return JsonOps.INSTANCE.withEncoder(codec).apply(src).result().get()
}
}
@@ -1,41 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.util.adapters
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.Environment
import com.cobblemon.mod.common.util.server
import com.google.gson.JsonElement
import com.mojang.serialization.DynamicOps
import com.mojang.serialization.JsonOps
import net.minecraft.client.Minecraft
import net.minecraft.resources.RegistryOps
/**
* Utility for obtaining RegistryOps with the correct client/server registry access.
* Used when manually encoding/decoding registry-backed values (e.g., items, predicates).
*/
object RegistryOpsProvider {
fun getOpsWithDefaultFallback(): DynamicOps<JsonElement> {
if (Cobblemon.implementation.environment() == Environment.CLIENT) {
val minecraft = Minecraft.getInstance()
if (minecraft != null && minecraft.level != null)
return RegistryOps.create(JsonOps.INSTANCE, minecraft.level!!.registryAccess())
}
if (Cobblemon.implementation.environment() == Environment.SERVER) {
val server = server()
if (server != null)
return RegistryOps.create(JsonOps.INSTANCE, server.registryAccess())
}
return JsonOps.INSTANCE
}
}
@@ -1,55 +0,0 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:mood_anger_steam",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/mood/steam_center_double"
}
},
"events": {
"veins": {
"particle_effect": {
"effect": "cobblemon:mood_anger_veins",
"type": "emitter"
}
}
},
"components": {
"minecraft:emitter_rate_instant": {
"num_particles": 1
},
"minecraft:emitter_lifetime_looping": {
"active_time": 1,
"sleep_time": 0.25
},
"minecraft:emitter_lifetime_events": {
"creation_event": "veins"
},
"minecraft:emitter_shape_point": {
"offset": [0, "math.clamp((v.entity_radius*1.2),0.48,0.96)*0.75", 0]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": 1
},
"minecraft:particle_initial_speed": 0,
"minecraft:particle_motion_dynamic": {},
"minecraft:particle_appearance_billboard": {
"size": ["math.clamp((v.entity_radius*1.5),0.9,2.4)", "math.clamp((v.entity_radius*0.5),0.3,0.8)"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 48,
"texture_height": 176,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [48, 16],
"step_UV": [0, 16],
"max_frame": 11,
"stretch_to_lifetime": true
}
}
}
}
}
}
@@ -1,66 +0,0 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:mood_anger_veins",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/mood/vein_red"
}
},
"components": {
"minecraft:emitter_initialization": {
"creation_expression": "v.particle_size = math.clamp((v.entity_radius*0.75),0.15,0.4);"
},
"minecraft:emitter_rate_steady": {
"spawn_rate": 1,
"max_particles": 1
},
"minecraft:emitter_lifetime_looping": {
"active_time": 1,
"sleep_time": 0.25
},
"minecraft:emitter_shape_point": {
"direction": ["math.random(-1,1)", 1.5, "math.random(-1,1)"]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": 1.25
},
"minecraft:particle_initial_spin": {
"rotation": "math.random_integer(-1,2)*90"
},
"minecraft:particle_initial_speed": "v.particle_size*13",
"minecraft:particle_motion_dynamic": {
"linear_acceleration": [0, 0.75, 0],
"linear_drag_coefficient": "v.particle_size*15"
},
"minecraft:particle_appearance_billboard": {
"size": ["math.clamp((v.entity_radius*0.75),0.15,0.3)", "math.clamp((v.entity_radius*0.75),0.15,0.3)"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 22,
"texture_height": 11,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [11, 11],
"step_UV": [11, 0],
"frames_per_second": 6,
"max_frame": 2,
"loop": true
}
}
},
"minecraft:particle_motion_collision": {},
"minecraft:particle_appearance_lighting": {},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age/v.particle_lifetime",
"gradient": {
"0.86": "#ffffffff",
"1.0": "#FF000000"
}
}
}
}
}
}
@@ -1,49 +0,0 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:mood_annoyed",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/mood/scribble_purple"
}
},
"components": {
"minecraft:emitter_initialization": {
"creation_expression": "v.particle_size = math.clamp((v.entity_radius*0.75),0.2,0.5);"
},
"minecraft:emitter_rate_instant": {
"num_particles": 1
},
"minecraft:emitter_lifetime_once": {
"active_time": 2
},
"minecraft:emitter_shape_point": {
"direction": [0, 1, 0]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": 1
},
"minecraft:particle_initial_speed": "v.particle_size*10",
"minecraft:particle_motion_dynamic": {
"linear_drag_coefficient": 3
},
"minecraft:particle_appearance_billboard": {
"size": ["math.clamp((v.entity_radius*0.75),0.2,0.5)", "math.clamp((v.entity_radius*0.75),0.2,0.5)"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 168,
"texture_height": 14,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [14, 14],
"step_UV": [14, 0],
"frames_per_second": 10,
"max_frame": 12
}
}
},
"minecraft:particle_appearance_lighting": {}
}
}
}
@@ -1,47 +0,0 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:mood_stress",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/mood/sweat_blue"
}
},
"components": {
"minecraft:emitter_initialization": {
"creation_expression": "v.particle_height = math.clamp((v.entity_radius*1.2),0.48,0.96);"
},
"minecraft:emitter_rate_instant": {
"num_particles": 1
},
"minecraft:emitter_lifetime_looping": {
"active_time": 1
},
"minecraft:emitter_shape_point": {
"offset": [0, "math.clamp((v.entity_radius*1.2),0.48,0.96)*0.75", 0]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": 0.45
},
"minecraft:particle_initial_speed": 0,
"minecraft:particle_motion_dynamic": {},
"minecraft:particle_appearance_billboard": {
"size": ["math.clamp((v.entity_radius*1.2),0.48,0.96)", "math.clamp((v.entity_radius*0.65),0.26,0.52)"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 216,
"texture_height": 13,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [24, 13],
"step_UV": [24, 0],
"max_frame": 9,
"stretch_to_lifetime": true
}
}
},
"minecraft:particle_appearance_lighting": {}
}
}
}
@@ -9445,8 +9445,5 @@
"stat.cobblemon.traded": "Pokémon Traded",
"stat.cobblemon.times_ridden": "Pokémon Ridden",
"stat.cobblemon.rod_casts": "PokéRod Casts",
"stat.cobblemon.reel_ins": "PokéRod Catches",
"stat.cobblemon.riding_land": "Distance by Pokémon on Land",
"stat.cobblemon.riding_air": "Distance by Pokémon in Air",
"stat.cobblemon.riding_liquid": "Distance by Pokémon in Liquid"
"stat.cobblemon.reel_ins": "PokéRod Catches"
}
@@ -0,0 +1,235 @@
{
"format_version": "1.21.6",
"credit": "Made with Blockbench",
"texture_size": [64, 24],
"textures": {
"0": "cobblemon:item/wearable/shell_helmet",
"particle": "cobblemon:item/wearable/shell_helmet"
},
"elements": [
{
"from": [4, 1, 7],
"to": [12, 4, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 2, 12]},
"faces": {
"north": {"uv": [4, 0, 6, 2], "texture": "#0"},
"east": {"uv": [4, 2, 4.75, 4], "texture": "#0"},
"south": {"uv": [1.75, 12.66667, 3.75, 14.66667], "texture": "#0"},
"west": {"uv": [4.75, 2, 5.5, 4], "texture": "#0"},
"up": {"uv": [4, 2, 2, 0], "texture": "#0"},
"down": {"uv": [4, 2, 2, 4.66667], "texture": "#0"}
}
},
{
"from": [11, 0, 7],
"to": [12, 1, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [7, -3, 9]},
"faces": {
"north": {"uv": [5.5, 3.33333, 5.75, 4], "texture": "#0"},
"east": {"uv": [0, 0, 0, 0.66667], "texture": "#0"},
"south": {"uv": [5.75, 3.33333, 6, 4], "texture": "#0"},
"west": {"uv": [0, 0, 0, 0.66667], "texture": "#0"},
"up": {"uv": [0.25, 0, 0, 0], "texture": "#0"},
"down": {"uv": [0.25, 0, 0, 0], "texture": "#0"}
}
},
{
"from": [4, 0, 7],
"to": [5, 1, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [0, -3, 9]},
"faces": {
"north": {"uv": [4, 4, 4.25, 4.66667], "texture": "#0"},
"east": {"uv": [0, 0, 0, 0.66667], "texture": "#0"},
"south": {"uv": [3.75, 12.66667, 4, 13.33333], "texture": "#0"},
"west": {"uv": [0, 0, 0, 0.66667], "texture": "#0"},
"up": {"uv": [0.25, 0, 0, 0], "texture": "#0"},
"down": {"uv": [0.25, 0, 0, 0], "texture": "#0"}
}
},
{
"from": [12, -1, 7],
"to": [12, 1, 9],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 2, 11]},
"faces": {
"north": {"uv": [0, 0, 0, 1.33333], "texture": "#0"},
"east": {"uv": [4.25, 6.66667, 4.75, 8], "texture": "#0"},
"south": {"uv": [0, 0, 0, 1.33333], "texture": "#0"},
"west": {"uv": [5.5, 2, 6, 3.33333], "texture": "#0"},
"up": {"uv": [0, 3.33333, 0, 0], "texture": "#0"},
"down": {"uv": [0, 0, 0, 3.33333], "texture": "#0"}
}
},
{
"from": [4, -1, 7],
"to": [4, 1, 9],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 2, 11]},
"faces": {
"north": {"uv": [0, 0, 0, 1.33333], "texture": "#0"},
"east": {"uv": [4, 10, 4.5, 11.33333], "texture": "#0"},
"south": {"uv": [0, 0, 0, 1.33333], "texture": "#0"},
"west": {"uv": [4.75, 6.66667, 5.25, 8], "texture": "#0"},
"up": {"uv": [0, 3.33333, 0, 0], "texture": "#0"},
"down": {"uv": [0, 0, 0, 3.33333], "texture": "#0"}
}
},
{
"from": [5, 2, 4],
"to": [11, 4, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 2, 12]},
"faces": {
"north": {"uv": [4.25, 4, 5.75, 5.33333], "texture": "#0"},
"east": {"uv": [6, 2.66667, 6.75, 4], "texture": "#0"},
"south": {"uv": [4.25, 5.33333, 5.75, 6.66667], "texture": "#0"},
"west": {"uv": [5.75, 4, 6.5, 5.33333], "texture": "#0"},
"up": {"uv": [5.5, 13.33333, 4, 11.33333], "texture": "#0"},
"down": {"uv": [5.25, 13.33333, 3.75, 15.33333], "texture": "#0"}
}
},
{
"from": [5, 2, 7],
"to": [11, 2, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 2, 12]},
"faces": {
"north": {"uv": [4.25, 4, 5.75, 5.33333], "texture": "#0"},
"east": {"uv": [6, 2.66667, 6.75, 4], "texture": "#0"},
"south": {"uv": [4.25, 5.33333, 5.75, 6.66667], "texture": "#0"},
"west": {"uv": [5.75, 4, 6.5, 5.33333], "texture": "#0"},
"up": {"uv": [5.5, 13.33333, 4, 11.33333], "texture": "#0"},
"down": {"uv": [3.75, 15.33333, 5.25, 13.33333], "texture": "#0"}
}
},
{
"from": [11, 0, 4],
"to": [11, 2, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 2, 12]},
"faces": {
"north": {"uv": [0, 0, 0, 1.33333], "texture": "#0"},
"east": {"uv": [5.75, 5.33333, 6.5, 6.66667], "texture": "#0"},
"south": {"uv": [0, 0, 0, 1.33333], "texture": "#0"},
"west": {"uv": [6, 1.33333, 6.75, 2.66667], "texture": "#0"},
"up": {"uv": [0, 2, 0, 0], "texture": "#0"},
"down": {"uv": [0, 0, 0, 2], "texture": "#0"}
}
},
{
"from": [5, 0, 4],
"to": [5, 2, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 2, 12]},
"faces": {
"north": {"uv": [0, 0, 0, 1.33333], "texture": "#0"},
"east": {"uv": [6, 0, 6.75, 1.33333], "texture": "#0"},
"south": {"uv": [0, 0, 0, 1.33333], "texture": "#0"},
"west": {"uv": [5.25, 6.66667, 6, 8], "texture": "#0"},
"up": {"uv": [0, 2, 0, 0], "texture": "#0"},
"down": {"uv": [0, 0, 0, 2], "texture": "#0"}
}
},
{
"from": [4, 1, 10],
"to": [12, 4, 15],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 0, 12]},
"faces": {
"north": {"uv": [0, 10.66667, 1.75, 14], "texture": "#0"},
"east": {"uv": [3.25, 8, 4.5, 10], "texture": "#0"},
"south": {"uv": [1.75, 10.66667, 4, 12.66667], "texture": "#0"},
"west": {"uv": [2, 8, 3.25, 10], "texture": "#0"},
"up": {"uv": [6.5, 11.33333, 4.5, 8], "texture": "#0"},
"down": {"uv": [4.25, 4.66667, 2, 8], "texture": "#0"}
}
},
{
"from": [4, -4, 9],
"to": [12, 1, 15],
"rotation": {"angle": 0, "axis": "y", "origin": [4, -3, 13]},
"faces": {
"north": {"uv": [10.75, 3.33333, 12.75, 6.66667], "texture": "#0"},
"east": {"uv": [12.75, 0, 14.25, 3.33333], "texture": "#0"},
"south": {"uv": [10.75, 0, 12.75, 3.33333], "texture": "#0"},
"west": {"uv": [14.25, 0, 15.75, 3.33333], "texture": "#0"},
"up": {"uv": [8.75, 4, 10.75, 8], "texture": "#0"},
"down": {"uv": [8.75, 0, 10.75, 4], "texture": "#0"}
}
},
{
"from": [6, -1.3, 10.5],
"to": [10, 6.7, 18.5],
"rotation": {"angle": 45, "axis": "x", "origin": [7.5, 1.65, 13.5]},
"faces": {
"north": {"uv": [12.75, 3.33333, 13.75, 8.66667], "texture": "#0"},
"east": {"uv": [2, 0, 0, 5.33333], "texture": "#0"},
"south": {"uv": [13.75, 3.33333, 14.75, 8.66667], "texture": "#0"},
"west": {"uv": [0, 0, 2, 5.33333], "texture": "#0"},
"up": {"uv": [12.75, 8.66667, 13.75, 14], "texture": "#0"},
"down": {"uv": [13.75, 8.66667, 14.75, 14], "texture": "#0"}
}
},
{
"from": [4, -1.4, 7.4],
"to": [12, -1.4, 18.4],
"rotation": {"angle": 45, "axis": "x", "origin": [7.5, 1.65, 13.5]},
"faces": {
"north": {"uv": [12.75, 3.33333, 13.75, 8.66667], "texture": "#0"},
"east": {"uv": [0, 5.33333, 2, 10.66667], "texture": "#0"},
"south": {"uv": [13.75, 3.33333, 14.75, 8.66667], "texture": "#0"},
"west": {"uv": [0, 0, 2, 5.33333], "texture": "#0"},
"up": {"uv": [12.75, 8.66667, 13.75, 14], "texture": "#0"},
"down": {"uv": [6.75, 0, 8.75, 6.66667], "texture": "#0"}
}
},
{
"from": [4.01, -4, 7],
"to": [4.01, 4, 15],
"faces": {
"north": {"uv": [0, 0, 0, 5.33333], "texture": "#0"},
"east": {"uv": [8.75, 8, 10.75, 13.33333], "texture": "#0"},
"south": {"uv": [0, 0, 0, 5.33333], "texture": "#0"},
"west": {"uv": [6.5, 6.66667, 8.5, 12], "texture": "#0"},
"up": {"uv": [0, 0, 0, 5.33333], "texture": "#0"},
"down": {"uv": [0, 0, 0, 5.33333], "texture": "#0"}
}
},
{
"from": [11.99, -4, 7],
"to": [11.99, 4, 15],
"faces": {
"north": {"uv": [0, 0, 0, 5.33333], "texture": "#0"},
"east": {"uv": [6.5, 6.66667, 8.5, 12], "texture": "#0"},
"south": {"uv": [0, 0, 0, 5.33333], "texture": "#0"},
"west": {"uv": [10.75, 9.33333, 12.75, 14.66667], "texture": "#0"},
"up": {"uv": [0, 0, 0, 5.33333], "texture": "#0"},
"down": {"uv": [0, 0, 0, 5.33333], "texture": "#0"}
}
},
{
"from": [4, 0, 7.01],
"to": [12, 4, 7.01],
"rotation": {"angle": 0, "axis": "y", "origin": [7, -3, 9]},
"faces": {
"north": {"uv": [10.75, 3.33333, 12.75, 6.66667], "texture": "#0"},
"east": {"uv": [0, 0, 0, 0.66667], "texture": "#0"},
"south": {"uv": [10.75, 6.66667, 12.75, 9.33333], "texture": "#0"},
"west": {"uv": [0, 0, 0, 0.66667], "texture": "#0"},
"up": {"uv": [0.25, 0, 0, 0], "texture": "#0"},
"down": {"uv": [0.25, 0, 0, 0], "texture": "#0"}
}
},
{
"from": [4, -3.99, 12],
"to": [12, -3.99, 15],
"faces": {
"north": {"uv": [0, 0, 2, 0], "texture": "#0"},
"east": {"uv": [0, 0, 0.75, 0], "texture": "#0"},
"south": {"uv": [0, 0, 2, 0], "texture": "#0"},
"west": {"uv": [0, 0, 0.75, 0], "texture": "#0"},
"up": {"uv": [10.75, 8.66667, 12.75, 6.66667], "texture": "#0"},
"down": {"uv": [10.75, 4.66667, 12.75, 6.66667], "texture": "#0"}
}
}
],
"display": {
"head": {
"translation": [0, 15.25, -6],
"scale": [1.9, 1.9, 1.9]
}
}
}
@@ -1517,139 +1517,76 @@
{ "name": "cobblemon:animation/wings/steel_wing_flap_medium_8", "volume": 0.25 }
]
},
"ride.loop.wind.mono": {
"ride.loop.wind": {
"sounds": [
{
"name": "cobblemon:ride/loop/wind_loop_mono",
"name": "cobblemon:ride/loop/wind_loop",
"stream": true,
"attenuation_distance": 48.0,
"volume": 0.15
}
]
},
"ride.loop.wind.stereo": {
"ride.loop.leather": {
"sounds": [
{
"name": "cobblemon:ride/loop/wind_loop_stereo",
"stream": true,
"volume": 0.04
}
]
},
"ride.loop.leather.mono": {
"sounds": [
{
"name": "cobblemon:ride/loop/leather_flight_loop_mono",
"name": "cobblemon:ride/loop/leather_flight_loop",
"stream": true,
"attenuation_distance": 48.0,
"volume": 0.25
}
]
},
"ride.loop.leather.stereo": {
"ride.loop.plumage": {
"sounds": [
{
"name": "cobblemon:ride/loop/leather_flight_loop_stereo",
"stream": true,
"volume": 0.05
}
]
},
"ride.loop.plumage.mono": {
"sounds": [
{
"name": "cobblemon:ride/loop/plumage_flight_loop_mono",
"name": "cobblemon:ride/loop/plumage_flight_loop",
"stream": true,
"attenuation_distance": 48.0,
"volume": 0.25
}
]
},
"ride.loop.plumage.stereo": {
"ride.loop.saucer": {
"sounds": [
{
"name": "cobblemon:ride/loop/plumage_flight_loop_stereo",
"stream": true,
"volume": 0.05
}
]
},
"ride.loop.saucer.mono": {
"sounds": [
{
"name": "cobblemon:ride/loop/saucer_flight_loop_mono",
"name": "cobblemon:ride/loop/saucer_flight_loop",
"stream": true,
"attenuation_distance": 48.0,
"volume": 0.25
}
]
},
"ride.loop.saucer.stereo": {
"ride.loop.rocket": {
"sounds": [
{
"name": "cobblemon:ride/loop/saucer_flight_loop_stereo",
"stream": true,
"volume": 0.1
}
]
},
"ride.loop.rocket.mono": {
"sounds": [
{
"name": "cobblemon:ride/loop/rocket_flight_loop_mono",
"name": "cobblemon:ride/loop/rocket_flight_loop",
"stream": true,
"attenuation_distance": 48.0,
"volume": 0.4
}
]
},
"ride.loop.rocket.stereo": {
"ride.loop.water_surface": {
"sounds": [
{
"name": "cobblemon:ride/loop/rocket_flight_loop_stereo",
"stream": true,
"volume": 0.3
}
]
},
"ride.loop.water_surface.mono": {
"sounds": [
{
"name": "cobblemon:ride/loop/water_surface_loop_mono",
"name": "cobblemon:ride/loop/water_surface_loop",
"stream": true,
"attenuation_distance": 32.0,
"volume": 0.4
}
]
},
"ride.loop.water_surface.stereo": {
"ride.loop.underwater": {
"sounds": [
{
"name": "cobblemon:ride/loop/water_surface_loop_stereo",
"stream": true,
"volume": 0.13
}
]
},
"ride.loop.underwater.mono": {
"sounds": [
{
"name": "cobblemon:ride/loop/underwater_loop_mono",
"name": "cobblemon:ride/loop/underwater_loop",
"stream": true,
"attenuation_distance": 16.0,
"volume": 0.4
}
]
},
"ride.loop.underwater.stereo": {
"sounds": [
{
"name": "cobblemon:ride/loop/underwater_loop_stereo",
"stream": true,
"volume": 0.2
}
]
},
"pokemon.bulbasaur.ambient": {
"sounds": [ "cobblemon:pokemon/bulbasaur/bulbasaur_ambient" ]
},
Binary file not shown.

After

Width:  |  Height:  |  Size: 863 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 415 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 847 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 979 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 744 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 589 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 290 B

@@ -1,41 +0,0 @@
t.ticks_between_checks = 20 * 10;
math.mod(q.player.world.game_time, t.ticks_between_checks) != 0 ? {
return 0;
};
t.steps_required = 10000;
t.friendship_required = 200;
t.total_blocks =
q.player.get_custom_stat('minecraft:walk_one_cm') +
q.player.get_custom_stat('minecraft:crouch_one_cm') +
q.player.get_custom_stat('minecraft:sprint_one_cm') +
q.player.get_custom_stat('minecraft:walk_on_water_one_cm') +
q.player.get_custom_stat('minecraft:fall_one_cm') +
q.player.get_custom_stat('minecraft:climb_one_cm') +
q.player.get_custom_stat('minecraft:fly_one_cm') +
q.player.get_custom_stat('minecraft:walk_under_water_one_cm') +
q.player.get_custom_stat('minecraft:minecart_one_cm') +
q.player.get_custom_stat('minecraft:boat_one_cm') +
q.player.get_custom_stat('minecraft:pig_one_cm') +
q.player.get_custom_stat('minecraft:horse_one_cm') +
q.player.get_custom_stat('minecraft:aviate_one_cm') +
q.player.get_custom_stat('minecraft:swim_one_cm') +
q.player.get_custom_stat('minecraft:strider_one_cm') +
q.player.get_custom_stat('cobblemon:riding_land') +
q.player.get_custom_stat('cobblemon:riding_air') +
q.player.get_custom_stat('cobblemon:riding_liquid');
t.total_blocks = t.total_blocks / 100.0;
t.player_data = q.player.data();
math.floor(t.total_blocks / t.steps_required) > math.floor(t.player_data.last_partner_mark_check / t.steps_required) ? {
t.party = q.player.party;
for_each(t.pokemon, t.party.pokemon, {
t.pokemon.friendship >= t.friendship_required ? {
t.pokemon.add_marks_with_chance('cobblemon:mark_partner');
};
});
};
t.player_data.last_partner_mark_check = t.total_blocks;
@@ -4,6 +4,5 @@
"titleColor": "40B282",
"description": "cobblemon.mark.mark_partner.desc",
"texture": "cobblemon:textures/gui/mark/mark_partner.png",
"indexNumber": 104,
"chance": 0.01
"indexNumber": 104
}
@@ -57,33 +57,15 @@
{
"muffleEnabled": true,
"pitchExpr": "math.max(1.0 ,0.2 + math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2))",
"playForPassengers": true,
"playForNonPassengers": false,
"soundLocation": "cobblemon:ride.loop.wind.stereo",
"volumeExpr": "math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2)"
},
{
"muffleEnabled": true,
"pitchExpr": "math.max(1.0 ,0.2 + math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2))",
"playForPassengers": false,
"playForNonPassengers": true,
"soundLocation": "cobblemon:ride.loop.wind.mono",
"soundLocation": "cobblemon:ride.loop.wind",
"volumeExpr": "math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2)"
},
{
"muffleEnabled": true,
"pitchExpr": "math.max(1.0 ,0.2 + math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2))",
"playForPassengers": true,
"playForNonPassengers": false,
"soundLocation": "cobblemon:ride.loop.leather.stereo",
"volumeExpr": "math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2)"
},
{
"muffleEnabled": true,
"pitchExpr": "math.max(1.0 ,0.2 + math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2))",
"playForPassengers": false,
"playForNonPassengers": true,
"soundLocation": "cobblemon:ride.loop.leather.mono",
"soundLocation": "cobblemon:ride.loop.leather",
"volumeExpr": "math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2)"
}
],
@@ -58,18 +58,14 @@
{
"muffleEnabled": true,
"pitchExpr": "math.max(1.0 ,0.2 + math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2))",
"playForPassengers": true,
"playForNonPassengers": true,
"submerged": false,
"soundLocation": "cobblemon:ride.loop.wind",
"volumeExpr": "math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2)"
},
{
"muffleEnabled": true,
"pitchExpr": "math.max(1.0 ,0.2 + math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2))",
"playForPassengers": true,
"playForNonPassengers": true,
"submerged": false,
"soundLocation": "cobblemon:ride.loop.leather",
"volumeExpr": "math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2)"
}
@@ -97,44 +93,7 @@
},
"LIQUID": {
"key": "cobblemon:liquid/dolphin",
"rideSounds": [
{
"muffleEnabled": true,
"pitchExpr": "math.max(1.0 ,0.2 + math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2))",
"playForPassengers": true,
"playForNonPassengers": false,
"submerged": false,
"soundLocation": "cobblemon:ride.loop.water_surface.stereo",
"volumeExpr": "math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2)"
},
{
"muffleEnabled": true,
"pitchExpr": "math.max(1.0 ,0.2 + math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2))",
"playForPassengers": false,
"playForNonPassengers": true,
"submerged": false,
"soundLocation": "cobblemon:ride.loop.water_surface.mono",
"volumeExpr": "math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2)"
},
{
"muffleEnabled": true,
"pitchExpr": "math.max(1.0 ,0.2 + math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2))",
"playForPassengers": true,
"playForNonPassengers": false,
"submerged": true,
"soundLocation": "cobblemon:ride.loop.underwater.stereo",
"volumeExpr": "math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2)"
},
{
"muffleEnabled": true,
"pitchExpr": "math.max(1.0 ,0.2 + math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2))",
"playForPassengers": false,
"playForNonPassengers": true,
"submerged": true,
"soundLocation": "cobblemon:ride.loop.underwater.mono",
"volumeExpr": "math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2)"
}
],
"rideSounds": [],
"stats": {
"ACCELERATION": "30-65",
"JUMP": "55-85",
@@ -1,7 +1,7 @@
{
"parent": "adorn:block/templates/bench_leg",
"textures": {
"log": "cobblemon:block/wood/apricorn_log",
"end": "cobblemon:block/wood/apricorn_log_top"
"log": "cobblemon:block/apricorn_log",
"end": "cobblemon:block/apricorn_log_top"
}
}
@@ -1,6 +1,6 @@
{
"parent": "adorn:block/templates/bench_top",
"textures": {
"planks": "cobblemon:block/wood/apricorn_planks"
"planks": "cobblemon:block/apricorn_planks"
}
}
@@ -1,6 +1,6 @@
{
"parent": "adorn:block/templates/chair_lower",
"textures": {
"planks": "cobblemon:block/wood/apricorn_planks"
"planks": "cobblemon:block/apricorn_planks"
}
}
@@ -1,6 +1,6 @@
{
"parent": "adorn:block/templates/chair_upper",
"textures": {
"planks": "cobblemon:block/wood/apricorn_planks"
"planks": "cobblemon:block/apricorn_planks"
}
}
@@ -1,8 +1,8 @@
{
"parent": "adorn:block/templates/coffee_table",
"textures": {
"planks": "cobblemon:block/wood/apricorn_planks",
"leg": "cobblemon:block/wood/apricorn_log",
"rim": "cobblemon:block/wood/apricorn_log"
"planks": "cobblemon:block/apricorn_planks",
"leg": "cobblemon:block/apricorn_log",
"rim": "cobblemon:block/apricorn_log"
}
}
@@ -1,6 +1,6 @@
{
"parent": "adorn:block/templates/drawer",
"textures": {
"planks": "cobblemon:block/wood/apricorn_planks"
"planks": "cobblemon:block/apricorn_planks"
}
}
@@ -1,6 +1,6 @@
{
"parent": "adorn:block/templates/kitchen_counter",
"textures": {
"planks": "cobblemon:block/wood/apricorn_planks"
"planks": "cobblemon:block/apricorn_planks"
}
}
@@ -1,6 +1,6 @@
{
"parent": "adorn:block/templates/kitchen_counter_connection_left",
"textures": {
"planks": "cobblemon:block/wood/apricorn_planks"
"planks": "cobblemon:block/apricorn_planks"
}
}
Loaded 100 of 115 files, more files were not shown because too many files have changed in this diff. Show more