Compare commits

..
Author SHA1 Message Date
Jackson Bowes 72b6cb06ff Merge branch 'soon-to-be-implemented-steps' into 'main'
Implementing some steps

See merge request cable-mc/cobblemon!2519
2026-11-01 08:15:06 -06:00
Jackson Bowes 74a57eb972 Merge branch 'sterr/move-sound-implementation' into 'main'
Added sounds to Gigaton Hammer and Pyro Ball

See merge request cable-mc/cobblemon!2518
2026-11-01 08:14:14 -06:00
Sterrezo 7246c7f8e6 Update CHANGELOG.md 2026-11-01 13:22:32 +01:00
Sterrezo cd05f741ae Merge branch 'main' into soon-to-be-implemented-steps 2026-11-01 13:21:23 +01:00
Sterrezo 00222d929d Added sounds to Gigaton Hammer and Pyro Ball 2026-11-01 13:18:22 +01:00
Polymeta b8f4637cb3 Merge branch 'feat/power-ride-training' into 'main'
power bracer ride stat training

See merge request cable-mc/cobblemon!2503
2026-10-31 12:33:22 +00:00
Ronak Chavva 9f572250f5 fix(*): modularization 2026-10-31 06:59:37 -05:00
Ronak Chavva 0927d6fa43 fix(*): enum change, configurable item stat 2026-10-31 06:26:45 -05:00
Ronak Chavva a293b3d71f changelog additions 2026-10-31 05:09:36 -05:00
Ronak Chavva 162b1cc68f Merge branch 'main' of https://gitlab.com/ronakch8/cobblemon into feat/power-ride-training 2026-10-31 05:07:29 -05:00
Polymeta 67f906dec2 [skip-ci] changelog cleanup
Signed-off-by: Polymeta <4726322-polymeta@users.noreply.gitlab.com>
2026-10-30 23:47:43 +00:00
Polymeta 0570afbe05 Merge branch 'main' into 'main'
Fix habitat structure misspelling

Closes #2132

See merge request cable-mc/cobblemon!2500
2026-10-30 23:46:30 +00:00
Rayegun dfba2d27ab Fix habitat structure misspelling 2026-10-30 23:46:29 +00:00
Polymeta 9c7cd4b616 Merge branch 'healer-spawn-point' into 'main'
Healer spawn point

See merge request cable-mc/cobblemon!2489
2026-10-30 23:43:30 +00:00
Polymeta 9fe0e9c87e [skip-ci] changelog cleanup
Signed-off-by: Polymeta <4726322-polymeta@users.noreply.gitlab.com>
2026-10-30 23:40:22 +00:00
Polymeta bd0e5a44bd Merge branch 'feat/amethyst-core' into 'main'
feat/amethyst core

See merge request cable-mc/cobblemon!2505
2026-10-30 23:39:37 +00:00
Polymeta 229ec4176b [skip-ci] changelog cleanup
Signed-off-by: Polymeta <4726322-polymeta@users.noreply.gitlab.com>
2026-10-30 23:38:54 +00:00
Polymeta 323413efdc Merge branch 'fix/ponigiri-food-values-appleskin' into 'main'
fix: correct ponigiri values for AppleSkin

See merge request cable-mc/cobblemon!2513
2026-10-30 23:35:37 +00:00
Polymeta a309cc2522 [skip-ci] changelog cleanup
Signed-off-by: Polymeta <4726322-polymeta@users.noreply.gitlab.com>
2026-10-30 23:33:53 +00:00
Polymeta cb782a2aa1 Merge branch 'steppy-steps' into 'main'
Pokémon Stepsounds

Closes #2107

See merge request cable-mc/cobblemon!2432
2026-10-30 23:30:31 +00:00
Sterrezo 2c58dcb8ef Update CHANGELOG.md 2026-10-31 00:31:51 +01:00
Sterrezo d91cd4322c Merge branch 'main' into steppy-steps 2026-10-31 00:29:14 +01:00
whatsy e48e492392 Update CHANGELOG.md 2026-10-27 23:45:20 -04:00
whatsy 1f93994eba Merge branch 'main' into healer-spawn-point
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/world/gamerules/CobblemonGameRules.kt
2026-10-27 23:45:02 -04:00
whatsy 5210121b3d Update CHANGELOG.md 2026-10-27 23:36:23 -04:00
Gitoido Okaski 7fa3bf24d1 chore: update explanation skip_cl 2026-10-28 03:10:34 +00:00
Gitoido Okaski 1128d7edf3 fix: appleskin gradle stuff for runtime 2026-10-28 03:10:34 +00:00
Gitoido Okaski eef50a7237 fix: correct ponigiri values for AppleSkin 2026-10-28 03:10:34 +00:00
Ronak Chavva 397d3c618d reverted amythest pokespawn condition 2026-10-23 18:28:22 -05:00
Ronak Chavva 066a6b56f7 Merge branch 'main' of https://gitlab.com/ronakch8/cobblemon into feat/power-ride-training 2026-10-23 18:13:32 -05:00
Ronak Chavva 29f6feab6c Merge branch 'main' of https://gitlab.com/ronakch8/cobblemon into feat/amethyst-core 2026-10-23 18:09:35 -05:00
Ronak Chavva ea5d3ae40f amethyst grows on core 2026-10-23 18:09:11 -05:00
Ronak Chavva 7687833add mapping rewrite 2026-10-22 21:35:48 -05:00
Ronak Chavva cb9ba82fcc holding power bracer while riding, 1 to all 5 stats 2026-10-22 03:11:14 -05:00
whatsy bacc482bf0 finishing touches 2026-10-14 16:25:16 -04:00
Gertimoshka edb3f906f8 Simpler Mixin 2026-10-14 21:48:14 +02:00
whatsy 4171bf341b Add config option to allow using healing machines as a respawn point 2026-10-14 15:02:54 -04:00
Gitoido 61d53f3052 Merge branch 'main' into 'steppy-steps'
# Conflicts:
#   common/src/main/kotlin/com/cobblemon/mod/common/entity/pokemon/PokemonEntity.kt
2026-10-09 16:19:32 +00:00
Sterrezo 4221993f7d Added stepsounds to Mr. Mime 2026-10-03 14:39:21 +02:00
Sterrezo a616c25c8c Added stepsounds to Parasect 2026-09-30 14:45:00 +02:00
Sterrezo 6ce4bf5673 Added stepsounds to Rhyhorn 2026-09-30 14:34:07 +02:00
Sterrezo 1b652ba99f Added stepsounds to Rhydron 2026-09-30 14:01:50 +02:00
Sterrezo 11b59df386 Added stepsounds to Dewgong 2026-09-28 20:20:16 +02:00
Sterrezo ac2b068bf3 Added stepsounds to Blastoise 2026-09-28 14:06:42 +02:00
Sterrezo 8e8f346e52 Added stepsounds keyframes to Venusaur 2026-09-28 13:47:47 +02:00
dhi_holo b426df7271 A Metric Buttton of Tagging
Added a bunch of tags, IDs, and redundancies, it doesn't cover everything but it should cover a lot of the base game without much worry
2026-09-28 10:29:50 +10:00
Sterrezo 1543e06a06 Update CHANGELOG.md 2026-09-27 14:56:17 +02:00
Sterrezo d7b4ccb1e5 Update corviknight.animation.json 2026-09-27 14:46:07 +02:00
Sterrezo dedd449329 Update corviknight.animation.json 2026-09-27 14:45:31 +02:00
Sterrezo 38c589658f Finalized assets and added amethyst stepsounds it'S FINALLY DONE 2026-09-27 14:44:29 +02:00
Sterrezo 2f961bd7bf Expanded on all stepsounds to cover metal surfaces 2026-09-26 23:52:15 +02:00
Sterrezo b72244a986 Added large and medium claw stepsounds for glass surfaces 2026-09-26 19:42:06 +02:00
Sterrezo 6710f25190 Added medium and large claw stepsounds for mud, wood and snow surfaces, updated mud hoof stepsounds 2026-09-26 15:44:32 +02:00
Sterrezo 4089e5d7a9 Added medium and large claw stepsounds for dirt and sand surfaces, updated stone claw stepsounds 2026-09-26 11:54:45 +02:00
Sterrezo 0a49b5b17b Added medium and large claw stepsounds for stone surfaces, updated grass claw stepsounds 2026-09-25 16:57:06 +02:00
Sterrezo 34c40de429 Suppressed Pidgeot's and Corviknight's Minecraft stepsounds 2026-09-25 12:03:03 +02:00
Sterrezo 6d02144401 Updated grass claw stepsound assets 2026-09-25 12:01:42 +02:00
Sterrezo 561687ce0f Added stepsounds to Pidgeot's ride walk animations 2026-09-25 11:30:28 +02:00
Sterrezo 20973c6724 Added stepsound keyframes to Pidgeot, added medium and large claw stepsounds for grass surfaces 2026-09-24 22:44:15 +02:00
Sterrezo bf10a4dcef Added medium and large hoof stepsounds for glass and ice surfaces 2026-09-24 21:23:37 +02:00
Sterrezo 565987a780 Added standard medium and large stepsounds for glass/ice surfaces, updated mud hoof sounds 2026-09-23 14:49:34 +02:00
Sterrezo 4f9a6c8e98 Added medium and large hoof stepsounds for mud surfaces 2026-09-23 10:46:56 +02:00
Sterrezo 3a3e92d441 Update CHANGELOG.md 2026-09-23 00:38:26 +02:00
Sterrezo bc0dc809f9 Merge branch 'main' into steppy-steps 2026-09-23 00:37:33 +02:00
Sterrezo 92310847aa Footsteps now check from depth 0 instead of 1 2026-09-23 00:08:37 +02:00
Polymeta 5bdc59830c change standingOn logic to consider non-full blocks
Signed-off-by: Polymeta <4726322-polymeta@users.noreply.gitlab.com>
2026-09-22 22:44:09 +01:00
Sterrezo 17f524d3da Added standard medium and large stepsounds for mud surfaces 2026-09-22 18:45:29 +02:00
Sterrezo 4d0de2bb45 Corrected the size sound variation for leaves stepsounds 2026-09-22 15:52:05 +02:00
Sterrezo b3b8f56bb8 Made block tags optional 2026-09-22 15:45:46 +02:00
Sterrezo f036b83693 Added universal stepsounds for leaves 2026-09-22 15:34:17 +02:00
Sterrezo 73fb31c2fc Added hoof stepsounds for wood surfaces 2026-09-22 10:49:03 +02:00
Sterrezo 381787f39d Updated standard wood stepsounds 2026-09-22 10:24:12 +02:00
Sterrezo 2cb942a24b Merge branch 'main' into steppy-steps 2026-09-10 21:26:50 +02:00
Sterrezo c79cb5731e Missclicked 2026-09-10 18:14:43 +02:00
Sterrezo 4760bb15a4 Added standard medium and large footsteps for wood surfaces 2026-09-10 18:14:28 +02:00
Sterrezo aac881f23c Added large and medium hoof footstep sounds 2026-09-09 18:31:27 +02:00
Sterrezo da19c51566 Implemented standard medium and large snow footsteps 2026-09-09 17:58:27 +02:00
Sterrezo 37dd354155 Merge branch 'main' into steppy-steps 2026-09-06 11:12:32 +02:00
Sterrezo acb1ebda19 Finalized hoof sounds 2026-05-27 12:34:57 +02:00
Sterrezo 5dddc05626 Merge branch 'main' into steppy-steps 2026-05-27 00:16:42 +02:00
Sterrezo 99890671bd Added hoof footsteps for sand surfaces and updated other hoof sounds 2026-05-26 22:21:56 +02:00
Sterrezo 9451ac5f46 Merge branch 'main' into steppy-steps 2026-05-26 21:42:41 +02:00
Sterrezo a8e4e21ba1 Merge branch 'main' into steppy-steps 2026-05-19 14:15:48 +02:00
Sterrezo f555ba3703 Made Molang slightly less cursed with proper random functions 2026-05-16 14:24:18 +02:00
Sterrezo 37677b3730 Asset updates, added hoof on stone sounds 2026-05-16 12:17:24 +02:00
Sterrezo 2a298b2268 Merge branch 'main' into steppy-steps 2026-05-16 11:01:28 +02:00
Sterrezo ad3f94fb80 Added hoof grass medium and large sounds 2026-05-16 02:27:46 +02:00
Sterrezo 719660798e Started hoof sound implementation with Wyrdeer, asset and keyframe updates 2026-05-15 18:17:04 +02:00
Sterrezo 8d973a09e1 Tweaks to the footstep function logic to better account for depth
If depth is 2 outright, the function could pick a block below the actual block the entity is standing on if it was checked earlier in the function. Loop iterates twice, so now it plays footsteps even when standing on the edge of a block or running down slopes.
2026-05-15 11:48:50 +02:00
Sterrezo 3579a86cde Merge branch 'main' into steppy-steps 2026-05-15 11:08:00 +02:00
Sterrezo ba96a6a205 Added standard medium and large sand footsteps 2026-05-14 20:18:04 +02:00
Sterrezo f07d2a9a9a First implementation of footstep keyframes with Arcanine 2026-05-14 16:56:13 +02:00
Sterrezo 2469067fd4 Allow for silencing step sounds within the species file 2026-05-14 02:24:18 +02:00
704 changed files with 3736 additions and 2813 deletions

No files matched your search

+14 -2
View File
@@ -1,15 +1,27 @@
# Changelog
## [1.8.x (MONTH xth, 2026)](#1-8-x)
## [1.8.5 (MONTH xth, 2026)](#1-8-5)
### Additions
- Added the `healersSetSpawn` gamerule. When enabled, using a healing machine will set your spawnpoint.
- A Pokémon holding a Power item now gains 1 point in the corresponding riding stat every two minutes while being ridden. The interval is configurable, and can be disabled with `-1`.
- Added sounds to Gigaton Hammer and Pyro Ball
- Added stepsounds to Venusaur, Blastoise, Dewgong, Rhydon, Rhyhorn, Parasect and Mr. Mime.
### Changes
- Amethyst now grows from Typegem core blocks like typegems do
### Fixes
- Fixed Ponigiri food values for AppleSkin integration
- Fixed errors emitted by typos in Parched Peat bog structure files
### Developer
### Molang & Datapacks
- `q.is_standing_on_blocks` now properly checks for non-full blocks like slabs, Mud or Soul Sand
- Added Molang functions to play footstep sounds based on the corresponding surface. These are intended to be used by Pokémon animations.
- Pokémon can now have their Minecraft footstep sounds silenced in their poser. This doesn't affect emitting game events.
### Particles
### Localization
- Updated translations for:
- Updated translations for:
@@ -15,6 +15,7 @@ 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.block.HealingMachineBlock;
import com.cobblemon.mod.common.duck.ServerLevelDuck;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules;
@@ -22,10 +23,14 @@ 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.core.BlockPos;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -33,6 +38,9 @@ import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Optional;
@Mixin(ServerPlayer.class)
public abstract class ServerPlayerMixin implements PlayerSpawnerAccessor {
@@ -142,4 +150,17 @@ public abstract class ServerPlayerMixin implements PlayerSpawnerAccessor {
((ServerLevelDuck) this.serverLevel()).cobblemon$getLevelResourceLocation()
);
}
@Inject(
method = "findRespawnAndUseSpawnBlock(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;FZZ)Ljava/util/Optional;",
at = @At(value = "HEAD"),
cancellable = true
)
private static void cobblemon$useHealthStationAsRespawn(ServerLevel level, BlockPos pos, float angle, boolean forced, boolean keepInventory, CallbackInfoReturnable<Optional<ServerPlayer.RespawnPosAngle>> cir) {
BlockState state = level.getBlockState(pos);
Block block = state.getBlock();
if (block instanceof HealingMachineBlock && HealingMachineBlock.Companion.canSetSpawn(level)) {
cir.setReturnValue(HealingMachineBlock.Companion.findStandUpPosition(EntityType.PLAYER, level, pos).map((vec3) -> ServerPlayer.RespawnPosAngle.of(vec3, pos)));
}
}
}
@@ -15,9 +15,7 @@ import com.cobblemon.mod.common.ModAPI;
import com.cobblemon.mod.common.item.PokeBallItem;
import com.cobblemon.mod.common.item.PokedexItem;
import com.cobblemon.mod.common.item.WearableItem;
import com.cobblemon.mod.common.item.components.PokeBallComponent;
import com.cobblemon.mod.common.item.components.TMMoveComponent;
import com.cobblemon.mod.common.pokeball.PokeBall;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.ItemModelShaper;
@@ -59,32 +57,12 @@ public abstract class ItemRendererMixin {
cancellable = true
)
private void cobblemon$overrideItemModel(ItemStack stack, ItemDisplayContext renderMode, boolean leftHanded, PoseStack matrices, MultiBufferSource multiBufferSource, int light, int overlay, BakedModel model, CallbackInfo ci) {
boolean shouldBe2d =
renderMode == ItemDisplayContext.GUI
|| renderMode == ItemDisplayContext.FIXED
|| stack.getItem() == CobblemonItems.TECHNICAL_MACHINE;
boolean shouldBe3d =
renderMode == ItemDisplayContext.FIRST_PERSON_LEFT_HAND
|| renderMode == ItemDisplayContext.FIRST_PERSON_RIGHT_HAND
|| renderMode == ItemDisplayContext.THIRD_PERSON_LEFT_HAND
|| renderMode == ItemDisplayContext.THIRD_PERSON_RIGHT_HAND
|| renderMode == ItemDisplayContext.GROUND
|| renderMode == ItemDisplayContext.HEAD;
boolean shouldBe2d = renderMode == ItemDisplayContext.GUI || renderMode == ItemDisplayContext.FIXED || stack.getItem() == CobblemonItems.TECHNICAL_MACHINE;
ResourceLocation resourceLocation = null;
if (stack.getItem() instanceof PokeBallItem) {
if (shouldBe2d || renderMode == ItemDisplayContext.NONE) {
resourceLocation = PokeBallComponent.getPokeBall(stack).getModel2d();
}
if (shouldBe3d) {
resourceLocation = PokeBallComponent.getPokeBall(stack).getModel3d();
}
}
if (shouldBe2d) {
if (stack.getItem() instanceof PokedexItem pokedexItem) resourceLocation = pokedexItem.getType().getItemSpritePath();
if (stack.getItem() == CobblemonItems.TECHNICAL_MACHINE) {
if (stack.getItem() instanceof PokeBallItem pokeBallItem) resourceLocation = pokeBallItem.getPokeBall().getModel2d();
else if (stack.getItem() instanceof PokedexItem pokedexItem) resourceLocation = pokedexItem.getType().getItemSpritePath();
else if (stack.getItem() == CobblemonItems.TECHNICAL_MACHINE) {
TMMoveComponent component = stack.get(CobblemonItemComponents.TM_MOVE);
if (component != null) {
resourceLocation = new ResourceLocation(Cobblemon.MODID, "tm/" + component.getMove().getElementalType().showdownId() + "_tm");
@@ -96,9 +74,6 @@ public abstract class ItemRendererMixin {
if (resourceLocation != null) {
BakedModel replacementModel = this.itemModelShaper.getModelManager().getModel(new ModelResourceLocation(resourceLocation, "inventory"));
if (!cobblemon$isSameModel(model, replacementModel)) {
if (stack.getItem() instanceof PokeBallItem) {
ci.cancel();
}
ci.cancel();
render(stack, renderMode, leftHanded, matrices, multiBufferSource, light, overlay, replacementModel);
}
@@ -108,21 +83,16 @@ public abstract class ItemRendererMixin {
@Inject(method = "getModel", at = @At("HEAD"), cancellable = true)
private void cobblemon$getItemModel(ItemStack stack, Level world, LivingEntity entity, int seed, CallbackInfoReturnable<BakedModel> cir) {
ResourceLocation resourceLocation = null;
switch (stack.getItem()) {
case PokeBallItem ignored -> resourceLocation = PokeBallComponent.getPokeBall(stack).getModel3d();
case PokedexItem pokedexItem -> {
boolean isScanModel = entity instanceof Player && entity.getUseItem() == stack && entity.isUsingItem();
boolean canOpenScreen = entity != null && ((entity.getOffhandItem() == stack && !(entity.getMainHandItem().getItem() instanceof PokedexItem)) || entity.getMainHandItem() == stack);
resourceLocation = pokedexItem.getType().getItemModelPath(isScanModel ? "scanning" : (canOpenScreen ? null : "off"));
}
case WearableItem wearableItem -> resourceLocation = wearableItem.getModel3d();
default -> {
}
if (stack.getItem() instanceof PokeBallItem pokeBallItem) resourceLocation = pokeBallItem.getPokeBall().getModel3d();
else if (stack.getItem() instanceof PokedexItem pokedexItem) {
boolean isScanModel = entity instanceof Player && entity.getUseItem() == stack && entity.isUsingItem();
boolean canOpenScreen = entity != null && ((entity.getOffhandItem() == stack && !(entity.getMainHandItem().getItem() instanceof PokedexItem)) || entity.getMainHandItem() == stack);
resourceLocation = pokedexItem.getType().getItemModelPath(isScanModel ? "scanning" : (canOpenScreen ? null : "off"));
}
else if (stack.getItem() instanceof WearableItem wearableItem) resourceLocation = wearableItem.getModel3d();
if (resourceLocation != null) {
String modelPath = (stack.getItem() instanceof PokeBallItem && stack.has(CobblemonItemComponents.POKE_BALL)) ? "inventory" : MODEL_PATH;
BakedModel model = this.itemModelShaper.getModelManager().getModel(new ModelResourceLocation(resourceLocation, modelPath));
BakedModel model = this.itemModelShaper.getModelManager().getModel(new ModelResourceLocation(resourceLocation, MODEL_PATH));
ClientLevel clientWorld = world instanceof ClientLevel ? (ClientLevel) world : null;
BakedModel overriddenModel = model.getOverrides().resolve(model, stack, clientWorld, entity, seed);
cir.setReturnValue(overriddenModel == null ? this.itemModelShaper.getModelManager().getMissingModel() : overriddenModel);
@@ -133,11 +103,10 @@ public abstract class ItemRendererMixin {
// this falls back to comparing the model contents (e.g. location of the texture, width and height)
@Unique
private static boolean cobblemon$isSameModel(BakedModel original, BakedModel replacement) {
return original.equals(replacement) || (
original.getParticleIcon().contents().name().equals(replacement.getParticleIcon().contents().name())
&& original.getParticleIcon().contents().width() == replacement.getParticleIcon().contents().width()
&& original.getParticleIcon().contents().height() == replacement.getParticleIcon().contents().height()
);
return original.equals(replacement) ||
(original.getParticleIcon().contents().name().equals(replacement.getParticleIcon().contents().name()) &&
original.getParticleIcon().contents().width() == replacement.getParticleIcon().contents().width() &&
original.getParticleIcon().contents().height() == replacement.getParticleIcon().contents().height());
}
}
@@ -9,7 +9,6 @@
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.client.CobblemonBakingOverrides;
import com.cobblemon.mod.common.client.CobblemonClient;
import net.minecraft.client.Minecraft;
import net.minecraft.client.color.block.BlockColors;
import net.minecraft.client.renderer.block.model.BlockModel;
@@ -20,7 +19,6 @@ import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.Resource;
import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.world.item.ItemDisplayContext;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
@@ -31,7 +29,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@Mixin(ModelBakery.class)
public abstract class ModelLoaderMixin {
@@ -41,18 +38,15 @@ public abstract class ModelLoaderMixin {
@Shadow protected abstract void loadItemModelAndDependencies(ResourceLocation resourceLocation);
@Shadow protected abstract void loadSpecialItemModelAndDependencies(ModelResourceLocation modelResourceLocation);
@Unique
List<String> dynamicFolders = Arrays.asList("egg", "tm", "poke_ball");
List<String> dynamicFolders = Arrays.asList("egg", "tm");
@Inject(
method = "<init>",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/util/profiling/ProfilerFiller;popPush(Ljava/lang/String;)V",
ordinal = 1,
shift = At.Shift.AFTER
ordinal = 1
)
)
public void loadCustomItemModels(BlockColors blockColors,
@@ -73,24 +67,13 @@ public abstract class ModelLoaderMixin {
* hacky at the init stage and hacky at the render stage. Pretty cool in the gameplay stage though.
*
* - Hiro
*
* We also want to load different contexts (first/third person etc.) for poke ball models, so additional check was added for them.
* - Gito
*/
dynamicFolders.forEach(folder -> {
Map<ResourceLocation, Resource> map = Minecraft.getInstance().getResourceManager().listResources("models/item/" + folder, (t) -> true);
map.forEach((key, value) -> {
ResourceLocation resourceLocation = new ResourceLocation(key.getNamespace(), key.getPath().replace("models/item/", "").replace(".json", ""));
this.loadItemModelAndDependencies(resourceLocation);
if (folder.equals("poke_ball")) {
// also load variants for different display ctx
Arrays.stream(ItemDisplayContext.values())
.forEach(item -> {
ModelResourceLocation model = new ModelResourceLocation(resourceLocation, item.getSerializedName());
this.loadSpecialItemModelAndDependencies(model);
});
}
});
});
}
@@ -47,7 +47,7 @@ object CobblemonEntities : PlatformRegistry<Registry<EntityType<*>>, ResourceKey
@JvmField
val EMPTY_POKEBALL: EntityType<EmptyPokeBallEntity> = this.create(
EMPTY_POKEBALL_KEY.path,
EntityType.Builder.of({ _, world -> EmptyPokeBallEntity(PokeBalls.STRANGE_BALL, world) }, MobCategory.MISC)
EntityType.Builder.of({ _, world -> EmptyPokeBallEntity(PokeBalls.POKE_BALL, world) }, MobCategory.MISC)
.build(EMPTY_POKEBALL_KEY.toString())
)
@@ -99,4 +99,4 @@ object CobblemonEntities : PlatformRegistry<Registry<EntityType<*>>, ResourceKey
consumer(POKEMON, PokemonEntity.createAttributes())
consumer(NPC, NPCEntity.createAttributes())
}
}
}
@@ -99,12 +99,6 @@ object CobblemonItemComponents : PlatformRegistry<Registry<DataComponentType<*>>
.networkSynchronized(ByteBufCodecs.BOOL)
.build())
@JvmField
val POKE_BALL: DataComponentType<PokeBallComponent> = create("poke_ball", DataComponentType.builder<PokeBallComponent>()
.persistent(PokeBallComponent.CODEC)
.networkSynchronized(PokeBallComponent.PACKET_CODEC)
.build())
fun register() {
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:pokemon_item"), POKEMON_ITEM)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:bait"), BAIT)
@@ -118,10 +112,9 @@ object CobblemonItemComponents : PlatformRegistry<Registry<DataComponentType<*>>
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:food"), FOOD)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:mob_effects"), MOB_EFFECTS)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:held_item_effect"), HELD_ITEM_EFFECT)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:poke_ball"), POKE_BALL)
}
override val registry = BuiltInRegistries.DATA_COMPONENT_TYPE
override val resourceKey = Registries.DATA_COMPONENT_TYPE
}
}
@@ -75,105 +75,103 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
val NPC_EDITOR = create("npc_editor", CobblemonItem(Item.Properties().stacksTo(1)))
@JvmField
val pokeBalls = mutableMapOf< ResourceLocation, PokeBallItem>()
val pokeBalls = mutableListOf<PokeBallItem>()
@JvmField
val STRANGE_BALL = pokeBallItem("strange_ball")
val POKE_BALL = pokeBallItem(PokeBalls.POKE_BALL)
@JvmField
val POKE_BALL = pokeBallItem("poke_ball")
val CITRINE_BALL = pokeBallItem(PokeBalls.CITRINE_BALL)
@JvmField
val CITRINE_BALL = pokeBallItem("citrine_ball")
val VERDANT_BALL = pokeBallItem(PokeBalls.VERDANT_BALL)
@JvmField
val VERDANT_BALL = pokeBallItem("verdant_ball")
val AZURE_BALL = pokeBallItem(PokeBalls.AZURE_BALL)
@JvmField
val AZURE_BALL = pokeBallItem("azure_ball")
val ROSEATE_BALL = pokeBallItem(PokeBalls.ROSEATE_BALL)
@JvmField
val ROSEATE_BALL = pokeBallItem("roseate_ball")
val SLATE_BALL = pokeBallItem(PokeBalls.SLATE_BALL)
@JvmField
val SLATE_BALL = pokeBallItem("slate_ball")
val PREMIER_BALL = pokeBallItem(PokeBalls.PREMIER_BALL)
@JvmField
val PREMIER_BALL = pokeBallItem("premier_ball")
val GREAT_BALL = pokeBallItem(PokeBalls.GREAT_BALL)
@JvmField
val GREAT_BALL = pokeBallItem("great_ball")
val ULTRA_BALL = pokeBallItem(PokeBalls.ULTRA_BALL)
@JvmField
val ULTRA_BALL = pokeBallItem("ultra_ball")
val SAFARI_BALL = pokeBallItem(PokeBalls.SAFARI_BALL)
@JvmField
val SAFARI_BALL = pokeBallItem("safari_ball")
val FAST_BALL = pokeBallItem(PokeBalls.FAST_BALL)
@JvmField
val FAST_BALL = pokeBallItem("fast_ball")
val LEVEL_BALL = pokeBallItem(PokeBalls.LEVEL_BALL)
@JvmField
val LEVEL_BALL = pokeBallItem("level_ball")
val LURE_BALL = pokeBallItem(PokeBalls.LURE_BALL)
@JvmField
val LURE_BALL = pokeBallItem("lure_ball")
val HEAVY_BALL = pokeBallItem(PokeBalls.HEAVY_BALL)
@JvmField
val HEAVY_BALL = pokeBallItem("heavy_ball")
val LOVE_BALL = pokeBallItem(PokeBalls.LOVE_BALL)
@JvmField
val LOVE_BALL = pokeBallItem("love_ball")
val FRIEND_BALL = pokeBallItem(PokeBalls.FRIEND_BALL)
@JvmField
val FRIEND_BALL = pokeBallItem("friend_ball")
val MOON_BALL = pokeBallItem(PokeBalls.MOON_BALL)
@JvmField
val MOON_BALL = pokeBallItem("moon_ball")
val SPORT_BALL = pokeBallItem(PokeBalls.SPORT_BALL)
@JvmField
val SPORT_BALL = pokeBallItem("sport_ball")
val PARK_BALL = pokeBallItem(PokeBalls.PARK_BALL)
@JvmField
val PARK_BALL = pokeBallItem("park_ball")
val NET_BALL = pokeBallItem(PokeBalls.NET_BALL)
@JvmField
val NET_BALL = pokeBallItem("net_ball")
val DIVE_BALL = pokeBallItem(PokeBalls.DIVE_BALL)
@JvmField
val DIVE_BALL = pokeBallItem("dive_ball")
val NEST_BALL = pokeBallItem(PokeBalls.NEST_BALL)
@JvmField
val NEST_BALL = pokeBallItem("nest_ball")
val REPEAT_BALL = pokeBallItem(PokeBalls.REPEAT_BALL)
@JvmField
val REPEAT_BALL = pokeBallItem("repeat_ball")
val TIMER_BALL = pokeBallItem(PokeBalls.TIMER_BALL)
@JvmField
val TIMER_BALL = pokeBallItem("timer_ball")
val LUXURY_BALL = pokeBallItem(PokeBalls.LUXURY_BALL)
@JvmField
val LUXURY_BALL = pokeBallItem("luxury_ball")
val DUSK_BALL = pokeBallItem(PokeBalls.DUSK_BALL)
@JvmField
val DUSK_BALL = pokeBallItem("dusk_ball")
val HEAL_BALL = pokeBallItem(PokeBalls.HEAL_BALL)
@JvmField
val HEAL_BALL = pokeBallItem("heal_ball")
val QUICK_BALL = pokeBallItem(PokeBalls.QUICK_BALL)
@JvmField
val QUICK_BALL = pokeBallItem("quick_ball")
val DREAM_BALL = pokeBallItem(PokeBalls.DREAM_BALL)
@JvmField
val DREAM_BALL = pokeBallItem("dream_ball")
val BEAST_BALL = pokeBallItem(PokeBalls.BEAST_BALL)
@JvmField
val BEAST_BALL = pokeBallItem("beast_ball")
val MASTER_BALL = pokeBallItem(PokeBalls.MASTER_BALL)
@JvmField
val MASTER_BALL = pokeBallItem("master_ball")
val CHERISH_BALL = pokeBallItem(PokeBalls.CHERISH_BALL)
@JvmField
val CHERISH_BALL = pokeBallItem("cherish_ball")
val ANCIENT_POKE_BALL = pokeBallItem(PokeBalls.ANCIENT_POKE_BALL)
@JvmField
val ANCIENT_POKE_BALL = pokeBallItem("ancient_poke_ball")
val ANCIENT_CITRINE_BALL = pokeBallItem(PokeBalls.ANCIENT_CITRINE_BALL)
@JvmField
val ANCIENT_CITRINE_BALL = pokeBallItem("ancient_citrine_ball")
val ANCIENT_VERDANT_BALL = pokeBallItem(PokeBalls.ANCIENT_VERDANT_BALL)
@JvmField
val ANCIENT_VERDANT_BALL = pokeBallItem("ancient_verdant_ball")
val ANCIENT_AZURE_BALL = pokeBallItem(PokeBalls.ANCIENT_AZURE_BALL)
@JvmField
val ANCIENT_AZURE_BALL = pokeBallItem("ancient_azure_ball")
val ANCIENT_ROSEATE_BALL = pokeBallItem(PokeBalls.ANCIENT_ROSEATE_BALL)
@JvmField
val ANCIENT_ROSEATE_BALL = pokeBallItem("ancient_roseate_ball")
val ANCIENT_SLATE_BALL = pokeBallItem(PokeBalls.ANCIENT_SLATE_BALL)
@JvmField
val ANCIENT_SLATE_BALL = pokeBallItem("ancient_slate_ball")
val ANCIENT_IVORY_BALL = pokeBallItem(PokeBalls.ANCIENT_IVORY_BALL)
@JvmField
val ANCIENT_IVORY_BALL = pokeBallItem("ancient_ivory_ball")
val ANCIENT_GREAT_BALL = pokeBallItem(PokeBalls.ANCIENT_GREAT_BALL)
@JvmField
val ANCIENT_GREAT_BALL = pokeBallItem("ancient_great_ball")
val ANCIENT_ULTRA_BALL = pokeBallItem(PokeBalls.ANCIENT_ULTRA_BALL)
@JvmField
val ANCIENT_ULTRA_BALL = pokeBallItem("ancient_ultra_ball")
val ANCIENT_FEATHER_BALL = pokeBallItem(PokeBalls.ANCIENT_FEATHER_BALL)
@JvmField
val ANCIENT_FEATHER_BALL = pokeBallItem("ancient_feather_ball")
val ANCIENT_WING_BALL = pokeBallItem(PokeBalls.ANCIENT_WING_BALL)
@JvmField
val ANCIENT_WING_BALL = pokeBallItem("ancient_wing_ball")
val ANCIENT_JET_BALL = pokeBallItem(PokeBalls.ANCIENT_JET_BALL)
@JvmField
val ANCIENT_JET_BALL = pokeBallItem("ancient_jet_ball")
val ANCIENT_HEAVY_BALL = pokeBallItem(PokeBalls.ANCIENT_HEAVY_BALL)
@JvmField
val ANCIENT_HEAVY_BALL = pokeBallItem("ancient_heavy_ball")
val ANCIENT_LEADEN_BALL = pokeBallItem(PokeBalls.ANCIENT_LEADEN_BALL)
@JvmField
val ANCIENT_LEADEN_BALL = pokeBallItem("ancient_leaden_ball")
val ANCIENT_GIGATON_BALL = pokeBallItem(PokeBalls.ANCIENT_GIGATON_BALL)
@JvmField
val ANCIENT_GIGATON_BALL = pokeBallItem("ancient_gigaton_ball")
@JvmField
val ANCIENT_ORIGIN_BALL = pokeBallItem("ancient_origin_ball")
val ANCIENT_ORIGIN_BALL = pokeBallItem(PokeBalls.ANCIENT_ORIGIN_BALL)
val pokedexes = mutableListOf<PokedexItem>()
@JvmField
@@ -1408,102 +1406,102 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
)
val pokeRods = mutableListOf<PokerodItem>()
// @JvmField
// val POKE_ROD = pokerodItem(cobblemonResource("poke_rod"))
// @JvmField
// val CITRINE_ROD = pokerodItem(cobblemonResource("citrine_rod"))
// @JvmField
// val VERDANT_ROD = pokerodItem(cobblemonResource("verdant_rod"))
// @JvmField
// val AZURE_ROD = pokerodItem(cobblemonResource("azure_rod"))
// @JvmField
// val ROSEATE_ROD = pokerodItem(cobblemonResource("roseate_rod"))
// @JvmField
// val SLATE_ROD = pokerodItem(cobblemonResource("slate_rod"))
// @JvmField
// val PREMIER_ROD = pokerodItem(cobblemonResource("premier_rod"))
// @JvmField
// val GREAT_ROD = pokerodItem(cobblemonResource("great_rod"))
// @JvmField
// val ULTRA_ROD = pokerodItem(cobblemonResource("ultra_rod"))
// @JvmField
// val SAFARI_ROD = pokerodItem(cobblemonResource("safari_rod"))
// @JvmField
// val FAST_ROD = pokerodItem(cobblemonResource("fast_rod"))
// @JvmField
// val LEVEL_ROD = pokerodItem(cobblemonResource("level_rod"))
// @JvmField
// val LURE_ROD = pokerodItem(cobblemonResource("lure_rod"))
// @JvmField
// val HEAVY_ROD = pokerodItem(cobblemonResource("heavy_rod"))
// @JvmField
// val LOVE_ROD = pokerodItem(cobblemonResource("love_rod"))
// @JvmField
// val FRIEND_ROD = pokerodItem(cobblemonResource("friend_rod"))
// @JvmField
// val MOON_ROD = pokerodItem(cobblemonResource("moon_rod"))
// @JvmField
// val SPORT_ROD = pokerodItem(cobblemonResource("sport_rod"))
// @JvmField
// val PARK_ROD = pokerodItem(cobblemonResource("park_rod"))
// @JvmField
// val NET_ROD = pokerodItem(cobblemonResource("net_rod"))
// @JvmField
// val DIVE_ROD = pokerodItem(cobblemonResource("dive_rod"))
// @JvmField
// val NEST_ROD = pokerodItem(cobblemonResource("nest_rod"))
// @JvmField
// val REPEAT_ROD = pokerodItem(cobblemonResource("repeat_rod"))
// @JvmField
// val TIMER_ROD = pokerodItem(cobblemonResource("timer_rod"))
// @JvmField
// val LUXURY_ROD = pokerodItem(cobblemonResource("luxury_rod"))
// @JvmField
// val DUSK_ROD = pokerodItem(cobblemonResource("dusk_rod"))
// @JvmField
// val HEAL_ROD = pokerodItem(cobblemonResource("heal_rod"))
// @JvmField
// val QUICK_ROD = pokerodItem(cobblemonResource("quick_rod"))
// @JvmField
// val DREAM_ROD = pokerodItem(cobblemonResource("dream_rod"))
// @JvmField
// val BEAST_ROD = pokerodItem(cobblemonResource("beast_rod"), Rarity.RARE)
// @JvmField
// val MASTER_ROD = pokerodItem(cobblemonResource("master_rod"), Rarity.EPIC)
// @JvmField
// val CHERISH_ROD = pokerodItem(cobblemonResource("cherish_rod"), Rarity.EPIC)
// @JvmField
// val ANCIENT_POKE_ROD = pokerodItem(cobblemonResource("ancient_poke_rod"))
// @JvmField
// val ANCIENT_CITRINE_ROD = pokerodItem(cobblemonResource("ancient_citrine_rod"))
// @JvmField
// val ANCIENT_VERDANT_ROD = pokerodItem(cobblemonResource("ancient_verdant_rod"))
// @JvmField
// val ANCIENT_AZURE_ROD = pokerodItem(cobblemonResource("ancient_azure_rod"))
// @JvmField
// val ANCIENT_ROSEATE_ROD = pokerodItem(cobblemonResource("ancient_roseate_rod"))
// @JvmField
// val ANCIENT_SLATE_ROD = pokerodItem(cobblemonResource("ancient_slate_rod"))
// @JvmField
// val ANCIENT_IVORY_ROD = pokerodItem(cobblemonResource("ancient_ivory_rod"))
// @JvmField
// val ANCIENT_GREAT_ROD = pokerodItem(cobblemonResource("ancient_great_rod"))
// @JvmField
// val ANCIENT_ULTRA_ROD = pokerodItem(cobblemonResource("ancient_ultra_rod"))
// @JvmField
// val ANCIENT_FEATHER_ROD = pokerodItem(cobblemonResource("ancient_feather_rod"))
// @JvmField
// val ANCIENT_WING_ROD = pokerodItem(cobblemonResource("ancient_wing_rod"))
// @JvmField
// val ANCIENT_JET_ROD = pokerodItem(cobblemonResource("ancient_jet_rod"))
// @JvmField
// val ANCIENT_HEAVY_ROD = pokerodItem(cobblemonResource("ancient_heavy_rod"))
// @JvmField
// val ANCIENT_LEADEN_ROD = pokerodItem(cobblemonResource("ancient_leaden_rod"))
// @JvmField
// val ANCIENT_GIGATON_ROD = pokerodItem(cobblemonResource("ancient_gigaton_rod"))
// @JvmField
// val ANCIENT_ORIGIN_ROD = pokerodItem(cobblemonResource("ancient_origin_rod"), Rarity.EPIC)
@JvmField
val POKE_ROD = pokerodItem(cobblemonResource("poke_rod"))
@JvmField
val CITRINE_ROD = pokerodItem(cobblemonResource("citrine_rod"))
@JvmField
val VERDANT_ROD = pokerodItem(cobblemonResource("verdant_rod"))
@JvmField
val AZURE_ROD = pokerodItem(cobblemonResource("azure_rod"))
@JvmField
val ROSEATE_ROD = pokerodItem(cobblemonResource("roseate_rod"))
@JvmField
val SLATE_ROD = pokerodItem(cobblemonResource("slate_rod"))
@JvmField
val PREMIER_ROD = pokerodItem(cobblemonResource("premier_rod"))
@JvmField
val GREAT_ROD = pokerodItem(cobblemonResource("great_rod"))
@JvmField
val ULTRA_ROD = pokerodItem(cobblemonResource("ultra_rod"))
@JvmField
val SAFARI_ROD = pokerodItem(cobblemonResource("safari_rod"))
@JvmField
val FAST_ROD = pokerodItem(cobblemonResource("fast_rod"))
@JvmField
val LEVEL_ROD = pokerodItem(cobblemonResource("level_rod"))
@JvmField
val LURE_ROD = pokerodItem(cobblemonResource("lure_rod"))
@JvmField
val HEAVY_ROD = pokerodItem(cobblemonResource("heavy_rod"))
@JvmField
val LOVE_ROD = pokerodItem(cobblemonResource("love_rod"))
@JvmField
val FRIEND_ROD = pokerodItem(cobblemonResource("friend_rod"))
@JvmField
val MOON_ROD = pokerodItem(cobblemonResource("moon_rod"))
@JvmField
val SPORT_ROD = pokerodItem(cobblemonResource("sport_rod"))
@JvmField
val PARK_ROD = pokerodItem(cobblemonResource("park_rod"))
@JvmField
val NET_ROD = pokerodItem(cobblemonResource("net_rod"))
@JvmField
val DIVE_ROD = pokerodItem(cobblemonResource("dive_rod"))
@JvmField
val NEST_ROD = pokerodItem(cobblemonResource("nest_rod"))
@JvmField
val REPEAT_ROD = pokerodItem(cobblemonResource("repeat_rod"))
@JvmField
val TIMER_ROD = pokerodItem(cobblemonResource("timer_rod"))
@JvmField
val LUXURY_ROD = pokerodItem(cobblemonResource("luxury_rod"))
@JvmField
val DUSK_ROD = pokerodItem(cobblemonResource("dusk_rod"))
@JvmField
val HEAL_ROD = pokerodItem(cobblemonResource("heal_rod"))
@JvmField
val QUICK_ROD = pokerodItem(cobblemonResource("quick_rod"))
@JvmField
val DREAM_ROD = pokerodItem(cobblemonResource("dream_rod"))
@JvmField
val BEAST_ROD = pokerodItem(cobblemonResource("beast_rod"), Rarity.RARE)
@JvmField
val MASTER_ROD = pokerodItem(cobblemonResource("master_rod"), Rarity.EPIC)
@JvmField
val CHERISH_ROD = pokerodItem(cobblemonResource("cherish_rod"), Rarity.EPIC)
@JvmField
val ANCIENT_POKE_ROD = pokerodItem(cobblemonResource("ancient_poke_rod"))
@JvmField
val ANCIENT_CITRINE_ROD = pokerodItem(cobblemonResource("ancient_citrine_rod"))
@JvmField
val ANCIENT_VERDANT_ROD = pokerodItem(cobblemonResource("ancient_verdant_rod"))
@JvmField
val ANCIENT_AZURE_ROD = pokerodItem(cobblemonResource("ancient_azure_rod"))
@JvmField
val ANCIENT_ROSEATE_ROD = pokerodItem(cobblemonResource("ancient_roseate_rod"))
@JvmField
val ANCIENT_SLATE_ROD = pokerodItem(cobblemonResource("ancient_slate_rod"))
@JvmField
val ANCIENT_IVORY_ROD = pokerodItem(cobblemonResource("ancient_ivory_rod"))
@JvmField
val ANCIENT_GREAT_ROD = pokerodItem(cobblemonResource("ancient_great_rod"))
@JvmField
val ANCIENT_ULTRA_ROD = pokerodItem(cobblemonResource("ancient_ultra_rod"))
@JvmField
val ANCIENT_FEATHER_ROD = pokerodItem(cobblemonResource("ancient_feather_rod"))
@JvmField
val ANCIENT_WING_ROD = pokerodItem(cobblemonResource("ancient_wing_rod"))
@JvmField
val ANCIENT_JET_ROD = pokerodItem(cobblemonResource("ancient_jet_rod"))
@JvmField
val ANCIENT_HEAVY_ROD = pokerodItem(cobblemonResource("ancient_heavy_rod"))
@JvmField
val ANCIENT_LEADEN_ROD = pokerodItem(cobblemonResource("ancient_leaden_rod"))
@JvmField
val ANCIENT_GIGATON_ROD = pokerodItem(cobblemonResource("ancient_gigaton_rod"))
@JvmField
val ANCIENT_ORIGIN_ROD = pokerodItem(cobblemonResource("ancient_origin_rod"), Rarity.EPIC)
// Misc
@JvmField
@@ -1586,19 +1584,15 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
private fun noSettingsItem(name: String): CobblemonItem = this.create(name, CobblemonItem(Item.Properties()))
private fun itemWithRarity(name: String, rarity: Rarity): CobblemonItem = this.create(name, CobblemonItem(Item.Properties().rarity(rarity)))
fun berries() = this.berries.toMap()
private fun mulchItem(name: String, mulchVariant: MulchVariant): MulchItem = this.create(name, MulchItem(mulchVariant))
private fun pokeBallItem(name: String): PokeBallItem {
// we attach strange ball by default to let registry load
// actual ball configurations will be attached on datapack loading stage
// see PokeBalls.reload
val ball = PokeBalls.STRANGE_BALL
val item = create(name, PokeBallItem(ball))
ball.stack = item.defaultInstance
pokeBalls.put(cobblemonResource(name), item)
private fun pokeBallItem(pokeBall: PokeBall): PokeBallItem {
val item = create(pokeBall.name.path, PokeBallItem(pokeBall))
pokeBall.item = item
pokeBalls.add(item)
return item
}
@@ -101,7 +101,6 @@ 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.pokeballs.PokeBallsRegistrySyncPacket
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
@@ -446,7 +445,6 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(MarkRegistrySyncPacket.ID, MarkRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(RideSettingsSyncPacket.ID, RideSettingsSyncPacket::decode, RideSettingsSyncHandler))
list.add(PacketRegisterInfo(TechnicalMachineRegistrySyncPacket.ID, TechnicalMachineRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(PokeBallsRegistrySyncPacket.ID, PokeBallsRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
// Effects
list.add(PacketRegisterInfo(SpawnSnowstormParticlePacket.ID, SpawnSnowstormParticlePacket::decode, SpawnSnowstormParticleHandler))
@@ -659,4 +657,4 @@ object CobblemonNetwork {
fun sendPacketToPlayer(player: ServerPlayer, packet: NetworkPacket<*>) {
Cobblemon.implementation.networkManager.sendPacketToPlayer(player, packet)
}
}
}
@@ -25,7 +25,6 @@ data class PokemonCapturedEvent (
"pokemon" to pokemon.struct,
"player" to player.asMoLangValue(),
"poke_ball" to pokeBallEntity.struct,
"item" to player.level().itemRegistry.wrapAsHolder(pokeBallEntity.pokeBall.item()).asMoLangValue(Registries.ITEM),
"stack" to pokeBallEntity.pokeBall.stack.asMoLangValue(player.level().registryAccess())
"item" to player.level().itemRegistry.wrapAsHolder(pokeBallEntity.pokeBall.item).asMoLangValue(Registries.ITEM)
)
}
}
@@ -37,7 +37,6 @@ import com.cobblemon.mod.common.api.molang.function.NPCMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.PCMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.PartyMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.PlayerMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.PokeBallMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.PokedexMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.PokemonEntityMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.PokemonMoLangFunctions
@@ -57,7 +56,6 @@ import com.cobblemon.mod.common.api.storage.party.PartyStore
import com.cobblemon.mod.common.api.storage.pc.PCStore
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.pokeball.PokeBall
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.Species
import com.cobblemon.mod.common.util.effectiveName
@@ -264,18 +262,6 @@ object MoLangFunctions {
return value
}
fun PokeBall.asMoLangValue(): ObjectValue<PokeBall> {
val value =
ObjectValue(
obj = this,
stringify = { it.name.toString() }
)
value.addFunctions(PokeBallMoLangFunctions.attach(this))
return value
}
fun Vec3.asMoLangValue(): ObjectValue<Vec3> {
val value =
ObjectValue(
@@ -403,12 +389,6 @@ object MoLangFunctions {
return this
}
fun QueryStruct.addPokeBallFunctions(ball: PokeBall): QueryStruct {
val addedFunctions = PokeBallMoLangFunctions.attach(ball)
addFunctions(addedFunctions)
return this
}
fun <T : QueryStruct> T.addFunctions(functions: Map<String, Function<MoParams, Any>>): T {
this.functions.putAll(functions)
return this
@@ -23,7 +23,6 @@ import com.cobblemon.mod.common.api.scheduling.Schedulable
import com.cobblemon.mod.common.api.text.text
import com.cobblemon.mod.common.entity.MoLangScriptingEntity
import com.cobblemon.mod.common.entity.PosableEntity
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
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.util.asArrayValue
@@ -308,15 +307,6 @@ object EntityMoLangFunctions : AbstractMoLangFunctionHolder<Entity>() {
functions["face"] = { params ->
ObjectValue(ReferenceDialogueFaceProvider(entity.id, params.getBooleanOrNull(0) != false))
}
// EmptyPokeBallEntity is a subclass of PosableEntity
// meaning we need to add a condition here to attach our func
// only to instance of EmptyPokeBallEntity
if (entity is EmptyPokeBallEntity) {
functions["capture_state"] = {
StringValue(entity.captureState.toString())
}
}
}
is Schedulable -> {
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.api.molang.function
import com.bedrockk.molang.runtime.MoParams
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.api.storage.party.PartyStore
import com.cobblemon.mod.common.pokemon.Pokemon
@@ -31,12 +30,6 @@ object PartyMoLangFunctions : AbstractMoLangFunctionHolder<PartyStore>() {
party.set(index, pokemon)
DoubleValue.ONE
}
functions["max_level"] = {
MoValue.of(party.maxOf { it.level })
}
functions["avg_level"] = {
MoValue.of(party.sumOf { it.level }.div(party.occupied()))
}
return functions
}
@@ -32,7 +32,6 @@ import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.activeDialogue
import com.cobblemon.mod.common.util.asBlockPos
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import com.cobblemon.mod.common.util.asResource
import com.cobblemon.mod.common.util.asUUID
import com.cobblemon.mod.common.util.getBattleState
@@ -48,18 +47,15 @@ import com.cobblemon.mod.common.util.pc
import com.cobblemon.mod.common.util.pokedex
import com.cobblemon.mod.common.util.server
import com.cobblemon.mod.common.util.tmList
import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.core.registries.Registries
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.sounds.SoundSource
import net.minecraft.stats.Stats
import net.minecraft.tags.TagKey
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.GameType
import kotlin.jvm.optionals.getOrNull
object PlayerMoLangFunctions : AbstractMoLangFunctionHolder<Player>() {
override fun Player.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
@@ -436,32 +432,6 @@ object PlayerMoLangFunctions : AbstractMoLangFunctionHolder<Player>() {
functions["has_chosen_starter"] = {
DoubleValue(Cobblemon.playerDataManager.getGenericData(player).starterSelected)
}
functions["has_item"] = hasItem@{ params ->
val check = params.getString(0)
if (check.isNullOrBlank()) return@hasItem DoubleValue.ZERO
when (check.startsWith("#")) {
true -> {
val tag = TagKey.create(
Registries.ITEM,
check.replace("#", "").asIdentifierDefaultingNamespace(),
)
DoubleValue(player.inventory.contains(tag))
}
false -> {
val identifier = check.asIdentifierDefaultingNamespace();
val holder = registryAccess()
.registryOrThrow(Registries.ITEM)
.getHolder(identifier)
.getOrNull() ?: return@hasItem DoubleValue.ZERO
DoubleValue(player.inventory.contains { itemStack -> itemStack.`is`(holder) })
}
}
}
}
}
@@ -1,25 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.molang.function
import com.bedrockk.molang.runtime.MoParams
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.api.battles.interpreter.BattleMessage
import com.cobblemon.mod.common.pokeball.PokeBall
import com.cobblemon.mod.common.util.getStringOrNull
object PokeBallMoLangFunctions : AbstractMoLangFunctionHolder<PokeBall>() {
override fun PokeBall.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val ball = this
val functions = hashMapOf<String, (MoParams) -> Any>()
return functions
}
}
@@ -47,10 +47,6 @@ object PokemonMoLangFunctions : AbstractMoLangFunctionHolder<Pokemon>() {
functions["max_hp"] = { DoubleValue(pokemon.maxHealth.toDouble()) }
functions["current_hp"] = { DoubleValue(pokemon.currentHealth.toDouble()) }
functions["friendship"] = { DoubleValue(pokemon.friendship.toDouble()) }
functions["set_friendship"] = { params ->
val amount = params.getDouble(0)
pokemon.setFriendship(amount.toInt())
}
functions["max_fullness"] = { DoubleValue(pokemon.getMaxFullness().toDouble()) }
functions["fullness"] = { DoubleValue(pokemon.currentFullness.toDouble()) }
functions["lose_fullness"] = { params ->
@@ -456,7 +452,6 @@ object PokemonMoLangFunctions : AbstractMoLangFunctionHolder<Pokemon>() {
functions["entity"] = { pokemon.entity?.asMoLangValue() ?: DoubleValue.ZERO }
functions["is_alpha"] = { DoubleValue(pokemon.isAlpha) }
functions["size_category"] = { StringValue(pokemon.getSizeCategory().name) }
functions["full_heal"] = { pokemon.heal() }
return functions
}
@@ -8,344 +8,293 @@
package com.cobblemon.mod.common.api.pokeball
import com.bedrockk.molang.Expression
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.api.Priority
import com.cobblemon.mod.common.api.data.ServerJsonDataRegistry
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.pokeball.catching.CaptureEffect
import com.cobblemon.mod.common.api.pokeball.catching.CatchRateModifier
import com.cobblemon.mod.common.api.pokeball.catching.effects.CaptureEffects
import com.cobblemon.mod.common.api.pokeball.catching.effects.FriendshipEarningBoostEffect
import com.cobblemon.mod.common.api.pokeball.catching.modifiers.BaseStatModifier
import com.cobblemon.mod.common.api.pokeball.catching.modifiers.CatchRateModifiers
import com.cobblemon.mod.common.api.pokeball.catching.modifiers.DynamicMultiplierModifier
import com.cobblemon.mod.common.api.pokeball.catching.modifiers.ExpressionModifier
import com.cobblemon.mod.common.api.pokeball.catching.modifiers.*
import com.cobblemon.mod.common.api.pokemon.labels.CobblemonPokemonLabels
import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.api.pokemon.status.Statuses
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.api.types.ElementalTypes
import com.cobblemon.mod.common.item.components.PokeBallComponent
import com.cobblemon.mod.common.net.messages.client.pokeballs.PokeBallsRegistrySyncPacket
import com.cobblemon.mod.common.pokeball.PokeBall
import com.cobblemon.mod.common.util.adapters.*
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.removeIf
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import net.minecraft.advancements.critereon.MinMaxBounds
import net.minecraft.core.HolderLookup
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType
import net.minecraft.util.LowerCaseEnumTypeAdapterFactory
import java.awt.Color
import kotlin.math.roundToInt
/**
* The data registry for [PokeBall]s.
* All the pokeball fields are guaranteed to exist
*/
object PokeBalls : ServerJsonDataRegistry<PokeBall> {
// <editor-fold desc="Registry definitions">
override val type = PackType.SERVER_DATA
override val resourcePath = "pokeballs"
override val id = cobblemonResource(resourcePath)
override val observable = SimpleObservable<PokeBalls>()
override val typeToken: TypeToken<PokeBall> = TypeToken.get(PokeBall::class.java)
object PokeBalls : JsonDataRegistry<PokeBall> {
override fun setupParser(registry: HolderLookup.Provider): Gson = GsonBuilder()
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
.registerTypeAdapter(IntRange::class.java, IntRangeAdapter)
.registerTypeAdapter(MinMaxBounds.Doubles::class.java, FloatNumberRangeAdapter)
.registerTypeAdapter(CatchRateModifier::class.java, CobblemonCatchRateModifierAdapter)
.registerTypeAdapter(CaptureEffect::class.java, CobblemonCaptureEffectAdapter)
.registerTypeAdapter(Color::class.java, LiteralHexColorAdapter)
.registerTypeAdapter(PokeBall::class.java, PokeBallAdapter)
.registerTypeAdapterFactory(OptionalTypeAdapterFactory())
.registerTypeAdapterFactory(LowerCaseEnumTypeAdapterFactory())
override val id = cobblemonResource("pokeballs")
override val type = PackType.SERVER_DATA
override val observable = SimpleObservable<PokeBalls>()
// ToDo once datapack pokeball is implemented add required adapters here
override val gson: Gson = GsonBuilder()
.disableHtmlEscaping()
.setPrettyPrinting()
.create()
override val typeToken: TypeToken<PokeBall> = TypeToken.get(PokeBall::class.java)
override val resourcePath = "pokeballs"
private val entries = hashMapOf<ResourceLocation, PokeBall>()
// </editor-fold>
private val defaults = hashMapOf<ResourceLocation, PokeBall>()
// ToDo datapack pokeball type here instead
private val custom = hashMapOf<ResourceLocation, PokeBall>()
// <editor-fold desc="Default balls">
@JvmStatic
@get:JvmName("getPokeBall")
val POKE_BALL
get() = getPokeBall("poke_ball")
get() = this.byName("poke_ball")
@JvmStatic
@get:JvmName("getSlateBall")
val SLATE_BALL
get() = getPokeBall("slate_ball")
get() = this.byName("slate_ball")
@JvmStatic
@get:JvmName("getAzureBall")
val AZURE_BALL
get() = getPokeBall("azure_ball")
get() = this.byName("azure_ball")
@JvmStatic
@get:JvmName("getVerdantBall")
val VERDANT_BALL
get() = getPokeBall("verdant_ball")
get() = this.byName("verdant_ball")
@JvmStatic
@get:JvmName("getRoseateBall")
val ROSEATE_BALL
get() = getPokeBall("roseate_ball")
get() = this.byName("roseate_ball")
@JvmStatic
@get:JvmName("getCitrineBall")
val CITRINE_BALL
get() = getPokeBall("citrine_ball")
get() = this.byName("citrine_ball")
@JvmStatic
@get:JvmName("getGreatBall")
val GREAT_BALL
get() = getPokeBall("great_ball")
get() = this.byName("great_ball")
@JvmStatic
@get:JvmName("getUltraBall")
val ULTRA_BALL
get() = getPokeBall("ultra_ball")
get() = this.byName("ultra_ball")
@JvmStatic
@get:JvmName("getMasterBall")
val MASTER_BALL
get() = getPokeBall("master_ball")
get() = this.byName("master_ball")
@JvmStatic
@get:JvmName("getSafariBall")
val SAFARI_BALL
get() = getPokeBall("safari_ball")
get() = this.byName("safari_ball")
@JvmStatic
@get:JvmName("getFastBall")
val FAST_BALL
get() = getPokeBall("fast_ball")
get() = this.byName("fast_ball")
@JvmStatic
@get:JvmName("getLevelBall")
val LEVEL_BALL
get() = getPokeBall("level_ball")
get() = this.byName("level_ball")
@JvmStatic
@get:JvmName("getLureBall")
val LURE_BALL
get() = getPokeBall("lure_ball")
get() = this.byName("lure_ball")
@JvmStatic
@get:JvmName("getHeavyBall")
val HEAVY_BALL
get() = getPokeBall("heavy_ball")
get() = this.byName("heavy_ball")
@JvmStatic
@get:JvmName("getLoveBall")
val LOVE_BALL
get() = getPokeBall("love_ball")
get() = this.byName("love_ball")
@JvmStatic
@get:JvmName("getFriendBall")
val FRIEND_BALL
get() = getPokeBall("friend_ball")
get() = this.byName("friend_ball")
@JvmStatic
@get:JvmName("getMoonBall")
val MOON_BALL
get() = getPokeBall("moon_ball")
get() = this.byName("moon_ball")
@JvmStatic
@get:JvmName("getSportBall")
val SPORT_BALL
get() = getPokeBall("sport_ball")
get() = this.byName("sport_ball")
@JvmStatic
@get:JvmName("getNetBall")
val NET_BALL
get() = getPokeBall("net_ball")
get() = this.byName("net_ball")
@JvmStatic
@get:JvmName("getDiveBall")
val DIVE_BALL
get() = getPokeBall("dive_ball")
get() = this.byName("dive_ball")
@JvmStatic
@get:JvmName("getNestBall")
val NEST_BALL
get() = getPokeBall("nest_ball")
get() = this.byName("nest_ball")
@JvmStatic
@get:JvmName("getRepeatBall")
val REPEAT_BALL
get() = getPokeBall("repeat_ball")
get() = this.byName("repeat_ball")
@JvmStatic
@get:JvmName("getTimerBall")
val TIMER_BALL
get() = getPokeBall("timer_ball")
get() = this.byName("timer_ball")
@JvmStatic
@get:JvmName("getLuxuryBall")
val LUXURY_BALL
get() = getPokeBall("luxury_ball")
get() = this.byName("luxury_ball")
@JvmStatic
@get:JvmName("getPremierBall")
val PREMIER_BALL
get() = getPokeBall("premier_ball")
get() = this.byName("premier_ball")
@JvmStatic
@get:JvmName("getDuskBall")
val DUSK_BALL
get() = getPokeBall("dusk_ball")
get() = this.byName("dusk_ball")
@JvmStatic
@get:JvmName("getHealBall")
val HEAL_BALL
get() = getPokeBall("heal_ball")
get() = this.byName("heal_ball")
@JvmStatic
@get:JvmName("getQuickBall")
val QUICK_BALL
get() = getPokeBall("quick_ball")
get() = this.byName("quick_ball")
@JvmStatic
@get:JvmName("getCherishBall")
val CHERISH_BALL
get() = getPokeBall("cherish_ball")
get() = this.byName("cherish_ball")
@JvmStatic
@get:JvmName("getParkBall")
val PARK_BALL
get() = getPokeBall("park_ball")
get() = this.byName("park_ball")
@JvmStatic
@get:JvmName("getDreamBall")
val DREAM_BALL
get() = getPokeBall("dream_ball")
get() = this.byName("dream_ball")
@JvmStatic
@get:JvmName("getBeastBall")
val BEAST_BALL
get() = getPokeBall("beast_ball")
get() = this.byName("beast_ball")
@JvmStatic
@get:JvmName("getAncientPokeBall")
val ANCIENT_POKE_BALL
get() = getPokeBall("ancient_poke_ball")
get() = this.byName("ancient_poke_ball")
@JvmStatic
@get:JvmName("getAncientCitrineBall")
val ANCIENT_CITRINE_BALL
get() = getPokeBall("ancient_citrine_ball")
get() = this.byName("ancient_citrine_ball")
@JvmStatic
@get:JvmName("getAncientVerdantBall")
val ANCIENT_VERDANT_BALL
get() = getPokeBall("ancient_verdant_ball")
get() = this.byName("ancient_verdant_ball")
@JvmStatic
@get:JvmName("getAncientAzureBall")
val ANCIENT_AZURE_BALL
get() = getPokeBall("ancient_azure_ball")
get() = this.byName("ancient_azure_ball")
@JvmStatic
@get:JvmName("getAncientRoseateBall")
val ANCIENT_ROSEATE_BALL
get() = getPokeBall("ancient_roseate_ball")
get() = this.byName("ancient_roseate_ball")
@JvmStatic
@get:JvmName("getAncientSlateBall")
val ANCIENT_SLATE_BALL
get() = getPokeBall("ancient_slate_ball")
get() = this.byName("ancient_slate_ball")
@JvmStatic
@get:JvmName("getAncientIvoryBall")
val ANCIENT_IVORY_BALL
get() = getPokeBall("ancient_ivory_ball")
get() = this.byName("ancient_ivory_ball")
@JvmStatic
@get:JvmName("getAncientGreatBall")
val ANCIENT_GREAT_BALL
get() = getPokeBall("ancient_great_ball")
get() = this.byName("ancient_great_ball")
@JvmStatic
@get:JvmName("getAncientUltraBall")
val ANCIENT_ULTRA_BALL
get() = getPokeBall("ancient_ultra_ball")
get() = this.byName("ancient_ultra_ball")
@JvmStatic
@get:JvmName("getAncientHeavyBall")
val ANCIENT_HEAVY_BALL
get() = getPokeBall("ancient_heavy_ball")
get() = this.byName("ancient_heavy_ball")
@JvmStatic
@get:JvmName("getAncientLeadenBall")
val ANCIENT_LEADEN_BALL
get() = getPokeBall("ancient_leaden_ball")
get() = this.byName("ancient_leaden_ball")
@JvmStatic
@get:JvmName("getAncientGigatonBall")
val ANCIENT_GIGATON_BALL
get() = getPokeBall("ancient_gigaton_ball")
get() = this.byName("ancient_gigaton_ball")
@JvmStatic
@get:JvmName("getAncientFeatherBall")
val ANCIENT_FEATHER_BALL
get() = getPokeBall("ancient_feather_ball")
get() = this.byName("ancient_feather_ball")
@JvmStatic
@get:JvmName("getAncientWingBall")
val ANCIENT_WING_BALL
get() = getPokeBall("ancient_wing_ball")
get() = this.byName("ancient_wing_ball")
@JvmStatic
@get:JvmName("getAncientJetBall")
val ANCIENT_JET_BALL
get() = getPokeBall("ancient_jet_ball")
get() = this.byName("ancient_jet_ball")
@JvmStatic
@get:JvmName("getAncientOriginBall")
val ANCIENT_ORIGIN_BALL
get() = getPokeBall("ancient_origin_ball")
@JvmStatic
@get:JvmName("getStrangeBall")
val STRANGE_BALL = create("strange_ball")
// </editor-fold>
get() = this.byName("ancient_origin_ball")
init {
// we need at least one default ball in case of shenanigans
create("strange_ball")
create("heavy_ball", CatchRateModifiers.WEIGHT_BASED)
create("love_ball", CatchRateModifiers.LOVE)
create("friend_ball", effects = listOf("q.pokemon.set_friendship(150.0)".asExpressionLike()))
create("moon_ball", CatchRateModifiers.MOON_PHASES)
create("net_ball", CatchRateModifiers.typeBoosting(3F, ElementalTypes.BUG, ElementalTypes.WATER))
create("dive_ball", CatchRateModifiers.SUBMERGED_IN_WATER, waterDragValue = 0.99F)
create("nest_ball", CatchRateModifiers.NEST)
create("repeat_ball", CatchRateModifiers.REPEAT)
create("timer_ball", CatchRateModifiers.turnBased { turn -> (1F + turn * (1229F / 4096F)).coerceAtMost(4F) })
create("luxury_ball" /*effects = listOf(FriendshipEarningBoostEffect(2F))*/)
create("dusk_ball", CatchRateModifiers.LIGHT_LEVEL)
create("heal_ball", effects = listOf("q.pokemon.heal()".asExpressionLike()))
create("quick_ball", CatchRateModifiers.turnBased { turn -> if (turn == 1) 5F else 1F })
create("park_ball", CatchRateModifiers.PARK)
create("dream_ball", CatchRateModifiers.statusBoosting(4F, Statuses.SLEEP))
create(
"beast_ball",
DynamicMultiplierModifier({ _, pokemon -> if (pokemon.hasLabels(CobblemonPokemonLabels.ULTRA_BEAST)) 5F else 0.1F }) { _, _ -> true })
createDefault("poke_ball")
createDefault("slate_ball")
createDefault("azure_ball")
createDefault("verdant_ball")
createDefault("roseate_ball")
createDefault("citrine_ball")
createDefault("great_ball", MultiplierModifier(1.5F))
createDefault("ultra_ball", MultiplierModifier(2F))
createDefault("master_ball", GuaranteedModifier())
createDefault("safari_ball", CatchRateModifiers.SAFARI)
createDefault("fast_ball", BaseStatModifier(Stats.SPEED, { it >= 100 }, 4F))
createDefault("level_ball", CatchRateModifiers.LEVEL)
createDefault("lure_ball", CatchRateModifiers.LURE)
createDefault("heavy_ball", CatchRateModifiers.WEIGHT_BASED)
createDefault("love_ball", CatchRateModifiers.LOVE)
createDefault("friend_ball", effects = listOf(CaptureEffects.friendshipSetter(150)))
createDefault("moon_ball", CatchRateModifiers.MOON_PHASES)
createDefault("sport_ball", MultiplierModifier(1.5F))
createDefault("net_ball", CatchRateModifiers.typeBoosting(3F, ElementalTypes.BUG, ElementalTypes.WATER))
createDefault("dive_ball", CatchRateModifiers.SUBMERGED_IN_WATER, waterDragValue = 0.99F)
createDefault("nest_ball", CatchRateModifiers.NEST)
createDefault("repeat_ball", CatchRateModifiers.REPEAT)
createDefault("timer_ball", CatchRateModifiers.turnBased { turn -> (1F + turn * (1229F / 4096F)).coerceAtMost(4F) })
createDefault("luxury_ball", effects = listOf(FriendshipEarningBoostEffect(2F)))
createDefault("premier_ball")
createDefault("dusk_ball", CatchRateModifiers.LIGHT_LEVEL)
createDefault("heal_ball", effects = listOf(CaptureEffects.FULL_RESTORE))
createDefault("quick_ball", CatchRateModifiers.turnBased { turn -> if (turn == 1) 5F else 1F })
createDefault("cherish_ball")
createDefault("park_ball", CatchRateModifiers.PARK)
createDefault("dream_ball", CatchRateModifiers.statusBoosting(4F, Statuses.SLEEP))
createDefault("beast_ball", DynamicMultiplierModifier({ _, pokemon -> if (pokemon.hasLabels(CobblemonPokemonLabels.ULTRA_BEAST)) 5F else 0.1F }) { _, _ -> true })
createDefault("ancient_poke_ball", ancient = true)
createDefault("ancient_citrine_ball", ancient = true)
createDefault("ancient_verdant_ball", ancient = true)
createDefault("ancient_azure_ball", ancient = true)
createDefault("ancient_roseate_ball", ancient = true)
createDefault("ancient_slate_ball", ancient = true)
createDefault("ancient_ivory_ball", ancient = true)
createDefault("ancient_great_ball", MultiplierModifier(1.5F), ancient = true)
createDefault("ancient_ultra_ball", MultiplierModifier(2F), ancient = true)
createDefault("ancient_heavy_ball", throwPower = 0.75f, ancient = true)
createDefault("ancient_leaden_ball", MultiplierModifier(1.5F), throwPower = 0.75f, ancient = true)
createDefault("ancient_gigaton_ball", MultiplierModifier(2F), throwPower = 0.75f, ancient = true)
createDefault("ancient_feather_ball", throwPower = 2.5f, ancient = true)
createDefault("ancient_wing_ball", MultiplierModifier(1.5F), throwPower = 2.5f, ancient = true)
createDefault("ancient_jet_ball", MultiplierModifier(2F), throwPower = 2.5f, ancient = true)
createDefault("ancient_origin_ball", GuaranteedModifier(), ancient = true)
// Luxury ball effect, low priority as it must be triggered before soothe bell as of gen 4
CobblemonEvents.FRIENDSHIP_UPDATED.subscribe(priority = Priority.LOW) { event ->
if (!event.earned) {
@@ -361,73 +310,235 @@ object PokeBalls : ServerJsonDataRegistry<PokeBall> {
}
}
override fun reload(
data: Map<ResourceLocation, PokeBall>,
registry: HolderLookup.Provider
) {
this.entries.removeIf { it.key != cobblemonResource("strange_ball") }
data.entries.forEach {
val (key, ball) = it
ball.name = key
when(CobblemonItems.pokeBalls.containsKey(key)) {
true -> {
val item = CobblemonItems.pokeBalls.get(key)!!
item.pokeBall = ball
ball.stack = item.defaultInstance
}
false -> {
ball.stack = PokeBallComponent.createStack(ball)
}
}
this.entries[key] = ball
}
Cobblemon.LOGGER.info("Loaded ${data.size} poke balls.")
override fun reload(data: Map<ResourceLocation, PokeBall>) {
this.custom.clear()
// ToDo once datapack pokeball is implemented load them here, we will want datapacks to be able to override our default pokeballs too, however they will never be able to disable them
}
override fun sync(player: ServerPlayer) {
PokeBallsRegistrySyncPacket(this.entries).sendToPlayer(player)
// ToDo once datapack pokeball is implemented sync them here
}
/**
* Gets a Pokeball from registry name.
* @return the pokeball object if found otherwise strange ball.
* @return the pokeball object if found otherwise null.
*/
@JvmStatic
fun getPokeBall(name: ResourceLocation): PokeBall = this.entries[name] ?: STRANGE_BALL
fun getPokeBall(name : ResourceLocation): PokeBall? = this.custom[name] ?: this.defaults[name]
@JvmStatic
fun getPokeBall(name: String): PokeBall = getPokeBall(cobblemonResource(name))
fun all() = this.defaults.filterKeys { !this.custom.containsKey(it) }.values + this.custom.values
@JvmStatic
fun all() = this.entries.values
fun create(
private fun createDefault(
name: String,
modifier: CatchRateModifier = ExpressionModifier(),
effects: List<ExpressionLike> = emptyList(),
modifier: CatchRateModifier = MultiplierModifier(1F) { _, _ -> true },
effects: List<CaptureEffect> = emptyList(),
waterDragValue: Float = 0.8F,
model2d: ResourceLocation = cobblemonResource(name),
model3d: ResourceLocation = cobblemonResource("item/${name}_model"),
throwPower: Float = 1.25f,
ancient: Boolean = false,
color: Color = Color.RED
): PokeBall = PokeBall(
cobblemonResource(name),
modifier,
effects,
PokeBall.PokeBallProperties(),
waterDragValue,
model2d,
model3d,
throwPower,
ancient,
color
).also {
this.entries[it.name] = it
return it
ancient: Boolean = false
): PokeBall {
val identifier = cobblemonResource(name)
val pokeball = PokeBall(identifier, modifier, effects, waterDragValue, model2d, model3d, throwPower, ancient)
this.defaults[identifier] = pokeball
return pokeball
}
}
private fun byName(name: String): PokeBall {
val identifier = cobblemonResource(name)
return this.custom[identifier] ?: this.defaults[identifier]!!
}
/**
* Backwards compatibility getters
*/
@JvmName("getPOKE_BALL")
@Deprecated("Use PokeBalls.getPokeBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getPOKE_BALL() = POKE_BALL
@JvmName("getSLATE_BALL")
@Deprecated("Use PokeBalls.getSlateBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getSLATE_BALL() = SLATE_BALL
@JvmName("getAZURE_BALL")
@Deprecated("Use PokeBalls.getAzureBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getAZURE_BALL() = AZURE_BALL
@JvmName("getVERDANT_BALL")
@Deprecated("Use PokeBalls.getVerdantBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getVERDANT_BALL() = VERDANT_BALL
@JvmName("getROSEATE_BALL")
@Deprecated("Use PokeBalls.getRoseateBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getROSEATE_BALL() = ROSEATE_BALL
@JvmName("getCITRINE_BALL")
@Deprecated("Use PokeBalls.getCitrineBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getCITRINE_BALL() = CITRINE_BALL
@JvmName("getGREAT_BALL")
@Deprecated("Use PokeBalls.getGreatBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getGREAT_BALL() = GREAT_BALL
@JvmName("getULTRA_BALL")
@Deprecated("Use PokeBalls.getUltraBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getULTRA_BALL() = ULTRA_BALL
@JvmName("getMASTER_BALL")
@Deprecated("Use PokeBalls.getMasterBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getMASTER_BALL() = MASTER_BALL
@JvmName("getSAFARI_BALL")
@Deprecated("Use PokeBalls.getSafariBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getSAFARI_BALL() = SAFARI_BALL
@JvmName("getFAST_BALL")
@Deprecated("Use PokeBalls.getFastBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getFAST_BALL() = FAST_BALL
@JvmName("getLEVEL_BALL")
@Deprecated("Use PokeBalls.getLevelBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getLEVEL_BALL() = LEVEL_BALL
@JvmName("getLURE_BALL")
@Deprecated("Use PokeBalls.getLureBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getLURE_BALL() = LURE_BALL
@JvmName("getHEAVY_BALL")
@Deprecated("Use PokeBalls.getHeavyBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getHEAVY_BALL() = HEAVY_BALL
@JvmName("getLOVE_BALL")
@Deprecated("Use PokeBalls.getLoveBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getLOVE_BALL() = LOVE_BALL
@JvmName("getFRIEND_BALL")
@Deprecated("Use PokeBalls.getFriendBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getFRIEND_BALL() = FRIEND_BALL
@JvmName("getMOON_BALL")
@Deprecated("Use PokeBalls.getMoonBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getMOON_BALL() = MOON_BALL
@JvmName("getSPORT_BALL")
@Deprecated("Use PokeBalls.getSportBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getSPORT_BALL() = SPORT_BALL
@JvmName("getNET_BALL")
@Deprecated("Use PokeBalls.getNetBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getNET_BALL() = NET_BALL
@JvmName("getNEST_BALL")
@Deprecated("Use PokeBalls.getNestBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getNEST_BALL() = NEST_BALL
@JvmName("getREPEAT_BALL")
@Deprecated("Use PokeBalls.getRepeatBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getREPEAT_BALL() = REPEAT_BALL
@JvmName("getTIMER_BALL")
@Deprecated("Use PokeBalls.getTimerBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getTIMER_BALL() = TIMER_BALL
@JvmName("getLUXURY_BALL")
@Deprecated("Use PokeBalls.getLuxuryBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getLUXURY_BALL() = LUXURY_BALL
@JvmName("getPREMIER_BALL")
@Deprecated("Use PokeBalls.getPremierBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getPREMIER_BALL() = PREMIER_BALL
@JvmName("getDUSK_BALL")
@Deprecated("Use PokeBalls.getDuskBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getDUSK_BALL() = DUSK_BALL
@JvmName("getHEAL_BALL")
@Deprecated("Use PokeBalls.getHealBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getHEAL_BALL() = HEAL_BALL
@JvmName("getQUICK_BALL")
@Deprecated("Use PokeBalls.getQuickBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getQUICK_BALL() = QUICK_BALL
@JvmName("getCHERISH_BALL")
@Deprecated("Use PokeBalls.getCherishBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getCHERISH_BALL() = CHERISH_BALL
@JvmName("getPARK_BALL")
@Deprecated("Use PokeBalls.getParkBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getPARK_BALL() = PARK_BALL
@JvmName("getDREAM_BALL")
@Deprecated("Use PokeBalls.getDreamBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getDREAM_BALL() = DREAM_BALL
@JvmName("getBEAST_BALL")
@Deprecated("Use PokeBalls.getBeastBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getBEAST_BALL() = BEAST_BALL
@JvmName("getANCIENT_POKE_BALL")
@Deprecated("Use PokeBalls.getAncientPokeBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_POKE_BALL() = ANCIENT_POKE_BALL
@JvmName("getANCIENT_CITRINE_BALL")
@Deprecated("Use PokeBalls.getAncientCitrineBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_CITRINE_BALL() = ANCIENT_CITRINE_BALL
@JvmName("getANCIENT_VERDANT_BALL")
@Deprecated("Use PokeBalls.getAncientVerdantBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_VERDANT_BALL() = ANCIENT_VERDANT_BALL
@JvmName("getANCIENT_AZURE_BALL")
@Deprecated("Use PokeBalls.getAncientAzureBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_AZURE_BALL() = ANCIENT_AZURE_BALL
@JvmName("getANCIENT_ROSEATE_BALL")
@Deprecated("Use PokeBalls.getAncientRoseateBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_ROSEATE_BALL() = ANCIENT_ROSEATE_BALL
@JvmName("getANCIENT_SLATE_BALL")
@Deprecated("Use PokeBalls.getAncientSlateBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_SLATE_BALL() = ANCIENT_SLATE_BALL
@JvmName("getANCIENT_IVORY_BALL")
@Deprecated("Use PokeBalls.getAncientIvoryBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_IVORY_BALL() = ANCIENT_IVORY_BALL
@JvmName("getANCIENT_GREAT_BALL")
@Deprecated("Use PokeBalls.getAncientGreatBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_GREAT_BALL() = ANCIENT_GREAT_BALL
@JvmName("getANCIENT_ULTRA_BALL")
@Deprecated("Use PokeBalls.getAncientUltraBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_ULTRA_BALL() = ANCIENT_ULTRA_BALL
@JvmName("getANCIENT_HEAVY_BALL")
@Deprecated("Use PokeBalls.getAncientHeavyBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_HEAVY_BALL() = ANCIENT_HEAVY_BALL
@JvmName("getANCIENT_LEADEN_BALL")
@Deprecated("Use PokeBalls.getAncientLeadenBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_LEADEN_BALL() = ANCIENT_LEADEN_BALL
@JvmName("getANCIENT_GIGATON_BALL")
@Deprecated("Use PokeBalls.getAncientGigatonBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_GIGATON_BALL() = ANCIENT_GIGATON_BALL
@JvmName("getANCIENT_FEATHER_BALL")
@Deprecated("Use PokeBalls.getAncientFeatherBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_FEATHER_BALL() = ANCIENT_FEATHER_BALL
@JvmName("getANCIENT_WING_BALL")
@Deprecated("Use PokeBalls.getAncientWingBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_WING_BALL() = ANCIENT_WING_BALL
@JvmName("getANCIENT_JET_BALL")
@Deprecated("Use PokeBalls.getAncientJetBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_JET_BALL() = ANCIENT_JET_BALL
@JvmName("getANCIENT_ORIGIN_BALL")
@Deprecated("Use PokeBalls.getAncientOriginBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_ORIGIN_BALL() = ANCIENT_ORIGIN_BALL
}
@@ -18,10 +18,6 @@ import net.minecraft.world.entity.LivingEntity
*
* @property multiplier The multiplier for friendship gains
*/
data class FriendshipEarningBoostEffect(val multiplier: Float) : CaptureEffect {
companion object {
const val VARIANT = "friendship_boost"
}
class FriendshipEarningBoostEffect(val multiplier: Float) : CaptureEffect {
override fun apply(thrower: LivingEntity, pokemon: Pokemon) {}
}
}
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.api.pokeball.catching.modifiers
import com.cobblemon.mod.common.api.pokeball.catching.CatchRateModifier
import com.cobblemon.mod.common.api.pokemon.stats.Stat
import com.cobblemon.mod.common.pokemon.Pokemon
import net.minecraft.util.StringRepresentable
import net.minecraft.world.entity.LivingEntity
/**
@@ -27,13 +26,9 @@ import net.minecraft.world.entity.LivingEntity
*/
class BaseStatModifier(
val stat: Stat,
val value: Int,
val comparator: Comparator,
val multiplier: Float,
val comparator: (value: Int) -> Boolean,
val multiplier: Float
) : CatchRateModifier {
companion object {
const val VARIANT = "bst"
}
init {
if (stat.type != Stat.Type.PERMANENT) {
@@ -49,36 +44,9 @@ class BaseStatModifier(
override fun isValid(thrower: LivingEntity, pokemon: Pokemon): Boolean {
val valStat = pokemon.form.baseStats[this.stat] ?: return false
return when (comparator) {
Comparator.GT -> value > valStat
Comparator.LT -> value < valStat
Comparator.GTE -> value >= valStat
Comparator.LTE -> value <= valStat
Comparator.EQ -> value == valStat
Comparator.NOT -> value != valStat
}
return comparator(valStat)
}
override fun modifyCatchRate(
currentCatchRate: Float,
thrower: LivingEntity,
pokemon: Pokemon,
): Float = this.behavior(thrower, pokemon).mutator(currentCatchRate, this.value(thrower, pokemon))
override fun modifyCatchRate(currentCatchRate: Float, thrower: LivingEntity, pokemon: Pokemon): Float = this.behavior(thrower, pokemon).mutator(currentCatchRate, this.value(thrower, pokemon))
enum class Comparator : StringRepresentable {
@JvmField
GT,
@JvmField
LT,
@JvmField
GTE,
@JvmField
LTE,
@JvmField
EQ,
@JvmField
NOT,
;
override fun getSerializedName(): String = this.name.lowercase()
}
}
@@ -26,6 +26,20 @@ import com.cobblemon.mod.common.pokemon.Gender
* @since May 7th, 2022
*/
object CatchRateModifiers {
/**
* Used by [PokeBalls.LEVEL_BALL].
*/
val LEVEL = BattleModifier { _, playerPokemon, pokemon ->
val highestLevel = playerPokemon.maxOf { bp -> bp.battlePokemon?.originalPokemon?.level ?: 1 }
when {
highestLevel > (pokemon.level * 4) -> 4F
highestLevel > (pokemon.level * 2) -> 3F
highestLevel > pokemon.level -> 2F
else -> 1F
}
}
/**
* Used by [PokeBalls.DIVE_BALL].
* This is the Minecraft interpretation of the generation 3 mechanic.
@@ -90,6 +104,12 @@ object CatchRateModifiers {
}
}
/**
* Used by [PokeBalls.SAFARI_BALL].
* Checks if the target is not battling, if true boost by *1.5
*/
val SAFARI = MultiplierModifier(1.5f) { _, poke -> !poke.entity?.isBattling!! }
/**
* Used by [PokeBalls.PARK_BALL].
* Checks if the entity is in a biome valid for the tag [CobblemonBiomeTags.IS_TEMPERATE].
@@ -1,53 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokeball.catching.modifiers
import com.bedrockk.molang.runtime.MoLangRuntime
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
import com.cobblemon.mod.common.api.pokeball.catching.CatchRateModifier
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.asExpressionLike
import net.minecraft.world.entity.LivingEntity
class ExpressionModifier(
val query: ExpressionLike = "1.0".asExpressionLike(),
) : CatchRateModifier, MoLangModifier {
companion object {
const val VARIANT = "expression"
val runtime = MoLangRuntime().setup()
}
override fun isGuaranteed(): Boolean = false
override fun value(
thrower: LivingEntity,
pokemon: Pokemon
): Float {
if (query.getString().trim() == "1.0") return 1.0f
return query.resolveFloat(runtime(thrower, pokemon))
}
override fun behavior(
thrower: LivingEntity,
pokemon: Pokemon
): CatchRateModifier.Behavior = CatchRateModifier.Behavior.MULTIPLY
override fun isValid(
thrower: LivingEntity,
pokemon: Pokemon
): Boolean = true
override fun modifyCatchRate(
currentCatchRate: Float,
thrower: LivingEntity,
pokemon: Pokemon
): Float = this.behavior(thrower, pokemon).mutator(currentCatchRate, this.value(thrower, pokemon))
}
@@ -19,13 +19,11 @@ import net.minecraft.world.entity.LivingEntity
* @since August 9th, 2022
*/
class GuaranteedModifier : CatchRateModifier {
companion object {
const val VARIANT = "guaranteed"
}
override fun isGuaranteed() = true
override fun value(thrower: LivingEntity, pokemon: Pokemon): Float = 255F
override fun behavior(thrower: LivingEntity, pokemon: Pokemon): CatchRateModifier.Behavior = CatchRateModifier.Behavior.MULTIPLY
override fun isValid(thrower: LivingEntity, pokemon: Pokemon): Boolean = true
override fun modifyCatchRate(currentCatchRate: Float, thrower: LivingEntity, pokemon: Pokemon): Float = this.behavior(thrower, pokemon).mutator(currentCatchRate, this.value(thrower, pokemon))
}
}
@@ -22,22 +22,20 @@ import net.minecraft.world.entity.LivingEntity
* @property matching Will this multiplier should be applied if the labels match?
* @property labels The literal labels being queried.
*/
data class LabelModifier(val multiplier: Float, val matching: Boolean, val labels: List<String>) : CatchRateModifier {
companion object {
const val VARIANT = "labels"
}
class LabelModifier(
val multiplier: Float,
val matching: Boolean,
vararg val labels: String
) : CatchRateModifier {
override fun isGuaranteed(): Boolean = false
override fun value(thrower: LivingEntity, pokemon: Pokemon): Float = this.multiplier
override fun behavior(thrower: LivingEntity, pokemon: Pokemon): CatchRateModifier.Behavior =
CatchRateModifier.Behavior.MULTIPLY
override fun behavior(thrower: LivingEntity, pokemon: Pokemon): CatchRateModifier.Behavior = CatchRateModifier.Behavior.MULTIPLY
override fun isValid(thrower: LivingEntity, pokemon: Pokemon): Boolean =
if (this.matching) pokemon.hasLabels(*this.labels.toSet().toTypedArray()) else !pokemon.hasLabels(*this.labels.toSet().toTypedArray())
override fun isValid(thrower: LivingEntity, pokemon: Pokemon): Boolean = if (this.matching) pokemon.hasLabels(*this.labels) else !pokemon.hasLabels(*this.labels)
override fun modifyCatchRate(currentCatchRate: Float, thrower: LivingEntity, pokemon: Pokemon): Float =
this.behavior(thrower, pokemon).mutator(currentCatchRate, this.value(thrower, pokemon))
override fun modifyCatchRate(currentCatchRate: Float, thrower: LivingEntity, pokemon: Pokemon): Float = this.behavior(thrower, pokemon).mutator(currentCatchRate, this.value(thrower, pokemon))
}
}
@@ -1,42 +0,0 @@
package com.cobblemon.mod.common.api.pokeball.catching.modifiers
import com.bedrockk.molang.runtime.MoLangRuntime
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asBiomeMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asStruct
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asWorldMoLangValue
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.toBlockPos
import com.cobblemon.mod.common.util.withPlayerValue
import com.cobblemon.mod.common.util.withQueryValue
import net.minecraft.core.registries.Registries
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.LivingEntity
interface MoLangModifier {
fun runtime(thrower: LivingEntity, pokemon: Pokemon): MoLangRuntime {
val biomeValue = thrower.level().getBiome(thrower.position().toBlockPos()).asBiomeMoLangValue()
val worldValue = thrower
.level()
.registryAccess()
.registryOrThrow(Registries.DIMENSION)
.wrapAsHolder(thrower.level())
.asWorldMoLangValue()
return ExpressionModifier.runtime
.withQueryValue("world", worldValue)
.withQueryValue("biome", biomeValue)
.withQueryValue("pokemon", pokemon.asStruct())
.withQueryValue("thrower", thrower.asMostSpecificMoLangValue())
.let {
if (pokemon.entity?.battle != null) {
return@let it.withQueryValue("battle", pokemon.entity!!.battle!!.asMoLangValue())
}
it
}
}
}
@@ -13,21 +13,19 @@ import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.pokemon.Pokemon
import net.minecraft.world.entity.LivingEntity
data class PropertyBasedModifier(val property: PokemonProperties, val multiplier: Float) : CatchRateModifier {
companion object {
const val VARIANT = "property"
}
class PropertyBasedModifier(
val property: PokemonProperties,
val multiplier: Float
) : CatchRateModifier {
override fun isGuaranteed(): Boolean = false
override fun value(thrower: LivingEntity, pokemon: Pokemon): Float = this.multiplier
override fun behavior(thrower: LivingEntity, pokemon: Pokemon): CatchRateModifier.Behavior =
CatchRateModifier.Behavior.MULTIPLY
override fun behavior(thrower: LivingEntity, pokemon: Pokemon): CatchRateModifier.Behavior = CatchRateModifier.Behavior.MULTIPLY
override fun isValid(thrower: LivingEntity, pokemon: Pokemon): Boolean = this.property.matches(pokemon)
override fun modifyCatchRate(currentCatchRate: Float, thrower: LivingEntity, pokemon: Pokemon): Float =
this.behavior(thrower, pokemon).mutator(currentCatchRate, this.value(thrower, pokemon))
override fun modifyCatchRate(currentCatchRate: Float, thrower: LivingEntity, pokemon: Pokemon): Float = this.behavior(thrower, pokemon).mutator(currentCatchRate, this.value(thrower, pokemon))
}
@@ -1,34 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokeball.catching.modifiers
import com.cobblemon.mod.common.api.pokeball.catching.CatchRateModifier
import com.cobblemon.mod.common.pokemon.Pokemon
import net.minecraft.world.entity.LivingEntity
data class SimpleModifier(val value: Float) : CatchRateModifier {
companion object {
const val VARIANT = "simple"
}
override fun isGuaranteed(): Boolean = false
override fun value(thrower: LivingEntity, pokemon: Pokemon): Float = this.value
override fun behavior(thrower: LivingEntity, pokemon: Pokemon): CatchRateModifier.Behavior =
CatchRateModifier.Behavior.MULTIPLY
override fun isValid(thrower: LivingEntity, pokemon: Pokemon): Boolean = true
override fun modifyCatchRate(
currentCatchRate: Float,
thrower: LivingEntity,
pokemon: Pokemon,
): Float = behavior(thrower, pokemon).mutator(currentCatchRate, value(thrower, pokemon))
}
@@ -25,9 +25,7 @@ import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.item.PokeBallItem
import com.cobblemon.mod.common.item.components.PokeBallComponent
import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimationPacket
import com.cobblemon.mod.common.pokeball.PokeBall
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.activestate.ShoulderedState
import com.cobblemon.mod.common.pokemon.evolution.variants.ItemInteractionEvolution
@@ -140,7 +138,7 @@ interface Evolution : EvolutionLike {
val shedPokemon = pokemon.clone(registryAccess = owner.registryAccess())
shedPokemon.removeHeldItem()
innerShedder.apply(shedPokemon)
shedPokemon.caughtBall = pokeballStack?.let { PokeBallComponent.getPokeBall(it) } ?: CobblemonItems.STRANGE_BALL.pokeBall
shedPokemon.caughtBall = ((pokeballStack?.item ?: CobblemonItems.POKE_BALL) as PokeBallItem).pokeBall
pokemon.storeCoordinates.get()?.store?.add(shedPokemon)
CobblemonCriteria.EVOLVE_POKEMON.trigger(owner, EvolvePokemonContext(pokemon.preEvolution!!.species.resourceIdentifier, shedPokemon.species.resourceIdentifier, playerDataManager.getGenericData(owner).advancementData.totalEvolvedCount))
// Consume one of the balls (if the player isn't creative)
@@ -9,9 +9,12 @@
package com.cobblemon.mod.common.api.riding.stats
import com.cobblemon.mod.common.api.cooking.Flavour
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.util.lang
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.MutableComponent
import net.minecraft.tags.TagKey
import net.minecraft.world.item.Item
/**
* A stat that is used for riding Pokémon. The exact implementation of each of these depends on the [com.cobblemon.mod.common.api.riding.controller.RideController].
@@ -20,13 +23,14 @@ import net.minecraft.network.chat.MutableComponent
* @since February 17th, 2025
*/
enum class RidingStat(
val flavour: Flavour
val flavour: Flavour,
val powerItem: TagKey<Item>
) {
ACCELERATION(Flavour.SPICY),
SKILL(Flavour.DRY),
SPEED(Flavour.SWEET),
STAMINA(Flavour.SOUR),
JUMP(Flavour.BITTER);
ACCELERATION(Flavour.SPICY, CobblemonItemTags.POWER_BRACER),
SKILL(Flavour.DRY, CobblemonItemTags.POWER_BELT),
SPEED(Flavour.SWEET, CobblemonItemTags.POWER_ANKLET),
STAMINA(Flavour.SOUR, CobblemonItemTags.POWER_WEIGHT),
JUMP(Flavour.BITTER, CobblemonItemTags.POWER_BAND);
companion object {
fun getByName(name: String) = RidingStat.entries.firstOrNull { it.name.equals(name, ignoreCase = true) }
@@ -145,7 +145,7 @@ class ReforgedConversion(val base: Path) : CobblemonConverter<CompoundTag> {
// result.nickname = this.find(nbt, "Nickname", NbtCompound::getString)
val ball = this.find(nbt, "CaughtBall", CompoundTag::getString)
result.caughtBall = if(ball != null) PokeBalls.getPokeBall(ResourceLocation.parse(ball)) else PokeBalls.STRANGE_BALL
result.caughtBall = if(ball != null) PokeBalls.getPokeBall(ResourceLocation.parse(ball)) ?: PokeBalls.POKE_BALL else PokeBalls.POKE_BALL
return result
}
@@ -190,4 +190,4 @@ class ReforgedConversion(val base: Path) : CobblemonConverter<CompoundTag> {
CAREFUL,
}
}
}
@@ -24,6 +24,7 @@ import net.minecraft.network.chat.Component
import net.minecraft.server.level.ServerPlayer
import net.minecraft.util.RandomSource
import net.minecraft.world.InteractionResult
import net.minecraft.world.entity.EntityType
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.Item
@@ -31,13 +32,9 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.TooltipFlag
import net.minecraft.world.item.context.BlockPlaceContext
import net.minecraft.world.level.BlockGetter
import net.minecraft.world.level.CollisionGetter
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.BaseEntityBlock
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.HorizontalDirectionalBlock
import net.minecraft.world.level.block.Mirror
import net.minecraft.world.level.block.RenderShape
import net.minecraft.world.level.block.Rotation
import net.minecraft.world.level.block.*
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.entity.BlockEntityTicker
import net.minecraft.world.level.block.entity.BlockEntityType
@@ -48,9 +45,11 @@ import net.minecraft.world.level.block.state.properties.IntegerProperty
import net.minecraft.world.level.block.state.properties.Property
import net.minecraft.world.level.pathfinder.PathComputationType
import net.minecraft.world.phys.BlockHitResult
import net.minecraft.world.phys.Vec3
import net.minecraft.world.phys.shapes.CollisionContext
import net.minecraft.world.phys.shapes.Shapes
import net.minecraft.world.phys.shapes.VoxelShape
import java.util.Optional
@Suppress("DEPRECATED", "OVERRIDE_DEPRECATION")
class HealingMachineBlock(settings: Properties) : BaseEntityBlock(settings) {
@@ -79,6 +78,14 @@ class HealingMachineBlock(settings: Properties) : BaseEntityBlock(settings) {
const val MAX_CHARGE_LEVEL = 5
val CHARGE_LEVEL: IntegerProperty = IntegerProperty.create("charge", 0, MAX_CHARGE_LEVEL + 1)
val NATURAL: BooleanProperty = BooleanProperty.create("natural")
fun canSetSpawn(level: Level): Boolean {
return level.gameRules.getBoolean(CobblemonGameRules.HEALER_SET_SPAWN)
}
fun findStandUpPosition(entityType: EntityType<*>, level: CollisionGetter, pos: BlockPos): Optional<Vec3> {
return RespawnAnchorBlock.findStandUpPosition(entityType, level, pos) // Exists if we ever want to make something more custom, but anchor block logic should suffice
}
}
init {
@@ -158,7 +165,12 @@ class HealingMachineBlock(settings: Properties) : BaseEntityBlock(settings) {
}
val party = serverPlayerEntity.party()
val pc = serverPlayerEntity.pc()
val healPC = player.level().gameRules.getBoolean(CobblemonGameRules.HEALERS_HEAL_PC);
val healPC = player.level().gameRules.getBoolean(CobblemonGameRules.HEALERS_HEAL_PC)
// Do spawnpoint stuff
if (canSetSpawn(world)) {
player.setRespawnPosition(world.dimension(), blockPos, player.yRot, false, true)
}
if (party.none() && (!healPC || pc.none())) {
player.sendSystemMessage(lang("healingmachine.nopokemon").red(), true)
@@ -183,6 +195,7 @@ class HealingMachineBlock(settings: Properties) : BaseEntityBlock(settings) {
player.sendSystemMessage(lang("healingmachine.notenoughcharge", "${((neededCharge/party.count())*100f).toInt()}%").red(), true)
}
party.forEach { it.tryRecallWithAnimation() }
return InteractionResult.CONSUME
}
@@ -160,8 +160,8 @@ class TypeGemClusterBlock(
&& state.getValue(STAGE) == 3) return false
val supportPos = pos.relative(state.getValue(FACING).opposite)
val supportBlock = level.getBlockState(supportPos).block
return CobblemonBlocks.typeGemBlocks().containsValue(supportBlock) || (supportBlock == CobblemonBlocks.TYPE_GEM_CORE) // Cannot grow if not on any gem blocks
val supportState = level.getBlockState(supportPos)
return supportState.`is`(CobblemonBlockTags.TYPE_GEM_BLOCKS) || supportState.block == CobblemonBlocks.TYPE_GEM_CORE // Cannot grow if not on any gem blocks
}
@@ -51,10 +51,20 @@ class TypeGemCoreBlock(properties: Properties) : Block(properties) {
ResourceLocation.parse("cobblemon:dragon_gem_block") to CobblemonBlocks.TYPE_GEM_CLUSTER_DRAGON,
ResourceLocation.parse("cobblemon:dark_gem_block") to CobblemonBlocks.TYPE_GEM_CLUSTER_DARK,
ResourceLocation.parse("cobblemon:steel_gem_block") to CobblemonBlocks.TYPE_GEM_CLUSTER_STEEL,
ResourceLocation.parse("cobblemon:fairy_gem_block") to CobblemonBlocks.TYPE_GEM_CLUSTER_FAIRY
ResourceLocation.parse("cobblemon:fairy_gem_block") to CobblemonBlocks.TYPE_GEM_CLUSTER_FAIRY,
ResourceLocation.parse("minecraft:amethyst_block") to Blocks.SMALL_AMETHYST_BUD
)
}
val AMETHYST_STAGES = listOf(
Blocks.SMALL_AMETHYST_BUD,
Blocks.MEDIUM_AMETHYST_BUD,
Blocks.LARGE_AMETHYST_BUD,
Blocks.AMETHYST_CLUSTER
)
private fun isAmethystStage(block: Block) = block in AMETHYST_STAGES
fun getConnectedGemBlocks(level: BlockGetter, pos: BlockPos): List<Pair<BlockState, BlockPos>> {
val connectedGems = mutableListOf<Pair<BlockState, BlockPos>>()
val visited = mutableSetOf<BlockPos>()
@@ -85,12 +95,16 @@ class TypeGemCoreBlock(properties: Properties) : Block(properties) {
Direction.entries.forEach {
if (random.nextFloat() < Cobblemon.config.typeGemGrowthChance) {
val faceState = level.getBlockState(pos.relative(it))
val randomGrowthType = decideClusterGrowthType(level, pos)
val newState = BLOCK_TO_CLUSTER[BuiltInRegistries.BLOCK.getKey(state.block)]?.defaultBlockState()
var newState = BLOCK_TO_CLUSTER[BuiltInRegistries.BLOCK.getKey(state.block)]?.defaultBlockState()
?.setValue(DirectionalBlock.FACING, it)
?.setValue(GROWTH_TYPE, randomGrowthType)
?: return
if (newState.hasProperty(GROWTH_TYPE)) {
newState = newState.setValue(GROWTH_TYPE, decideClusterGrowthType(level, pos))
} else if (getConnectedGemBlocks(level, pos).size > Cobblemon.config.typeGemMaxConnected) {
return@forEach
}
if (faceState.`is`(Blocks.AIR)) {
level.setBlock(pos.relative(it), newState, 3)
}
@@ -132,7 +146,7 @@ class TypeGemCoreBlock(properties: Properties) : Block(properties) {
if (!visited.add(clusterPos)) continue
val clusterState = level.getBlockState(clusterPos)
if (clusterState.block == expectedCluster) {
if (clusterState.block == expectedCluster && clusterState.hasProperty(GROWTH_TYPE)) {
clusters += clusterState to clusterPos
}
}
@@ -178,13 +192,41 @@ class TypeGemCoreBlock(properties: Properties) : Block(properties) {
Direction.entries.forEach { direction ->
val relativePos = pos.relative(direction)
val relativeState = level.getBlockState(relativePos)
val clusterBlock = relativeState.block as? TypeGemClusterBlock ?: return@forEach
if ((relativeState.getValue(DirectionalBlock.FACING) == direction &&
random.nextFloat() < Cobblemon.config.typeGemGrowthChance) || forceGrow
) {
clusterBlock.advanceGrowth(relativeState, level, relativePos, random)
val matchesFace = relativeState.hasProperty(DirectionalBlock.FACING)
&& relativeState.getValue(DirectionalBlock.FACING) == direction
if (!(forceGrow || (matchesFace && random.nextFloat() < Cobblemon.config.typeGemGrowthChance))) {
return@forEach
}
val block = relativeState.block
if (block is TypeGemClusterBlock) {
block.advanceGrowth(relativeState, level, relativePos, random)
} else if (isAmethystStage(block)) {
advanceAmethyst(relativeState, level, relativePos)
}
}
}
private fun advanceAmethyst(state: BlockState, level: LevelAccessor, pos: BlockPos) {
val facing = state.getValue(DirectionalBlock.FACING)
val supportState = level.getBlockState(pos.relative(facing.opposite))
if (!supportState.`is`(CobblemonBlockTags.TYPE_GEM_BLOCKS) && supportState.block != CobblemonBlocks.TYPE_GEM_CORE) {
return
}
if (state.block != Blocks.AMETHYST_CLUSTER) {
val nextStage = AMETHYST_STAGES[AMETHYST_STAGES.indexOf(state.block) + 1]
level.setBlock(pos, nextStage.defaultBlockState().setValue(DirectionalBlock.FACING, facing), 3)
return
}
// Fully grown clusters mature into amethyst blocks unless boxed in, mirroring stunted type gems
val boxedIn = Direction.entries.any { direction ->
direction != facing.opposite
&& level.getBlockState(pos.relative(direction)).`is`(CobblemonBlockTags.TYPE_GEM_BLOCKS)
}
if (!boxedIn) {
level.setBlock(pos, Blocks.AMETHYST_BLOCK.defaultBlockState(), 3)
}
}
@@ -16,9 +16,7 @@ import com.cobblemon.mod.common.client.render.pokeball.PokeBallPosableState
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity.CaptureState
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity.CaptureState.NOT
import com.cobblemon.mod.common.util.toRGBA
import net.minecraft.network.syncher.EntityDataAccessor
import org.joml.Vector4f
class EmptyPokeBallClientDelegate : PokeBallPosableState(), EntitySideDelegate<EmptyPokeBallEntity> {
override val stateEmitter: SettableObservable<CaptureState> = SettableObservable(NOT)
@@ -54,8 +52,4 @@ class EmptyPokeBallClientDelegate : PokeBallPosableState(), EntitySideDelegate<E
EmptyPokeBallEntity.ASPECTS -> currentAspects = currentEntity.aspects
}
}
fun getBeamColor(): Vector4f {
return currentEntity.pokeBall.beamColor.rgb.toRGBA()
}
}
}
@@ -20,7 +20,7 @@ object BattleCaptureStartHandler : ClientNetworkPacketHandler<BattleCaptureStart
val battle = CobblemonClient.battle ?: return
val targetPokemon = battle.getPokemonFromPNX(packet.targetPNX)
val tile = targetPokemon.second
val pokeBall = PokeBalls.getPokeBall(packet.pokeBallType)
val pokeBall = PokeBalls.getPokeBall(packet.pokeBallType) ?: PokeBalls.POKE_BALL
tile.ballCapturing = ClientBallDisplay(pokeBall, packet.aspects).also { it.start() }
}
}
}
@@ -133,11 +133,11 @@ class PokeBobberEntityRenderer(context: EntityRendererProvider.Context?) : Entit
val pokeBobberBaitItemStack = fishingBobberEntity.entityData.get(PokeRodFishingBobberEntity.POKEBOBBER_BAIT)
val pokeRodId = ResourceLocation.tryParse(pokeRodIdStr)
val pokeRod = PokeRods.getPokeRod(pokeRodId!!)
val ballItem = PokeBalls.getPokeBall(pokeRod?.pokeBallId!!)!!.stack
val ballItem = PokeBalls.getPokeBall(pokeRod?.pokeBallId!!)!!.item
// render the pokebobber
Minecraft.getInstance().itemRenderer.renderStatic(
ballItem,
ballItem.defaultInstance,
ItemDisplayContext.GROUND,
light,
OverlayTexture.NO_OVERLAY,
@@ -25,55 +25,55 @@ object CobblemonModelPredicateRegistry {
fun registerPredicates() {
val rods = listOf<PokerodItem>(
// CobblemonItems.AZURE_ROD,
// CobblemonItems.BEAST_ROD,
// CobblemonItems.CHERISH_ROD,
// CobblemonItems.CITRINE_ROD,
// CobblemonItems.DIVE_ROD,
// CobblemonItems.DREAM_ROD,
// CobblemonItems.DUSK_ROD,
// CobblemonItems.FAST_ROD,
// CobblemonItems.FRIEND_ROD,
// CobblemonItems.GREAT_ROD,
// CobblemonItems.HEAL_ROD,
// CobblemonItems.HEAVY_ROD,
// CobblemonItems.LEVEL_ROD,
// CobblemonItems.LOVE_ROD,
// CobblemonItems.LURE_ROD,
// CobblemonItems.LUXURY_ROD,
// CobblemonItems.MASTER_ROD,
// CobblemonItems.MOON_ROD,
// CobblemonItems.NEST_ROD,
// CobblemonItems.NET_ROD,
// CobblemonItems.PARK_ROD,
// CobblemonItems.POKE_ROD,
// CobblemonItems.PREMIER_ROD,
// CobblemonItems.QUICK_ROD,
// CobblemonItems.REPEAT_ROD,
// CobblemonItems.ROSEATE_ROD,
// CobblemonItems.SAFARI_ROD,
// CobblemonItems.SLATE_ROD,
// CobblemonItems.SPORT_ROD,
// CobblemonItems.TIMER_ROD,
// CobblemonItems.ULTRA_ROD,
// CobblemonItems.VERDANT_ROD,
// CobblemonItems.ANCIENT_AZURE_ROD,
// CobblemonItems.ANCIENT_CITRINE_ROD,
// CobblemonItems.ANCIENT_FEATHER_ROD,
// CobblemonItems.ANCIENT_GIGATON_ROD,
// CobblemonItems.ANCIENT_GREAT_ROD,
// CobblemonItems.ANCIENT_HEAVY_ROD,
// CobblemonItems.ANCIENT_IVORY_ROD,
// CobblemonItems.ANCIENT_JET_ROD,
// CobblemonItems.ANCIENT_LEADEN_ROD,
// CobblemonItems.ANCIENT_ORIGIN_ROD,
// CobblemonItems.ANCIENT_POKE_ROD,
// CobblemonItems.ANCIENT_ROSEATE_ROD,
// CobblemonItems.ANCIENT_SLATE_ROD,
// CobblemonItems.ANCIENT_ULTRA_ROD,
// CobblemonItems.ANCIENT_VERDANT_ROD,
// CobblemonItems.ANCIENT_WING_ROD
val rods = listOf(
CobblemonItems.AZURE_ROD,
CobblemonItems.BEAST_ROD,
CobblemonItems.CHERISH_ROD,
CobblemonItems.CITRINE_ROD,
CobblemonItems.DIVE_ROD,
CobblemonItems.DREAM_ROD,
CobblemonItems.DUSK_ROD,
CobblemonItems.FAST_ROD,
CobblemonItems.FRIEND_ROD,
CobblemonItems.GREAT_ROD,
CobblemonItems.HEAL_ROD,
CobblemonItems.HEAVY_ROD,
CobblemonItems.LEVEL_ROD,
CobblemonItems.LOVE_ROD,
CobblemonItems.LURE_ROD,
CobblemonItems.LUXURY_ROD,
CobblemonItems.MASTER_ROD,
CobblemonItems.MOON_ROD,
CobblemonItems.NEST_ROD,
CobblemonItems.NET_ROD,
CobblemonItems.PARK_ROD,
CobblemonItems.POKE_ROD,
CobblemonItems.PREMIER_ROD,
CobblemonItems.QUICK_ROD,
CobblemonItems.REPEAT_ROD,
CobblemonItems.ROSEATE_ROD,
CobblemonItems.SAFARI_ROD,
CobblemonItems.SLATE_ROD,
CobblemonItems.SPORT_ROD,
CobblemonItems.TIMER_ROD,
CobblemonItems.ULTRA_ROD,
CobblemonItems.VERDANT_ROD,
CobblemonItems.ANCIENT_AZURE_ROD,
CobblemonItems.ANCIENT_CITRINE_ROD,
CobblemonItems.ANCIENT_FEATHER_ROD,
CobblemonItems.ANCIENT_GIGATON_ROD,
CobblemonItems.ANCIENT_GREAT_ROD,
CobblemonItems.ANCIENT_HEAVY_ROD,
CobblemonItems.ANCIENT_IVORY_ROD,
CobblemonItems.ANCIENT_JET_ROD,
CobblemonItems.ANCIENT_LEADEN_ROD,
CobblemonItems.ANCIENT_ORIGIN_ROD,
CobblemonItems.ANCIENT_POKE_ROD,
CobblemonItems.ANCIENT_ROSEATE_ROD,
CobblemonItems.ANCIENT_SLATE_ROD,
CobblemonItems.ANCIENT_ULTRA_ROD,
CobblemonItems.ANCIENT_VERDANT_ROD,
CobblemonItems.ANCIENT_WING_ROD
)
rods.forEach { rod ->
@@ -186,4 +186,4 @@ object CobblemonModelPredicateRegistry {
}
*/
}
}
}
@@ -1,25 +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.render.models.blockbench.pokeball
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.frame.ModelFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Bone
import net.minecraft.client.model.geom.ModelPart
open class PokeBallPosableModel(root: Bone) : PosableModel(root), ModelFrame {
@Transient
override val rootPart =
(root as ModelPart)
.children.entries
.first()
.let { root.registerChildWithAllChildren(it.key) }
val rootBone: String = (root as ModelPart).children.entries.first().key
}
@@ -13,11 +13,11 @@ import com.cobblemon.mod.common.client.render.models.blockbench.repository.Rende
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import net.minecraft.world.entity.Entity
class PosablePokeBallEntityModel : PosableEntityModel<EmptyPokeBallEntity>() {
class PosablePokeBallModel : PosableEntityModel<EmptyPokeBallEntity>() {
override fun setupEntityTypeContext(entity: Entity?) {
super.setupEntityTypeContext(entity)
if (entity is EmptyPokeBallEntity) {
context.put(RenderContext.ASPECTS, entity.aspects)
}
}
}
}
@@ -20,7 +20,9 @@ import com.cobblemon.mod.common.client.render.models.blockbench.*
import com.cobblemon.mod.common.client.render.models.blockbench.bedrock.animation.BedrockAnimationRepository
import com.cobblemon.mod.common.client.render.models.blockbench.blockentity.BlockEntityModel
import com.cobblemon.mod.common.client.render.models.blockbench.fossil.FossilModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.PokeBallPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.AncientPokeBallModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.BeastBallModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.PokeBallModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen1.*
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen2.*
@@ -86,7 +88,7 @@ object VaryingModelRepository {
"bedrock/fossils/posers" to FossilModel::class.java,
"bedrock/block_entities/posers" to BlockEntityModel::class.java,
"bedrock/npcs/posers" to PosableModel::class.java,
"bedrock/poke_balls/posers" to PokeBallPosableModel::class.java,
"bedrock/poke_balls/posers" to PosableModel::class.java,
"bedrock/generic/posers" to PosableModel::class.java,
)
@@ -114,7 +116,6 @@ object VaryingModelRepository {
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
.registerTypeAdapter(PosableModel::class.java, JsonModelAdapter(::PosableModel))
.registerTypeAdapter(PokemonPosableModel::class.java, JsonModelAdapter(::PokemonPosableModel))
.registerTypeAdapter(PokeBallPosableModel::class.java, JsonModelAdapter(::PokeBallPosableModel))
.registerTypeAdapter(FossilModel::class.java, JsonModelAdapter(::FossilModel))
.registerTypeAdapter(BlockEntityModel::class.java, JsonModelAdapter(::BlockEntityModel))
.registerTypeAdapter(Pose::class.java, PoseAdapter { JsonModelAdapter.model!! })
@@ -154,8 +155,8 @@ object VaryingModelRepository {
return {
var boneName = jsonObject.getAsJsonPrimitive("rootBone")
JsonModelAdapter.modelPart = if (boneName != null && it.children[boneName.asString] != null) it.children[boneName.asString] else it.children[fileName] ?: it.children.entries.filter { LocatorAccess.PREFIX !in it.key }.first().value
gson.fromJson(jsonObject, poserClass).also { model ->
model.poses.forEach { (poseName, pose) -> pose.poseName = poseName }
gson.fromJson(jsonObject, poserClass).also {
it.poses.forEach { (poseName, pose) -> pose.poseName = poseName }
}
}
}
@@ -168,6 +169,55 @@ object VaryingModelRepository {
}
fun registerInBuiltPosers() {
inbuilt("azure_ball", ::PokeBallModel)
inbuilt("beast_ball", ::BeastBallModel)
inbuilt("cherish_ball", ::PokeBallModel)
inbuilt("citrine_ball", ::PokeBallModel)
inbuilt("dive_ball", ::PokeBallModel)
inbuilt("dream_ball", ::PokeBallModel)
inbuilt("dusk_ball", ::PokeBallModel)
inbuilt("fast_ball", ::PokeBallModel)
inbuilt("friend_ball", ::PokeBallModel)
inbuilt("great_ball", ::PokeBallModel)
inbuilt("heal_ball", ::PokeBallModel)
inbuilt("heavy_ball", ::PokeBallModel)
inbuilt("level_ball", ::PokeBallModel)
inbuilt("love_ball", ::PokeBallModel)
inbuilt("lure_ball", ::PokeBallModel)
inbuilt("luxury_ball", ::PokeBallModel)
inbuilt("master_ball", ::PokeBallModel)
inbuilt("moon_ball", ::PokeBallModel)
inbuilt("nest_ball", ::PokeBallModel)
inbuilt("net_ball", ::PokeBallModel)
inbuilt("park_ball", ::PokeBallModel)
inbuilt("poke_ball", ::PokeBallModel)
inbuilt("premier_ball", ::PokeBallModel)
inbuilt("quick_ball", ::PokeBallModel)
inbuilt("repeat_ball", ::PokeBallModel)
inbuilt("roseate_ball", ::PokeBallModel)
inbuilt("safari_ball", ::PokeBallModel)
inbuilt("slate_ball", ::PokeBallModel)
inbuilt("sport_ball", ::PokeBallModel)
inbuilt("strange_ball", ::PokeBallModel)
inbuilt("timer_ball", ::PokeBallModel)
inbuilt("ultra_ball", ::PokeBallModel)
inbuilt("verdant_ball", ::PokeBallModel)
inbuilt("ancient_poke_ball", ::AncientPokeBallModel)
inbuilt("ancient_citrine_ball", ::AncientPokeBallModel)
inbuilt("ancient_verdant_ball", ::AncientPokeBallModel)
inbuilt("ancient_azure_ball", ::AncientPokeBallModel)
inbuilt("ancient_roseate_ball", ::AncientPokeBallModel)
inbuilt("ancient_slate_ball", ::AncientPokeBallModel)
inbuilt("ancient_ivory_ball", ::AncientPokeBallModel)
inbuilt("ancient_great_ball", ::AncientPokeBallModel)
inbuilt("ancient_ultra_ball", ::AncientPokeBallModel)
inbuilt("ancient_feather_ball", ::AncientPokeBallModel)
inbuilt("ancient_wing_ball", ::AncientPokeBallModel)
inbuilt("ancient_jet_ball", ::AncientPokeBallModel)
inbuilt("ancient_heavy_ball", ::AncientPokeBallModel)
inbuilt("ancient_leaden_ball", ::AncientPokeBallModel)
inbuilt("ancient_gigaton_ball", ::AncientPokeBallModel)
inbuilt("squirtle", ::SquirtleModel)
inbuilt("wartortle", ::WartortleModel)
inbuilt("metapod", ::MetapodModel)
@@ -616,4 +666,4 @@ object VaryingModelRepository {
}
}
}
}
}
@@ -12,7 +12,8 @@ import com.cobblemon.mod.common.api.reactive.Observable
import com.cobblemon.mod.common.api.reactive.SettableObservable
import com.cobblemon.mod.common.api.scheduling.Schedulable
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.PokeBallPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.AncientPokeBallModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.PokeBallModel
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import kotlin.random.Random
@@ -20,21 +21,18 @@ import kotlin.random.Random
abstract class PokeBallPosableState : PosableState(), Schedulable {
abstract val stateEmitter: SettableObservable<EmptyPokeBallEntity.CaptureState>
abstract val shakeEmitter: Observable<Unit>
protected open val group: String
get() = if (this.currentModel is AncientPokeBallModel) "ancient_poke_ball" else "poke_ball"
protected open var lastKnownState: EmptyPokeBallEntity.CaptureState? = null
open fun initSubscriptions() {
stateEmitter.subscribe { state ->
// if we fail to cast, provide default bone name.
val group = (currentModel as? PokeBallPosableModel)?.rootBone ?: "poke_ball"
when (state) {
EmptyPokeBallEntity.CaptureState.HIT -> {
doLater {
val model = this.currentModel!!
after(seconds = 0.2F) {
if (model is PokeBallPosableModel && stateEmitter.get() == EmptyPokeBallEntity.CaptureState.HIT) {
if (model is PokeBallModel && stateEmitter.get() == EmptyPokeBallEntity.CaptureState.HIT) {
doLater latest@{
model.moveToPose(this, model.poses["open"]!!)
after(seconds = 1.75F) {
@@ -62,7 +60,7 @@ abstract class PokeBallPosableState : PosableState(), Schedulable {
shakeEmitter
.pipe(Observable.emitWhile { stateEmitter.get() == EmptyPokeBallEntity.CaptureState.SHAKE })
.subscribe {
val bob = "bob${Random.nextInt(6) + 1}"
val bob = "bob${Random.Default.nextInt(6) + 1}"
doLater { setActiveAnimations(currentModel!!.bedrockStateful(group, bob)) }
}
}
@@ -81,4 +79,4 @@ abstract class PokeBallPosableState : PosableState(), Schedulable {
this.lastKnownState = state
}
}
}
}
@@ -9,7 +9,7 @@
package com.cobblemon.mod.common.client.render.pokeball
import com.cobblemon.mod.common.client.entity.EmptyPokeBallClientDelegate
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.PosablePokeBallEntityModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.PosablePokeBallModel
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
@@ -24,7 +24,7 @@ import net.minecraft.client.renderer.texture.OverlayTexture
import net.minecraft.resources.ResourceLocation
class PokeBallRenderer(context: EntityRendererProvider.Context) : EntityRenderer<EmptyPokeBallEntity>(context) {
val model = PosablePokeBallEntityModel()
val model = PosablePokeBallModel()
override fun getTextureLocation(pEntity: EmptyPokeBallEntity): ResourceLocation {
return VaryingModelRepository.getTexture(pEntity.pokeBall.name, pEntity.delegate as EmptyPokeBallClientDelegate)
@@ -58,4 +58,4 @@ class PokeBallRenderer(context: EntityRendererProvider.Context) : EntityRenderer
poseStack.popPose()
super.render(entity, yaw, partialTicks, poseStack, buffer, packedLight)
}
}
}
@@ -13,7 +13,6 @@ import com.cobblemon.mod.common.OrientationControllable
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.battle.ClientBallDisplay
import com.cobblemon.mod.common.client.entity.EmptyPokeBallClientDelegate
import com.cobblemon.mod.common.client.entity.NPCClientDelegate
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate.Companion.BEAM_EXTEND_TIME
@@ -44,7 +43,6 @@ import com.cobblemon.mod.common.util.lang
import com.cobblemon.mod.common.util.math.DoubleRange
import com.cobblemon.mod.common.util.math.geometry.toRadians
import com.cobblemon.mod.common.util.math.remap
import com.cobblemon.mod.common.util.toRGBA
import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.math.Axis
import net.minecraft.ChatFormatting
@@ -322,11 +320,6 @@ class PokemonRenderer(
val pokemonPosition = entity.position().add(0.0, entity.bbHeight / 2.0 * clientDelegate.activeSendoutScale.toDouble(), 0.0)
val recallBallOrigin = (beamTarget as? Player)?.let { RecallArmAnimationTracker.get(it.uuid)?.beamOrigin }
val beamColorVec4f = when(beamTarget) {
is EmptyPokeBallEntity -> (beamTarget.delegate as EmptyPokeBallClientDelegate).getBeamColor()
else -> entity.pokemon.caughtBall.beamColor.rgb.toRGBA()
}
val beamSourcePosition = when {
// cover the recall ball origin presence
recallBallOrigin != null -> recallBallOrigin
@@ -392,10 +385,10 @@ class PokemonRenderer(
partialTicks = partialTicks,
totalLevelTime = entity.level().gameTime,
height = pokemonPosition.distanceTo(beamSourcePosition.add(offset)).toFloat() * ratio,
red = beamColorVec4f.x,
green = beamColorVec4f.y,
blue = beamColorVec4f.z,
alpha = beamColorVec4f.w,
red = recallBeamColour.x,
green = recallBeamColour.y,
blue = recallBeamColour.z,
alpha = recallBeamColour.w,
beamRadius = 0.03F,
glowRadius = 0.07F,
glowAlpha = 0.4F
@@ -30,7 +30,7 @@ object FishingRodTooltipGenerator : TooltipGenerator() {
val baitComponent = stack.get(CobblemonItemComponents.BAIT)
// Add the description of the Poke Ball used in the rod
ball.stack.item.description.let {
ball.item.description.let {
val bobberDescription = Component.translatable(
"cobblemon.pokerod.bobber",
it.copy().gray()
@@ -40,7 +40,7 @@ object FishingRodTooltipGenerator : TooltipGenerator() {
val client = Minecraft.getInstance()
val itemRegistry = client.level?.registryAccess()?.registryOrThrow(Registries.ITEM)
itemRegistry?.let {
itemRegistry?.let { registry ->
baitComponent?.stack?.item?.description
?.let { // maybe this can be simplified to not use the FishingBaits to get the stack and just use PokerodItem to get the stack since we have it already
val baitDescription = "cobblemon.pokerod.bait".asTranslated(it.copy().gray(), PokerodItem.getBaitStackOnRod(stack).count)
@@ -77,4 +77,4 @@ object FishingRodTooltipGenerator : TooltipGenerator() {
return resultLines
}
}
}
@@ -47,6 +47,10 @@ class CobblemonConfig {
@IntConstraint(min = 0, max = 1000)
var maxPokemonFriendship = 255
@CobblemonConfigField(Category.Pokemon, lang = "power_item_ride_stat_gain_interval_seconds", SERVER)
@IntConstraint(min = -1, max = Int.MAX_VALUE)
var powerItemRideStatGainIntervalSeconds = 120
@CobblemonConfigField(Category.Pokemon, lang = "announce_drop_items", SERVER)
var announceDropItems = true
@CobblemonConfigField(Category.Pokemon, lang = "default_drop_item_method", SERVER)
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common.entity.pokeball
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.StringValue
@@ -19,9 +18,7 @@ import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.pokeball.PokeBallCaptureCalculatedEvent
import com.cobblemon.mod.common.api.events.pokeball.ThrownPokeballHitEvent
import com.cobblemon.mod.common.api.events.pokemon.PokemonCapturedEvent
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
import com.cobblemon.mod.common.api.net.serializers.StringSetDataSerializer
import com.cobblemon.mod.common.api.net.serializers.Vec3DataSerializer
import com.cobblemon.mod.common.api.pokeball.PokeBalls
@@ -52,16 +49,7 @@ import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokeballPacket
import com.cobblemon.mod.common.pokeball.PokeBall
import com.cobblemon.mod.common.pokemon.ai.PokemonBrain
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
import com.cobblemon.mod.common.util.asArrayValue
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.isServerSide
import com.cobblemon.mod.common.util.lang
import com.cobblemon.mod.common.util.party
import com.cobblemon.mod.common.util.playSoundServer
import com.cobblemon.mod.common.util.sendParticlesServer
import com.cobblemon.mod.common.util.setPositionSafely
import com.cobblemon.mod.common.util.update
import com.cobblemon.mod.common.util.withQueryValue
import com.cobblemon.mod.common.util.*
import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.client.Minecraft
import net.minecraft.core.particles.ParticleTypes
@@ -77,10 +65,7 @@ import net.minecraft.server.level.ServerPlayer
import net.minecraft.sounds.SoundEvents
import net.minecraft.util.Mth
import net.minecraft.util.Mth.PI
import net.minecraft.world.entity.EntityDimensions
import net.minecraft.world.entity.EntityType
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.Pose
import net.minecraft.world.entity.*
import net.minecraft.world.entity.decoration.LeashFenceKnotEntity
import net.minecraft.world.entity.projectile.ThrowableItemProjectile
import net.minecraft.world.item.Item
@@ -112,9 +97,7 @@ class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragMod
const val SECONDS_BETWEEN_SHAKES = 1.25F
const val SECONDS_BEFORE_SHAKE = 1F
val DIMENSIONS: EntityDimensions = EntityDimensions.fixed(0.4F, 0.4F)
val runtime = MoLangRuntime().setup()
val DIMENSIONS = EntityDimensions.fixed(0.4F, 0.4F)
}
val dataTrackerEmitter = SimpleObservable<EntityDataAccessor<*>>()
@@ -142,7 +125,7 @@ class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragMod
.addFunction("thrower") { owner?.asMostSpecificMoLangValue() ?: DoubleValue.ZERO }
override fun defineSynchedData(builder: SynchedEntityData.Builder) {
pokeBall = PokeBalls.STRANGE_BALL
pokeBall = PokeBalls.POKE_BALL
super.defineSynchedData(builder)
builder.define(CAPTURE_STATE, CaptureState.NOT.ordinal.toByte())
builder.define(ASPECTS, emptySet())
@@ -175,7 +158,7 @@ class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragMod
addPosableFunctions(struct)
}
constructor(world: Level) : this(pokeBall = PokeBalls.STRANGE_BALL, world = world)
constructor(world: Level) : this(pokeBall = PokeBalls.POKE_BALL, world = world)
constructor(
pokeBall: PokeBall,
world: Level,
@@ -193,7 +176,7 @@ class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragMod
this.pokeBall = pokeBall
}
var pokeBall: PokeBall = PokeBalls.STRANGE_BALL
var pokeBall: PokeBall = PokeBalls.POKE_BALL
override fun onHitBlock(hitResult: BlockHitResult) {
if (captureState == CaptureState.NOT) {
@@ -204,7 +187,7 @@ class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragMod
discard()
val player = this.owner as? ServerPlayer
if (player?.isCreative == false) {
spawnAtLocation(pokeBall.stack())
spawnAtLocation(defaultItem)
}
}
} else {
@@ -262,7 +245,7 @@ class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragMod
lang(
"capture.attempted_capture",
throwerActor.getName(),
pokeBall.item().getDescriptionId(pokeBall.stack),
pokeBall.item().description,
pokemonEntity.exposedSpecies.translatedName
).yellow()
)
@@ -301,7 +284,7 @@ class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragMod
val owner = owner
discard()
val player = owner?.takeIf { it is ServerPlayer } as? ServerPlayer
if (player?.isCreative != true) spawnAtLocation(pokeBall.stack())
if (player?.isCreative != true) spawnAtLocation(defaultItem)
return
}
@@ -313,7 +296,7 @@ class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragMod
delegate.tick(this)
if (level().isServerSide()) {
if (this.tickCount > 600 && this.capturingPokemon == null) {
this.remove(RemovalReason.DISCARDED)
@@ -363,8 +346,7 @@ class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragMod
// Do a capture
val pokemon = capturingPokemon ?: return
val player = this.owner as? ServerPlayer ?: return
val captureTime = if (pokeBall.ancient) 1.8F else 1F
val captureTime = if (pokeBall.ancient == true) 1.8F else 1F
after(seconds = captureTime) {
// Dupes occurred by double-adding Pokémon, this hopefully prevents it triple-condom style
// wtf did I just read above me
@@ -373,13 +355,8 @@ class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragMod
discard()
captureFuture.complete(true)
val party = player.party()
val effectsRuntime = runtime
.withQueryValue("pokeball", struct)
.withQueryValue("pokemon", pokemon.asMoLangValue())
pokemon.pokemon.caughtBall = pokeBall
pokeBall.effects.forEach { effect -> effect.resolve(effectsRuntime) }
pokeBall.effects.forEach { effect -> effect.apply(player, pokemon.pokemon) }
party.add(pokemon.pokemon)
val leashHolder = pokemon.leashHolder
@@ -403,7 +380,7 @@ class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragMod
}
// Emits a shake by changing the value to the opposite of what it currently is. Sends an update to the client basically.
// We could replace this with a packet, but it feels awfully excessive when we already have 5 bajillion packets.
if (pokeBall.ancient) {
if (this.pokeBall.ancient) {
when (captureResult.numberOfShakes) {
1 -> ancientBallShake(setOf("q.bedrock_stateful('ancient_poke_ball', 'weirdhop')"))
2 -> ancientBallShake(setOf("q.bedrock_stateful('ancient_poke_ball', 'bighop')"))
@@ -418,7 +395,7 @@ class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragMod
private fun breakFree() {
val pokemon = capturingPokemon ?: return
pokemon.setPositionSafely(position())
pokemon.beamMode = 2
pokemon.isInvisible = false
pokemon.isSilent = false
@@ -448,7 +425,8 @@ class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragMod
after(seconds = 0.1F) {
captureFuture.complete(false)
val ballType = pokeBall.name.path.lowercase().replace("_", "")
val ballType =
this.pokeBall.name.path.lowercase().replace("_", "")
val mode = "casual"
val sendflash =
BedrockParticleOptionsRepository.getEffect(cobblemonResource("${ballType}/${mode}/sendflash"))
@@ -465,7 +443,7 @@ class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragMod
override fun getDefaultItem(): Item = pokeBall.item()
override fun getDimensions(pPose: Pose): EntityDimensions = DIMENSIONS
override fun getDimensions(pPose: Pose) = DIMENSIONS
private fun attemptCatch(pokemonEntity: PokemonEntity) {
pokemonEntity.busyLocks.add(this)
@@ -573,4 +551,4 @@ class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragMod
override fun waterDrag(): Float = this.pokeBall.waterDragValue
}
}
@@ -2744,4 +2744,9 @@ open class PokemonEntity(
}
fun hasRider() = this.passengers.any { it is LivingEntity }
}
override fun playStepSound(pos: BlockPos, state: BlockState) {
if (this.pokemon.species.silenceStepSounds) return
super.playStepSound(pos, state)
}
}
@@ -22,6 +22,7 @@ import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.pokemon.feature.TickingSpeciesFeature
import com.cobblemon.mod.common.api.pokemon.status.Statuses
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.api.spawning.fishing.FishingSpawnCause.Companion.DROPS_REROLL_ASPECT
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.battles.BattleRegistry
@@ -46,10 +47,15 @@ import kotlin.math.*
/** Handles purely server logic for a Pokémon */
class PokemonServerDelegate : PokemonSideDelegate {
companion object {
private const val RIDE_STAT_GAIN_AMOUNT = 1F
}
lateinit var entity: PokemonEntity
var acknowledgedHPValue = -1
var acknowledgedLevel = -1
val passengerOffsets = mutableMapOf<Int, Vec3>()
private var rideStatGainAnchor: Vec3? = null
/** Mocked properties exposed to the client [PokemonEntity]. */
private val mock: PokemonProperties?
@@ -355,9 +361,30 @@ class PokemonServerDelegate : PokemonSideDelegate {
}
}
val rideStatGainIntervalSeconds = Cobblemon.config.powerItemRideStatGainIntervalSeconds
if (rideStatGainIntervalSeconds > 0) {
val rideStatGainIntervalTicks = rideStatGainIntervalSeconds * 20L
if (entity.level().gameTime % rideStatGainIntervalTicks == 0L) {
trainRideStats()
}
}
updateTrackedValues()
}
private fun trainRideStats() {
val position = entity.position()
val anchor = rideStatGainAnchor
rideStatGainAnchor = position
if (anchor == null || anchor == position || entity.passengers.isEmpty()) return
val heldItem = entity.pokemon.heldItemNoCopy()
if (heldItem.isEmpty) return
val stat = RidingStat.entries.firstOrNull { heldItem.`is`(it.powerItem) } ?: return
entity.pokemon.addRideBoost(stat, RIDE_STAT_GAIN_AMOUNT)
}
fun updateShownItem() {
val trackedShownItem = when {
// Show Hand Item if Held item is hidden
@@ -8,31 +8,42 @@
package com.cobblemon.mod.common.item
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import com.cobblemon.mod.common.item.components.PokeBallComponent
import com.cobblemon.mod.common.pokeball.PokeBall
import com.cobblemon.mod.common.util.isServerSide
import com.cobblemon.mod.common.util.math.geometry.toRadians
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.InteractionHand
import net.minecraft.world.InteractionResultHolder
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Rarity
import net.minecraft.world.level.Level
import kotlin.math.cos
class PokeBallItem(var pokeBall: PokeBall) : CobblemonItem(pokeBall.itemProperties()) {
class PokeBallItem(
val pokeBall: PokeBall
) : CobblemonItem(Properties().apply {
when (pokeBall.name) {
// Master balls are a netherite product and should be fire immune
PokeBalls.MASTER_BALL.name -> fireResistant().rarity(Rarity.EPIC)
PokeBalls.CHERISH_BALL.name -> rarity(Rarity.EPIC)
PokeBalls.ANCIENT_ORIGIN_BALL.name -> rarity(Rarity.EPIC)
PokeBalls.BEAST_BALL.name -> rarity(Rarity.RARE)
}
}) {
override fun use(world: Level, player: Player, usedHand: InteractionHand): InteractionResultHolder<ItemStack> {
val itemStack = player.getItemInHand(usedHand)
if (world.isServerSide()) {
throwPokeBall(world, player as ServerPlayer, PokeBallComponent.getPokeBall(itemStack))
throwPokeBall(world, player as ServerPlayer)
}
itemStack.consume(1, player)
return InteractionResultHolder.sidedSuccess(itemStack, world.isClientSide)
}
private fun throwPokeBall(world: Level, player: ServerPlayer, pokeBall: PokeBall) {
private fun throwPokeBall(world: Level, player: ServerPlayer) {
val pokeBallEntity = EmptyPokeBallEntity(pokeBall, player.level(), player).apply {
val overhandFactor: Float = if (player.xRot < 0) {
5f * cos(player.xRot.toRadians())
@@ -46,7 +57,4 @@ class PokeBallItem(var pokeBall: PokeBall) : CobblemonItem(pokeBall.itemProperti
}
world.addFreshEntity(pokeBallEntity)
}
override fun getDescriptionId(itemStack: ItemStack): String =
PokeBallComponent.getPokeBall(itemStack).name.toLanguageKey("item")
}
}
@@ -1,64 +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.item.components
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonItemComponents
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.item.PokeBallItem
import com.cobblemon.mod.common.pokeball.PokeBall
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import io.netty.buffer.ByteBuf
import net.minecraft.network.codec.ByteBufCodecs
import net.minecraft.network.codec.StreamCodec
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.ItemStack
data class PokeBallComponent(val name: ResourceLocation) {
companion object {
val CODEC: Codec<PokeBallComponent> = RecordCodecBuilder.create {
it
.group(ResourceLocation.CODEC.fieldOf("type").forGetter(PokeBallComponent::name))
.apply(it, ::PokeBallComponent)
}
val PACKET_CODEC: StreamCodec<ByteBuf, PokeBallComponent> = ByteBufCodecs.fromCodec(CODEC)
@JvmStatic
fun getPokeBall(stack: ItemStack): PokeBall {
return stack.get(CobblemonItemComponents.POKE_BALL)?.name?.let(PokeBalls::getPokeBall)
?: (stack.item as? PokeBallItem)?.pokeBall
?: PokeBalls.STRANGE_BALL
}
@JvmStatic
fun setPokeBall(stack: ItemStack, ball: PokeBall): ItemStack {
stack.set(CobblemonItemComponents.POKE_BALL, PokeBallComponent(ball.name))
return stack
}
@JvmStatic
fun createStack(ball: PokeBall?): ItemStack {
var result = PokeBalls.STRANGE_BALL
if (ball == null) {
Cobblemon.LOGGER.error("Attempted to create poke ball stack with null config, falling to strange ball.")
} else {
result = ball
}
val stack = ItemStack(CobblemonItems.STRANGE_BALL)
return setPokeBall(stack, result)
}
}
val ball: PokeBall
get() = PokeBalls.getPokeBall(name)
}
@@ -11,12 +11,10 @@ package com.cobblemon.mod.common.item.group
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonItemComponents
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.api.tms.TechnicalMachines
import com.cobblemon.mod.common.block.TypeGemClusterBlock
import com.cobblemon.mod.common.item.AprijuiceItem
import com.cobblemon.mod.common.item.components.PokeBallComponent
import com.cobblemon.mod.common.item.components.RideBoostsComponent
import com.cobblemon.mod.common.item.components.TMMoveComponent
import com.cobblemon.mod.common.util.cobblemonResource
@@ -944,12 +942,7 @@ object CobblemonItemGroups {
}
private fun utilityItemEntries(displayContext: ItemDisplayParameters, entries: Output) {
CobblemonItems.pokeBalls.values.forEach(entries::accept)
PokeBalls.all()
.filter { ball -> CobblemonItems.pokeBalls.keys.none { it == ball.name } }
.forEach { entries.accept(PokeBallComponent.createStack(it)) }
CobblemonItems.pokeBalls.forEach(entries::accept)
CobblemonItems.pokeRods.forEach(entries::accept)
CobblemonItems.pokedexes.forEach(entries::accept)
}
@@ -9,6 +9,7 @@
package com.cobblemon.mod.common.item.interactive
import com.cobblemon.mod.common.CobblemonItemComponents
import com.cobblemon.mod.common.item.components.FoodComponent
import net.minecraft.network.chat.Component
import net.minecraft.sounds.SoundEvent
import net.minecraft.sounds.SoundEvents
@@ -23,10 +24,15 @@ import net.minecraft.world.level.Level
class PonigiriItem : Item(
Properties().stacksTo(64)
.food(FoodProperties.Builder()
.nutrition(2)
.saturationModifier(0.55f)
.nutrition(NUTRITION)
.saturationModifier(SATURATION_MODIFIER)
.build())
) {
companion object {
const val NUTRITION = 2
const val SATURATION_MODIFIER = 0.55f
}
override fun getName(stack: ItemStack): Component {
val ingredients = stack.get(CobblemonItemComponents.INGREDIENT)
@@ -59,4 +65,9 @@ class PonigiriItem : Item(
override fun getEatingSound(): SoundEvent {
return SoundEvents.GENERIC_EAT
}
}
fun getFoodValues(stack: ItemStack): Pair<Int, Float> {
val (hunger, saturation) = stack.getOrDefault(CobblemonItemComponents.FOOD, FoodComponent(NUTRITION, SATURATION_MODIFIER))
return hunger to saturation
}
}
@@ -1,70 +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.pokeballs
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.net.messages.client.data.DataRegistrySyncPacket
import com.cobblemon.mod.common.pokeball.PokeBall
import com.cobblemon.mod.common.util.adapters.CobblemonCatchRateModifierAdapter
import com.cobblemon.mod.common.util.adapters.RegistryAccessResolver
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import java.awt.Color
class PokeBallsRegistrySyncPacket(balls: Map<ResourceLocation, PokeBall>) : DataRegistrySyncPacket<PokeBall, PokeBallsRegistrySyncPacket>(balls.values) {
companion object {
val ID = cobblemonResource("poke_balls")
fun decode(buffer: RegistryFriendlyByteBuf): PokeBallsRegistrySyncPacket {
return PokeBallsRegistrySyncPacket(emptyMap()).apply { decodeBuffer(buffer) }
}
}
override val id = ID
override fun encodeEntry(buffer: RegistryFriendlyByteBuf, entry: PokeBall) {
buffer.writeResourceLocation(entry.name)
buffer.writeResourceLocation(entry.model2d)
buffer.writeResourceLocation(entry.model3d)
buffer.writeFloat(entry.throwPower)
buffer.writeFloat(entry.waterDragValue)
buffer.writeBoolean(entry.ancient)
buffer.writeInt(entry.beamColor.rgb)
CobblemonCatchRateModifierAdapter.encode(entry.catchRateModifier, buffer)
}
override fun decodeEntry(buffer: RegistryFriendlyByteBuf): PokeBall {
val name = buffer.readResourceLocation()
val model2d = buffer.readResourceLocation()
val model3d = buffer.readResourceLocation()
val throwPower = buffer.readFloat()
val waterDrag = buffer.readFloat()
val ancient = buffer.readBoolean()
val color = Color(buffer.readInt())
val catchRateModifier = CobblemonCatchRateModifierAdapter.decode(buffer)
return PokeBall(
name = name,
model2d = model2d,
model3d = model3d,
throwPower = throwPower,
waterDragValue = waterDrag,
ancient = ancient,
beamColor = color,
catchRateModifier = catchRateModifier,
effects = listOf(),
)
}
override fun synchronizeDecoded(entries: Collection<PokeBall>) {
PokeBalls.reload(entries.associateBy { it.name }, RegistryAccessResolver.getAccess())
}
}
@@ -30,8 +30,8 @@ class CaughtBallUpdatePacket(pokemon: () -> Pokemon?, value: PokeBall): SingleUp
val ID = cobblemonResource("caught_ball_update")
fun decode(buffer: RegistryFriendlyByteBuf): CaughtBallUpdatePacket {
val pokemon = decodePokemon(buffer)
val pokeBall = PokeBalls.getPokeBall(buffer.readIdentifier())
val pokeBall = PokeBalls.getPokeBall(buffer.readIdentifier()) ?: PokeBalls.POKE_BALL
return CaughtBallUpdatePacket(pokemon, pokeBall)
}
}
}
}
@@ -9,25 +9,17 @@
package com.cobblemon.mod.common.pokeball
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addPokeBallFunctions
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.molang.ObjectValue
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.api.pokeball.catching.CaptureEffect
import com.cobblemon.mod.common.api.pokeball.catching.CatchRateModifier
import com.cobblemon.mod.common.item.PokeBallItem
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.adapters.RegistryAccessResolver
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.codec.CodecUtils
import com.google.gson.annotations.SerializedName
import com.mojang.serialization.Codec
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Rarity
import java.awt.Color
import net.minecraft.resources.ResourceLocation
/**
* Base poke ball object
@@ -39,50 +31,37 @@ import java.awt.Color
* @property waterDragValue The value of the water drag modifier when the entity travels, default is 0.8.
* @property model2d The identifier for the resource this Pokéball will use for the 2d model.
* @property model3d The identifier for the resource this Pokéball will use for the 3d model.
* @property ancient Marks this Pokéball as ancient, which makes it play different animations on catch hops
* @property beamColor Defines the beam color of pokeball
*/
class PokeBall @JvmOverloads constructor(
@Transient // Assigns in PokeBalls.reload
var name: ResourceLocation = cobblemonResource("strange_ball"),
@SerializedName("modifier")
open class PokeBall(
val name: ResourceLocation,
val catchRateModifier: CatchRateModifier = CatchRateModifier.DUMMY,
val effects: List<ExpressionLike> = listOf(),
@SerializedName("item_properties")
val itemProperties: PokeBallProperties = PokeBallProperties(),
@SerializedName("water_drag")
val effects: List<CaptureEffect> = listOf(),
val waterDragValue: Float,
@SerializedName("model_2d")
val model2d: ResourceLocation,
@SerializedName("model_3d")
val model3d: ResourceLocation,
@SerializedName("throw_power")
val throwPower: Float,
val ancient: Boolean = false,
@SerializedName("beam_color")
val beamColor: Color = Color.RED,
val ancient: Boolean
) {
@delegate:Transient
val struct: QueryStruct by lazy {
ObjectValue(this)
.addPokeBallFunctions(this)
.addFunction("stack") { this.stack().asMoLangValue(RegistryAccessResolver.getAccess()) }
}
val struct = QueryStruct(hashMapOf())
.addFunction("name") { StringValue(name.toString()) }
.addFunction("water_drag_value") { DoubleValue(waterDragValue) }
.addFunction("throw_power") { DoubleValue(throwPower) }
.addFunction("is_ancient") { DoubleValue(ancient) }
// .addFunction("item") { } // requires a registry which is hard
// This gets attached during item registry
@Transient
internal lateinit var stack: ItemStack
internal lateinit var item: PokeBallItem
fun item(): PokeBallItem = this.stack.item as PokeBallItem
fun item(): PokeBallItem = this.item
fun stack(count: Int = 1): ItemStack =
ItemStack(this.item(), count)
fun itemProperties(): Item.Properties = Item.Properties()
.rarity(this.itemProperties.rarity)
.let { if (itemProperties.fireResistant) it.fireResistant() else it }
@Deprecated("This is a temporary solution for the safari ball dilemma", ReplaceWith("target.currentHealth"))
internal fun hpForCalculation(target: Pokemon): Int = if (this.name == PokeBalls.SAFARI_BALL.name) target.maxHealth else target.currentHealth
companion object {
@JvmStatic
val BY_IDENTIFIER_CODEC: Codec<PokeBall> = CodecUtils.createByIdentifierCodec(
PokeBalls::getPokeBall,
@@ -91,8 +70,4 @@ class PokeBall @JvmOverloads constructor(
}
data class PokeBallProperties(
val fireResistant: Boolean = false,
val rarity: Rarity = Rarity.COMMON
)
}
}
@@ -46,7 +46,7 @@ object Gen1CaptureCalculator : CaptureCalculator {
}
// This value can be reused when calculating the shakes in case of breakout.
val nBound = when (pokeBall) {
PokeBalls.POKE_BALL, PokeBalls.STRANGE_BALL -> 255
PokeBalls.POKE_BALL -> 255
PokeBalls.GREAT_BALL -> 200
else -> 150
}
@@ -97,4 +97,4 @@ object Gen1CaptureCalculator : CaptureCalculator {
}
}
}
}
@@ -642,16 +642,7 @@ open class Pokemon : ShowdownIdentifiable {
scaleModifier = 1F + (roundedPercent / 100F)
}
var caughtBall: PokeBall = PokeBalls.STRANGE_BALL
get() {
return try {
field
} catch (_: Exception) {
// account for possibility of ball removal (datapack disable/removal)
CaughtBallUpdatePacket({ this }, PokeBalls.STRANGE_BALL)
PokeBalls.STRANGE_BALL
}
}
var caughtBall: PokeBall = PokeBalls.POKE_BALL
set(value) {
field = value
onChange(CaughtBallUpdatePacket({ this }, field))
@@ -173,6 +173,7 @@ class Species : ShowdownIdentifiable {
.addStandardFunctions()
.addSpeciesFunctions(this)
var silenceStepSounds = false
fun initialize() {
Cobblemon.statProvider.provide(this)
@@ -256,6 +257,7 @@ class Species : ShowdownIdentifiable {
}
this.riding.encode(buffer)
buffer.writeBoolean(this.silenceStepSounds)
}
fun decode(buffer: RegistryFriendlyByteBuf) {
@@ -299,6 +301,7 @@ class Species : ShowdownIdentifiable {
}
}
this.riding = RidingProperties.decode(buffer)
this.silenceStepSounds = buffer.readBoolean()
this.initialize()
}
@@ -19,8 +19,6 @@ import java.nio.file.SimpleFileVisitor
import java.nio.file.attribute.BasicFileAttributes
import kotlin.io.path.toPath
import net.minecraft.resources.ResourceLocation
import kotlin.io.path.name
import kotlin.text.endsWith
/**
* Basic functions for dealing with assets inside the mod, using the standard file visitor
@@ -31,9 +29,7 @@ import kotlin.text.endsWith
*/
object AssetLoading {
fun ResourceLocation.toPath() = toURL()?.toPath()
fun ResourceLocation.toURL() =
Cobblemon::class.java.getResource(String.format("/assets/%s/%s", namespace, path))?.toURI()
fun ResourceLocation.toURL() = Cobblemon::class.java.getResource(String.format("/assets/%s/%s", namespace, path))?.toURI()
fun fileSearch(dir: Path, filter: (Path) -> Boolean, recursive: Boolean): List<Path> {
val files = mutableListOf<Path>()
Files.walkFileTree(dir, object : SimpleFileVisitor<Path>() {
@@ -62,14 +58,4 @@ object AssetLoading {
}
}
}
/**
* very "clever" way to get all files in asset folder in loaded minecraft client env
*
*/
fun allAtPath(dir: Path, recursive: Boolean = false, suffix: String = ".json", take: Int = 2) = fileSearch(
dir = dir,
recursive = recursive,
filter = { path -> path.name.endsWith(suffix) },
).map { it.toString().removeSuffix(suffix).split("/").takeLast(take).joinToString("/") }
}
}
@@ -234,11 +234,11 @@ fun Entity.isDusk(): Boolean {
}
fun Entity.isStandingOn(blocks: Set<String>, depth: Int = 2): Boolean {
for (currentDepth in 1..depth) {
val bellowBlockPos = blockPosition().below(currentDepth)
for (currentDepth in 0..depth) {
val bellowBlockPos = blockPosBelowThatAffectsMyMovement.below(currentDepth)
val blockState = level().getBlockState(bellowBlockPos)
if (blockState.isAir || !blockState.isCollisionShapeFullBlock(level(), bellowBlockPos)) continue
if (blockState.isAir) continue
val elementOrTags = ExtraCodecs.TAG_OR_ELEMENT_ID.listOf().decode(JavaOps.INSTANCE, blocks.toList()).result().get().first
elementOrTags.forEach {
@@ -1,87 +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.api.pokeball.catching.CaptureEffect
import com.cobblemon.mod.common.util.readString
import com.cobblemon.mod.common.util.writeString
import com.google.common.collect.HashBiMap
import com.google.gson.Gson
import com.google.gson.GsonBuilder
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 net.minecraft.network.FriendlyByteBuf
import java.lang.reflect.Type
import kotlin.reflect.KClass
object CobblemonCaptureEffectAdapter : JsonDeserializer<CaptureEffect>, JsonSerializer<CaptureEffect> {
private const val VARIANT = "variant"
private val types = HashBiMap.create<String, KClass<out CaptureEffect>>()
val gson: Gson by lazy {
GsonBuilder()
.registerTypeAdapter(CaptureEffect::class.java, CobblemonCaptureEffectAdapter)
.setPrettyPrinting()
.create()
}
fun <T : CaptureEffect> registerType(id: String, type: KClass<T>) {
this.types[id.lowercase()] = type
}
override fun deserialize(
json: JsonElement,
typeOfT: Type,
context: JsonDeserializationContext,
): CaptureEffect {
val variant =
json.asJsonObject
.get(VARIANT)
.asString
.lowercase()
val type = getModifierType(variant)
return context.deserialize(json, type.java)
}
override fun serialize(
effect: CaptureEffect,
typeOfSrc: Type,
context: JsonSerializationContext,
): JsonElement {
val json = context.serialize(effect, effect::class.java).asJsonObject
val variant = getVariant(effect)
json.addProperty(VARIANT, variant)
return json
}
fun encode(effect: CaptureEffect, buffer: FriendlyByteBuf) {
buffer.writeString(gson.toJson(effect, CaptureEffect::class.java))
}
fun decode(buffer: FriendlyByteBuf): CaptureEffect = gson.fromJson(buffer.readString(), CaptureEffect::class.java)
private fun getVariant(effect: CaptureEffect): String {
val variant =
this.types.inverse()[effect::class]
?: throw IllegalArgumentException("Cannot resolve pokeball capture effect for type ${effect::class.qualifiedName}")
return variant
}
private fun getModifierType(variant: String): KClass<out CaptureEffect> {
val effectType =
this.types[variant] ?: throw IllegalArgumentException("Cannot resolve pokeball capture effect type for variant $variant")
return effectType
}
}
@@ -1,101 +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.bedrockk.molang.Expression
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.pokeball.catching.CatchRateModifier
import com.cobblemon.mod.common.api.pokeball.catching.modifiers.*
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
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.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import java.lang.reflect.Type
import kotlin.reflect.KClass
object CobblemonCatchRateModifierAdapter : CatchRateModifierAdapter {
private const val VARIANT = "variant"
private val types = HashBiMap.create<String, KClass<out CatchRateModifier>>()
init {
this.registerType(SimpleModifier.VARIANT, SimpleModifier::class)
this.registerType(BaseStatModifier.VARIANT, BaseStatModifier::class)
this.registerType(GuaranteedModifier.VARIANT, GuaranteedModifier::class)
this.registerType(PropertyBasedModifier.VARIANT, PropertyBasedModifier::class)
this.registerType(LabelModifier.VARIANT, LabelModifier::class)
this.registerType(ExpressionModifier.VARIANT, ExpressionModifier::class)
}
val gson: Gson by lazy {
GsonBuilder()
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
.registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter)
.registerTypeAdapter(CatchRateModifier::class.java, CobblemonCatchRateModifierAdapter)
.setPrettyPrinting()
.create()
}
override fun <T : CatchRateModifier> registerType(id: String, type: KClass<T>) {
this.types[id.lowercase()] = type
}
override fun deserialize(
json: JsonElement,
typeOfT: Type,
context: JsonDeserializationContext,
): CatchRateModifier {
val variant =
json.asJsonObject
.get(VARIANT)
.asString
.lowercase()
val type = getModifierType(variant)
return context.deserialize(json, type.java)
}
override fun serialize(
modifier: CatchRateModifier,
typeOfSrc: Type,
context: JsonSerializationContext,
): JsonElement {
val json = context.serialize(modifier, modifier::class.java).asJsonObject
val variant = getVariant(modifier)
json.addProperty(VARIANT, variant)
return json
}
fun encode(modifier: CatchRateModifier, buffer: FriendlyByteBuf) {
buffer.writeString(gson.toJson(modifier, CatchRateModifier::class.java))
}
fun decode(buffer: FriendlyByteBuf): CatchRateModifier =
gson.fromJson(buffer.readString(), CatchRateModifier::class.java)
private fun getVariant(modifier: CatchRateModifier): String {
val variant =
this.types.inverse()[modifier::class]
?: throw IllegalArgumentException("Cannot resolve pokeball catchrate modifier for type ${modifier::class.qualifiedName}")
return variant
}
private fun getModifierType(variant: String): KClass<out CatchRateModifier> {
val requirementType =
this.types[variant]
?: throw IllegalArgumentException("Cannot resolve pokeball catchrate modifier type for variant $variant")
return requirementType
}
}
@@ -1,64 +0,0 @@
/*
* Copyright (c) 2026. gitoido-mc
* This Source Code Form is subject to the terms of the GNU General Public License v3.0.
* If a copy of the GNU General Public License v3.0 was not distributed with this file,
* you can obtain one at https://github.com/gitoido-mc/conditional-riding/blob/main/LICENSE.
*/
package com.cobblemon.mod.common.util.adapters
import com.google.gson.Gson
import com.google.gson.TypeAdapter
import com.google.gson.TypeAdapterFactory
import com.google.gson.reflect.TypeToken
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken
import com.google.gson.stream.JsonWriter
import java.io.IOException
import java.lang.reflect.ParameterizedType
import java.util.*
class OptionalTypeAdapterFactory : TypeAdapterFactory {
class OptionalTypeAdapter<T>(
private val typeAdapter: TypeAdapter<T>,
) : TypeAdapter<Optional<T>>() {
@Throws(IOException::class)
override fun write(
out: JsonWriter,
value: Optional<T>,
) {
when (value.isPresent) {
true -> typeAdapter.write(out, value.get())
false -> out.nullValue()
}
}
@Throws(IOException::class)
override fun read(`in`: JsonReader): Optional<T> =
when (`in`.peek() != JsonToken.NULL) {
true -> {
Optional.ofNullable(typeAdapter.read(`in`))
}
false -> {
`in`.nextNull()
Optional.empty()
}
} as Optional<T>
}
override fun <T> create(
gson: Gson,
typeToken: TypeToken<T>,
): TypeAdapter<T>? {
if (!Optional::class.java.isAssignableFrom(typeToken.rawType)) return null
val optionalType = typeToken.type
val parametrizedType = optionalType as ParameterizedType
val typeArgs = parametrizedType.actualTypeArguments
val inner = TypeToken.get(typeArgs.first())
val innerAdapter = gson.getAdapter(inner)
return OptionalTypeAdapter(innerAdapter) as TypeAdapter<T>?
}
}
@@ -1,63 +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.api.pokeball.catching.CatchRateModifier
import com.cobblemon.mod.common.api.spawning.detail.PossibleHeldItem
import com.cobblemon.mod.common.pokeball.PokeBall
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.mojang.serialization.Codec
import com.mojang.serialization.JsonOps
import net.minecraft.client.renderer.item.ItemProperties
import net.minecraft.core.component.DataComponentMap
import net.minecraft.resources.ResourceLocation
import java.awt.Color
import java.lang.reflect.Type
import kotlin.jvm.optionals.getOrNull
/**
* A JSON deserializer for [PokeBall].
*
* @author Gito
* @since October 28th, 2026
*/
object PokeBallAdapter : JsonDeserializer<PokeBall> {
override fun deserialize(json: JsonElement, tp: Type, ctx: JsonDeserializationContext): PokeBall {
json as JsonObject
val beamColor: Color = when(json.has("beam_color")) {
true -> Color.decode(json.get("beam_color").asString)
false -> Color.RED
}
val properties: PokeBall.PokeBallProperties = when(json.has("item_properties")) {
true -> ctx.deserialize(json.get("item_properties"), PokeBall.PokeBallProperties::class.java)
false -> PokeBall.PokeBallProperties()
}
return PokeBall(
catchRateModifier = ctx.deserialize(json.get("modifier"), CatchRateModifier::class.java),
effects = listOf(),
itemProperties = properties,
waterDragValue = tryParse(json.get("water_drag"), Codec.FLOAT),
model2d = tryParse(json.get("model_2d"), ResourceLocation.CODEC),
model3d = tryParse(json.get("model_3d"), ResourceLocation.CODEC),
throwPower = tryParse(json.get("throw_power"), Codec.FLOAT),
ancient = if (json.has("ancient")) json.get("ancient").asBoolean else false,
beamColor = beamColor,
)
}
private fun <T> tryParse(json: JsonElement, codec: Codec<T>): T {
return runCatching { JsonOps.INSTANCE.withDecoder(codec).apply(json).result().getOrNull()!!.first }.getOrThrow()
}
}
@@ -27,5 +27,7 @@ object CobblemonGameRules {
@JvmField
val HEALERS_HEAL_PC: GameRules.Key<GameRules.BooleanValue> = Cobblemon.implementation.registerGameRule("healersHealPC", GameRules.Category.MISC, BooleanRuleInvoker.`cobblemon$create`(false))
@JvmField
val HEALER_SET_SPAWN: GameRules.Key<GameRules.BooleanValue> = Cobblemon.implementation.registerGameRule("healersSetSpawn", GameRules.Category.MISC, BooleanRuleInvoker.`cobblemon$create`(false))
@JvmField
val DO_POKEMON_PREDATION: GameRules.Key<GameRules.BooleanValue> = Cobblemon.implementation.registerGameRule("doPokemonPredation", GameRules.Category.MOBS, BooleanRuleInvoker.`cobblemon$create`(true))
}
@@ -1,33 +0,0 @@
{
"portraitScale": 1,
"portraitTranslation": [0, 0, 0],
"profileScale": 1,
"profileTranslation": [0, 0, 0],
"rootBone": "ancient_ball",
"poses": {
"flying": {
"poseTypes": ["NONE"],
"condition": "q.capture_state() == 'NOT'",
"animations": ["q.bedrock('ancient_ball', 'throw')"],
"transitions": {
"open": "q.bedrock_stateful('ancient_ball', 'open')"
}
},
"open": {
"poseTypes": ["NONE", "PORTRAIT"],
"animations": ["q.bedrock('ancient_ball', 'open_idle')"],
"transitions": {
"shut": "q.bedrock_stateful('ancient_ball', 'shut')"
}
},
"shut": {
"poseTypes": ["NONE", "PORTRAIT"],
"animations": [
"q.bedrock('ancient_ball', 'shut_idle')"
],
"transitions": {
"open": "q.bedrock_stateful('ancient_ball', 'open')"
}
}
}
}
@@ -1,33 +0,0 @@
{
"portraitScale": 1,
"portraitTranslation": [0, 0, 0],
"profileScale": 1,
"profileTranslation": [0, 0, 0],
"rootBone": "poke_ball",
"poses": {
"flying": {
"poseTypes": ["NONE"],
"condition": "q.capture_state() == 'NOT'",
"animations": ["q.bedrock('poke_ball', 'throw')"],
"transitions": {
"open": "q.bedrock_stateful('poke_ball', 'open')"
}
},
"open": {
"poseTypes": ["NONE", "PORTRAIT"],
"animations": ["q.bedrock('poke_ball', 'open_idle')"],
"transitions": {
"shut": "q.bedrock_stateful('poke_ball', 'shut')"
}
},
"shut": {
"poseTypes": ["NONE", "PORTRAIT"],
"animations": [
"q.bedrock('poke_ball', 'shut_idle')"
],
"transitions": {
"open": "q.bedrock_stateful('poke_ball', 'open')"
}
}
}
}
@@ -456,6 +456,12 @@
"cannon_left": {
"position": [0, 0, 3]
}
},
"timeline": {
"0.25": "q.run_molang('cobblemon:stepsound_standard_large');",
"1.25": "q.run_molang('cobblemon:stepsound_standard_large');",
"2.25": "q.run_molang('cobblemon:stepsound_standard_large');",
"3.25": "q.run_molang('cobblemon:stepsound_standard_large');"
}
},
"animation.blastoise.ground_run": {
@@ -1815,6 +1815,12 @@
"wings_open": {
"scale": 0
}
},
"timeline": {
"0.0": "q.run_molang('cobblemon:stepsound_claw_medium');",
"0.5": "q.run_molang('cobblemon:stepsound_claw_medium');",
"1.0": "q.run_molang('cobblemon:stepsound_claw_medium');",
"1.5": "q.run_molang('cobblemon:stepsound_claw_medium');"
}
},
"animation.pidgeot.mount_ground_idle": {
@@ -3631,6 +3637,12 @@
"wings_open": {
"scale": 0
}
},
"timeline": {
"0.0": "q.run_molang('cobblemon:stepsound_claw_medium');",
"0.5": "q.run_molang('cobblemon:stepsound_claw_medium');",
"1.0": "q.run_molang('cobblemon:stepsound_claw_medium');",
"1.5": "q.run_molang('cobblemon:stepsound_claw_medium');"
}
},
"animation.pidgeot.ride_ground_walk": {
@@ -83,6 +83,7 @@
},
"animation.parasect.ground_walk": {
"loop": true,
"animation_length": 1,
"bones": {
"body": {
"rotation": [0, 0, 0],
@@ -134,6 +135,12 @@
"locator_seat_1": {
"rotation": [7.5, 0, 0]
}
},
"timeline": {
"0.0": "q.run_molang('cobblemon:stepsound_minecraft');",
"0.25": "q.run_molang('cobblemon:stepsound_minecraft');",
"0.5": "q.run_molang('cobblemon:stepsound_minecraft');",
"0.75": "q.run_molang('cobblemon:stepsound_minecraft');"
}
},
"animation.parasect.ground_run": {
@@ -258,6 +265,10 @@
"rotation": ["5+Math.cos((query.anim_time) * 90 * 16 - 90) * 2", 0, 0],
"position": [0, "0+Math.cos((query.anim_time) * 90 * 32) * -0.2", -0.25]
}
},
"timeline": {
"0.0": "q.run_molang('cobblemon:stepsound_minecraft');",
"0.125": "q.run_molang('cobblemon:stepsound_minecraft');"
}
},
"animation.parasect.ride_ground_run": {
@@ -1682,6 +1682,12 @@
"1.3333": [10, 9, 0]
}
}
},
"timeline": {
"0.0": "q.run_molang('cobblemon:stepsound_standard_medium');",
"0.4583": "q.run_molang('cobblemon:stepsound_standard_medium');",
"0.6667": "q.run_molang('cobblemon:stepsound_standard_medium');",
"1.125": "q.run_molang('cobblemon:stepsound_standard_medium');"
}
},
"animation.arcanine.ride_ground_walk": {
@@ -2639,6 +2645,12 @@
"chest_fluff_right": {
"rotation": [5, "-22.5+math.cos(q.anim_time*90*8-120)*15", "-math.sin(q.anim_time*90*8-120)*3"]
}
},
"timeline": {
"0.125": "q.run_molang('cobblemon:stepsound_standard_medium');",
"0.2083": "q.run_molang('cobblemon:stepsound_standard_large');",
"0.2917": "q.run_molang('cobblemon:stepsound_standard_medium');",
"0.375": "q.run_molang('cobblemon:stepsound_standard_medium');"
}
},
"animation.arcanine.ride_ground_run": {
@@ -4161,41 +4173,101 @@
"eye_left": {
"position": {
"0.0": [0, 0, 0],
"0.1667": {"pre": [0, 0, 0], "post": [-0.1, 0, 0.1]},
"0.5": {"pre": [-0.1, 0, 0.1], "post": [0, 0, 0]},
"1.4167": {"pre": [0, 0, 0], "post": [-0.1, 0, 0.1]},
"1.6667": {"pre": [-0.1, 0, 0.1], "post": [0, 0, 0]},
"2.5": {"pre": [0, 0, 0], "post": [0, 0, 0]}
"0.1667": {
"pre": [0, 0, 0],
"post": [-0.1, 0, 0.1]
},
"0.5": {
"pre": [-0.1, 0, 0.1],
"post": [0, 0, 0]
},
"1.4167": {
"pre": [0, 0, 0],
"post": [-0.1, 0, 0.1]
},
"1.6667": {
"pre": [-0.1, 0, 0.1],
"post": [0, 0, 0]
},
"2.5": {
"pre": [0, 0, 0],
"post": [0, 0, 0]
}
}
},
"eye_right": {
"position": {
"0.0": [0, 0, 0],
"0.1667": {"pre": [0, 0, 0], "post": [0.1, 0, 0.1]},
"0.5": {"pre": [0.1, 0, 0.1], "post": [0, 0, 0]},
"1.4167": {"pre": [0, 0, 0], "post": [0.1, 0, 0.1]},
"1.6667": {"pre": [0.1, 0, 0.1], "post": [0, 0, 0]},
"2.5": {"pre": [0, 0, 0], "post": [0, 0, 0]}
"0.1667": {
"pre": [0, 0, 0],
"post": [0.1, 0, 0.1]
},
"0.5": {
"pre": [0.1, 0, 0.1],
"post": [0, 0, 0]
},
"1.4167": {
"pre": [0, 0, 0],
"post": [0.1, 0, 0.1]
},
"1.6667": {
"pre": [0.1, 0, 0.1],
"post": [0, 0, 0]
},
"2.5": {
"pre": [0, 0, 0],
"post": [0, 0, 0]
}
}
},
"eyelid_left": {
"position": {
"0.0": [0, 0, 0],
"0.1667": {"pre": [0, 0, 0], "post": [0.1, 0, -0.1]},
"0.5": {"pre": [0.1, 0, -0.1], "post": [0, 0, 0]},
"1.4167": {"pre": [0, 0, 0], "post": [0.1, 0, -0.1]},
"1.6667": {"pre": [0.1, 0, -0.1], "post": [0, 0, 0]},
"2.5": {"pre": [0, 0, 0], "post": [0, 0, 0]}
"0.1667": {
"pre": [0, 0, 0],
"post": [0.1, 0, -0.1]
},
"0.5": {
"pre": [0.1, 0, -0.1],
"post": [0, 0, 0]
},
"1.4167": {
"pre": [0, 0, 0],
"post": [0.1, 0, -0.1]
},
"1.6667": {
"pre": [0.1, 0, -0.1],
"post": [0, 0, 0]
},
"2.5": {
"pre": [0, 0, 0],
"post": [0, 0, 0]
}
}
},
"eyelid_right": {
"position": {
"0.0": [0, 0, 0],
"0.1667": {"pre": [0, 0, 0], "post": [-0.1, 0, -0.1]},
"0.5": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]},
"1.4167": {"pre": [0, 0, 0], "post": [-0.1, 0, -0.1]},
"1.6667": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]},
"2.5": {"pre": [0, 0, 0], "post": [0, 0, 0]}
"0.1667": {
"pre": [0, 0, 0],
"post": [-0.1, 0, -0.1]
},
"0.5": {
"pre": [-0.1, 0, -0.1],
"post": [0, 0, 0]
},
"1.4167": {
"pre": [0, 0, 0],
"post": [-0.1, 0, -0.1]
},
"1.6667": {
"pre": [-0.1, 0, -0.1],
"post": [0, 0, 0]
},
"2.5": {
"pre": [0, 0, 0],
"post": [0, 0, 0]
}
}
},
"jaw": {
@@ -4823,41 +4895,101 @@
"eye_left": {
"position": {
"0.0": [0, 0, 0],
"0.1667": {"pre": [0, 0, 0], "post": [-0.1, 0, 0.1]},
"0.5": {"pre": [-0.1, 0, 0.1], "post": [0, 0, 0]},
"1.4167": {"pre": [0, 0, 0], "post": [-0.1, 0, 0.1]},
"1.6667": {"pre": [-0.1, 0, 0.1], "post": [0, 0, 0]},
"2.5": {"pre": [0, 0, 0], "post": [0, 0, 0]}
"0.1667": {
"pre": [0, 0, 0],
"post": [-0.1, 0, 0.1]
},
"0.5": {
"pre": [-0.1, 0, 0.1],
"post": [0, 0, 0]
},
"1.4167": {
"pre": [0, 0, 0],
"post": [-0.1, 0, 0.1]
},
"1.6667": {
"pre": [-0.1, 0, 0.1],
"post": [0, 0, 0]
},
"2.5": {
"pre": [0, 0, 0],
"post": [0, 0, 0]
}
}
},
"eye_right": {
"position": {
"0.0": [0, 0, 0],
"0.1667": {"pre": [0, 0, 0], "post": [0.1, 0, 0.1]},
"0.5": {"pre": [0.1, 0, 0.1], "post": [0, 0, 0]},
"1.4167": {"pre": [0, 0, 0], "post": [0.1, 0, 0.1]},
"1.6667": {"pre": [0.1, 0, 0.1], "post": [0, 0, 0]},
"2.5": {"pre": [0, 0, 0], "post": [0, 0, 0]}
"0.1667": {
"pre": [0, 0, 0],
"post": [0.1, 0, 0.1]
},
"0.5": {
"pre": [0.1, 0, 0.1],
"post": [0, 0, 0]
},
"1.4167": {
"pre": [0, 0, 0],
"post": [0.1, 0, 0.1]
},
"1.6667": {
"pre": [0.1, 0, 0.1],
"post": [0, 0, 0]
},
"2.5": {
"pre": [0, 0, 0],
"post": [0, 0, 0]
}
}
},
"eyelid_left": {
"position": {
"0.0": [0, 0, 0],
"0.1667": {"pre": [0, 0, 0], "post": [0.1, 0, -0.1]},
"0.5": {"pre": [0.1, 0, -0.1], "post": [0, 0, 0]},
"1.4167": {"pre": [0, 0, 0], "post": [0.1, 0, -0.1]},
"1.6667": {"pre": [0.1, 0, -0.1], "post": [0, 0, 0]},
"2.5": {"pre": [0, 0, 0], "post": [0, 0, 0]}
"0.1667": {
"pre": [0, 0, 0],
"post": [0.1, 0, -0.1]
},
"0.5": {
"pre": [0.1, 0, -0.1],
"post": [0, 0, 0]
},
"1.4167": {
"pre": [0, 0, 0],
"post": [0.1, 0, -0.1]
},
"1.6667": {
"pre": [0.1, 0, -0.1],
"post": [0, 0, 0]
},
"2.5": {
"pre": [0, 0, 0],
"post": [0, 0, 0]
}
}
},
"eyelid_right": {
"position": {
"0.0": [0, 0, 0],
"0.1667": {"pre": [0, 0, 0], "post": [-0.1, 0, -0.1]},
"0.5": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]},
"1.4167": {"pre": [0, 0, 0], "post": [-0.1, 0, -0.1]},
"1.6667": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]},
"2.5": {"pre": [0, 0, 0], "post": [0, 0, 0]}
"0.1667": {
"pre": [0, 0, 0],
"post": [-0.1, 0, -0.1]
},
"0.5": {
"pre": [-0.1, 0, -0.1],
"post": [0, 0, 0]
},
"1.4167": {
"pre": [0, 0, 0],
"post": [-0.1, 0, -0.1]
},
"1.6667": {
"pre": [-0.1, 0, -0.1],
"post": [0, 0, 0]
},
"2.5": {
"pre": [0, 0, 0],
"post": [0, 0, 0]
}
}
},
"jaw": {
@@ -5287,14 +5419,20 @@
"position": {
"0.0": [-0.1, 0, 0.1],
"0.125": [-0.1, 0, 0.1],
"0.1667": {"pre": [-0.1, 0, 0.1], "post": [0, 0, 0]}
"0.1667": {
"pre": [-0.1, 0, 0.1],
"post": [0, 0, 0]
}
}
},
"eye_right": {
"position": {
"0.0": [0.1, 0, 0.1],
"0.125": [0.1, 0, 0.1],
"0.1667": {"pre": [0.1, 0, 0.1], "post": [0, 0, 0]}
"0.1667": {
"pre": [0.1, 0, 0.1],
"post": [0, 0, 0]
}
}
}
}
@@ -5491,47 +5629,95 @@
"eye_left": {
"position": {
"0.0": [0, 0, 0],
"0.0417": {"pre": [0, 0, 0], "post": [-0.2, 0, 0.1]},
"0.3333": {"pre": [-0.2, 0, 0.1], "post": [0, 0, 0]},
"1.25": {"pre": [0, 0, 0], "post": [0, 0, 0]}
"0.0417": {
"pre": [0, 0, 0],
"post": [-0.2, 0, 0.1]
},
"0.3333": {
"pre": [-0.2, 0, 0.1],
"post": [0, 0, 0]
},
"1.25": {
"pre": [0, 0, 0],
"post": [0, 0, 0]
}
}
},
"eye_right": {
"position": {
"0.0": [0, 0, 0],
"0.0417": {"pre": [0, 0, 0], "post": [0.2, 0, 0.1]},
"0.3333": {"pre": [0.2, 0, 0.1], "post": [0, 0, 0]},
"1.25": {"pre": [0, 0, 0], "post": [0, 0, 0]}
"0.0417": {
"pre": [0, 0, 0],
"post": [0.2, 0, 0.1]
},
"0.3333": {
"pre": [0.2, 0, 0.1],
"post": [0, 0, 0]
},
"1.25": {
"pre": [0, 0, 0],
"post": [0, 0, 0]
}
}
},
"eyelid_left": {
"position": {
"0.0": [0, 0, 0],
"0.0417": {"pre": [0, 0, 0], "post": [-0.2, 0, 0.1]},
"0.3333": {"pre": [-0.2, 0, 0.1], "post": [0, 0, 0]},
"1.25": {"pre": [0, 0, 0], "post": [0, 0, 0]}
"0.0417": {
"pre": [0, 0, 0],
"post": [-0.2, 0, 0.1]
},
"0.3333": {
"pre": [-0.2, 0, 0.1],
"post": [0, 0, 0]
},
"1.25": {
"pre": [0, 0, 0],
"post": [0, 0, 0]
}
}
},
"eyelid_right": {
"position": {
"0.0": [0, 0, 0],
"0.0417": {"pre": [0, 0, 0], "post": [0.2, 0, 0.1]},
"0.3333": {"pre": [0.2, 0, 0.1], "post": [0, 0, 0]},
"1.25": {"pre": [0, 0, 0], "post": [0, 0, 0]}
"0.0417": {
"pre": [0, 0, 0],
"post": [0.2, 0, 0.1]
},
"0.3333": {
"pre": [0.2, 0, 0.1],
"post": [0, 0, 0]
},
"1.25": {
"pre": [0, 0, 0],
"post": [0, 0, 0]
}
}
},
"eyelid_left_hurt": {
"position": {
"0.0": [0, 0, 0],
"0.0417": {"pre": [0, 0, 0], "post": [0.1, 0, -0.1]},
"0.3333": {"pre": [0.1, 0, -0.1], "post": [0, 0, 0]}
"0.0417": {
"pre": [0, 0, 0],
"post": [0.1, 0, -0.1]
},
"0.3333": {
"pre": [0.1, 0, -0.1],
"post": [0, 0, 0]
}
}
},
"eyelid_right_hurt": {
"position": {
"0.0": [0, 0, 0],
"0.0417": {"pre": [0, 0, 0], "post": [-0.1, 0, -0.1]},
"0.3333": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]}
"0.0417": {
"pre": [0, 0, 0],
"post": [-0.1, 0, -0.1]
},
"0.3333": {
"pre": [-0.1, 0, -0.1],
"post": [0, 0, 0]
}
}
},
"jaw": {
@@ -6238,47 +6424,95 @@
"eye_left": {
"position": {
"0.0": [0, 0, 0],
"0.0417": {"pre": [0, 0, 0], "post": [-0.2, 0, 0.1]},
"0.3333": {"pre": [-0.2, 0, 0.1], "post": [0, 0, 0]},
"1.25": {"pre": [0, 0, 0], "post": [0, 0, 0]}
"0.0417": {
"pre": [0, 0, 0],
"post": [-0.2, 0, 0.1]
},
"0.3333": {
"pre": [-0.2, 0, 0.1],
"post": [0, 0, 0]
},
"1.25": {
"pre": [0, 0, 0],
"post": [0, 0, 0]
}
}
},
"eye_right": {
"position": {
"0.0": [0, 0, 0],
"0.0417": {"pre": [0, 0, 0], "post": [0.2, 0, 0.1]},
"0.3333": {"pre": [0.2, 0, 0.1], "post": [0, 0, 0]},
"1.25": {"pre": [0, 0, 0], "post": [0, 0, 0]}
"0.0417": {
"pre": [0, 0, 0],
"post": [0.2, 0, 0.1]
},
"0.3333": {
"pre": [0.2, 0, 0.1],
"post": [0, 0, 0]
},
"1.25": {
"pre": [0, 0, 0],
"post": [0, 0, 0]
}
}
},
"eyelid_left": {
"position": {
"0.0": [0, 0, 0],
"0.0417": {"pre": [0, 0, 0], "post": [-0.2, 0, 0.1]},
"0.3333": {"pre": [-0.2, 0, 0.1], "post": [0, 0, 0]},
"1.25": {"pre": [0, 0, 0], "post": [0, 0, 0]}
"0.0417": {
"pre": [0, 0, 0],
"post": [-0.2, 0, 0.1]
},
"0.3333": {
"pre": [-0.2, 0, 0.1],
"post": [0, 0, 0]
},
"1.25": {
"pre": [0, 0, 0],
"post": [0, 0, 0]
}
}
},
"eyelid_right": {
"position": {
"0.0": [0, 0, 0],
"0.0417": {"pre": [0, 0, 0], "post": [0.2, 0, 0.1]},
"0.3333": {"pre": [0.2, 0, 0.1], "post": [0, 0, 0]},
"1.25": {"pre": [0, 0, 0], "post": [0, 0, 0]}
"0.0417": {
"pre": [0, 0, 0],
"post": [0.2, 0, 0.1]
},
"0.3333": {
"pre": [0.2, 0, 0.1],
"post": [0, 0, 0]
},
"1.25": {
"pre": [0, 0, 0],
"post": [0, 0, 0]
}
}
},
"eyelid_left_hurt": {
"position": {
"0.0": [0, 0, 0],
"0.0417": {"pre": [0, 0, 0], "post": [0.1, 0, -0.1]},
"0.3333": {"pre": [0.1, 0, -0.1], "post": [0, 0, 0]}
"0.0417": {
"pre": [0, 0, 0],
"post": [0.1, 0, -0.1]
},
"0.3333": {
"pre": [0.1, 0, -0.1],
"post": [0, 0, 0]
}
}
},
"eyelid_right_hurt": {
"position": {
"0.0": [0, 0, 0],
"0.0417": {"pre": [0, 0, 0], "post": [-0.1, 0, -0.1]},
"0.3333": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]}
"0.0417": {
"pre": [0, 0, 0],
"post": [-0.1, 0, -0.1]
},
"0.3333": {
"pre": [-0.1, 0, -0.1],
"post": [0, 0, 0]
}
}
},
"jaw": {
@@ -391,6 +391,10 @@
"0.7083": [0, 0, 0]
}
}
},
"timeline": {
"0.0833": "q.run_molang('cobblemon:stepsound_standard_medium');",
"0.2917": "q.run_molang('cobblemon:stepsound_standard_medium');"
}
},
"animation.dewgong.water_idle": {
@@ -1071,6 +1071,16 @@
"head": {
"rotation": ["-0.8*math.cos(q.anim_time*90*8-120)", 0, "3*math.sin(q.anim_time*90*4+70)"]
}
},
"timeline": {
"0.0": "q.run_molang('cobblemon:stepsound_standard_large');",
"0.5": "q.run_molang('cobblemon:stepsound_standard_large');",
"1.0": "q.run_molang('cobblemon:stepsound_standard_large');",
"1.5": "q.run_molang('cobblemon:stepsound_standard_large');",
"2.0": "q.run_molang('cobblemon:stepsound_standard_large');",
"2.5": "q.run_molang('cobblemon:stepsound_standard_large');",
"3.0": "q.run_molang('cobblemon:stepsound_standard_large');",
"3.5": "q.run_molang('cobblemon:stepsound_standard_large');"
}
},
"animation.rhyhorn.ride_ground_walk": {
@@ -1917,6 +1927,16 @@
],
"position": [0, "0.4+0.6*math.cos(q.anim_time*90*8-120)", 0]
}
},
"timeline": {
"0.0": "q.run_molang('cobblemon:stepsound_standard_large');",
"0.375": "q.run_molang('cobblemon:stepsound_standard_medium');",
"0.5": "q.run_molang('cobblemon:stepsound_standard_large');",
"0.875": "q.run_molang('cobblemon:stepsound_standard_medium');",
"1.0": "q.run_molang('cobblemon:stepsound_standard_large');",
"1.375": "q.run_molang('cobblemon:stepsound_standard_medium');",
"1.5": "q.run_molang('cobblemon:stepsound_standard_large');",
"1.875": "q.run_molang('cobblemon:stepsound_standard_medium');"
}
},
"animation.rhyhorn.ride_ground_run": {
@@ -329,6 +329,12 @@
"locator_seat_1": {
"rotation": [-15, 0, 0]
}
},
"timeline": {
"0.0": "q.run_molang('cobblemon:stepsound_standard_large');",
"1.0": "q.run_molang('cobblemon:stepsound_standard_large');",
"2.0": "q.run_molang('cobblemon:stepsound_standard_large');",
"3.0": "q.run_molang('cobblemon:stepsound_standard_large');"
}
},
"animation.rhydon.ride_ground_walk": {
@@ -807,6 +813,12 @@
"locator_seat_1": {
"rotation": [-15, 0, 0]
}
},
"timeline": {
"0.3333": "q.run_molang('cobblemon:stepsound_standard_large');",
"0.8333": "q.run_molang('cobblemon:stepsound_standard_large');",
"1.3333": "q.run_molang('cobblemon:stepsound_standard_large');",
"1.8333": "q.run_molang('cobblemon:stepsound_standard_large');"
}
},
"animation.rhydon.ride_ground_run": {
@@ -391,6 +391,10 @@
"1.0": [0, 0, 0]
}
}
},
"timeline": {
"0.0833": "q.run_molang('cobblemon:stepsound_minecraft');",
"0.5833": "q.run_molang('cobblemon:stepsound_minecraft');"
}
},
"animation.mr_mime.ground_run": {
@@ -3150,6 +3150,10 @@
"locator_seat_2": {
"rotation": [45, 0, 0]
}
},
"timeline": {
"0.5": "q.run_molang('cobblemon:stepsound_claw_large');",
"1.5": "q.run_molang('cobblemon:stepsound_claw_large');"
}
},
"animation.corviknight.ground_run": {
@@ -4473,6 +4477,10 @@
"locator_seat_2": {
"rotation": [25, 0, 0]
}
},
"timeline": {
"0.3333": "q.run_molang('cobblemon:stepsound_claw_large');",
"0.8333": "q.run_molang('cobblemon:stepsound_claw_large');"
}
},
"animation.corviknight.air_idle": {
@@ -566,6 +566,12 @@
"1.5": [0, 0.2, 0]
}
}
},
"timeline": {
"0.5417": "q.run_molang('cobblemon:stepsound_hoof_medium');",
"0.7083": "q.run_molang('cobblemon:stepsound_hoof_medium');",
"1.2917": "q.run_molang('cobblemon:stepsound_hoof_medium');",
"1.4583": "q.run_molang('cobblemon:stepsound_hoof_medium');"
}
},
"animation.wyrdeer.sleep": {
@@ -780,15 +786,27 @@
"eyelid_right": {
"position": {
"0.0": [0, 0, 0],
"0.25": {"pre": [0, 0, 0], "post": [-0.1, 0, -0.1]},
"0.5": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]}
"0.25": {
"pre": [0, 0, 0],
"post": [-0.1, 0, -0.1]
},
"0.5": {
"pre": [-0.1, 0, -0.1],
"post": [0, 0, 0]
}
}
},
"eyelid_left": {
"position": {
"0.0": [0, 0, 0],
"0.25": {"pre": [0, 0, 0], "post": [0.1, 0, -0.1]},
"0.5": {"pre": [0.1, 0, -0.1], "post": [0, 0, 0]}
"0.25": {
"pre": [0, 0, 0],
"post": [0.1, 0, -0.1]
},
"0.5": {
"pre": [0.1, 0, -0.1],
"post": [0, 0, 0]
}
}
},
"ear_right": {
@@ -1186,18 +1204,36 @@
"position": {
"0.0": [0, 0, 0],
"1.5833": [-0.1, 0, -0.1],
"1.6667": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]},
"3.0": {"pre": [0, 0, 0], "post": [-0.1, 0, -0.1]},
"3.125": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]}
"1.6667": {
"pre": [-0.1, 0, -0.1],
"post": [0, 0, 0]
},
"3.0": {
"pre": [0, 0, 0],
"post": [-0.1, 0, -0.1]
},
"3.125": {
"pre": [-0.1, 0, -0.1],
"post": [0, 0, 0]
}
}
},
"eyelid_left": {
"position": {
"0.0": [0, 0, 0],
"1.5833": [0.1, 0, -0.1],
"1.6667": {"pre": [0.1, 0, -0.1], "post": [0, 0, 0]},
"3.0": {"pre": [0, 0, 0], "post": [0.1, 0, -0.1]},
"3.125": {"pre": [0.1, 0, -0.1], "post": [0, 0, 0]}
"1.6667": {
"pre": [0.1, 0, -0.1],
"post": [0, 0, 0]
},
"3.0": {
"pre": [0, 0, 0],
"post": [0.1, 0, -0.1]
},
"3.125": {
"pre": [0.1, 0, -0.1],
"post": [0, 0, 0]
}
}
},
"tail": {
@@ -2204,6 +2240,16 @@
"1.1667": [0, 0, 0]
}
}
},
"timeline": {
"0.2083": "q.run_molang('cobblemon:stepsound_hoof_medium');",
"0.2917": "q.run_molang('cobblemon:stepsound_hoof_medium');",
"0.375": "q.run_molang('cobblemon:stepsound_hoof_medium');",
"0.4583": "q.run_molang('cobblemon:stepsound_hoof_large');",
"0.7917": "q.run_molang('cobblemon:stepsound_hoof_medium');",
"0.875": "q.run_molang('cobblemon:stepsound_hoof_medium');",
"0.9583": "q.run_molang('cobblemon:stepsound_hoof_medium');",
"1.0417": "q.run_molang('cobblemon:stepsound_hoof_large');"
}
},
"animation.wyrdeer.ride_jump": {
@@ -31,7 +31,6 @@
"item.cobblemon.park_ball": "Park Ball",
"item.cobblemon.dream_ball": "Dream Ball",
"item.cobblemon.beast_ball": "Beast Ball",
"item.cobblemon.strange_ball": "Strange Ball",
"item.cobblemon.ancient_poke_ball": "Ancient Poké Ball",
"item.cobblemon.ancient_citrine_ball": "Ancient Citrine Ball",
"item.cobblemon.ancient_verdant_ball": "Ancient Verdant Ball",
@@ -2435,6 +2434,8 @@
"cobblemon.config.ui.max_pokemon_level.tooltip": "The maximum level Pokémon can get to.",
"cobblemon.config.ui.max_pokemon_friendship": "Max Pokémon Friendship",
"cobblemon.config.ui.max_pokemon_friendship.tooltip": "The maximum friendship value.",
"cobblemon.config.ui.power_item_ride_stat_gain_interval_seconds": "Power Item Riding Stat Training Interval (Seconds)",
"cobblemon.config.ui.power_item_ride_stat_gain_interval_seconds.tooltip": "Seconds between riding stat gains while riding a Pokémon holding a Power item. Defaults to 120 seconds. Set to -1 or 0 to disable; values below -1 are clamped to -1.",
"cobblemon.config.ui.announce_drop_items": "Announce Drop Items",
"cobblemon.config.ui.announce_drop_items.tooltip": "Whether to notify the Player of dropped items from defeating wild Pokémon.",
"cobblemon.config.ui.default_drop_item_method": "Default Drop Item Method",
@@ -1,6 +1,6 @@
{
"parent": "cobblemon:item/poke_ball/ancient_poke_ball_model",
"parent": "cobblemon:item/ancient_poke_ball_model",
"textures": {
"layer0": "cobblemon:item/poke_balls/models/ancient_azure_ball"
}
}
}
@@ -1,6 +1,6 @@
{
"parent": "cobblemon:item/poke_ball/ancient_poke_ball_model",
"parent": "cobblemon:item/ancient_poke_ball_model",
"textures": {
"layer0": "cobblemon:item/poke_balls/models/ancient_citrine_ball"
}
}
}
@@ -1,6 +1,6 @@
{
"parent": "cobblemon:item/poke_ball/ancient_poke_ball_model",
"parent": "cobblemon:item/ancient_poke_ball_model",
"textures": {
"layer0": "cobblemon:item/poke_balls/models/ancient_feather_ball"
}
}
}
@@ -1,6 +1,6 @@
{
"parent": "cobblemon:item/poke_ball/ancient_poke_ball_model",
"parent": "cobblemon:item/ancient_poke_ball_model",
"textures": {
"layer0": "cobblemon:item/poke_balls/models/ancient_gigaton_ball"
}
}
}
@@ -1,6 +1,6 @@
{
"parent": "cobblemon:item/poke_ball/ancient_poke_ball_model",
"parent": "cobblemon:item/ancient_poke_ball_model",
"textures": {
"layer0": "cobblemon:item/poke_balls/models/ancient_great_ball"
}
}
}
@@ -1,6 +1,6 @@
{
"parent": "cobblemon:item/poke_ball/ancient_poke_ball_model",
"parent": "cobblemon:item/ancient_poke_ball_model",
"textures": {
"layer0": "cobblemon:item/poke_balls/models/ancient_heavy_ball"
}
}
}
@@ -1,6 +1,6 @@
{
"parent": "cobblemon:item/poke_ball/ancient_poke_ball_model",
"parent": "cobblemon:item/ancient_poke_ball_model",
"textures": {
"layer0": "cobblemon:item/poke_balls/models/ancient_ivory_ball"
}
}
}
@@ -1,6 +1,6 @@
{
"parent": "cobblemon:item/poke_ball/ancient_poke_ball_model",
"parent": "cobblemon:item/ancient_poke_ball_model",
"textures": {
"layer0": "cobblemon:item/poke_balls/models/ancient_jet_ball"
}
}
}
@@ -1,6 +1,6 @@
{
"parent": "cobblemon:item/poke_ball/ancient_poke_ball_model",
"parent": "cobblemon:item/ancient_poke_ball_model",
"textures": {
"layer0": "cobblemon:item/poke_balls/models/ancient_leaden_ball"
}
}
}
@@ -1,6 +1,6 @@
{
"parent": "cobblemon:item/poke_ball/ancient_poke_ball_model",
"parent": "cobblemon:item/ancient_poke_ball_model",
"textures": {
"layer0": "cobblemon:item/poke_balls/models/ancient_origin_ball"
}
}
}
Loaded 100 of 704 files, more files were not shown because too many files have changed in this diff. Show more