Compare commits

...
Author SHA1 Message Date
Plastered_Crab db25ebf7f1 Add placeholder type gem blocks (regular and budding) for testing 2024-12-03 13:41:57 -08:00
Hiroku cec0ee04e0 Merge branch 'ability-patch-fix' into 'main'
Ability Patch fix

See merge request cable-mc/cobblemon!1342
2024-12-03 11:41:07 +00:00
Conan 069bc91aa1 Added fix to changelog 2024-12-03 12:39:54 +01:00
Hiroku 692a1bd6ba Merge branch 'stat-sanity' into 'main'
Make Stats#getStat use actual sane checking logic

See merge request cable-mc/cobblemon!1343
2024-12-03 11:22:35 +00:00
amo 3d877496b3 🍋‍🟩 Chore: why was it ever any other way 2024-12-03 02:18:33 +00:00
Conan 1e4964d80c Fixed an issue where Pokémon with their hidden ability couldn't change back to their original abilities 2024-12-02 13:41:01 +01:00
Hiroku 92ecaa66fa Merge branch 'power-items-tooltips' into 'main'
Fixes power items tooltips

See merge request cable-mc/cobblemon!1340
2024-12-01 09:46:08 +00:00
Guilherme Pereira 4d3e6400ab fixes power items tooltips 2024-12-01 05:30:46 -03:00
Paul 60d0c490dd Critical typo correction 2024-12-01 12:23:23 +10:00
Hiroku 3ec89cd84e Merge branch 'beast-rod-line-fix' into 'main'
Fix fishing line color for beast rod

See merge request cable-mc/cobblemon!1339
2024-12-01 01:50:25 +00:00
Hiroku 6452521434 Merge branch 'held-items-tooltips' into 'main'
Held items, evolutions items and candies tooltips

See merge request cable-mc/cobblemon!1318
2024-12-01 01:39:30 +00:00
Guilherme Pereira 5cbf961ac2 Held items, evolutions items and candies tooltips 2024-12-01 01:39:30 +00:00
Hiroku 6b473cffa3 Merge branch 'dex' into 'main'
refactor pokedex item model registration, update Pokedex rendering

See merge request cable-mc/cobblemon!1323
2024-12-01 01:38:41 +00:00
Nick f353548f9e Merge branch 'TheRaftShow' into 'main'
Battle Rafts

See merge request cable-mc/cobblemon!1338
2024-12-01 01:02:38 +00:00
JazzMcNade bba995f3d2 Battle Rafts 2024-12-01 01:02:38 +00:00
Plastered_Crab 46266c08ac Fix fishing line color for beast rod 2024-11-29 21:40:47 -08:00
Test 5f7451c284 rm unused files 2024-11-29 19:13:17 +00:00
Test 454c2c60ab merge from main 2024-11-28 17:35:37 -05:00
Test c581673ef1 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into dex
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/client/gui/pokedex/PokedexGUI.kt
2024-11-28 17:19:53 -05:00
Test 09e29137fc check for view counter block in packet handler 2024-11-28 17:04:48 -05:00
Test fd1e5ef421 split lectern block entity into reuseable class 2024-11-28 16:38:39 -05:00
Test 8de05006f4 update dex rendering for player and blockEntities 2024-11-28 11:15:15 -05:00
Test bd801b1517 refactor pokedex item model registration 2024-11-23 23:08:47 -05:00
264 changed files with 2359 additions and 816 deletions

No files matched your search

+5
View File
@@ -51,6 +51,7 @@
- Added new sounds for Poké Balls bouncing off of Pokémon and landing on the ground during capture.
- Added a unique set of sounds for Ancient Poké Balls.
- Added a sound for using Exp Candy and Rare Candy items.
- Added raft platforms for non-swimming, non-flying Pokémon to stand on during battles that take place on the water's surface. (Flying Pokémon will fly over water in battle, and water breathing Pokémon will swim in water during battle.)
### Pokémon Added
#### Gen 1
@@ -339,8 +340,11 @@
- A high jump indicates 2 shakes.
- A medium jump indicates 3 shakes.
- A short jump indicates that you caught the Pokémon.
- Pokémon sent out during battle will spawn facing their opponent.
- Pokémon sent out outside a battle will spawn facing their trainer.
### Fixes
- Fixed Ability Patches not reverting Hidden Abilities back to Normal Abilities.
- Fixed awarding Pokémon experience upon forfeiting battles.
- Scaled down Amaura's fetus model to avoid clipping through the tank while animating.
- Fixed Cubone's cry not having a sound.
@@ -421,6 +425,7 @@
- Delay when successfully catching a Pokémon in an Ancient Poké Ball has been increased to account for the new sounds and particles.
- Prevent summary stats tab from making sounds when clicking on an already open tab.
- Fixed display case not being able to be fed items from underneath.
- Fixed Pokémon battling in water continuously sinking to the bottom.
### Developer
- `SpawnCause` is now an implementation of `SpawningInfluence`.
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.Cobblemon;
import com.cobblemon.mod.common.ModAPI;
import com.cobblemon.mod.common.client.CobblemonBakingOverrides;
import com.cobblemon.mod.common.item.PokeBallItem;
import com.cobblemon.mod.common.item.PokedexItem;
import com.mojang.blaze3d.vertex.PoseStack;
@@ -20,7 +19,9 @@ import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
@@ -52,25 +53,33 @@ public abstract class ItemRendererMixin {
)
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;
if (!shouldBe2d && stack.getItem() instanceof PokedexItem) {
BakedModel replacementModel = CobblemonBakingOverrides.INSTANCE.getPokedexOverride(((PokedexItem) stack.getItem()).getType()).getModel();
if (!cobblemon$isSameModel(model, replacementModel)) {
ci.cancel();
render(stack, renderMode, leftHanded, matrices, multiBufferSource, light, overlay, replacementModel);
}
} else if (shouldBe2d && stack.getItem() instanceof PokeBallItem pokeBallItem) {
BakedModel replacementModel = this.itemModelShaper.getModelManager().getModel(new ModelResourceLocation(pokeBallItem.getPokeBall().getModel2d(), "inventory"));
if (!cobblemon$isSameModel(model, replacementModel)) {
ci.cancel();
render(stack, renderMode, leftHanded, matrices, multiBufferSource, light, overlay, replacementModel);
if (shouldBe2d) {
ResourceLocation resourceLocation = null;
if (stack.getItem() instanceof PokeBallItem pokeBallItem) resourceLocation = pokeBallItem.getPokeBall().getModel2d();
else if (stack.getItem() instanceof PokedexItem pokedexItem) resourceLocation = pokedexItem.getType().getItemSpritePath();
if (resourceLocation != null) {
BakedModel replacementModel = this.itemModelShaper.getModelManager().getModel(new ModelResourceLocation(resourceLocation, "inventory"));
if (!cobblemon$isSameModel(model, replacementModel)) {
ci.cancel();
render(stack, renderMode, leftHanded, matrices, multiBufferSource, light, overlay, replacementModel);
}
}
}
}
@Inject(method = "getModel", at = @At("HEAD"), cancellable = true)
private void cobblemon$bakePokeballModel(ItemStack stack, Level world, LivingEntity entity, int seed, CallbackInfoReturnable<BakedModel> cir) {
if (stack.getItem() instanceof PokeBallItem pokeBallItem) {
BakedModel model = this.itemModelShaper.getModelManager().getModel(new ModelResourceLocation(pokeBallItem.getPokeBall().getModel3d(), MODEL_PATH));
private void cobblemon$getItemModel(ItemStack stack, Level world, LivingEntity entity, int seed, CallbackInfoReturnable<BakedModel> cir) {
ResourceLocation resourceLocation = null;
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"));
}
if (resourceLocation != null) {
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);
@@ -52,10 +52,11 @@ public abstract class LecternBlockMixin {
if (lecternEntity instanceof LecternBlockEntity) {
((LecternBlockEntity) lecternEntity).setItemStack((pokedexItemStack));
world.playSound(null, blockPos, CobblemonSounds.POKEDEX_CLOSE, SoundSource.BLOCKS, 0.5F, 1.25F);
cir.setReturnValue(ItemInteractionResult.SUCCESS);
} else {
cir.setReturnValue(itemStack.isEmpty() && interactionHand == InteractionHand.MAIN_HAND ? ItemInteractionResult.SKIP_DEFAULT_BLOCK_INTERACTION : ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION);
}
world.playSound(null, blockPos, CobblemonSounds.POKEDEX_CLOSE, SoundSource.BLOCKS, 0.5F, 1.25F);
cir.setReturnValue(itemStack.isEmpty() && interactionHand == InteractionHand.MAIN_HAND ? ItemInteractionResult.SKIP_DEFAULT_BLOCK_INTERACTION : ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION);
}
}
}
@@ -276,6 +276,81 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
@JvmField
val CHISELED_BLACK_TUMBLESTONE_BRICKS = this.create("chiseled_black_tumblestone_bricks", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_BUG_BLOCK = this.create("gem_bug_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_DARK_BLOCK = this.create("gem_dark_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_DRAGON_BLOCK = this.create("gem_dragon_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_ELECTRIC_BLOCK = this.create("gem_electric_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_FAIRY_BLOCK = this.create("gem_fairy_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_FIGHTING_BLOCK = this.create("gem_fighting_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_FIRE_BLOCK = this.create("gem_fire_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_FLYING_BLOCK = this.create("gem_flying_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_GHOST_BLOCK = this.create("gem_ghost_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_GRASS_BLOCK = this.create("gem_grass_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_GROUND_BLOCK = this.create("gem_ground_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_ICE_BLOCK = this.create("gem_ice_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_NORMAL_BLOCK = this.create("gem_normal_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_POISON_BLOCK = this.create("gem_poison_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_PSYCHIC_BLOCK = this.create("gem_psychic_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_ROCK_BLOCK = this.create("gem_rock_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_STEEL_BLOCK = this.create("gem_steel_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_WATER_BLOCK = this.create("gem_water_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_BUG_BUDDING = this.create("gem_bug_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_DARK_BUDDING = this.create("gem_dark_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_DRAGON_BUDDING = this.create("gem_dragon_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_ELECTRIC_BUDDING = this.create("gem_electric_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_FAIRY_BUDDING = this.create("gem_fairy_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_FIGHTING_BUDDING = this.create("gem_fighting_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_FIRE_BUDDING = this.create("gem_fire_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_FLYING_BUDDING = this.create("gem_flying_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_GHOST_BUDDING = this.create("gem_ghost_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_GRASS_BUDDING = this.create("gem_grass_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_GROUND_BUDDING = this.create("gem_ground_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_ICE_BUDDING = this.create("gem_ice_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_NORMAL_BUDDING = this.create("gem_normal_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_POISON_BUDDING = this.create("gem_poison_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_PSYCHIC_BUDDING = this.create("gem_psychic_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_ROCK_BUDDING = this.create("gem_rock_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_STEEL_BUDDING = this.create("gem_steel_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val GEM_WATER_BUDDING = this.create("gem_water_budding", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val FIRE_STONE_BLOCK = this.create("fire_stone_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.FIRE).strength(1.0F).sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BIT).lightLevel{13}))
@JvmField
@@ -19,7 +19,7 @@ import com.cobblemon.mod.common.api.text.gray
import com.cobblemon.mod.common.block.BerryBlock
import com.cobblemon.mod.common.block.MintBlock
import com.cobblemon.mod.common.block.MintBlock.MintType
import com.cobblemon.mod.common.client.pokedex.PokedexTypes
import com.cobblemon.mod.common.client.pokedex.PokedexType
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
import com.cobblemon.mod.common.item.*
import com.cobblemon.mod.common.item.armor.CobblemonArmorTrims
@@ -155,19 +155,19 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
val pokedexes = mutableListOf<PokedexItem>()
@JvmField
val POKEDEX_RED = pokedexItem(PokedexTypes.RED)
val POKEDEX_RED = pokedexItem(PokedexType.RED)
@JvmField
val POKEDEX_YELLOW = pokedexItem(PokedexTypes.YELLOW)
val POKEDEX_YELLOW = pokedexItem(PokedexType.YELLOW)
@JvmField
val POKEDEX_GREEN = pokedexItem(PokedexTypes.GREEN)
val POKEDEX_GREEN = pokedexItem(PokedexType.GREEN)
@JvmField
val POKEDEX_BLUE = pokedexItem(PokedexTypes.BLUE)
val POKEDEX_BLUE = pokedexItem(PokedexType.BLUE)
@JvmField
val POKEDEX_PINK = pokedexItem(PokedexTypes.PINK)
val POKEDEX_PINK = pokedexItem(PokedexType.PINK)
@JvmField
val POKEDEX_BLACK = pokedexItem(PokedexTypes.BLACK)
val POKEDEX_BLACK = pokedexItem(PokedexType.BLACK)
@JvmField
val POKEDEX_WHITE = pokedexItem(PokedexTypes.WHITE)
val POKEDEX_WHITE = pokedexItem(PokedexType.WHITE)
@JvmField
val VIVICHOKE = compostableItem("vivichoke")
@@ -1224,6 +1224,80 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
//@JvmField
//val BINDING_SOIL = blockItem("binding_soil", CobblemonBlocks.BINDING_SOIL)
@JvmField
val GEM_BUG_BLOCK = blockItem("gem_bug_block", CobblemonBlocks.GEM_BUG_BLOCK)
@JvmField
val GEM_DARK_BLOCK = blockItem("gem_dark_block", CobblemonBlocks.GEM_DARK_BLOCK)
@JvmField
val GEM_DRAGON_BLOCK = blockItem("gem_dragon_block", CobblemonBlocks.GEM_DRAGON_BLOCK)
@JvmField
val GEM_ELECTRIC_BLOCK = blockItem("gem_electric_block", CobblemonBlocks.GEM_ELECTRIC_BLOCK)
@JvmField
val GEM_FAIRY_BLOCK = blockItem("gem_fairy_block", CobblemonBlocks.GEM_FAIRY_BLOCK)
@JvmField
val GEM_FIGHTING_BLOCK = blockItem("gem_fighting_block", CobblemonBlocks.GEM_FIGHTING_BLOCK)
@JvmField
val GEM_FIRE_BLOCK = blockItem("gem_fire_block", CobblemonBlocks.GEM_FIRE_BLOCK)
@JvmField
val GEM_FLYING_BLOCK = blockItem("gem_flying_block", CobblemonBlocks.GEM_FLYING_BLOCK)
@JvmField
val GEM_GHOST_BLOCK = blockItem("gem_ghost_block", CobblemonBlocks.GEM_GHOST_BLOCK)
@JvmField
val GEM_GRASS_BLOCK = blockItem("gem_grass_block", CobblemonBlocks.GEM_GRASS_BLOCK)
@JvmField
val GEM_GROUND_BLOCK = blockItem("gem_ground_block", CobblemonBlocks.GEM_GROUND_BLOCK)
@JvmField
val GEM_ICE_BLOCK = blockItem("gem_ice_block", CobblemonBlocks.GEM_ICE_BLOCK)
@JvmField
val GEM_NORMAL_BLOCK = blockItem("gem_normal_block", CobblemonBlocks.GEM_NORMAL_BLOCK)
@JvmField
val GEM_POISON_BLOCK = blockItem("gem_poison_block", CobblemonBlocks.GEM_POISON_BLOCK)
@JvmField
val GEM_PSYCHIC_BLOCK = blockItem("gem_psychic_block", CobblemonBlocks.GEM_PSYCHIC_BLOCK)
@JvmField
val GEM_ROCK_BLOCK = blockItem("gem_rock_block", CobblemonBlocks.GEM_ROCK_BLOCK)
@JvmField
val GEM_STEEL_BLOCK = blockItem("gem_steel_block", CobblemonBlocks.GEM_STEEL_BLOCK)
@JvmField
val GEM_WATER_BLOCK = blockItem("gem_water_block", CobblemonBlocks.GEM_WATER_BLOCK)
@JvmField
val GEM_BUG_BUDDING = blockItem("gem_bug_budding", CobblemonBlocks.GEM_BUG_BUDDING)
@JvmField
val GEM_DARK_BUDDING = blockItem("gem_dark_budding", CobblemonBlocks.GEM_DARK_BUDDING)
@JvmField
val GEM_DRAGON_BUDDING = blockItem("gem_dragon_budding", CobblemonBlocks.GEM_DRAGON_BUDDING)
@JvmField
val GEM_ELECTRIC_BUDDING = blockItem("gem_electric_budding", CobblemonBlocks.GEM_ELECTRIC_BUDDING)
@JvmField
val GEM_FAIRY_BUDDING = blockItem("gem_fairy_budding", CobblemonBlocks.GEM_FAIRY_BUDDING)
@JvmField
val GEM_FIGHTING_BUDDING = blockItem("gem_fighting_budding", CobblemonBlocks.GEM_FIGHTING_BUDDING)
@JvmField
val GEM_FIRE_BUDDING = blockItem("gem_fire_budding", CobblemonBlocks.GEM_FIRE_BUDDING)
@JvmField
val GEM_FLYING_BUDDING = blockItem("gem_flying_budding", CobblemonBlocks.GEM_FLYING_BUDDING)
@JvmField
val GEM_GHOST_BUDDING = blockItem("gem_ghost_budding", CobblemonBlocks.GEM_GHOST_BUDDING)
@JvmField
val GEM_GRASS_BUDDING = blockItem("gem_grass_budding", CobblemonBlocks.GEM_GRASS_BUDDING)
@JvmField
val GEM_GROUND_BUDDING = blockItem("gem_ground_budding", CobblemonBlocks.GEM_GROUND_BUDDING)
@JvmField
val GEM_ICE_BUDDING = blockItem("gem_ice_budding", CobblemonBlocks.GEM_ICE_BUDDING)
@JvmField
val GEM_NORMAL_BUDDING = blockItem("gem_normal_budding", CobblemonBlocks.GEM_NORMAL_BUDDING)
@JvmField
val GEM_POISON_BUDDING = blockItem("gem_poison_budding", CobblemonBlocks.GEM_POISON_BUDDING)
@JvmField
val GEM_PSYCHIC_BUDDING = blockItem("gem_psychic_budding", CobblemonBlocks.GEM_PSYCHIC_BUDDING)
@JvmField
val GEM_ROCK_BUDDING = blockItem("gem_rock_budding", CobblemonBlocks.GEM_ROCK_BUDDING)
@JvmField
val GEM_STEEL_BUDDING = blockItem("gem_steel_budding", CobblemonBlocks.GEM_STEEL_BUDDING)
@JvmField
val GEM_WATER_BUDDING = blockItem("gem_water_budding", CobblemonBlocks.GEM_WATER_BUDDING)
private fun blockItem(name: String, block: Block): BlockItem = this.create(name, BlockItem(block, Item.Properties()))
private fun noSettingsItem(name: String): CobblemonItem = this.create(name, CobblemonItem(Item.Properties()))
@@ -1248,7 +1322,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
return item
}
private fun pokedexItem(type: PokedexTypes): PokedexItem {
private fun pokedexItem(type: PokedexType): PokedexItem {
val item = create("pokedex_${type.name.lowercase()}", PokedexItem(type))
pokedexes.add(item)
return item
@@ -165,8 +165,10 @@ import com.cobblemon.mod.common.net.messages.server.battle.*
import com.cobblemon.mod.common.net.serverhandling.battle.*
import com.cobblemon.mod.common.net.messages.client.pokedex.ServerConfirmedRegisterPacket
import com.cobblemon.mod.common.net.messages.client.trade.*
import com.cobblemon.mod.common.net.messages.server.block.AdjustBlockEntityViewerCountPacket
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.FinishScanningPacket
import com.cobblemon.mod.common.net.messages.server.trade.*
import com.cobblemon.mod.common.net.serverhandling.block.AdjustBlockEntityViewerCountHandler
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.FinishScanningHandler
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.StartScanningHandler
import com.cobblemon.mod.common.net.serverhandling.trade.*
@@ -356,7 +358,7 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(CloseNPCEditorPacket.ID, CloseNPCEditorPacket::decode, CloseNPCEditorHandler))
list.add(PacketRegisterInfo(OpenNPCEditorPacket.ID, OpenNPCEditorPacket::decode, OpenNPCEditorHandler))
//Pokedex scanning
// Pokédex scanning
list.add(PacketRegisterInfo(ServerConfirmedRegisterPacket.ID, ServerConfirmedRegisterPacket::decode, ServerConfirmedRegisterHandler))
return list
}
@@ -414,7 +416,7 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(OfferTradePacket.ID, OfferTradePacket::decode, OfferTradeHandler))
list.add(PacketRegisterInfo(UpdateTradeOfferPacket.ID, UpdateTradeOfferPacket::decode, UpdateTradeOfferHandler))
// Pokedex scanning
// Pokédex scanning
list.add(PacketRegisterInfo(StartScanningPacket.ID, StartScanningPacket::decode, StartScanningHandler))
list.add(PacketRegisterInfo(FinishScanningPacket.ID, FinishScanningPacket::decode, FinishScanningHandler))
@@ -423,6 +425,9 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(UnpasturePokemonPacket.ID, UnpasturePokemonPacket::decode, UnpasturePokemonHandler))
list.add(PacketRegisterInfo(UnpastureAllPokemonPacket.ID, UnpastureAllPokemonPacket::decode, UnpastureAllPokemonHandler))
// Block entity
list.add(PacketRegisterInfo(AdjustBlockEntityViewerCountPacket.ID, AdjustBlockEntityViewerCountPacket::decode, AdjustBlockEntityViewerCountHandler))
// Move select packets
list.add(PacketRegisterInfo(MoveSelectedPacket.ID, MoveSelectedPacket::decode, MoveSelectedHandler))
list.add(PacketRegisterInfo(MoveSelectCancelledPacket.ID, MoveSelectCancelledPacket::decode, MoveSelectCancelledHandler))
@@ -41,6 +41,7 @@ import com.cobblemon.mod.common.battles.dispatch.WaitDispatch
import com.cobblemon.mod.common.battles.interpreter.ContextManager
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.battles.runner.ShowdownService
import com.cobblemon.mod.common.entity.PlatformType
import com.cobblemon.mod.common.entity.npc.NPCBattleActor
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
@@ -303,6 +304,11 @@ open class PokemonBattle(
actors.forEach { actor ->
actor.pokemonList.forEach { battlePokemon ->
battlePokemon.entity?.let { entity -> battlePokemon.postBattleEntityOperation(entity) }
if (battlePokemon.effectedPokemon.entity != null
&& battlePokemon.effectedPokemon.entity?.beamMode == 0
&& battlePokemon.effectedPokemon.entity?.platform != PlatformType.NONE) {
battlePokemon.effectedPokemon.tryRecallWithAnimation()
}
}
}
sendUpdate(BattleEndPacket())
@@ -0,0 +1,27 @@
/*
* 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.net.serializers
import com.cobblemon.mod.common.entity.PlatformType
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.network.codec.StreamCodec
import net.minecraft.network.syncher.EntityDataSerializer
object PlatformTypeDataSerializer : EntityDataSerializer<PlatformType> {
// TODO: This ID only looks it's used by NeoForge and that hasn't been tested yet
val ID = cobblemonResource("platform_type")
fun read(buf: RegistryFriendlyByteBuf) = PlatformType.entries[buf.readInt()]
override fun copy(value: PlatformType) = value
fun write(buf: RegistryFriendlyByteBuf, value: PlatformType) {
buf.writeInt(value.ordinal)
}
override fun codec() = StreamCodec.of(::write, ::read)
}
@@ -50,13 +50,13 @@ enum class Stats(override val identifier: ResourceLocation, override val display
val BATTLE_ONLY: Set<Stat> = EnumSet.of(EVASION, ACCURACY)
/** Gets the [Stat] from the respective Showdown id. */
fun getStat(statKey: String) = when(statKey) {
fun getStat(statKey: String) = when(statKey.lowercase()) {
"hp" -> HP
"atk", "Attack" -> ATTACK // Hyper Cutter states the full stat name "Attack"
"def", "Defense" -> DEFENCE // Big Pecks states the full stat name "Defense"
"atk", "attack" -> ATTACK // Hyper Cutter states the full stat name "Attack"
"def", "defense" -> DEFENCE // Big Pecks states the full stat name "Defense"
"spa" -> SPECIAL_ATTACK
"spd" -> SPECIAL_DEFENCE
"spe" -> SPEED
"spe", "speed" -> SPEED
"evasion" -> EVASION
else -> ACCURACY
}
@@ -10,17 +10,14 @@ package com.cobblemon.mod.common.battles.interpreter.instructions
import com.cobblemon.mod.common.api.battles.interpreter.BattleMessage
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.text.yellow
import com.cobblemon.mod.common.battles.ShowdownInterpreter
import com.cobblemon.mod.common.battles.dispatch.InstructionSet
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
import com.cobblemon.mod.common.entity.pokemon.effects.IllusionEffect
import com.cobblemon.mod.common.net.messages.client.battle.BattleSwapPokemonPacket
import com.cobblemon.mod.common.util.battleLang
import com.cobblemon.mod.common.util.setPositionSafely
import com.cobblemon.mod.common.util.swap
import net.minecraft.server.level.ServerLevel
import net.minecraft.world.phys.Vec3
import java.util.logging.Level
/**
@@ -32,58 +29,30 @@ import java.util.logging.Level
*/
class SwapInstruction(val message: BattleMessage, val instructionSet: InstructionSet): InterpreterInstruction {
override fun invoke(battle: PokemonBattle) {
// TODO: more error checks
battle.dispatchWaiting {
val battlePokemonA = message.battlePokemon(0, battle) ?: return@dispatchWaiting
val pnxA = message.argumentAt(0)?.substring(0, 3)
var posA: Vec3? = null
val (actor, activePokemonA) = battle.getActorAndActiveSlotFromPNX(pnxA!!)
if (battlePokemonA.entity == null) {
posA = ShowdownInterpreter.getSendoutPosition(battle, activePokemonA, battlePokemonA.actor)
} else {
posA = battlePokemonA.entity?.position()
}
val activeBattlePokemonB = activePokemonA.getAdjacentAllies().firstOrNull()
if(activeBattlePokemonB != null) {
if (activeBattlePokemonB != null) {
val pnxB = activeBattlePokemonB.getPNX()
val (actorB, activePokemonB) = battle.getActorAndActiveSlotFromPNX(pnxB)
// Swap the position of the 2 on the field
var posB: Vec3? = null
if (activePokemonB.battlePokemon?.entity == null) {
// target slot is likely fainted
posB = ShowdownInterpreter.getSendoutPosition(battle, activePokemonB, actorB)
} else {
posB = activePokemonB.battlePokemon?.entity?.position()
}
if (posB != null && battlePokemonA.entity != null) {
battlePokemonA.entity?.setPositionSafely(posB)
} else if(posB != null) {
if (activePokemonA.battlePokemon?.entity != null) {
activePokemonA.battlePokemon?.entity?.setPositionSafely(posB)
} else {
activePokemonB.position.let {
if (it != null) {
activePokemonB.position = Pair<ServerLevel, Vec3>(it.first, posB)
}
}
}
}
if(posA != null) {
if (activePokemonB.battlePokemon?.entity != null) {
activePokemonB.battlePokemon?.entity?.setPositionSafely(posA)
} else {
activePokemonA.position.let {
if (it != null) {
activePokemonB.position = Pair<ServerLevel, Vec3>(it.first, posA)
}
}
}
}
// Swap references of the 2 pokemon
actor.activePokemon.swap((pnxA[2] - 'a'), (pnxB[2] - 'a'))
val posA = ShowdownInterpreter.getSendoutPosition(battle, activePokemonA, battlePokemonA.actor) ?: activePokemonA.position?.second
if (posA != null && battlePokemonA.entity != null) {
battlePokemonA.entity?.setPositionSafely(battlePokemonA.entity!!.getAjustedSendoutPosition(posA))
}
val posB = ShowdownInterpreter.getSendoutPosition(battle, activePokemonB, battlePokemonA.actor) ?: activePokemonB.position?.second
val battlePokemonB = activePokemonB.battlePokemon
if (posB != null && battlePokemonB?.entity != null) {
activePokemonB.battlePokemon?.entity?.setPositionSafely(battlePokemonB.entity!!.getAjustedSendoutPosition(posB))
}
// Notify clients of the swap
battle.sendUpdate(BattleSwapPokemonPacket(pnxA))
@@ -8,10 +8,14 @@
package com.cobblemon.mod.common.block
import com.cobblemon.mod.common.CobblemonBlockEntities
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.block.entity.LecternBlockEntity
import com.cobblemon.mod.common.block.entity.ViewerCountBlockEntity
import com.cobblemon.mod.common.item.PokedexItem
import com.cobblemon.mod.common.net.messages.client.ui.PokedexUIPacket
import com.cobblemon.mod.common.util.playSoundServer
import com.cobblemon.mod.common.util.toVec3d
import com.mojang.serialization.MapCodec
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
@@ -29,6 +33,7 @@ import net.minecraft.world.level.Level
import net.minecraft.world.level.LevelReader
import net.minecraft.world.level.block.*
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.block.state.StateDefinition
import net.minecraft.world.level.block.state.properties.DirectionProperty
@@ -52,6 +57,8 @@ class LecternBlock(properties: Properties): BaseEntityBlock(properties) {
override fun codec() = CODEC
override fun <T : BlockEntity> getTicker(world: Level, blockState: BlockState, BlockWithEntityType: BlockEntityType<T>) = createTickerHelper(BlockWithEntityType, CobblemonBlockEntities.LECTERN, ViewerCountBlockEntity.TICKER::tick)
override fun getRenderShape(blockState: BlockState?) = RenderShape.MODEL
override fun getOcclusionShape(blockState: BlockState?, blockGetter: BlockGetter?, blockPos: BlockPos?): VoxelShape = MinecraftLecternBlock.SHAPE_COMMON
@@ -117,12 +124,15 @@ class LecternBlock(properties: Properties): BaseEntityBlock(properties) {
if (!itemStack.isEmpty && itemStack.item is PokedexItem) {
if (!level.isClientSide) {
if (player.isCrouching) takeStoredItem(blockEntity, blockState, level, blockPos, player)
else PokedexUIPacket((blockEntity.getItemStack().item as PokedexItem).type).sendToPlayer(player as ServerPlayer)
else {
blockEntity.incrementViewerCount()
PokedexUIPacket(type = (blockEntity.getItemStack().item as PokedexItem).type, blockPos = blockPos).sendToPlayer(player as ServerPlayer)
level.playSoundServer(position = blockPos.toVec3d(), sound = CobblemonSounds.POKEDEX_OPEN, volume = 0.25F)
}
}
else if (!player.isCrouching) player.playSound(CobblemonSounds.POKEDEX_OPEN)
}
}
return InteractionResult.CONSUME
return InteractionResult.SUCCESS_NO_ITEM_USED
}
override fun isPathfindable(blockState: BlockState?, pathComputationType: PathComputationType?) = false
@@ -13,17 +13,12 @@ import net.minecraft.core.BlockPos
import net.minecraft.core.HolderLookup
import net.minecraft.core.NonNullList
import net.minecraft.nbt.CompoundTag
import net.minecraft.network.protocol.Packet
import net.minecraft.network.protocol.game.ClientGamePacketListener
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket
import net.minecraft.world.ContainerHelper
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.entity.BlockEntityTicker
import net.minecraft.world.level.block.state.BlockState
class LecternBlockEntity(blockPos: BlockPos, blockState: BlockState) : BlockEntity(CobblemonBlockEntities.LECTERN, blockPos, blockState) {
class LecternBlockEntity(blockPos: BlockPos, blockState: BlockState) : ViewerCountBlockEntity(CobblemonBlockEntities.LECTERN, blockPos, blockState) {
val inventory: NonNullList<ItemStack> = NonNullList.withSize(1, ItemStack.EMPTY)
override fun saveAdditional(compoundTag: CompoundTag, registryLookup: HolderLookup.Provider) {
@@ -36,10 +31,6 @@ class LecternBlockEntity(blockPos: BlockPos, blockState: BlockState) : BlockEnti
ContainerHelper.loadAllItems(compoundTag, inventory, registryLookup)
}
override fun getUpdatePacket(): Packet<ClientGamePacketListener>? {
return ClientboundBlockEntityDataPacket.create(this)
}
override fun getUpdateTag(registryLookup: HolderLookup.Provider): CompoundTag {
return this.saveWithoutMetadata(registryLookup)
}
@@ -51,23 +42,16 @@ class LecternBlockEntity(blockPos: BlockPos, blockState: BlockState) : BlockEnti
fun setItemStack(itemStack: ItemStack) {
if (level != null) {
inventory[0] = itemStack
onItemUpdate(level!!)
updateBlock(level!!)
}
}
fun removeItemStack(): ItemStack {
if (level != null) {
val itemStack = ContainerHelper.removeItem(inventory, 0, 1)
onItemUpdate(level!!)
updateBlock(level!!)
return itemStack
}
return ItemStack.EMPTY
}
private fun onItemUpdate(level: Level) {
val oldState = level.getBlockState(blockPos)
level.sendBlockUpdated(blockPos, oldState, level.getBlockState(blockPos), Block.UPDATE_ALL)
level.updateNeighbourForOutputSignal(blockPos, level.getBlockState(blockPos).block)
setChanged()
}
}
}
@@ -0,0 +1,99 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.block.entity
import com.cobblemon.mod.common.util.DataKeys
import net.minecraft.core.BlockPos
import net.minecraft.core.HolderLookup
import net.minecraft.nbt.CompoundTag
import net.minecraft.network.protocol.Packet
import net.minecraft.network.protocol.game.ClientGamePacketListener
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket
import net.minecraft.world.entity.player.Player
import net.minecraft.world.level.ClipContext
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.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
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.entity.EntityTypeTest
import net.minecraft.world.phys.AABB
open class ViewerCountBlockEntity(type: BlockEntityType<*>?, blockPos: BlockPos, blockState: BlockState) : BlockEntity(type, blockPos, blockState) {
companion object {
internal val TICKER = BlockEntityTicker<ViewerCountBlockEntity> { world, _, _, blockEntity ->
if (world.isClientSide) return@BlockEntityTicker
blockEntity.checkUsers(blockEntity.getInRangeViewerCount(world, blockEntity.blockPos))
}
}
var viewerCount: Int = 0
private fun checkUsers(inRangeViewers: Int) {
if (inRangeViewers < viewerCount) changeViewerCount(inRangeViewers)
}
override fun saveAdditional(compoundTag: CompoundTag, registryLookup: HolderLookup.Provider) {
super.saveAdditional(compoundTag, registryLookup)
compoundTag.putInt(DataKeys.BLOCK_ENTITY_USER_AMOUNT, viewerCount)
}
override fun loadAdditional(compoundTag: CompoundTag, registryLookup: HolderLookup.Provider) {
super.loadAdditional(compoundTag, registryLookup)
viewerCount = if (compoundTag.contains(DataKeys.BLOCK_ENTITY_USER_AMOUNT)) compoundTag.getInt(DataKeys.BLOCK_ENTITY_USER_AMOUNT) else 0
}
override fun getUpdatePacket(): Packet<ClientGamePacketListener>? {
return ClientboundBlockEntityDataPacket.create(this)
}
override fun getUpdateTag(registryLookup: HolderLookup.Provider): CompoundTag {
return this.saveWithoutMetadata(registryLookup)
}
fun updateBlock(level: Level) {
val oldState = level.getBlockState(blockPos)
level.sendBlockUpdated(blockPos, oldState, level.getBlockState(blockPos), Block.UPDATE_ALL)
level.updateNeighbourForOutputSignal(blockPos, level.getBlockState(blockPos).block)
setChanged()
}
private fun isPlayerLookingAt(world: Level, player: Player, blockPos: BlockPos): Boolean {
val vec3 = player.eyePosition
val vec32 = vec3.add(player.calculateViewVector(player.xRot, player.yRot).scale(player.blockInteractionRange()))
val blockHitResult = world.clip(ClipContext(vec3, vec32, ClipContext.Block.OUTLINE, ClipContext.Fluid.ANY, player))
return blockPos == blockHitResult.blockPos
}
private fun getInRangeViewerCount(world: Level, pos: BlockPos, range: Double = 5.0): Int {
val box = AABB(
pos.x.toDouble() - range,
pos.y.toDouble() - range,
pos.z.toDouble() - range,
(pos.x + 1).toDouble() + range,
(pos.y + 1).toDouble() + range,
(pos.z + 1).toDouble() + range
)
return world.getEntities(EntityTypeTest.forClass(Player::class.java), box) { player: Player? -> isPlayerLookingAt(world, player!!, pos) }.size
}
fun changeViewerCount(amount: Int) {
if (level != null) {
viewerCount = maxOf(0, amount)
updateBlock(level!!)
}
}
fun incrementViewerCount() = changeViewerCount(viewerCount + 1)
fun decrementViewerCount() = changeViewerCount(viewerCount - 1)
}
@@ -9,7 +9,6 @@
package com.cobblemon.mod.common.client
import com.cobblemon.mod.common.BakingOverride
import com.cobblemon.mod.common.client.pokedex.PokedexTypes
import com.cobblemon.mod.common.util.cobblemonModel
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.client.resources.model.ModelResourceLocation
@@ -104,51 +103,9 @@ object CobblemonBakingOverrides {
cobblemonModel("surprise_mulch", "none")
)
// Items
val POKEDEX_BLACK = registerOverride(
cobblemonResource("item/pokedex_black_model"),
cobblemonModel("pokedex_black_model", "inventory")
)
val POKEDEX_BLUE = registerOverride(
cobblemonResource("item/pokedex_blue_model"),
cobblemonModel("pokedex_blue_model", "inventory")
)
val POKEDEX_GREEN = registerOverride(
cobblemonResource("item/pokedex_green_model"),
cobblemonModel("pokedex_green_model", "inventory")
)
val POKEDEX_PINK = registerOverride(
cobblemonResource("item/pokedex_pink_model"),
cobblemonModel("pokedex_pink_model", "inventory")
)
val POKEDEX_RED = registerOverride(
cobblemonResource("item/pokedex_red_model"),
cobblemonModel("pokedex_red_model", "inventory")
)
val POKEDEX_WHITE = registerOverride(
cobblemonResource("item/pokedex_white_model"),
cobblemonModel("pokedex_white_model", "inventory")
)
val POKEDEX_YELLOW = registerOverride(
cobblemonResource("item/pokedex_yellow_model"),
cobblemonModel("pokedex_yellow_model", "inventory")
)
fun getPokedexOverride(type: PokedexTypes): BakingOverride {
return when (type) {
PokedexTypes.BLACK -> POKEDEX_BLACK
PokedexTypes.BLUE -> POKEDEX_BLUE
PokedexTypes.GREEN -> POKEDEX_GREEN
PokedexTypes.PINK -> POKEDEX_PINK
PokedexTypes.WHITE -> POKEDEX_WHITE
PokedexTypes.YELLOW -> POKEDEX_YELLOW
PokedexTypes.RED -> POKEDEX_RED
}
}
fun registerOverride(modelLocation: ResourceLocation, modelIdentifier: ModelResourceLocation): BakingOverride {
val result = BakingOverride(modelLocation, modelIdentifier)
models.add(result)
return result
}
}
}
@@ -47,8 +47,9 @@ import com.cobblemon.mod.common.client.gui.pokedex.widgets.PokemonInfoWidget
import com.cobblemon.mod.common.client.gui.pokedex.widgets.SearchWidget
import com.cobblemon.mod.common.client.gui.pokedex.widgets.SizeWidget
import com.cobblemon.mod.common.client.gui.pokedex.widgets.StatsWidget
import com.cobblemon.mod.common.client.pokedex.PokedexTypes
import com.cobblemon.mod.common.client.pokedex.PokedexType
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.net.messages.server.block.AdjustBlockEntityViewerCountPacket
import com.cobblemon.mod.common.pokemon.abilities.HiddenAbility
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.lang
@@ -59,6 +60,7 @@ import net.minecraft.client.gui.components.events.GuiEventListener
import net.minecraft.client.gui.narration.NarratableEntry
import net.minecraft.client.gui.screens.Screen
import net.minecraft.client.resources.sounds.SimpleSoundInstance
import net.minecraft.core.BlockPos
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.sounds.SoundEvent
@@ -70,8 +72,9 @@ import net.minecraft.sounds.SoundEvent
* @since February 24, 2024
*/
class PokedexGUI private constructor(
val type: PokedexTypes,
val initSpecies: ResourceLocation?
val type: PokedexType,
val initSpecies: ResourceLocation?,
val blockPos: BlockPos?
): Screen(Component.translatable("cobblemon.ui.pokedex.title")) {
companion object {
private val screenBackground = cobblemonResource("textures/gui/pokedex/pokedex_screen.png")
@@ -97,9 +100,9 @@ class PokedexGUI private constructor(
/**
* Attempts to open this screen for a client.
*/
fun open(pokedex: ClientPokedexManager, type: PokedexTypes, species: ResourceLocation? = null) {
fun open(pokedex: ClientPokedexManager, type: PokedexType, species: ResourceLocation? = null, blockPos: BlockPos? = null) {
val mc = Minecraft.getInstance()
val screen = PokedexGUI(type, species)
val screen = PokedexGUI(type, species, blockPos)
mc.setScreen(screen)
}
}
@@ -341,6 +344,7 @@ class PokedexGUI private constructor(
}
override fun onClose() {
if (blockPos != null) AdjustBlockEntityViewerCountPacket(blockPos, false).sendToServer()
playSound(CobblemonSounds.POKEDEX_CLOSE)
super.onClose()
}
@@ -18,7 +18,7 @@ import net.minecraft.client.Minecraft
object PokedexUIPacketHandler: ClientNetworkPacketHandler<PokedexUIPacket> {
override fun handle(packet: PokedexUIPacket, client: Minecraft) {
try {
PokedexGUI.open(CobblemonClient.clientPokedexData, packet.type, packet.initSpecies)
PokedexGUI.open(CobblemonClient.clientPokedexData, packet.type, packet.initSpecies, packet.blockPos)
} catch (e: Exception) {
Cobblemon.LOGGER.debug("Failed to open the Pokedex from the Pokedex UI packet", e)
}
@@ -10,14 +10,16 @@ package com.cobblemon.mod.common.client.pokedex
import com.cobblemon.mod.common.util.cobblemonResource
enum class PokedexTypes {
BLACK,
BLUE,
GREEN,
PINK,
enum class PokedexType {
RED,
WHITE,
YELLOW;
YELLOW,
GREEN,
BLUE,
PINK,
BLACK,
WHITE;
fun getTexturePath() = cobblemonResource("textures/gui/pokedex/pokedex_base_${this.name.lowercase()}.png")
fun getItemModelPath(additionalState: String? = null) = cobblemonResource("item/pokedex_${this.name.lowercase()}_model${if (additionalState != null) "_$additionalState" else ""}")
fun getItemSpritePath() = cobblemonResource("pokedex_${this.name.lowercase()}")
}
@@ -14,6 +14,7 @@ import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.block.DisplayCaseBlock
import com.cobblemon.mod.common.block.entity.DisplayCaseBlockEntity
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.item.PokedexItem
import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.math.Axis
import net.minecraft.client.Minecraft
@@ -159,6 +160,7 @@ class DisplayCaseRenderer(ctx: BlockEntityRendererProvider.Context) : BlockEntit
stack.item is BedItem -> PositioningType.BED
stack.item is BannerItem -> PositioningType.BANNER
stack.`is`(CobblemonItemTags.POKE_BALLS) -> PositioningType.POKE_BALL
stack.item is PokedexItem -> PositioningType.POKEDEX
stack.item == CobblemonItems.RELIC_COIN_POUCH -> PositioningType.COIN_POUCH
stack.item == CobblemonItems.PASTURE -> PositioningType.PASTURE
//stack.item == CobblemonItems.POKEMON_MODEL -> PositioningType.ITEM_MODEL
@@ -175,6 +177,7 @@ class DisplayCaseRenderer(ctx: BlockEntityRendererProvider.Context) : BlockEntit
val rotY: Float = 0f
) {
POKE_BALL(1f, 1f, 1f, 0f, 0.04f, 0f),
POKEDEX(1f, 1f, 1f, 0f, 0.04f, 0f, 180f),
BLOCK_MODEL(1f, 1f, 1f, 0f, -0.15f, 0f),
ITEM_MODEL(1f, 1f, 1f, 0f, 0.04f, 0f),
BED(1f, 1f, 1f, 0f, -0.02f, 0f),
@@ -8,21 +8,30 @@
package com.cobblemon.mod.common.client.render.block
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonBlocks
import com.cobblemon.mod.common.ModAPI
import com.cobblemon.mod.common.block.entity.LecternBlockEntity
import com.cobblemon.mod.common.item.PokedexItem
import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.math.Axis
import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.MultiBufferSource
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
import net.minecraft.client.resources.model.ModelResourceLocation
import net.minecraft.core.Direction
import net.minecraft.world.item.*
import net.minecraft.world.level.block.HorizontalDirectionalBlock
import net.minecraft.world.level.block.state.BlockState
import org.spongepowered.asm.mixin.Unique
class LecternBlockEntityRenderer(ctx: BlockEntityRendererProvider.Context) : BlockEntityRenderer<LecternBlockEntity> {
@Unique
private val MODEL_PATH = if (Cobblemon.implementation.modAPI == ModAPI.FABRIC) "fabric_resource" else "standalone"
override fun render(blockEntity: LecternBlockEntity, tickDelta: Float, poseStack: PoseStack, multiBufferSource: MultiBufferSource, light: Int, overlay: Int ) {
if (blockEntity !is LecternBlockEntity) return
if (!blockEntity.isEmpty()) {
@@ -35,7 +44,15 @@ class LecternBlockEntityRenderer(ctx: BlockEntityRendererProvider.Context) : Blo
poseStack.mulPose(Axis.YP.rotationDegrees(-yRot))
poseStack.mulPose(Axis.XP.rotationDegrees(22.5F))
poseStack.translate(0.0, 0.0, 0.13)
Minecraft.getInstance().itemRenderer.renderStatic(blockEntity.getItemStack(), ItemDisplayContext.GROUND, light, overlay, poseStack, multiBufferSource, blockEntity.level, 0)
if (blockEntity.getItemStack().item is PokedexItem) {
val resourceLocation = (blockEntity.getItemStack().item as PokedexItem).type.getItemModelPath(if (blockEntity.viewerCount > 0) "flat" else "flat_off")
val model = Minecraft.getInstance().itemRenderer.itemModelShaper.getModelManager().getModel(ModelResourceLocation(resourceLocation, MODEL_PATH))
Minecraft.getInstance().itemRenderer.render(blockEntity.getItemStack(), ItemDisplayContext.GROUND, false, poseStack, multiBufferSource, light, overlay, model)
} else {
Minecraft.getInstance().itemRenderer.renderStatic(blockEntity.getItemStack(), ItemDisplayContext.GROUND, light, overlay, poseStack, multiBufferSource, blockEntity.level, 0)
}
poseStack.popPose()
}
}
@@ -21,21 +21,21 @@ import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PosablePokemonEntityModel
import com.cobblemon.mod.common.client.render.models.blockbench.repository.MiscModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokeBallModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.pokeball.PokeBallPosableState
import com.cobblemon.mod.common.client.render.renderBeaconBeam
import com.cobblemon.mod.common.client.settings.ServerSettings
import com.cobblemon.mod.common.entity.PlatformType
import com.cobblemon.mod.common.entity.PosableEntity
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity.Companion.SPAWN_DIRECTION
import com.cobblemon.mod.common.pokeball.PokeBall
import com.cobblemon.mod.common.util.effectiveName
import com.cobblemon.mod.common.util.isLookingAt
import com.cobblemon.mod.common.util.lang
import com.cobblemon.mod.common.util.*
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
@@ -120,6 +120,18 @@ class PokemonRenderer(
clientDelegate
)
}
if(entity.platform != PlatformType.NONE) {
drawPlatform(
poseMatrix,
entity,
(entity.delegate as PokemonClientDelegate).entityScaleModifier,
partialTicks,
buffer,
packedLight,
)
// keeps the pokemon's root on the raft
poseMatrix.translate(0.0, 0.25 * (entity.delegate as PokemonClientDelegate).entityScaleModifier, 0.0)
}
modelNow.setLayerContext(buffer, clientDelegate, PokemonModelRepository.getLayers(entity.pokemon.species.resourceIdentifier, clientDelegate))
@@ -349,7 +361,7 @@ class PokemonRenderer(
val matrix4f = matrices.last().pose()
val opacity = (Minecraft.getInstance().options.getBackgroundOpacity(0.25F) * 255.0F).toInt() shl 24
var label = if (ServerSettings.displayEntityNameLabel &&
!Cobblemon.config.diplayNameForUnknownPokemon &&
!Cobblemon.config.displayNameForUnknownPokemon &&
CobblemonClient.clientPokedexData.getKnowledgeForSpecies(entity.pokemon.species.resourceIdentifier) == PokedexEntryProgress.NONE) {
Component.literal("???")
} else if (ServerSettings.displayEntityNameLabel) {
@@ -425,4 +437,24 @@ class PokemonRenderer(
model.resetLayerContext()
matrixStack.popPose()
}
private fun drawPlatform(
matrixStack: PoseStack,
entity: PokemonEntity,
scale: Float = 1F,
partialTicks: Float,
buff: MultiBufferSource,
packedLight: Int,
) {
val (modelResource, textureResource) = PlatformType.GetModelWithTexture(entity.platform)
val model = MiscModelRepository.modelOf(modelResource) ?: return
matrixStack.pushPose()
matrixStack.mulPose(Axis.ZP.rotationDegrees(180f))
matrixStack.rotateAround(Axis.YP.rotationDegrees(entity.entityData.get(SPAWN_DIRECTION)), 0.0f, 0f, 0.0f)
matrixStack.scale(scale, scale, scale)
val buffer = ItemRenderer.getFoilBufferDirect(buff, RenderType.entityCutout(textureResource), false, false)
model.render(matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
matrixStack.popPose()
}
}
@@ -178,7 +178,7 @@ class CobblemonConfig {
var displayEntityNameLabel = true
@NodeCategory(Category.Pokemon)
var diplayNameForUnknownPokemon = false
var displayNameForUnknownPokemon = false
@NodeCategory(Category.Pokemon)
var displayEntityLabelsWhenCrouchingOnly = true
@@ -0,0 +1,64 @@
/*
* 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.entity
import com.cobblemon.mod.common.pokemon.FormData
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.resources.ResourceLocation
import java.text.Normalizer
import java.util.EnumSet
/**
* The type of a platform. Used to give pokemon a "surface" to stand on over water.
*
* @author JazzMcNade
* @since September 29th, 2024
*/
enum class PlatformType {
NONE,
WATER_XS,
WATER_S,
WATER_M,
WATER_L,
WATER_XL;
companion object {
val ALL_POSES = EnumSet.allOf(PlatformType::class.java)
val WATER = EnumSet.of(WATER_XS, WATER_S, WATER_M, WATER_L, WATER_XL)
fun GetModelWithTexture(type: PlatformType) : Pair<ResourceLocation, ResourceLocation> {
return when (type) {
WATER_XS -> Pair(cobblemonResource("water_platform_xs.geo"), cobblemonResource("textures/platforms/water_platform_xs.png"))
WATER_S -> Pair(cobblemonResource("water_platform_s.geo"), cobblemonResource("textures/platforms/water_platform_s.png"))
WATER_M -> Pair(cobblemonResource("water_platform_m.geo"), cobblemonResource("textures/platforms/water_platform_m.png"))
WATER_L -> Pair(cobblemonResource("water_platform_l.geo"), cobblemonResource("textures/platforms/water_platform_l.png"))
WATER_XL -> Pair(cobblemonResource("water_platform_xl.geo"), cobblemonResource("textures/platforms/water_platform_xl.png"))
else -> Pair(cobblemonResource("water_platform_xs.geo"), cobblemonResource("textures/platforms/water_platform_xs"))
}
}
fun GetPlatformTypeForPokemon(form: FormData) : PlatformType {
val width = form.hitbox.width * form.baseScale
return if (width <= 0.511) {
WATER_XS
} else if (width < 1.01) {
WATER_S
} else if (width < 1.8) {
WATER_M
} else if (width < 2.875) {
WATER_L
} else {
WATER_XL
}
}
}
}
@@ -733,7 +733,7 @@ class PokeRodFishingBobberEntity(type: EntityType<out PokeRodFishingBobberEntity
hookedEntity = level().getEntity(hookedEntityID)
}
afterOnServer(seconds = 0.1F) {
afterOnServer(seconds = 1.0F) {
if (player !in player.level().players()) {
return@afterOnServer
}
@@ -24,6 +24,7 @@ import com.cobblemon.mod.common.api.molang.MoLangFunctions.addEntityFunctions
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addPokemonEntityFunctions
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addPokemonFunctions
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addStandardFunctions
import com.cobblemon.mod.common.api.net.serializers.PlatformTypeDataSerializer
import com.cobblemon.mod.common.api.net.serializers.PoseTypeDataSerializer
import com.cobblemon.mod.common.api.net.serializers.StringSetDataSerializer
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
@@ -45,6 +46,7 @@ import com.cobblemon.mod.common.battles.BattleBuilder
import com.cobblemon.mod.common.battles.BattleRegistry
import com.cobblemon.mod.common.block.entity.PokemonPastureBlockEntity
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
import com.cobblemon.mod.common.entity.PlatformType
import com.cobblemon.mod.common.entity.PosableEntity
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.generic.GenericBedrockEntity
@@ -141,6 +143,7 @@ open class PokemonEntity(
@JvmStatic val MOVING = SynchedEntityData.defineId(PokemonEntity::class.java, EntityDataSerializers.BOOLEAN)
@JvmStatic val BEHAVIOUR_FLAGS = SynchedEntityData.defineId(PokemonEntity::class.java, EntityDataSerializers.BYTE)
@JvmStatic val PHASING_TARGET_ID = SynchedEntityData.defineId(PokemonEntity::class.java, EntityDataSerializers.INT)
@JvmStatic val PLATFORM_TYPE = SynchedEntityData.defineId(PokemonEntity::class.java, PlatformTypeDataSerializer)
@JvmStatic val BEAM_MODE = SynchedEntityData.defineId(PokemonEntity::class.java, EntityDataSerializers.BYTE)
@JvmStatic val BATTLE_ID = SynchedEntityData.defineId(PokemonEntity::class.java, EntityDataSerializers.OPTIONAL_UUID)
@JvmStatic val ASPECTS = SynchedEntityData.defineId(PokemonEntity::class.java, StringSetDataSerializer)
@@ -260,6 +263,10 @@ open class PokemonEntity(
/** The pokeball exposed to the client. Used for sendout animation. */
val exposedBall: PokeBall get() = this.effects.mockEffect?.exposedBall ?: this.pokemon.caughtBall
var platform : PlatformType
get() = entityData.get(PLATFORM_TYPE)
set(value) { entityData.set(PLATFORM_TYPE, value) }
override val struct: QueryStruct = QueryStruct(hashMapOf())
.addStandardFunctions()
.addEntityFunctions(this)
@@ -283,6 +290,7 @@ open class PokemonEntity(
builder.define(MOVING, false)
builder.define(BEHAVIOUR_FLAGS, 0)
builder.define(BEAM_MODE, 0)
builder.define(PLATFORM_TYPE, PlatformType.NONE)
builder.define(PHASING_TARGET_ID, -1)
builder.define(BATTLE_ID, Optional.empty())
builder.define(ASPECTS, emptySet())
@@ -333,7 +341,7 @@ open class PokemonEntity(
// val targetPos = node?.blockPos
// if (targetPos == null || world.getBlockState(targetPos.up()).isAir) {
return if (state.`is`(FluidTags.WATER) && !isEyeInFluid(FluidTags.WATER)) {
behaviour.moving.swim.canWalkOnWater
behaviour.moving.swim.canWalkOnWater || platform != PlatformType.NONE
} else if (state.`is`(FluidTags.LAVA) && !isEyeInFluid(FluidTags.LAVA)) {
behaviour.moving.swim.canWalkOnLava
} else {
@@ -640,6 +648,10 @@ open class PokemonEntity(
enablePoseTypeRecalculation = nbt.getBoolean(DataKeys.POKEMON_RECALCULATE_POSE)
}
if (nbt.contains(DataKeys.POKEMON_PLATFORM_TYPE)) {
entityData.set(PLATFORM_TYPE, PlatformType.valueOf(nbt.getString(DataKeys.POKEMON_PLATFORM_TYPE)))
}
CobblemonEvents.POKEMON_ENTITY_LOAD.postThen(
event = PokemonEntityLoadEvent(this, nbt),
ifSucceeded = {},
@@ -1117,6 +1129,91 @@ open class PokemonEntity(
return true
}
/**
* Adjusts a given sent out position based on the local environment.
* Returns the new position and a PlatformType if the pokemon should be placed on one.
*/
fun getAjustedSendoutPosition(pos: Vec3) : Vec3 {
var platform = PlatformType.NONE
var blockPos = BlockPos(pos.x.toInt(), pos.y.toInt(), pos.z.toInt())
var blockLookCount = 5
var foundSurface = false
val species = this.exposedSpecies
val form = this.exposedForm
var result = pos
if (this.level().isWaterAt(blockPos)) {
// look upward for a water surface
var testPos = blockPos
if (!species.behaviour.moving.swim.canBreatheUnderwater) {
// move sendout pos to surface if it's near
for (i in 0..blockLookCount) {
// Try to find a surface...
val blockState = this.level().getBlockState(testPos)
if (blockState.fluidState.isEmpty) {
if(blockState.getCollisionShape(this.level(), testPos).isEmpty) {
foundSurface = true
}
// No space above the water surface
break
}
testPos = testPos.above()
}
if (foundSurface) {
val hasHeadRoom = !collidesWithBlock(Vec3(blockPos.x.toDouble(), (blockPos.y).toDouble(), (blockPos.z).toDouble()))
if (hasHeadRoom) {
result = Vec3(result.x, testPos.y.toDouble(), result.z)
}
} else {
foundSurface = false
}
}
} else if (this.level().isEmptyBlock(blockPos)) {
// look downward for a water surface
blockLookCount = 64 // Higher because the pokemon can fall down to water below
var testPos = BlockPos(pos.x.toInt(), pos.y.toInt(), pos.z.toInt())
for (i in 0..blockLookCount) {
// Try to find a surface...
val blockState = this.level().getBlockState(testPos)
if (!blockState.fluidState.isEmpty) {
foundSurface = true
break
}
if (!blockState.getCollisionShape(this.level(), testPos).isEmpty) {
break
}
testPos = testPos.below()
}
}
if (foundSurface) {
val canFly = species.behaviour.moving.fly.canFly
if (canFly) {
val hasHeadRoom = !collidesWithBlock(Vec3(blockPos.x.toDouble(), (result.y + 1), (blockPos.z).toDouble()))
if (hasHeadRoom) {
result = Vec3(result.x, result.y + 1.0, result.z)
}
} else if (species.behaviour.moving.swim.canBreatheUnderwater && !species.behaviour.moving.swim.canWalkOnWater) {
// Use half hitbox height for swimmers
val halfHeight = species.hitbox.height * species.baseScale / 2.0
for (i in 1..halfHeight.toInt()) {
blockPos = blockPos.below()
if (!this.level().isWaterAt(blockPos) || !this.level().getBlockState(blockPos).getCollisionShape(this.level(), blockPos).isEmpty) {
break
}
}
result = Vec3(result.x, result.y + halfHeight - halfHeight.toInt(), result.z)
} else {
platform = if (species.behaviour.moving.swim.canWalkOnWater || collidesWithBlock(Vec3(result.x, result.y, result.z))) PlatformType.NONE else PlatformType.GetPlatformTypeForPokemon(form)
}
}
this.platform = platform
return result
}
private fun Entity.collidesWithBlock(pos: Vec3) : Boolean {
return level().getBlockCollisions(this, boundingBox.move(pos)).iterator().hasNext()
}
override fun remove(reason: RemovalReason) {
val stateEntity = (pokemon.state as? ActivePokemonState)?.entity
super.remove(reason)
@@ -1196,6 +1293,10 @@ open class PokemonEntity(
super.travel(movementInput)
this.updateBlocksTraveled(prevBlockPos)
}
if (isBattling && this.isInWater) {
// Prevent swimmers from sinking in battle
this.deltaMovement = Vec3(deltaMovement.x, 0.0, deltaMovement.z)
}
}
private fun updateBlocksTraveled(fromBp: BlockPos) {
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.api.pokemon.status.Statuses
import com.cobblemon.mod.common.battles.BattleRegistry
import com.cobblemon.mod.common.entity.PlatformType
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.activestate.ActivePokemonState
@@ -114,7 +115,7 @@ class PokemonServerDelegate : PokemonSideDelegate {
}
entity.entityData.set(PokemonEntity.ASPECTS, trackedAspects)
entity.entityData.set(PokemonEntity.LABEL_LEVEL, entity.pokemon.level)
entity.entityData.set(PokemonEntity.MOVING, entity.deltaMovement.multiply(1.0, if (entity.onGround()) 0.0 else 1.0, 1.0).length() > 0.005F)
entity.entityData.set(PokemonEntity.MOVING, entity.platform == PlatformType.NONE && entity.deltaMovement.multiply(1.0, if (entity.onGround()) 0.0 else 1.0, 1.0).length() > 0.005F)
entity.entityData.set(PokemonEntity.FRIENDSHIP, entity.pokemon.friendship)
entity.entityData.set(PokemonEntity.CAUGHT_BALL, trackedBall)
@@ -12,6 +12,7 @@ import com.bedrockk.molang.runtime.MoLangRuntime
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunctions
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addStandardFunctions
import com.cobblemon.mod.common.api.pokemon.status.Statuses
import com.cobblemon.mod.common.entity.PlatformType
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.pokemon.PokemonBehaviourFlag
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
@@ -26,12 +27,13 @@ import net.minecraft.tags.FluidTags
import net.minecraft.util.Mth
import net.minecraft.world.entity.ai.attributes.Attributes
import net.minecraft.world.entity.ai.control.MoveControl
import net.minecraft.world.level.material.FluidState
import net.minecraft.world.level.pathfinder.PathType
import net.minecraft.world.phys.AABB
import net.minecraft.world.phys.Vec3
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
import kotlin.math.sqrt
class PokemonMoveControl(val pokemonEntity: PokemonEntity) : MoveControl(pokemonEntity) {
companion object {
@@ -42,6 +44,8 @@ class PokemonMoveControl(val pokemonEntity: PokemonEntity) : MoveControl(pokemon
it.environment.query.addStandardFunctions().addFunctions(pokemonEntity.struct.functions)
}
private var waterLevel : Double = 0.0
override fun tick() {
if (pokemonEntity.pokemon.status?.status == Statuses.SLEEP || pokemonEntity.isDeadOrDying) {
pokemonEntity.speed = 0F
@@ -189,12 +193,106 @@ class PokemonMoveControl(val pokemonEntity: PokemonEntity) : MoveControl(pokemon
}
// Float
if (mob.isEyeInFluid(FluidTags.WATER) && behaviour.moving.swim.canSwimInWater) {
if (mob.isEyeInFluid(FluidTags.WATER) && behaviour.moving.swim.canSwimInWater && !this.pokemonEntity.isBattling) {
pokemonEntity.yya = 0.2F
}
// In battle water antics
// Borrowing hard from Minecraft's Boat logic
if (this.pokemonEntity.isBattling && mob.isInWater) {
var e = 0.0F
val exposedSpecies = this.pokemonEntity.exposedSpecies
if (isUnderwater()) {
if (this.pokemonEntity.platform != PlatformType.NONE) {
// Float up if on a platform
e = 0.3F
}
} else if (checkInWater()) {
if (this.pokemonEntity.platform != PlatformType.NONE ) {
// Hold Steady
e = ((this.waterLevel - this.pokemonEntity.y) / this.pokemonEntity.bbHeight).toFloat()
} else if (exposedSpecies.behaviour.moving.swim.canBreatheUnderwater) {
// allow swimmers to sink a bit into the water
e = -1.5F
}
}
if (Mth.abs(e) > VERY_CLOSE) {
val vec32: Vec3 = this.pokemonEntity.deltaMovement
this.pokemonEntity.setDeltaMovement(vec32.x, (vec32.y + e * (this.pokemonEntity.gravity / 0.65)) * 0.75, vec32.z)
}
}
}
}
/*
* Returns the ideal water level y position of a given pokemon during battle.
* This is separate for the eye height check and is dependent on if the pokemon is rafted or swimming.
*/
private fun getStableBattleFloatHeight(): Double {
val aABB: AABB = this.pokemonEntity.boundingBox
return if (this.pokemonEntity.exposedSpecies.behaviour.moving.swim.canBreatheUnderwater) ((aABB.maxY - aABB.minY) / 2.0) else 0.05
}
/*
* Returns true if a pokemon is touching a water block.
* Based on vanilla Minecraft's Boat.checkInWater()
*/
private fun checkInWater(): Boolean {
val aABB: AABB = mob.boundingBox
val i = Mth.floor(aABB.minX)
val j = Mth.ceil(aABB.maxX)
val k = Mth.floor(aABB.minY)
val l = Mth.ceil(aABB.minY + 0.001)
val m = Mth.floor(aABB.minZ)
val n = Mth.ceil(aABB.maxZ)
var bl = false
this.waterLevel = -1.7976931348623157E308
val mutableBlockPos = BlockPos.MutableBlockPos()
for (o in i until j) {
for (p in k until l) {
for (q in m until n) {
mutableBlockPos[o, p] = q
val fluidState: FluidState = mob.level().getFluidState(mutableBlockPos)
if (fluidState.`is`(FluidTags.WATER)) {
val f = p.toFloat() + fluidState.getHeight(mob.level(), mutableBlockPos)
this.waterLevel = max(f.toDouble(), waterLevel)
bl = bl or (aABB.minY < f.toDouble())
}
}
}
}
return bl
}
/*
* Returns true if a pokemon's y level is below it's idealized float height in battle.
* Based on vanilla Minecraft's Boat.isUnderWater()
*/
private fun isUnderwater(): Boolean {
val aABB: AABB = this.pokemonEntity.boundingBox
val d = aABB.minY + getStableBattleFloatHeight()
val i = Mth.floor(aABB.minX)
val j = Mth.ceil(aABB.maxX)
val k = Mth.floor(aABB.minY)
val l = Mth.ceil(aABB.maxY)
val m = Mth.floor(aABB.minZ)
val n = Mth.ceil(aABB.maxZ)
val bl = false
val mutableBlockPos = BlockPos.MutableBlockPos()
for (o in i until j) {
for (p in k until l) {
for (q in m until n) {
mutableBlockPos[o, p] = q
val fluidState: FluidState = mob.level().getFluidState(mutableBlockPos)
if (fluidState.`is`(FluidTags.WATER) && d < (mutableBlockPos.y.toFloat() + fluidState.getHeight(mob.level(), mutableBlockPos)).toDouble()) {
return true
}
}
}
}
return bl
}
private fun isWalkable(xMovement: Float, zMovement: Float): Boolean {
val entityNavigation = mob.navigation
val pathNodeMaker = entityNavigation.nodeEvaluator
@@ -36,7 +36,7 @@ class PokemonNavigation(val world: Level, val pokemonEntity: PokemonEntity) : Gr
// Lazy init because navigation is instantiated during entity construction and pokemonEntity.form isn't set yet.
// (pokemonEntity.behaviour is a shortcut to pokemonEntity.form.behaviour)
// It's JVM field instantiation order stuff, too niche to explain further.
val moving: MoveBehaviour by lazy { pokemonEntity.behaviour.moving }
val moving: MoveBehaviour by lazy { pokemonEntity.exposedSpecies.behaviour.moving }
var cachedCurrentNode: Node? = null
var currentNodeDistance = 0F
@@ -176,7 +176,7 @@ class PokemonNavigation(val world: Level, val pokemonEntity: PokemonEntity) : Gr
var target = target
var blockPos: BlockPos
if (this.world.getBlockState(target).isAir && !pokemonEntity.behaviour.moving.fly.canFly) {
if (this.world.getBlockState(target).isAir && !pokemonEntity.exposedSpecies.behaviour.moving.fly.canFly) {
blockPos = target.below()
while (blockPos.y > this.world.minBuildHeight && this.world.getBlockState(blockPos).isAir) {
blockPos = blockPos.below()
@@ -237,7 +237,7 @@ class PokemonNavigation(val world: Level, val pokemonEntity: PokemonEntity) : Gr
// pokemonEntity.discard()
// return false
// If we just started moving and it's to an open node, fly
if (node.type == PathType.OPEN && pokemonEntity.form.behaviour.moving.fly.canFly && !pokemonEntity.isFlying()) {
if (node.type == PathType.OPEN && pokemonEntity.exposedForm.behaviour.moving.fly.canFly && !pokemonEntity.isFlying()) {
pokemonEntity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, true)
}
}
@@ -10,16 +10,22 @@ package com.cobblemon.mod.common.entity.pokemon.ai.goals
import com.cobblemon.mod.common.battles.BattleRegistry
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.pokemon.PokemonBehaviourFlag
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import net.minecraft.world.entity.ai.goal.Goal
import net.minecraft.world.phys.Vec3
class PokemonInBattleMovementGoal(val entity: PokemonEntity, val range: Int) : Goal() {
var battlePos : Vec3? = null
var hasMovedToPos = false
override fun canUse(): Boolean {
return entity.isBattling && getClosestPokemonEntity() != null && entity.getCurrentPoseType() != PoseType.SLEEP
return entity.isBattling && entity.getCurrentPoseType() != PoseType.SLEEP
}
override fun start() {
super.start()
battlePos = entity.position()
entity.navigation.stop()
}
@@ -36,5 +42,17 @@ class PokemonInBattleMovementGoal(val entity: PokemonEntity, val range: Int) : G
if (closestPokemonEntity != null) {
entity.lookControl.setLookAt(closestPokemonEntity.x, closestPokemonEntity.eyeY, closestPokemonEntity.z)
}
if (entity.exposedSpecies.behaviour.moving.fly.canFly) {
// Flyer logic
if (!hasMovedToPos) {
entity.navigation.moveTo(battlePos!!.x, battlePos!!.y, battlePos!!.z, 1.0)
hasMovedToPos = true
}
if (entity.ticksLived > 1 && !entity.onGround() && !entity.getBehaviourFlag(PokemonBehaviourFlag.FLYING)) {
// Let flyers fly in battle if they're in the air
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, true)
}
}
}
}
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.api.entity.pokemon.*
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.pokemon.PokemonPropertyExtractor
import com.cobblemon.mod.common.api.scheduling.afterOnServer
import com.cobblemon.mod.common.entity.pokemon.PokemonBehaviourFlag
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
import com.cobblemon.mod.common.pokemon.Pokemon
@@ -45,6 +46,12 @@ class IllusionEffect(
override fun revert(entity: PokemonEntity, future: CompletableFuture<PokemonEntity>) {
entity.effects.mockEffect = null
if (!entity.exposedSpecies.behaviour.moving.fly.canFly && entity.getBehaviourFlag(PokemonBehaviourFlag.FLYING)) {
// Transitioning from a flying form to a non-flying form.
// If we were flying, need to turn the behavior flag off or the pokemon will continue to float in the air.
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, false)
}
afterOnServer(seconds = 1.0F) {
entity.cry()
if (entity.pokemon.shiny) SpawnSnowstormEntityParticlePacket(cobblemonResource("shiny_ring"), entity.id, listOf("shiny_particles", "middle")).sendToPlayersAround(entity.x, entity.y, entity.z, 64.0, entity.level().dimension())
@@ -9,7 +9,7 @@
package com.cobblemon.mod.common.item
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.pokedex.PokedexTypes
import com.cobblemon.mod.common.client.pokedex.PokedexType
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.isLookingAt
import net.minecraft.client.player.LocalPlayer
@@ -24,7 +24,7 @@ import net.minecraft.world.item.UseAnim
import net.minecraft.world.level.Level
import net.minecraft.world.phys.AABB
class PokedexItem(val type: PokedexTypes): CobblemonItem(Item.Properties().stacksTo(1)) {
class PokedexItem(val type: PokedexType): CobblemonItem(Item.Properties().stacksTo(1)) {
override fun getUseAnimation(itemStack: ItemStack): UseAnim? = UseAnim.TOOT_HORN
@@ -228,6 +228,44 @@ object CobblemonItemGroups {
entries.accept(CobblemonItems.DARK_GEM)
entries.accept(CobblemonItems.STEEL_GEM)
entries.accept(CobblemonItems.FAIRY_GEM)
entries.accept(CobblemonItems.GEM_NORMAL_BLOCK)
entries.accept(CobblemonItems.GEM_FIRE_BLOCK)
entries.accept(CobblemonItems.GEM_WATER_BLOCK)
entries.accept(CobblemonItems.GEM_GRASS_BLOCK)
entries.accept(CobblemonItems.GEM_ELECTRIC_BLOCK)
entries.accept(CobblemonItems.GEM_ICE_BLOCK)
entries.accept(CobblemonItems.GEM_FIGHTING_BLOCK)
entries.accept(CobblemonItems.GEM_POISON_BLOCK)
entries.accept(CobblemonItems.GEM_GROUND_BLOCK)
entries.accept(CobblemonItems.GEM_FLYING_BLOCK)
entries.accept(CobblemonItems.GEM_PSYCHIC_BLOCK)
entries.accept(CobblemonItems.GEM_BUG_BLOCK)
entries.accept(CobblemonItems.GEM_ROCK_BLOCK)
entries.accept(CobblemonItems.GEM_GHOST_BLOCK)
entries.accept(CobblemonItems.GEM_DRAGON_BLOCK)
entries.accept(CobblemonItems.GEM_DARK_BLOCK)
entries.accept(CobblemonItems.GEM_STEEL_BLOCK)
entries.accept(CobblemonItems.GEM_FAIRY_BLOCK)
entries.accept(CobblemonItems.GEM_NORMAL_BUDDING)
entries.accept(CobblemonItems.GEM_FIRE_BUDDING)
entries.accept(CobblemonItems.GEM_WATER_BUDDING)
entries.accept(CobblemonItems.GEM_GRASS_BUDDING)
entries.accept(CobblemonItems.GEM_ELECTRIC_BUDDING)
entries.accept(CobblemonItems.GEM_ICE_BUDDING)
entries.accept(CobblemonItems.GEM_FIGHTING_BUDDING)
entries.accept(CobblemonItems.GEM_POISON_BUDDING)
entries.accept(CobblemonItems.GEM_GROUND_BUDDING)
entries.accept(CobblemonItems.GEM_FLYING_BUDDING)
entries.accept(CobblemonItems.GEM_PSYCHIC_BUDDING)
entries.accept(CobblemonItems.GEM_BUG_BUDDING)
entries.accept(CobblemonItems.GEM_ROCK_BUDDING)
entries.accept(CobblemonItems.GEM_GHOST_BUDDING)
entries.accept(CobblemonItems.GEM_DRAGON_BUDDING)
entries.accept(CobblemonItems.GEM_DARK_BUDDING)
entries.accept(CobblemonItems.GEM_STEEL_BUDDING)
entries.accept(CobblemonItems.GEM_FAIRY_BUDDING)
}
private fun blockEntries(displayContext: ItemDisplayParameters, entries: Output) {
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.item.interactive.ability
import com.cobblemon.mod.common.api.abilities.*
import com.cobblemon.mod.common.api.item.ability.AbilityChanger
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.abilities.HiddenAbilityType
// TODO Polish me down the line when we actually release the item in the mod, we need a way to select the ability
@@ -20,8 +21,11 @@ open class AbilityTypeChanger<T : PotentialAbility>(
) : AbilityChanger<T> {
override fun queryPossible(pokemon: Pokemon): Set<AbilityTemplate> {
val ofType = pokemon.form.abilities.filter { it.type == this.type }
return ofType.filter { it.template != pokemon.ability.template }
val currentType = this.findCurrent(pokemon)
val targetType = if (currentType == HiddenAbilityType) CommonAbilityType else this.type
return pokemon.form.abilities
.filter { it.type == targetType && it.template != pokemon.ability.template }
.map { it.template }
.toSet()
}
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.net.messages.client.spawn
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
import com.cobblemon.mod.common.entity.PlatformType
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.pokemon.Gender
@@ -33,6 +34,7 @@ class SpawnPokemonPacket(
private val battleId: UUID?,
private val phasingTargetId: Int,
private val beamMode: Byte,
private val platform: PlatformType,
private val nickname: MutableComponent?,
private val labelLevel: Int,
private val poseType: PoseType,
@@ -58,6 +60,7 @@ class SpawnPokemonPacket(
entity.battleId,
entity.phasingTargetId,
entity.beamMode.toByte(),
entity.platform,
entity.pokemon.nickname,
if (Cobblemon.config.displayEntityLevelLabel) entity.entityData.get(PokemonEntity.LABEL_LEVEL) else -1,
entity.entityData.get(PokemonEntity.POSE_TYPE),
@@ -81,6 +84,7 @@ class SpawnPokemonPacket(
buffer.writeNullable(this.battleId) { pb, value -> pb.writeUUID(value) }
buffer.writeInt(this.phasingTargetId)
buffer.writeByte(this.beamMode.toInt())
buffer.writeEnumConstant(this.platform)
buffer.writeNullable(this.nickname) { _, v -> buffer.writeText(v) }
buffer.writeInt(this.labelLevel)
buffer.writeEnumConstant(this.poseType)
@@ -106,6 +110,7 @@ class SpawnPokemonPacket(
}
entity.phasingTargetId = this.phasingTargetId
entity.beamMode = this.beamMode.toInt()
entity.platform = this.platform
entity.battleId = this.battleId
entity.entityData.set(PokemonEntity.LABEL_LEVEL, labelLevel)
entity.entityData.set(PokemonEntity.SPECIES, entity.pokemon.species.resourceIdentifier.toString())
@@ -133,6 +138,7 @@ class SpawnPokemonPacket(
val battleId = buffer.readNullable { buffer.readUUID() }
val phasingTargetId = buffer.readInt()
val beamModeEmitter = buffer.readByte()
val platform = buffer.readEnumConstant(PlatformType::class.java)
val nickname = buffer.readNullable { buffer.readText().copy() }
val labelLevel = buffer.readInt()
val poseType = buffer.readEnumConstant(PoseType::class.java)
@@ -144,7 +150,7 @@ class SpawnPokemonPacket(
val freezeFrame = buffer.readFloat()
val vanillaPacket = decodeVanillaPacket(buffer)
return SpawnPokemonPacket(ownerId, scaleModifier, speciesId, gender, shiny, formName, aspects, battleId, phasingTargetId, beamModeEmitter, nickname, labelLevel, poseType, unbattlable, hideLabel, caughtBall, spawnAngle, friendship, freezeFrame, vanillaPacket)
return SpawnPokemonPacket(ownerId, scaleModifier, speciesId, gender, shiny, formName, aspects, battleId, phasingTargetId, beamModeEmitter, platform, nickname, labelLevel, poseType, unbattlable, hideLabel, caughtBall, spawnAngle, friendship, freezeFrame, vanillaPacket)
}
}
@@ -10,14 +10,9 @@ package com.cobblemon.mod.common.net.messages.client.ui
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.client.net.gui.PokedexUIPacketHandler
import com.cobblemon.mod.common.client.pokedex.PokedexTypes
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.readEnumConstant
import com.cobblemon.mod.common.util.readIdentifier
import com.cobblemon.mod.common.util.readString
import com.cobblemon.mod.common.util.writeEnumConstant
import com.cobblemon.mod.common.util.writeIdentifier
import com.cobblemon.mod.common.util.writeString
import com.cobblemon.mod.common.client.pokedex.PokedexType
import com.cobblemon.mod.common.util.*
import net.minecraft.core.BlockPos
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.resources.ResourceLocation
@@ -26,18 +21,19 @@ import net.minecraft.resources.ResourceLocation
*
* Handled by [PokedexUIPacketHandler].
*/
class PokedexUIPacket(val type: PokedexTypes, val initSpecies: ResourceLocation? = null): NetworkPacket<PokedexUIPacket> {
class PokedexUIPacket(val type: PokedexType, val initSpecies: ResourceLocation? = null, val blockPos: BlockPos? = null): NetworkPacket<PokedexUIPacket> {
override val id = ID
override fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeEnumConstant(type)
buffer.writeNullable(initSpecies) { pb, value -> pb.writeIdentifier(value) }
buffer.writeNullable(blockPos) { pb, value -> pb.writeBlockPos(value) }
}
companion object {
val ID = cobblemonResource("pokedex_ui")
fun decode(buffer: RegistryFriendlyByteBuf) = PokedexUIPacket(buffer.readEnumConstant(PokedexTypes::class.java), buffer.readNullable { it.readIdentifier() })
fun decode(buffer: RegistryFriendlyByteBuf) = PokedexUIPacket(buffer.readEnumConstant(PokedexType::class.java), buffer.readNullable { it.readIdentifier() }, buffer.readNullable { it.readBlockPos() })
}
}
@@ -0,0 +1,31 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.net.messages.server.block
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.net.serverhandling.block.AdjustBlockEntityViewerCountHandler
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.core.BlockPos
import net.minecraft.network.RegistryFriendlyByteBuf
/**
* Handled by [AdjustBlockEntityViewerCountHandler].
*/
class AdjustBlockEntityViewerCountPacket(val blockPos: BlockPos, val increment: Boolean) : NetworkPacket<AdjustBlockEntityViewerCountPacket> {
override val id = ID
override fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeBlockPos(blockPos)
buffer.writeBoolean(increment)
}
companion object {
val ID = cobblemonResource("adjust_block_entity_viewer_count")
fun decode(buffer: RegistryFriendlyByteBuf): AdjustBlockEntityViewerCountPacket = AdjustBlockEntityViewerCountPacket(buffer.readBlockPos(), buffer.readBoolean())
}
}
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.net.serverhandling.block
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
import com.cobblemon.mod.common.block.entity.ViewerCountBlockEntity
import com.cobblemon.mod.common.net.messages.server.block.AdjustBlockEntityViewerCountPacket
import net.minecraft.server.MinecraftServer
import net.minecraft.server.level.ServerPlayer
object AdjustBlockEntityViewerCountHandler : ServerNetworkPacketHandler<AdjustBlockEntityViewerCountPacket> {
override fun handle(packet: AdjustBlockEntityViewerCountPacket, server: MinecraftServer, player: ServerPlayer) {
val blockEntity = player.level().getBlockEntity(packet.blockPos)
if (blockEntity != null && blockEntity is ViewerCountBlockEntity) {
if (packet.increment) blockEntity.incrementViewerCount()
else blockEntity.decrementViewerCount()
}
}
}
@@ -14,7 +14,7 @@ import com.cobblemon.mod.common.api.pokedex.PokedexLearnedInformation
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUI
import com.cobblemon.mod.common.client.pokedex.PokedexScannerRenderer
import com.cobblemon.mod.common.client.pokedex.PokedexTypes
import com.cobblemon.mod.common.client.pokedex.PokedexType
import com.cobblemon.mod.common.net.messages.client.pokedex.ServerConfirmedRegisterPacket
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.FinishScanningPacket
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.StartScanningPacket
@@ -60,7 +60,7 @@ class PokedexUsageContext {
var innerRingRotation: Float = 0F
var zoomLevel: Float = 0F
var newPokemonInfo: PokedexLearnedInformation = PokedexLearnedInformation.NONE
var type: PokedexTypes = PokedexTypes.RED
var type: PokedexType = PokedexType.RED
var availableInfoFrames: MutableList<Boolean?> = mutableListOf(null, null, null, null)
val renderer: PokedexScannerRenderer = PokedexScannerRenderer()
@@ -128,7 +128,7 @@ class PokedexUsageContext {
}
}
fun openPokedexGUI(types: PokedexTypes = PokedexTypes.RED, speciesId: ResourceLocation? = null) {
fun openPokedexGUI(types: PokedexType = PokedexType.RED, speciesId: ResourceLocation? = null) {
PokedexGUI.open(CobblemonClient.clientPokedexData, types, speciesId)
playSound(CobblemonSounds.POKEDEX_OPEN)
}
@@ -14,6 +14,8 @@ import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.abilities.Abilities
import com.cobblemon.mod.common.api.abilities.Ability
import com.cobblemon.mod.common.api.abilities.AbilityPool
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
import com.cobblemon.mod.common.api.battles.model.actor.EntityBackedBattleActor
import com.cobblemon.mod.common.api.data.ShowdownIdentifiable
import com.cobblemon.mod.common.api.entity.PokemonSender
import com.cobblemon.mod.common.api.events.CobblemonEvents
@@ -64,9 +66,12 @@ import com.cobblemon.mod.common.api.types.ElementalType
import com.cobblemon.mod.common.api.types.ElementalTypes
import com.cobblemon.mod.common.api.types.tera.TeraType
import com.cobblemon.mod.common.api.types.tera.TeraTypes
import com.cobblemon.mod.common.battles.ActiveBattlePokemon
import com.cobblemon.mod.common.battles.ShowdownInterpreter
import com.cobblemon.mod.common.config.CobblemonConfig
import com.cobblemon.mod.common.datafixer.CobblemonSchemas
import com.cobblemon.mod.common.datafixer.CobblemonTypeReferences
import com.cobblemon.mod.common.entity.PlatformType
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.entity.pokemon.effects.IllusionEffect
@@ -147,6 +152,7 @@ import net.minecraft.world.level.block.MagmaBlock
import net.minecraft.world.level.block.SweetBerryBushBlock
import net.minecraft.world.level.block.WitherRoseBlock
import net.minecraft.world.phys.Vec3
import kotlin.math.*
enum class OriginalTrainerType : StringRepresentable {
NONE, PLAYER, NPC;
@@ -562,10 +568,11 @@ open class Pokemon : ShowdownIdentifiable {
SeasonFeatureHandler.updateSeason(this, level, position.toBlockPos())
val entity = PokemonEntity(level, this)
illusion?.start(entity)
val sentOut = entity.setPositionSafely(position)
val adjustedPosition = entity.getAjustedSendoutPosition(position)
val sentOut = entity.setPositionSafely(adjustedPosition)
//If sendout failed, fall back
if (!sentOut) {
entity.setPos(position.x, position.y, position.z)
entity.setPos(adjustedPosition.x, adjustedPosition.y, adjustedPosition.z)
}
mutation(entity)
level.addFreshEntity(entity)
@@ -585,18 +592,6 @@ open class Pokemon : ShowdownIdentifiable {
mutation: (PokemonEntity) -> Unit = {},
): CompletableFuture<PokemonEntity> {
// send out raft if over water
if (position != null) {
// todo if send out position is over water then add a raft entity to stand on
if (level.isWaterAt(
BlockPos(
position.x.toInt(),
position.y.toInt() - 1,
position.z.toInt()
)
) && this.species.types.all { it != ElementalTypes.WATER && it != ElementalTypes.FLYING }) {
}
}
// Handle special case of shouldered Cobblemon
if (this.state is ShoulderedState) {
@@ -616,6 +611,36 @@ open class Pokemon : ShowdownIdentifiable {
val owner = getOwnerEntity()
if (owner is LivingEntity) {
owner.swing(InteractionHand.MAIN_HAND, true)
val spawnDirection: Vec3
val spawnYaw: Double
if (battleId != null) {
// Look for an opposing opponent to face
val battle = Cobblemon.battleRegistry.getBattle(battleId)
val activeBattlePokemon = battle?.activePokemon?.firstOrNull { activePokemon -> activePokemon.battlePokemon?.originalPokemon?.uuid == it.pokemon.uuid }
val opposingActiveBattlePokemon = (activeBattlePokemon?.getOppositeOpponent() as ActiveBattlePokemon?)
var opposingEntityPos = opposingActiveBattlePokemon?.battlePokemon?.entity?.position()
if (opposingEntityPos == null) {
// Can't find the opposing pokemon, it probably doesn't exist yet. Try to calculate the opponent's sendout position
val opposingEntityBattleActor = battle?.actors?.first { battleActor ->
battleActor is EntityBackedBattleActor<*> && battleActor.entity != null && battleActor.entity?.uuid !== owner.uuid
} as EntityBackedBattleActor<*>
if (activeBattlePokemon != null) {
opposingEntityPos = ShowdownInterpreter.getSendoutPosition(battle, activeBattlePokemon, opposingEntityBattleActor as BattleActor)
}
if (opposingEntityPos == null) {
// Sendout calculation failed, fallback to using the opposing actor's position
opposingEntityPos = opposingEntityBattleActor.initialPos
}
}
spawnDirection = opposingEntityPos?.subtract(it.position()) ?: position.subtract(owner.position())
val battleYaw = (atan2(spawnDirection.z, spawnDirection.x) * 180.0 / PI) - 90.0
spawnYaw = battleYaw
} else {
// Non-battle send out, face the trainer
spawnDirection = position.subtract(owner.position())
spawnYaw = atan2(spawnDirection.z, spawnDirection.x) * 180.0 / PI + 102.5
}
it.entityData.set(PokemonEntity.SPAWN_DIRECTION, spawnYaw.toFloat())
}
if (owner != null) {
level.playSoundServer(owner.position(), CobblemonSounds.POKE_BALL_THROW, volume = 0.6F)
@@ -625,6 +650,10 @@ open class Pokemon : ShowdownIdentifiable {
it.beamMode = 1
it.battleId = battleId
if (it.battleId == null) {
it.platform = PlatformType.NONE
}
it.after(seconds = THROW_DURATION) {
it.phasingTargetId = -1
}
@@ -65,6 +65,7 @@ object DataKeys {
const val POKEMON_COUNTS_TOWARDS_SPAWN_CAP = "CountsTowardsSpawnCap"
const val POKEMON_FREEZE_FRAME = "FreezeFrame"
const val POKEMON_RECALCULATE_POSE = "RecalculatePose"
const val POKEMON_PLATFORM_TYPE = "PlatformType"
const val POKEMON_ORIGINAL_TRAINER = "PokemonOriginalTrainer"
const val POKEMON_ORIGINAL_TRAINER_TYPE = "PokemonOriginalTrainerType"
@@ -93,7 +94,7 @@ object DataKeys {
const val STORE_BOX_COUNT_LOCKED = "BoxCountLocked"
const val STORE_BACKUP = "BackupStore"
// Pokedex Keys
// Pokédex Keys
const val POKEDEX_TYPE = "PokedexType"
const val NUM_ENCOUNTED_WILD = "NumberEncounteredWild"
const val NUM_ENCOUNTED_BATTLE = "NumberEncounteredBattle"
@@ -111,28 +112,26 @@ object DataKeys {
const val TETHERING_PLAYER_ID = "PlayerId"
const val TETHERING_ENTITY_ID = "EntityId"
/* Form stuff */
// Form stuff
const val ALOLAN = "alolan"
const val GALARIAN = "galarian"
const val HISUIAN = "hisuian"
const val VALENCIAN = "valencian"
const val CRYSTAL = "crystal"
/* ---------- */
const val POKEMON_PROPERTIES = "Properties"
const val POKEMON_PROPERTIES_CUSTOM = "CustomProperties"
const val POKEMON_PROPERTIES_ORIGINAL_TEXT = "OriginalText"
const val POKEMON_SPECIES_TEXT = "SpeciesText"
/* Healer Block */
// Healer Block
const val HEALER_MACHINE_USER = "MachineUser"
const val HEALER_MACHINE_POKEBALLS = "MachinePokeBalls"
const val HEALER_MACHINE_TIME_LEFT = "MachineTimeLeft"
const val HEALER_MACHINE_CHARGE = "MachineCharge"
const val HEALER_MACHINE_INFINITE = "MachineInfinite"
/* ----------- */
// Pokemon Item
// Pokémon Item
const val POKEMON_ITEM_SPECIES = "species"
const val POKEMON_ITEM_ASPECTS = "aspects"
const val POKEMON_ITEM_TINT_RED = "TintRed"
@@ -161,11 +160,11 @@ object DataKeys {
const val SHOULDER_ASPECTS = "shoulder_aspects"
const val SHOULDER_SCALE_MODIFIER = "shoulder_scale"
//Multiblock Stuff
// Multi-Block
const val MULTIBLOCK_STORAGE = "MultiblockStore"
const val CONTROLLER_BLOCK = "ControllerBlock"
//FossilMultiblockStructure Serialization
// FossilMultiblockStructure Serialization
const val MONITOR_POS = "MonitorPos"
const val TANK_BASE_POS = "TankBasePos"
const val ANALYZER_POS = "AnalyzerPos"
@@ -182,7 +181,10 @@ object DataKeys {
const val FOSSIL_OWNER = "FossilOwner"
const val FOSSIL_STATE = "FossilState"
/* Generic Bedrock Entity */
// Generic Block Entity
const val BLOCK_ENTITY_USER_AMOUNT = "userAmount"
// Generic Bedrock Entity
const val GENERIC_BEDROCK_CATEGORY = "Category"
const val GENERIC_BEDROCK_ASPECTS = "Aspects"
const val GENERIC_BEDROCK_POSE_TYPE = "PoseType"
@@ -0,0 +1,64 @@
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.unknown",
"texture_width": 128,
"texture_height": 128,
"visible_bounds_width": 5,
"visible_bounds_height": 1.5,
"visible_bounds_offset": [0, 0.25, 0]
},
"bones": [
{
"name": "water_platform_l",
"pivot": [0, 0, 0],
"cubes": [
{"origin": [-12, 4, -12], "size": [24, 1, 24], "uv": [0, 64]},
{"origin": [-1, 0, -23], "size": [2, 2, 5], "uv": [114, 82]},
{"origin": [-1, 0, 18], "size": [2, 2, 5], "uv": [114, 82]},
{"origin": [-6, 3, -2], "size": [60, 2, 4], "pivot": [24, 4, 0], "rotation": [0, -90, 0], "uv": [0, 89]},
{"origin": [-54, 3, -2], "size": [60, 2, 4], "pivot": [-24, 4, 0], "rotation": [0, 90, 0], "uv": [0, 89], "mirror": true}
]
},
{
"name": "water_platform1",
"parent": "water_platform_l",
"pivot": [15, 0, -15],
"cubes": [
{"origin": [1, 0, -29], "size": [28, 4, 28], "uv": [0, 0]},
{"origin": [3, -4, -29], "size": [24, 4, 28], "uv": [0, 32]}
]
},
{
"name": "water_platform2",
"parent": "water_platform_l",
"pivot": [-15, 0, -15],
"cubes": [
{"origin": [-29, 0, -29], "size": [28, 4, 28], "uv": [0, 0]},
{"origin": [-27, -4, -29], "size": [24, 4, 28], "uv": [0, 32]}
]
},
{
"name": "water_platform3",
"parent": "water_platform_l",
"pivot": [15, 0, 15],
"cubes": [
{"origin": [1, 0, 1], "size": [28, 4, 28], "uv": [0, 0]},
{"origin": [3, -4, 1], "size": [24, 4, 28], "uv": [0, 32]}
]
},
{
"name": "water_platform4",
"parent": "water_platform_l",
"pivot": [-15, 0, 15],
"cubes": [
{"origin": [-29, 0, 1], "size": [28, 4, 28], "uv": [0, 0]},
{"origin": [-27, -4, 1], "size": [24, 4, 28], "uv": [0, 32]}
]
}
]
}
]
}
@@ -0,0 +1,25 @@
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.unknown",
"texture_width": 256,
"texture_height": 128,
"visible_bounds_width": 4,
"visible_bounds_height": 1.5,
"visible_bounds_offset": [0, 0.25, 0]
},
"bones": [
{
"name": "water_platform_m",
"pivot": [0, 0, 0],
"cubes": [
{"origin": [-22, 0, -22], "size": [44, 4, 44], "uv": [0, 0]},
{"origin": [-20, -4, -22], "size": [40, 4, 44], "uv": [0, 48]}
]
}
]
}
]
}
@@ -0,0 +1,25 @@
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.unknown",
"texture_width": 128,
"texture_height": 64,
"visible_bounds_width": 3,
"visible_bounds_height": 1.5,
"visible_bounds_offset": [0, 0.25, 0]
},
"bones": [
{
"name": "water_platform_s",
"pivot": [0, 0, 0],
"cubes": [
{"origin": [-14, 0, -14], "size": [28, 4, 28], "uv": [0, 0]},
{"origin": [-12, -4, -14], "size": [24, 4, 28], "uv": [0, 32]}
]
}
]
}
]
}
@@ -0,0 +1,64 @@
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.unknown",
"texture_width": 256,
"texture_height": 256,
"visible_bounds_width": 8,
"visible_bounds_height": 1.5,
"visible_bounds_offset": [0, 0.25, 0]
},
"bones": [
{
"name": "water_platform_xl",
"pivot": [0, 0, -23],
"cubes": [
{"origin": [-18, 4, -41], "size": [36, 1, 36], "uv": [0, 96]},
{"origin": [-3, 0, 2], "size": [6, 2, 8], "uv": [0, 221]},
{"origin": [-3, 0, -56], "size": [6, 2, 8], "uv": [0, 221]},
{"origin": [-43, 3, -72], "size": [7, 2, 98], "uv": [0, 133]},
{"origin": [36, 3, -72], "size": [7, 2, 98], "uv": [0, 133]}
]
},
{
"name": "water_platform1",
"parent": "water_platform_xl",
"pivot": [-24, 0, -24],
"cubes": [
{"origin": [-46, 0, -69], "size": [44, 4, 44], "uv": [0, 0]},
{"origin": [-44, -4, -69], "size": [40, 4, 44], "uv": [0, 48]}
]
},
{
"name": "water_platform2",
"parent": "water_platform_xl",
"pivot": [24, 0, -24],
"cubes": [
{"origin": [2, 0, -69], "size": [44, 4, 44], "uv": [0, 0]},
{"origin": [4, -4, -69], "size": [40, 4, 44], "uv": [0, 48]}
]
},
{
"name": "water_platform3",
"parent": "water_platform_xl",
"pivot": [24, 0, 24],
"cubes": [
{"origin": [2, 0, -21], "size": [44, 4, 44], "uv": [0, 0]},
{"origin": [4, -4, -21], "size": [40, 4, 44], "uv": [0, 48]}
]
},
{
"name": "water_platform4",
"parent": "water_platform_xl",
"pivot": [-24, 0, 24],
"cubes": [
{"origin": [-46, 0, -21], "size": [44, 4, 44], "uv": [0, 0]},
{"origin": [-44, -4, -21], "size": [40, 4, 44], "uv": [0, 48]}
]
}
]
}
]
}
@@ -0,0 +1,25 @@
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.unknown",
"texture_width": 128,
"texture_height": 64,
"visible_bounds_width": 3,
"visible_bounds_height": 1.5,
"visible_bounds_offset": [0, 0.25, 0]
},
"bones": [
{
"name": "water_platform_xs",
"pivot": [0, 0, 0],
"cubes": [
{"origin": [-10, 0, -10], "size": [20, 4, 20], "uv": [0, 0]},
{"origin": [-8, -4, -10], "size": [16, 4, 20], "uv": [0, 24]}
]
}
]
}
]
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_bug_block"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_bug_budding"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_dark_block"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_dark_budding"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_dragon_block"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_dragon_budding"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_electric_block"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_electric_budding"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_fairy_block"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_fairy_budding"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_fighting_block"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_fighting_budding"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_fire_block"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_fire_budding"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_flying_block"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_flying_budding"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_ghost_block"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_ghost_budding"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_grass_block"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_grass_budding"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_ground_block"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_ground_budding"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_ice_block"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_ice_budding"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_normal_block"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_normal_budding"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_poison_block"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_poison_budding"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_psychic_block"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_psychic_budding"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_rock_block"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_rock_budding"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_steel_block"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_steel_budding"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_water_block"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cobblemon:block/gem_water_budding"
}
}
}
@@ -88,55 +88,110 @@
"item.cobblemon.pokedex_yellow": "Pokédex",
"item.cobblemon.link_cable": "Link Cable",
"item.cobblemon.link_cable.tooltip": "Evolves pokemon that require trading",
"item.cobblemon.dragon_scale": "Dragon Scale",
"item.cobblemon.dragon_scale.tooltip": "Evolves Seadra into Kingdra when held while trading",
"item.cobblemon.kings_rock": "Kings Rock",
"item.cobblemon.kings_rock.tooltip_1": "When the holder successfully inflicts damage, the target may also flinch",
"item.cobblemon.kings_rock.tooltip_2": "Evolves Poliwhirl into Politoed and Slowpoke into Slowking when held during trading",
"item.cobblemon.metal_coat": "Metal Coat",
"item.cobblemon.metal_coat.tooltip_1": "Boosts the power of the holder's Steel-type moves",
"item.cobblemon.metal_coat.tooltip_2": "Evolves Onix into Steelix and Scyther into Scizor when held during trading",
"item.cobblemon.upgrade": "Upgrade",
"item.cobblemon.upgrade.tooltip": "Evolves Porygon into Porygon2 when held during trading",
"item.cobblemon.dubious_disc": "Dubious Disc",
"item.cobblemon.dubious_disc.tooltip": "Evolves Porygon2 into Porygon-Z when held during trading",
"item.cobblemon.deep_sea_scale": "Deep Sea Scale",
"item.cobblemon.deep_sea_scale.tooltip_1": "Boosts Clamperl's Sp. Def",
"item.cobblemon.deep_sea_scale.tooltip_2": "Evolves Clamperl into Gorebyss when held during trading",
"item.cobblemon.deep_sea_tooth": "Deep Sea Tooth",
"item.cobblemon.deep_sea_tooth.tooltip_1": "Boosts Clamperl's Sp. Atk",
"item.cobblemon.deep_sea_tooth.tooltip_2": "Evolves Clamperl into Huntail when held during trading",
"item.cobblemon.electirizer": "Electirizer",
"item.cobblemon.electirizer.tooltip": "Evolves Electabuzz into Electivire when held while trading",
"item.cobblemon.magmarizer": "Magmarizer",
"item.cobblemon.magmarizer.tooltip": "Evolves Magmar into Magmortar when held during trading",
"item.cobblemon.oval_stone": "Oval Stone",
"item.cobblemon.oval_stone.tooltip": "Evolves Happiny into Chansey when held during the day",
"item.cobblemon.protector": "Protector",
"item.cobblemon.protector.tooltip": "Evolves Rhydon into Rhyperior when held while trading",
"item.cobblemon.reaper_cloth": "Reaper Cloth",
"item.cobblemon.reaper_cloth.tooltip": "Evolves Dusclops into Dusknoir when held while trading",
"item.cobblemon.prism_scale": "Prism Scale",
"item.cobblemon.prism_scale.tooltip": "Evolves Feebas into Milotic when held while trading",
"item.cobblemon.sachet": "Sachet",
"item.cobblemon.sachet.tooltip": "Evolves Spritzee into Aromatisse when held while trading",
"item.cobblemon.whipped_dream": "Whipped Dream",
"item.cobblemon.whipped_dream.tooltip": "Evolves Swirlix into Slurpuff when held while trading",
"item.cobblemon.strawberry_sweet": "Strawberry Sweet",
"item.cobblemon.strawberry_sweet.tooltip": "Evolves Milcery into Alcremie's Strawberry form",
"item.cobblemon.love_sweet": "Love Sweet",
"item.cobblemon.love_sweet.tooltip": "Evolves Milcery into Alcremie's Love form",
"item.cobblemon.berry_sweet": "Berry Sweet",
"item.cobblemon.berry_sweet.tooltip": "Evolves Milcery into Alcremie's Berry form",
"item.cobblemon.clover_sweet": "Clover Sweet",
"item.cobblemon.clover_sweet.tooltip": "Evolves Milcery into Alcremie's Clover form",
"item.cobblemon.flower_sweet": "Flower Sweet",
"item.cobblemon.flower_sweet.tooltip": "Evolves Milcery into Alcremie's Flower form",
"item.cobblemon.star_sweet": "Star Sweet",
"item.cobblemon.star_sweet.tooltip": "Evolves Milcery into Alcremie's Star form",
"item.cobblemon.ribbon_sweet": "Ribbon Sweet",
"item.cobblemon.ribbon_sweet.tooltip": "Evolves Milcery into Alcremie's Ribbon form",
"item.cobblemon.chipped_pot": "Chipped Pot",
"item.cobblemon.chipped_pot.tooltip": "Evolves Antique Sinistea into Polteageist",
"item.cobblemon.cracked_pot": "Cracked Pot",
"item.cobblemon.cracked_pot.tooltip": "Evolves Phony Sinistea into Polteageist",
"item.cobblemon.masterpiece_teacup": "Masterpiece Teacup",
"item.cobblemon.masterpiece_teacup.tooltip": "Evolves Artisan Form Poltchageist into Masterpiece Sinistcha",
"item.cobblemon.unremarkable_teacup": "Unremarkable Teacup",
"item.cobblemon.unremarkable_teacup.tooltip": "Evolves Counterfeit Poltchageist into Unremarkable Sinistcha",
"item.cobblemon.sweet_apple": "Sweet Apple",
"item.cobblemon.sweet_apple.tooltip": "Evolves Applin into Appletun",
"item.cobblemon.tart_apple": "Tart Apple",
"item.cobblemon.tart_apple.tooltip": "Evolves Applin into Flapple",
"item.cobblemon.galarica_cuff": "Galarica Cuff",
"item.cobblemon.galarica_cuff.tooltip": "Evolves Galarian Slowpoke into Galarian Slowbro",
"item.cobblemon.galarica_wreath": "Galarica Wreath",
"item.cobblemon.galarica_wreath.tooltip": "Evolves Galarian Slowpoke into Galarian Slowking",
"item.cobblemon.black_augurite": "Black Augurite",
"item.cobblemon.black_augurite.tooltip": "Evolves Scyther into Kleavor",
"item.cobblemon.peat_block": "Peat Block",
"item.cobblemon.peat_block.tooltip": "Evolves Ursaring into Ursaluna when used during a full moon at night",
"item.cobblemon.dawn_stone": "Dawn Stone",
"item.cobblemon.dawn_stone.tooltip": "Evolves certain Pokémon",
"item.cobblemon.dusk_stone": "Dusk Stone",
"item.cobblemon.dusk_stone.tooltip": "Evolves certain Pokémon",
"item.cobblemon.fire_stone": "Fire Stone",
"item.cobblemon.fire_stone.tooltip": "Evolves certain Pokémon",
"item.cobblemon.ice_stone": "Ice Stone",
"item.cobblemon.ice_stone.tooltip": "Evolves certain Pokémon",
"item.cobblemon.leaf_stone": "Leaf Stone",
"item.cobblemon.leaf_stone.tooltip": "Evolves certain Pokémon",
"item.cobblemon.moon_stone": "Moon Stone",
"item.cobblemon.moon_stone.tooltip": "Evolves certain Pokémon",
"item.cobblemon.shiny_stone": "Shiny Stone",
"item.cobblemon.shiny_stone.tooltip": "Evolves certain Pokémon",
"item.cobblemon.sun_stone": "Sun Stone",
"item.cobblemon.sun_stone.tooltip": "Evolves certain Pokémon",
"item.cobblemon.thunder_stone": "Thunder Stone",
"item.cobblemon.thunder_stone.tooltip": "Evolves certain Pokémon",
"item.cobblemon.water_stone": "Water Stone",
"item.cobblemon.water_stone.tooltip": "Evolves certain Pokémon",
"item.cobblemon.rare_candy": "Rare Candy",
"item.cobblemon.rare_candy.tooltip": "Increases a Pokémon's level by one",
"item.cobblemon.exp_candy_xs": "Exp. Candy XS",
"item.cobblemon.exp_candy_xs.tooltip": "Increases a Pokémon's experience by 100 Exp. Points",
"item.cobblemon.exp_candy_s": "Exp. Candy S",
"item.cobblemon.exp_candy_s.tooltip": "Increases a Pokémon's experience by 800 Exp. Points",
"item.cobblemon.exp_candy_m": "Exp. Candy M",
"item.cobblemon.exp_candy_m.tooltip": "Increases a Pokémon's experience by 3000 Exp. Points",
"item.cobblemon.exp_candy_l": "Exp. Candy L",
"item.cobblemon.exp_candy_l.tooltip": "Increases a Pokémon's experience by 10000 Exp. Points",
"item.cobblemon.exp_candy_xl": "Exp. Candy XL",
"item.cobblemon.exp_candy_xl.tooltip": "Increases a Pokémon's experience by 30000 Exp. Points",
"item.cobblemon.calcium": "Calcium",
"item.cobblemon.carbos": "Carbos",
"item.cobblemon.hp_up": "HP Up",
@@ -193,107 +248,222 @@
"item.cobblemon.naive_mint": "Naive Mint",
"item.cobblemon.serious_mint": "Serious Mint",
"item.cobblemon.ability_shield": "Ability Shield",
"item.cobblemon.ability_shield.tooltip": "Prevents the holder's ability from being changed or suppressed",
"item.cobblemon.absorb_bulb": "Absorb Bulb",
"item.cobblemon.absorb_bulb.tooltip_1": "Boosts the holder's Sp. Atk when hit by a Water-type move",
"item.cobblemon.absorb_bulb.tooltip_2": "Consumed after use",
"item.cobblemon.air_balloon": "Air Balloon",
"item.cobblemon.air_balloon.tooltip_1": "Makes the holder ungrounded",
"item.cobblemon.air_balloon.tooltip_2": "Destroyed on hit",
"item.cobblemon.assault_vest": "Assault Vest",
"item.cobblemon.assault_vest.tooltip": "Raises the holder's Sp. Def but prevents the use of status moves",
"item.cobblemon.auspicious_armor": "Auspicious Armor",
"item.cobblemon.auspicious_armor.tooltip": "Evolves Charcadet into Armarouge",
"item.cobblemon.malicious_armor": "Malicious Armor",
"item.cobblemon.malicious_armor.tooltip": "Evolves Charcadet into Armarouge",
"item.cobblemon.binding_band": "Binding Band",
"item.cobblemon.binding_band.tooltip": "Increases damage dealt by the binding status",
"item.cobblemon.black_belt": "Black Belt",
"item.cobblemon.black_belt.tooltip": "Boosts the power of the holder's Fighting-type moves",
"item.cobblemon.black_glasses": "Black Glasses",
"item.cobblemon.black_glasses.tooltip": "Boosts the power of the holder's Dark-type moves",
"item.cobblemon.black_sludge": "Black Sludge",
"item.cobblemon.black_sludge.tooltip": "If the holder is a Poison-type, its HP is gradually restored throughout a battle. It damages any other type",
"item.cobblemon.blunder_policy": "Blunder Policy",
"item.cobblemon.blunder_policy.tooltip_1": "Boosts the holder's Speed when an attack is missed",
"item.cobblemon.blunder_policy.tooltip_2": "Consumed after use",
"item.cobblemon.cell_battery": "Cell Battery",
"item.cobblemon.cell_battery.tooltip_1": "Boosts the holder's Attack when hit by an Electric-type move",
"item.cobblemon.cell_battery.tooltip_2": "Consumed after use",
"item.cobblemon.charcoal_stick": "Charcoal Stick",
"item.cobblemon.charcoal_stick.tooltip": "Boosts the power of the holder's Fire-type moves",
"item.cobblemon.choice_band": "Choice Band",
"item.cobblemon.choice_band.tooltip": "Boosts the holder's Attack, but locks it into only using one move",
"item.cobblemon.choice_scarf": "Choice Scarf",
"item.cobblemon.choice_scarf.tooltip": "Boosts the holder's Speed, but locks it into only using one move",
"item.cobblemon.choice_specs": "Choice Specs",
"item.cobblemon.choice_specs.tooltip": "Boosts the holder's Sp. Attack, but locks it into only using one move",
"item.cobblemon.cleanse_tag": "Cleanse Tag",
"item.cobblemon.cleanse_tag.tooltip": "Has no effect",
"item.cobblemon.clear_amulet": "Clear Amulet",
"item.cobblemon.covert_cloak": "Covert Cloak",
"item.cobblemon.covert_cloak.tooltip": "Protects the holder from additional effects when hit by a damaging move",
"item.cobblemon.dragon_fang": "Dragon Fang",
"item.cobblemon.dragon_fang.tooltip": "Boosts the power of the holder's Dragon-type moves",
"item.cobblemon.eject_button": "Eject Button",
"item.cobblemon.eject_button.tooltip_1": "Switches the holder out when hit by a damaging move",
"item.cobblemon.eject_button.tooltip_2": "Consumed after use",
"item.cobblemon.eject_pack": "Eject Pack",
"item.cobblemon.eject_pack.tooltip_1": "Switches out the holder if any stats are lowered",
"item.cobblemon.eject_pack.tooltip_2": "Consumed after use",
"item.cobblemon.electric_seed": "Electric Seed",
"item.cobblemon.electric_seed.tooltip": "Boosts the holder's Defense in Electric terrain",
"item.cobblemon.everstone": "Everstone",
"item.cobblemon.everstone.tooltip": "Prevents the holder from evolving",
"item.cobblemon.eviolite": "Eviolite",
"item.cobblemon.eviolite.tooltip": "Boosts the holder's Defense and Sp. Atk if it is not fully evolved",
"item.cobblemon.exp_share": "Exp. Share",
"item.cobblemon.exp_share.tooltip": "Allows the holder to receive a share of experience from battles without participating",
"item.cobblemon.expert_belt": "Expert Belt",
"item.cobblemon.expert_belt.tooltip": "Boosts the damage of super-effective moves",
"item.cobblemon.fairy_feather": "Fairy Feather",
"item.cobblemon.fairy_feather.tooltip": "Boosts the power of the holder's Fairy-type moves",
"item.cobblemon.float_stone": "Float Stone",
"item.cobblemon.float_stone.tooltip": "The holder's weight is halved",
"item.cobblemon.focus_band": "Focus Band",
"item.cobblemon.focus_band.tooltip": "Provides a chance for the holder to survive a potential KO attack, leaving it with 1 HP",
"item.cobblemon.focus_sash": "Focus Sash",
"item.cobblemon.focus_sash.tooltip_1": "Prevents the holder from fainting in a single hit",
"item.cobblemon.focus_sash.tooltip_2": "Consumed after use",
"item.cobblemon.grassy_seed": "Grassy Seed",
"item.cobblemon.grassy_seed.tooltip": "Boosts the holder's Defense in Grassy terrain",
"item.cobblemon.grip_claw": "Grip Claw",
"item.cobblemon.hard_stone": "Hard Stone",
"item.cobblemon.hard_stone.tooltip": "Boosts the power of the holder's Rock-type moves",
"item.cobblemon.heavy_duty_boots": "Heavy-Duty Boots",
"item.cobblemon.heavy_duty_boots.tooltip": "Prevents the effects of traps set on the battlefield",
"item.cobblemon.iron_ball": "Iron Ball",
"item.cobblemon.iron_ball.tooltip": "Grounds the holder, and halves their speed",
"item.cobblemon.lagging_tail": "Lagging Tail",
"item.cobblemon.leftovers": "Leftovers",
"item.cobblemon.leftovers.tooltip": "Gradually restores the holder's HP throughout a battle",
"item.cobblemon.light_ball": "Light Ball",
"item.cobblemon.light_ball.tooltip": "Boosts Pikachu's Attack and Sp. Atk",
"item.cobblemon.light_clay": "Light Clay",
"item.cobblemon.light_clay.tooltip": "Protective moves like Light Screen and Reflect will be effective longer",
"item.cobblemon.loaded_dice": "Loaded Dice",
"item.cobblemon.loaded_dice.tooltip": "Multi-strike moves always hit at least four times",
"item.cobblemon.lucky_egg": "Lucky Egg",
"item.cobblemon.lucky_egg.tooltip": "Increases the amount of experience earned by the holder in battle",
"item.cobblemon.luminous_moss": "Luminous Moss",
"item.cobblemon.magnet": "Magnet",
"item.cobblemon.magnet.tooltip": "Boosts the power of the holder's Electric-type moves",
"item.cobblemon.metronome": "Metronome",
"item.cobblemon.metronome.tooltip": "Boosts the power of moves used consecutively",
"item.cobblemon.miracle_seed": "Miracle Seed",
"item.cobblemon.miracle_seed.tooltip": "Boosts the power of the holder's Grass-type moves",
"item.cobblemon.muscle_band": "Muscle Band",
"item.cobblemon.muscle_band.tooltip": "Boosts the power of the holder's Physical moves",
"item.cobblemon.mystic_water": "Mystic Water",
"item.cobblemon.mystic_water.tooltip": "Boosts the power of the holder's Water-type moves",
"item.cobblemon.never_melt_ice": "Never-Melt Ice",
"item.cobblemon.never_melt_ice.tooltip": "Boosts the power of the holder's Ice-type moves",
"item.cobblemon.poison_barb": "Poison Barb",
"item.cobblemon.poison_barb.tooltip": "Boosts the power of the holder's Poison-type moves",
"item.cobblemon.protective_pads": "Protective Pads",
"item.cobblemon.protective_pads.tooltip": "Protects the holder from contact effects from the target",
"item.cobblemon.punching_glove": "Punching Glove",
"item.cobblemon.punching_glove.tooltip": "Boosts the power of the holder's punching moves and prevents them from triggering contact with the target",
"item.cobblemon.quick_claw": "Quick Claw",
"item.cobblemon.quick_claw.tooltip": "Occasionally allows the holder to strike first",
"item.cobblemon.razor_claw": "Razor Claw",
"item.cobblemon.razor_claw.tooltip_1": "Boosts the critical-hit ratio of the holder's moves",
"item.cobblemon.razor_claw.tooltip_2": "Evolves Sneasel into Sneasler or Weavile when held while leveling up during the day or night, respectively",
"item.cobblemon.razor_fang": "Razor Fang",
"item.cobblemon.razor_fang.tooltip_1": "When the holder successfully inflicts damage, the target may also flinch",
"item.cobblemon.razor_fang.tooltip_2": "Evolves Gligar into Gliscor when held while leveling up during the night",
"item.cobblemon.red_card": "Red Card",
"item.cobblemon.red_card.tooltip_1": "Pokemon that damage the holder are forced to switch out",
"item.cobblemon.red_card.tooltip_2": "Consumed after use",
"item.cobblemon.ring_target": "Ring Target",
"item.cobblemon.ring_target.tooltip": "The holder's type immunities are removed",
"item.cobblemon.rocky_helmet": "Rocky Helmet",
"item.cobblemon.rocky_helmet.tooltip": "Causes a Pokémon that makes direct contact with the holder to take damage",
"item.cobblemon.room_service": "Room Service",
"item.cobblemon.room_service.tooltip_1": "Lowers the holder's Speed when Trick Room is in effect",
"item.cobblemon.room_service.tooltip_2": "Consumed after use",
"item.cobblemon.safety_goggles": "Safety Goggles",
"item.cobblemon.safety_goggles.tooltip": "Grants the holder immunity to powder and spore moves and damage from weather",
"item.cobblemon.scope_lens": "Scope Lens",
"item.cobblemon.scope_lens.tooltip": "Boosts the holder's critical hit ratio",
"item.cobblemon.sharp_beak": "Sharp Beak",
"item.cobblemon.sharp_beak.tooltip": "Boosts the power of the holder's Flying-type moves",
"item.cobblemon.shed_shell": "Shed Shell",
"item.cobblemon.shed_shell.tooltip": "Allows the holder to switch out in any situation",
"item.cobblemon.shell_bell": "Shell Bell",
"item.cobblemon.shell_bell.tooltip": "Heals the holder for a fraction of damage dealt every turn",
"item.cobblemon.silk_scarf": "Silk Scarf",
"item.cobblemon.silk_scarf.tooltip": "Boosts the power of the holder's Normal-type moves",
"item.cobblemon.silver_powder": "Silver Powder",
"item.cobblemon.silver_powder.tooltip": "Boosts the power of the holder's Bug-type moves",
"item.cobblemon.soft_sand": "Soft Sand",
"item.cobblemon.soft_sand.tooltip": "Boosts the power of the holder's Ground-type moves",
"item.cobblemon.soothe_bell": "Soothe Bell",
"item.cobblemon.soothe_bell.tooltip": "Boosts the holder's friendship gains",
"item.cobblemon.spell_tag": "Spell Tag",
"item.cobblemon.spell_tag.tooltip": "Boosts the power of the holder's Ghost-type moves",
"item.cobblemon.sticky_barb": "Sticky Barb",
"item.cobblemon.sticky_barb.tooltip": "Damages the holder each turn, and transfers holders when hit",
"item.cobblemon.terrain_extender": "Terrain Extender",
"item.cobblemon.terrain_extender.tooltip": "Lengthens the duration of moves and Abilities that alter the terrain of the battlefield",
"item.cobblemon.throat_spray": "Throat Spray",
"item.cobblemon.throat_spray.tooltip_1": "Raises the holder's Sp. Atk when using a sound-based move",
"item.cobblemon.throat_spray.tooltip_2": "Consumed after use",
"item.cobblemon.twisted_spoon": "Twisted Spoon",
"item.cobblemon.twisted_spoon.tooltip": "Boosts the power of the holder's Psychic-type moves",
"item.cobblemon.utility_umbrella": "Utility Umbrella",
"item.cobblemon.utility_umbrella.tooltip": "The holder is unaffected by Rain or Harsh Sunlight",
"item.cobblemon.weakness_policy": "Weakness Policy",
"item.cobblemon.weakness_policy.tooltip_1": "Boosts the holder's Attack and Sp. Atk when hit by a super-effective move",
"item.cobblemon.weakness_policy.tooltip_2": "Consumed after use",
"item.cobblemon.wide_lens": "Wide Lens",
"item.cobblemon.wide_lens.tooltip": "Boosts the holder's Accuracy",
"item.cobblemon.wise_glasses": "Wise Glasses",
"item.cobblemon.wise_glasses.tooltip": "Boosts the power of Special moves",
"item.cobblemon.zoom_lens": "Zoom Lens",
"item.cobblemon.zoom_lens.tooltip": "Boosts the holder's Accuracy",
"item.cobblemon.mental_herb": "Mental Herb",
"item.cobblemon.mental_herb.tooltip_1": "Cures the holder of infatuation and other mental effects",
"item.cobblemon.mental_herb.tooltip_2": "Consumed after use",
"item.cobblemon.mirror_herb": "Mirror Herb",
"item.cobblemon.mirror_herb.tooltip_1": "Allows the holder to mirror an opponent's stat increases to boost its own stats",
"item.cobblemon.mirror_herb.tooltip_2": "Consumed after use",
"item.cobblemon.misty_seed": "Misty Seed",
"item.cobblemon.misty_seed.tooltip": "Boosts the holder's Sp. Defense in Misty terrain",
"item.cobblemon.power_herb": "Power Herb",
"item.cobblemon.power_herb.tooltip_1": "Allows the holder to immediately use a move that normally requires a change of turn to charge",
"item.cobblemon.power_herb.tooltip_2": "Consumed after use",
"item.cobblemon.white_herb": "White Herb",
"item.cobblemon.white_herb.tooltip_1": "Restores any lowered stat in battle",
"item.cobblemon.white_herb.tooltip_2": "Consumed after use",
"item.cobblemon.bright_powder": "Bright Powder",
"item.cobblemon.bright_powder.tooltip": "Reduces the accuracy of enemy pokemon's moves by 10%",
"item.cobblemon.metal_powder": "Metal Powder",
"item.cobblemon.metal_powder.tooltip": "Raises an untransformed Ditto's Defense and Sp. Def by 50%",
"item.cobblemon.quick_powder": "Quick Powder",
"item.cobblemon.quick_powder.tooltip": "Doubles an untransformed Ditto's Speed",
"item.cobblemon.destiny_knot": "Destiny Knot",
"item.cobblemon.destiny_knot.tooltip": "If the holder become infatuated, the Pokémon that the holder is in love with becomes infatuated as well",
"item.cobblemon.power_anklet": "Power Anklet",
"item.cobblemon.power_anklet.tooltip": "Grants 8 Speed EVs when gaining experience in battle",
"item.cobblemon.power_band": "Power Band",
"item.cobblemon.power_band.tooltip": "Grants 8 Sp. Defense EVs when gaining experience in battle",
"item.cobblemon.power_belt": "Power Belt",
"item.cobblemon.power_belt.tooltip": "Grants 8 Defense EVs when gaining experience in battle",
"item.cobblemon.power_bracer": "Power Bracer",
"item.cobblemon.power_bracer.tooltip": "Grants 8 Attack EVs when gaining experience in battle",
"item.cobblemon.power_lens": "Power Lens",
"item.cobblemon.power_lens.tooltip": "Grants 8 Sp. Atk EVs when gaining experience in battle",
"item.cobblemon.power_weight": "Power Weight",
"item.cobblemon.power_weight.tooltip": "Grants 8 HP EVs when gaining experience in battle",
"item.cobblemon.psychic_seed": "Psychic Seed",
"item.cobblemon.psychic_seed.tooltip": "Boosts the holder's Sp. Defense in Psychic terrain",
"item.cobblemon.flame_orb": "Flame Orb",
"item.cobblemon.flame_orb.tooltip": "Burns the holder",
"item.cobblemon.smoke_ball": "Smoke Ball",
"item.cobblemon.smoke_ball.tooltip": "Has no effect",
"item.cobblemon.toxic_orb": "Toxic Orb",
"item.cobblemon.toxic_orb.tooltip": "Poisons the holder",
"item.cobblemon.life_orb": "Life Orb",
"item.cobblemon.life_orb.tooltip": "Boosts the power of the holder's moves, but causes recoil damage",
"item.cobblemon.damp_rock": "Damp Rock",
"item.cobblemon.damp_rock.tooltip": "Extends the duration of Rain",
"item.cobblemon.heat_rock": "Heat Rock",
"item.cobblemon.heat_rock.tooltip": "Extends the duration of Harsh Sunlight",
"item.cobblemon.smooth_rock": "Smooth Rock",
"item.cobblemon.smooth_rock.tooltip": "Extends the duration of Sandstorm",
"item.cobblemon.icy_rock": "Icy Rock",
"item.cobblemon.icy_rock.tooltip": "Extends the duration of Snow or Hail",
"item.cobblemon.poke_ball.tooltip": "1× catch rate",
"item.cobblemon.slate_ball.tooltip": "1× catch rate",
@@ -395,23 +565,59 @@
"item.cobblemon.max_elixir": "Max Elixir",
"item.cobblemon.normal_gem": "Normal Gem",
"item.cobblemon.normal_gem.tooltip_1": "Boosts the power of the holder's first Normal-type move",
"item.cobblemon.normal_gem.tooltip_2": "Consumed after use",
"item.cobblemon.water_gem": "Water Gem",
"item.cobblemon.water_gem.tooltip_1": "Boosts the power of the holder's first Water-type move",
"item.cobblemon.water_gem.tooltip_2": "Consumed after use",
"item.cobblemon.fire_gem": "Fire Gem",
"item.cobblemon.fire_gem.tooltip_1": "Boosts the power of the holder's first Fire-type move",
"item.cobblemon.fire_gem.tooltip_2": "Consumed after use",
"item.cobblemon.grass_gem": "Grass Gem",
"item.cobblemon.grass_gem.tooltip_1": "Boosts the power of the holder's first Grass-type move",
"item.cobblemon.grass_gem.tooltip_2": "Consumed after use",
"item.cobblemon.dragon_gem": "Dragon Gem",
"item.cobblemon.dragon_gem.tooltip_1": "Boosts the power of the holder's first Dragon-type move",
"item.cobblemon.dragon_gem.tooltip_2": "Consumed after use",
"item.cobblemon.ghost_gem": "Ghost Gem",
"item.cobblemon.ghost_gem.tooltip_1": "Boosts the power of the holder's first Ghost-type move",
"item.cobblemon.ghost_gem.tooltip_2": "Consumed after use",
"item.cobblemon.ground_gem": "Ground Gem",
"item.cobblemon.ground_gem.tooltip_1": "Boosts the power of the holder's first Ground-type move",
"item.cobblemon.ground_gem.tooltip_2": "Consumed after use",
"item.cobblemon.steel_gem": "Steel Gem",
"item.cobblemon.steel_gem.tooltip_1": "Boosts the power of the holder's first Steel-type move",
"item.cobblemon.steel_gem.tooltip_2": "Consumed after use",
"item.cobblemon.fairy_gem": "Fairy Gem",
"item.cobblemon.fairy_gem.tooltip_1": "Boosts the power of the holder's first Fairy-type move",
"item.cobblemon.fairy_gem.tooltip_2": "Consumed after use",
"item.cobblemon.rock_gem": "Rock Gem",
"item.cobblemon.rock_gem.tooltip_1": "Boosts the power of the holder's first Rock-type move",
"item.cobblemon.rock_gem.tooltip_2": "Consumed after use",
"item.cobblemon.psychic_gem": "Psychic Gem",
"item.cobblemon.psychic_gem.tooltip_1": "Boosts the power of the holder's first Psychic-type move",
"item.cobblemon.psychic_gem.tooltip_2": "Consumed after use",
"item.cobblemon.electric_gem": "Electric Gem",
"item.cobblemon.electric_gem.tooltip_1": "Boosts the power of the holder's first Electric-type move",
"item.cobblemon.electric_gem.tooltip_2": "Consumed after use",
"item.cobblemon.bug_gem": "Bug Gem",
"item.cobblemon.bug_gem.tooltip_1": "Boosts the power of the holder's first Bug-type move",
"item.cobblemon.bug_gem.tooltip_2": "Consumed after use",
"item.cobblemon.poison_gem": "Poison Gem",
"item.cobblemon.poison_gem.tooltip_1": "Boosts the power of the holder's first Poison-type move",
"item.cobblemon.poison_gem.tooltip_2": "Consumed after use",
"item.cobblemon.ice_gem": "Ice Gem",
"item.cobblemon.ice_gem.tooltip_1": "Boosts the power of the holder's first Ice-type move",
"item.cobblemon.ice_gem.tooltip_2": "Consumed after use",
"item.cobblemon.dark_gem": "Dark Gem",
"item.cobblemon.dark_gem.tooltip_1": "Boosts the power of the holder's first Dark-type move",
"item.cobblemon.dark_gem.tooltip_2": "Consumed after use",
"item.cobblemon.fighting_gem": "Fighting Gem",
"item.cobblemon.fighting_gem.tooltip_1": "Boosts the power of the holder's first Fighting-type move",
"item.cobblemon.fighting_gem.tooltip_2": "Consumed after use",
"item.cobblemon.flying_gem": "Flying Gem",
"item.cobblemon.flying_gem.tooltip_1": "Boosts the power of the holder's first Flying-type move",
"item.cobblemon.flying_gem.tooltip_2": "Consumed after use",
"item.cobblemon.armor_fossil": "Armor Fossil",
"item.cobblemon.fossilized_bird": "Fossilized Bird",
@@ -501,6 +707,7 @@
"block.cobblemon.apricorn_slab": "Apricorn Slab",
"block.cobblemon.apricorn_fence_gate": "Apricorn Fence Gate",
"block.cobblemon.big_root": "Big Root",
"block.cobblemon.big_root.tooltip": "Boosts the amount of HP the holder recovers from HP-stealing moves",
"block.cobblemon.black_apricorn_sapling": "Black Apricorn Sapling",
"block.cobblemon.blue_apricorn_sapling": "Blue Apricorn Sapling",
"block.cobblemon.green_apricorn_sapling": "Green Apricorn Sapling",
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "cobblemon:block/gem_bug_block"
}
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "cobblemon:block/gem_bug_budding"
}
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "cobblemon:block/gem_dark_block"
}
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "cobblemon:block/gem_dark_budding"
}
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "cobblemon:block/gem_dragon_block"
}
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "cobblemon:block/gem_dragon_budding"
}
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "cobblemon:block/gem_electric_block"
}
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "cobblemon:block/gem_electric_budding"
}
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "cobblemon:block/gem_fairy_block"
}
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "cobblemon:block/gem_fairy_budding"
}
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "cobblemon:block/gem_fighting_block"
}
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "cobblemon:block/gem_fighting_budding"
}
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "cobblemon:block/gem_fire_block"
}
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "cobblemon:block/gem_fire_budding"
}
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "cobblemon:block/gem_flying_block"
}
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "cobblemon:block/gem_flying_budding"
}
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "cobblemon:block/gem_ghost_block"
}
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "cobblemon:block/gem_ghost_budding"
}
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "cobblemon:block/gem_grass_block"
}
}
Loaded 100 of 264 files, more files were not shown because too many files have changed in this diff. Show more