forked from mirrors/cobblemon
Compare commits
108
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc0d530484 | ||
|
|
1537816132 | ||
|
|
1705639950 | ||
|
|
ce32541dd6 | ||
|
|
3ffea4f4dd | ||
|
|
f942d7c34a | ||
|
|
0f1ada4624 | ||
|
|
b4ee4629bf | ||
|
|
d0b64e2d82 | ||
|
|
1ed2042283 | ||
|
|
948ca61ef3 | ||
|
|
e60aca30ba | ||
|
|
fb5055c39e | ||
|
|
dfb5650121 | ||
|
|
8a0cbf28fe | ||
|
|
a6b9060d57 | ||
|
|
8e57995e44 | ||
|
|
1d8257808c | ||
|
|
e3582ccfb4 | ||
|
|
4c6822b1c6 | ||
|
|
2e6a4c7341 | ||
|
|
8edb5e1013 | ||
|
|
6fb139cbb9 | ||
|
|
c81c95142b | ||
|
|
afde822860 | ||
|
|
474c386535 | ||
|
|
71b9ae8dee | ||
|
|
b87b47d62a | ||
|
|
2bb85718d7 | ||
|
|
ee187d7b89 | ||
|
|
3532cac278 | ||
|
|
1447ab25b4 | ||
|
|
9a06ca78c6 | ||
|
|
f6ba70634b | ||
|
|
148fd04a93 | ||
|
|
17f60623ee | ||
|
|
c5ece27c11 | ||
|
|
296ccd1a76 | ||
|
|
82a4f71f24 | ||
|
|
08b58e2f78 | ||
|
|
62d2b8db2d | ||
|
|
3869f7ed93 | ||
|
|
c9c44872d6 | ||
|
|
cae53efedc | ||
|
|
5fac24cee8 | ||
|
|
1954dfec80 | ||
|
|
2eea2b64c2 | ||
|
|
a127a93be8 | ||
|
|
9b32f85817 | ||
|
|
ec139d2677 | ||
|
|
4327be0cf9 | ||
|
|
c25c832b31 | ||
|
|
eabaabc535 | ||
|
|
9acf97f5a0 | ||
|
|
24fc212c76 | ||
|
|
04f88bdd63 | ||
|
|
a4eb58aa57 | ||
|
|
6704d4e5ee | ||
|
|
c88087de29 | ||
|
|
86bb802140 | ||
|
|
6b644b384d | ||
|
|
c370af8914 | ||
|
|
1cd6d2bfc7 | ||
|
|
fc720916fb | ||
|
|
1edeae2a60 | ||
|
|
409f1056b9 | ||
|
|
d8c470db3d | ||
|
|
c642c4b84b | ||
|
|
0b80f7e547 | ||
|
|
d543f45607 | ||
|
|
e5699c1cdc | ||
|
|
2b4fdfd219 | ||
|
|
1a3b655d3f | ||
|
|
1f5f278970 | ||
|
|
0b4eb5239a | ||
|
|
118e8f6205 | ||
|
|
cf126c5906 | ||
|
|
645cf61911 | ||
|
|
87d5ede3dd | ||
|
|
203e5d89cd | ||
|
|
ce611cc61c | ||
|
|
f6ad7ff865 | ||
|
|
d69627a9c8 | ||
|
|
54e8763470 | ||
|
|
db34687df0 | ||
|
|
7f008d85ff | ||
|
|
06ebf51078 | ||
|
|
39c5bcd73c | ||
|
|
8f5f158b60 | ||
|
|
3bc1e35125 | ||
|
|
460bedddae | ||
|
|
8b64c315f3 | ||
|
|
7c824a2b72 | ||
|
|
f197ac5077 | ||
|
|
e0be669482 | ||
|
|
08ea21fff4 | ||
|
|
9dac604a93 | ||
|
|
8540a73885 | ||
|
|
25ce784a60 | ||
|
|
5358cccb62 | ||
|
|
698fa9dff9 | ||
|
|
a8949cf1f9 | ||
|
|
61db6334f9 | ||
|
|
46d278ca55 | ||
|
|
339038956d | ||
|
|
116a93d8cc | ||
|
|
acebc35d3f | ||
|
|
aee89f1c92 |
+59
-12
@@ -4,35 +4,82 @@
|
||||
### Additions
|
||||
- Added riding statistics: `Distance by Pokémon on Land`, `Distance by Pokémon in Air` and `Distance by Pokémon in Liquid`.
|
||||
- Added the Partner Mark, which party Pokémon have a very small chance to earn as the player walks, provided they have enough friendship.
|
||||
- Added trades for Saccharine Saplings, Hearty Grains, Chipped Pot, and Masterpiece Teacup to the Wandering Trader.
|
||||
- Added brewing recipe for Throat Spray.
|
||||
- Added new effects
|
||||
- Mental Restoration: Reduces "Time Since Last Rest" statistic, which controls Insomnia, by half a minute per second per effect level
|
||||
- Negative Effect Cleanse: Removes all negative effects
|
||||
- Effect Cleanse: Removes all effects
|
||||
- Added more seasonings for sinister tea
|
||||
- Mental Herb - Mental Restoration I for 10 seconds
|
||||
- White Herb - Negative Effect Cleanse
|
||||
- Milk - Effect Cleanse
|
||||
- Moomoo Milk - Effect Cleanse
|
||||
- Added `label` as an alternate key to the `tag` property.
|
||||
- Added Saccharine wood furniture for Adorn.
|
||||
- Added block models for existing items: Potion, Super Potion, Hyper Potion, Max Potion, Full Restore, Antidote, Awakening, Burn Heal, Ice Heal, Paralyze Heal, Full Heal, Ether, Elixir, Max Ether, Max Elixir, X Accuracy, X Attack, X Defence, X Special Attack, X Special Defence, X Speed, Dire Hit, Guard Spec, Weakness Policy, Blunder Policy, Cleanse Tag, and Spell Tag.
|
||||
- Added decorative sign blocks, Plaques.
|
||||
|
||||
### Changes
|
||||
- Ride sounds have been separated into stereo for passengers and mono for other players. Riding will now sound more spacious.
|
||||
- Added a new config option, `Enable In-Flight Dismounting` (default: off), which lets you dismount while riding a Pokémon in the air.
|
||||
- Battle AI now uses a smarter threshold for switching, reducing unnecessary switches.
|
||||
- AI will always use the most damaging move when at low HP and when it is not switching, improving endgame decision-making.
|
||||
- Added support for optional message variants in battle activate instructions for more context-specific battle text.
|
||||
- Example: `this.add('-activate', pokemon, 'ability: example', '[msg]message1');` will parse to lang key `cobblemon.battle.activate.example.message1`
|
||||
|
||||
### Fixes
|
||||
- Fixed an issue in the OmniPathNodeMaker/Navigation that prevented Combee from pathing into and out of Saccharine Leaves.
|
||||
- Fixed orientation not getting reset after crashing while flying and getting back on the Pokémon.
|
||||
- Fixed Furfrou not being trimmable on NeoForge.
|
||||
- Fixed shiny Pokémon not respecting the silent flag on spawn.
|
||||
- Fixed honey from Saccharine Leaves being harvestable at less than the max age.
|
||||
- Items given from interacting with Saccharine Leaves are placed in the active hotbar slot if possible.
|
||||
- Fix all Pokémon being saved to chunks and never despawning.
|
||||
- Fixed PokeSnacks crashing if there was no available spawn.
|
||||
- Fixed Pokémon spawn influences not being specific to regional forms
|
||||
- Fixed crashing when viewing another player in spectator mode
|
||||
- Fixed missing apricorn textures for Adorn blocks
|
||||
- Fixed crashing when riding due to malformed json file, instead resetting it
|
||||
- Fixed mochi items consuming two items at a time
|
||||
- Fixed possible error on world generation when Combee are placed in naturally generated bee nests.
|
||||
- Fixed Poké Snacks crashing if there was no available spawn.
|
||||
- Fixed Pokémon spawn influences not being specific to regional forms.
|
||||
- Fixed crashing when viewing another player in spectator mode.
|
||||
- Fixed missing apricorn textures for Adorn blocks.
|
||||
- Fixed crashing when riding due to malformed json file instead of resetting it.
|
||||
- Fixed mochi items consuming two items at a time.
|
||||
- Fix item interaction sometimes not working properly when playing on servers.
|
||||
- Fixed Soothe Bell not being properly tagged as a held item.
|
||||
- Fixed Mint Leaves not being usable for filling the Resurrection Machine.
|
||||
- Added Saccharine Boats and Saccharine Boat with Chests to relevant boat tags.
|
||||
- Fixed the `run_script` Molang function to not fail if the environment's context is null.
|
||||
- Fixed battle item duplication issue.
|
||||
- Fixed the movesets of certain Pokémon being incorrectly sanitized upon reload.
|
||||
- Fixed the ordering of Aprijuice's riding stat boosts to always have the same order.
|
||||
- Fixed the Molang functions `date_local_time`, `date_of`, `date_is_after` to use the correct date format.
|
||||
- Fixed the bottom half of pasture blocks having an incorrect hit-box when facing north or south.
|
||||
- Fixed Galarian Mr. Mime incorrectly being rideable.
|
||||
- Fixed gimmicks not being usable in double / triple battles.
|
||||
- Fixed gimmick buttons showing when already used in the same turn in double / triple battles.
|
||||
- Fixed Apricorn block model rotation for counters/sinks/cupboards/drawers to match that of most recent version of Adorn.
|
||||
- Fixed Fresh Start Mochi EV reset not syncing health changes properly.
|
||||
- Fixed requirements such as `biomeCondition` crashing the game when used to define Pokémon interactions.
|
||||
- Fixed Pokémon interactions not playing sound effects when the volume was not specified.
|
||||
- Fixed Pokémon interaction cooldowns taking longer than intended when the Pokémon was in the player’s party.
|
||||
- Fixed Pokémon interactions occasionally crashing the game when spamming an interaction with a 0 cooldown.
|
||||
- Fixed Pokémon fullness decreasing more than intended when the Pokémon was pastured.
|
||||
- Fixed crashing when sending a Pokémon out after editing its form.
|
||||
- Fixed Super Potion recipes incorrectly using Hondew Berry instead of Aguav Berry.
|
||||
- Fixed `/calculateseatpositions` expecting a locator format that even we don't use. It needs an underscore after "seat".
|
||||
- Fixed invulnerability-bypassed damage being resisted by invulnerable NPC entities.
|
||||
- Fixed selected leading Pokémon in battle not being used when levels are raised.
|
||||
- Fixed killer not being set early enough on a wild wild Pokémon entity from WinInstruction.
|
||||
|
||||
### Developer
|
||||
- Changed the `owner` parameter in the `OwnerQueryRequirement` interface from `ServerPlayer` to `Player`. This method is now also called on the client to verify whether a Pokémon interaction succeeded, so make sure to update your implementations to handle both server and client contexts.
|
||||
- Changed the `owner` parameter in the `OwnerQueryRequirement` interface from `ServerPlayer` to `Player`. This method is now also called on the client to verify whether a Pokémon interaction succeeded, so make sure to update your implementations to handle both server and client contexts.
|
||||
- Added `pnx` to the `BattleFaintedEvent` and `FormeChangeEvent`.
|
||||
- Added register methods for custom instructions to `ShowdownInterpreter`.
|
||||
- Changed callback operations in `BattlePokemon` to allow multiple callbacks and is now mutable.
|
||||
|
||||
### Molang & Datapacks
|
||||
- Ride sounds can now be set as exclusive to passengers
|
||||
- Ride sounds no longer play when submerged unless specified with a new setting
|
||||
- Ride sounds can now be set as exclusive to passengers.
|
||||
- Ride sounds no longer play when submerged unless specified with a new setting.
|
||||
- Exception handling has been added to `run_molang`, resolving some crashes caused by malformed MoLang expressions.
|
||||
|
||||
### Particles
|
||||
|
||||
### Localization
|
||||
- Updated translations for:
|
||||
- Updated translations for:
|
||||
|
||||
@@ -11,7 +11,9 @@ package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories;
|
||||
import com.cobblemon.mod.common.api.ai.config.task.PathToBeeHiveTaskConfig;
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.world.feature.SaccharineTreeFeature;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
@@ -42,7 +44,21 @@ public abstract class BeeOccupantMixin {
|
||||
if (cir.getReturnValue() == null) {
|
||||
final BeehiveBlockEntity.Occupant occupant = (BeehiveBlockEntity.Occupant) (Object) this;
|
||||
CompoundTag compoundTag = occupant.entityData().copyTag();
|
||||
Entity entity = EntityType.loadEntityRecursive(compoundTag, level, (entityx) -> entityx);
|
||||
String id = compoundTag.getString("id");
|
||||
Entity entity = null;
|
||||
if (id.equals(SaccharineTreeFeature.Companion.getPOKEMON_PLACEHOLD_ID())) {
|
||||
// Special case for Pokemon stuffed into a beenest upon world gen.
|
||||
// For technical reasons we cannot create them as full entities during world gen.
|
||||
// So we look for this special id tag and complete the entity when it attempts to exit a hive.
|
||||
if (compoundTag.contains("pokemonProperties")) {
|
||||
String properties = compoundTag.getString("pokemonProperties");
|
||||
PokemonProperties pokemon = PokemonProperties.Companion.parse(properties);
|
||||
entity = pokemon.createEntity(level);
|
||||
}
|
||||
} else {
|
||||
entity = EntityType.loadEntityRecursive(compoundTag, level, (entityx) -> entityx);
|
||||
}
|
||||
|
||||
if (entity instanceof PokemonEntity pokemonEntity) {
|
||||
var state = level.getBlockState(pos);
|
||||
var newPos = Vec3.ZERO;
|
||||
|
||||
@@ -91,7 +91,7 @@ import com.cobblemon.mod.common.pokemon.feature.SlowpokeTailRegrowthSpeciesFeatu
|
||||
import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.pokemon.properties.*
|
||||
import com.cobblemon.mod.common.pokemon.properties.tags.PokemonFlagProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.LabelProperty
|
||||
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
|
||||
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
|
||||
import com.cobblemon.mod.common.util.*
|
||||
@@ -201,6 +201,7 @@ object Cobblemon {
|
||||
implementation.registerEntityDataSerializers()
|
||||
implementation.registerCriteria()
|
||||
implementation.registerEntitySubPredicates()
|
||||
implementation.registerMobEffects()
|
||||
DispenserBehaviorRegistry.registerDispenserBehaviors()
|
||||
|
||||
DropEntry.register("command", CommandDropEntry::class.java)
|
||||
@@ -314,7 +315,7 @@ object Cobblemon {
|
||||
|
||||
CustomPokemonProperty.register(UncatchableProperty)
|
||||
CustomPokemonProperty.register(BattleCloneProperty)
|
||||
CustomPokemonProperty.register(PokemonFlagProperty)
|
||||
CustomPokemonProperty.register(LabelProperty)
|
||||
CustomPokemonProperty.register(HiddenAbilityPropertyType)
|
||||
CustomPokemonProperty.register(AspectPropertyType)
|
||||
CustomPokemonProperty.register(UnaspectPropertyType)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.api.apricorn.Apricorn
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.block.*
|
||||
import com.cobblemon.mod.common.block.campfirepot.CampfireBlock
|
||||
import com.cobblemon.mod.common.block.LecternBlock
|
||||
@@ -41,11 +42,11 @@ import net.minecraft.world.level.block.state.BlockBehaviour
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.properties.BlockSetType
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties.LIT
|
||||
import net.minecraft.world.level.block.state.properties.NoteBlockInstrument
|
||||
import net.minecraft.world.level.block.state.properties.WoodType
|
||||
import net.minecraft.world.level.material.MapColor
|
||||
import net.minecraft.world.level.material.PushReaction
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
|
||||
@Suppress("SameParameterValue", "HasPlatformType", "MemberVisibilityCanBePrivate", "unused")
|
||||
object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<Block>>, Block>() {
|
||||
@@ -243,9 +244,9 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
val REVIVAL_HERB = this.create("revival_herb", RevivalHerbBlock(BlockBehaviour.Properties.of().pushReaction(PushReaction.DESTROY).mapColor(MapColor.PLANT).ignitedByLava().noCollission().instabreak().sound(CobblemonSounds.REVIVAL_HERB_SOUNDS)))
|
||||
|
||||
@JvmField
|
||||
val POKE_CAKE = this.create("poke_cake", PokeSnackBlock(BlockBehaviour.Properties.of().forceSolidOn().strength(0.5F).sound(SoundType.WOOL).pushReaction(PushReaction.DESTROY).lightLevel { if (it.getValue(LIT)) 3 else 0 }, false))
|
||||
val POKE_CAKE = this.create("poke_cake", PokeSnackBlock(BlockBehaviour.Properties.of().forceSolidOn().strength(0.5F).sound(SoundType.WOOL).pushReaction(PushReaction.DESTROY).lightLevel { if (it.getValue(BlockStateProperties.LIT)) 3 else 0 }, false))
|
||||
@JvmField
|
||||
val POKE_SNACK = this.create("poke_snack", PokeSnackBlock(BlockBehaviour.Properties.of().forceSolidOn().strength(0.5F).sound(SoundType.WOOL).pushReaction(PushReaction.DESTROY).lightLevel { if (it.getValue(LIT)) 3 else 0 }, true))
|
||||
val POKE_SNACK = this.create("poke_snack", PokeSnackBlock(BlockBehaviour.Properties.of().forceSolidOn().strength(0.5F).sound(SoundType.WOOL).pushReaction(PushReaction.DESTROY).lightLevel { if (it.getValue(BlockStateProperties.LIT)) 3 else 0 }, true))
|
||||
|
||||
@JvmField
|
||||
val TUMBLESTONE_CLUSTER = tumblestoneBlock("tumblestone_cluster", GrowableStoneBlock.STAGE_3, 7, 3, null)
|
||||
@@ -477,6 +478,99 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val GIMMIGHOUL_CHEST = create("gimmighoul_chest", GildedChestBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS), GildedChestBlock.Type.FAKE))
|
||||
|
||||
@JvmField
|
||||
val WHITE_PLAQUE = create("white_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val LIGHT_GRAY_PLAQUE = create("light_gray_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val GRAY_PLAQUE = create("gray_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val BLACK_PLAQUE = create("black_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val BROWN_PLAQUE = create("brown_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val RED_PLAQUE = create("red_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val ORANGE_PLAQUE = create("orange_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val YELLOW_PLAQUE = create("yellow_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val LIME_PLAQUE = create("lime_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val GREEN_PLAQUE = create("green_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val CYAN_PLAQUE = create("cyan_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val LIGHT_BLUE_PLAQUE = create("light_blue_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val BLUE_PLAQUE = create("blue_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val PURPLE_PLAQUE = create("purple_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val MAGENTA_PLAQUE = create("magenta_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val PINK_PLAQUE = create("pink_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
|
||||
@JvmField
|
||||
val CLEANSE_TAG = create("cleanse_tag", WallAttachedStackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.WOOD).mapColor(MapColor.NONE).pushReaction(PushReaction.DESTROY).noOcclusion().noCollission(), WallAttachedStackableItemBlock.WallStackableItemBlockType.TAG))
|
||||
@JvmField
|
||||
val SPELL_TAG = create("spell_tag", WallAttachedStackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.WOOD).mapColor(MapColor.NONE).pushReaction(PushReaction.DESTROY).noOcclusion().noCollission(), WallAttachedStackableItemBlock.WallStackableItemBlockType.TAG))
|
||||
|
||||
@JvmField
|
||||
val BLUNDER_POLICY = create("blunder_policy", WallAttachedDirectionalShapeBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion().noCollission(), 14, 12, 1))
|
||||
@JvmField
|
||||
val WEAKNESS_POLICY = create("weakness_policy", WallAttachedDirectionalShapeBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion().noCollission(), 14, 12, 1))
|
||||
|
||||
@JvmField
|
||||
val FULL_HEAL = create("full_heal", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.STATUS_RESTORE))
|
||||
@JvmField
|
||||
val ANTIDOTE = create("antidote", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.STATUS_RESTORE))
|
||||
@JvmField
|
||||
val AWAKENING = create("awakening", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.STATUS_RESTORE))
|
||||
@JvmField
|
||||
val BURN_HEAL = create("burn_heal", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.STATUS_RESTORE))
|
||||
@JvmField
|
||||
val ICE_HEAL = create("ice_heal", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.STATUS_RESTORE))
|
||||
@JvmField
|
||||
val PARALYZE_HEAL = create("paralyze_heal", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.STATUS_RESTORE))
|
||||
|
||||
@JvmField
|
||||
val ETHER = create("ether", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.ETHER))
|
||||
@JvmField
|
||||
val MAX_ETHER = create("max_ether", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.ETHER))
|
||||
@JvmField
|
||||
val ELIXIR = create("elixir", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.ETHER))
|
||||
@JvmField
|
||||
val MAX_ELIXIR = create("max_elixir", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.ETHER))
|
||||
|
||||
@JvmField
|
||||
val POTION = create("potion", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.POTION))
|
||||
@JvmField
|
||||
val SUPER_POTION = create("super_potion", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.POTION))
|
||||
@JvmField
|
||||
val HYPER_POTION = create("hyper_potion", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.POTION))
|
||||
@JvmField
|
||||
val MAX_POTION = create("max_potion", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.MAX_POTION))
|
||||
@JvmField
|
||||
val FULL_RESTORE = create("full_restore", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.MAX_POTION))
|
||||
|
||||
@JvmField
|
||||
val DIRE_HIT = create("dire_hit", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
|
||||
@JvmField
|
||||
val GUARD_SPEC = create("guard_spec", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
|
||||
@JvmField
|
||||
val X_ACCURACY = create("x_${Stats.ACCURACY.identifier.path}", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
|
||||
@JvmField
|
||||
val X_ATTACK = create("x_${Stats.ATTACK.identifier.path}", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
|
||||
@JvmField
|
||||
val X_DEFENSE = create("x_${Stats.DEFENCE.identifier.path}", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
|
||||
@JvmField
|
||||
val X_SP_ATK = create("x_${Stats.SPECIAL_ATTACK.identifier.path}", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
|
||||
@JvmField
|
||||
val X_SP_DEF = create("x_${Stats.SPECIAL_DEFENCE.identifier.path}", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
|
||||
@JvmField
|
||||
val X_SPEED = create("x_${Stats.SPEED.identifier.path}", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
|
||||
|
||||
@JvmField
|
||||
val MONITOR = create("monitor", MonitorBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).lightLevel { if (it.getValue(MonitorBlock.SCREEN) != MonitorBlock.MonitorScreen.OFF) 13 else 0 }))
|
||||
@JvmField
|
||||
|
||||
@@ -117,6 +117,11 @@ interface CobblemonImplementation {
|
||||
|
||||
fun registerEntitySubPredicates()
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
fun registerMobEffects()
|
||||
|
||||
|
||||
/**
|
||||
* Add a feature to the current platform implementation.
|
||||
|
||||
@@ -507,6 +507,23 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField val SCROLL_OF_DARKNESS = noSettingsItem("scroll_of_darkness")
|
||||
@JvmField val SCROLL_OF_WATERS = noSettingsItem("scroll_of_waters")
|
||||
|
||||
@JvmField val WHITE_PLAQUE = blockItem("white_plaque", CobblemonBlocks.WHITE_PLAQUE)
|
||||
@JvmField val LIGHT_GRAY_PLAQUE = blockItem("light_gray_plaque", CobblemonBlocks.LIGHT_GRAY_PLAQUE)
|
||||
@JvmField val GRAY_PLAQUE = blockItem("gray_plaque", CobblemonBlocks.GRAY_PLAQUE)
|
||||
@JvmField val BLACK_PLAQUE = blockItem("black_plaque", CobblemonBlocks.BLACK_PLAQUE)
|
||||
@JvmField val BROWN_PLAQUE = blockItem("brown_plaque", CobblemonBlocks.BROWN_PLAQUE)
|
||||
@JvmField val RED_PLAQUE = blockItem("red_plaque", CobblemonBlocks.RED_PLAQUE)
|
||||
@JvmField val ORANGE_PLAQUE = blockItem("orange_plaque", CobblemonBlocks.ORANGE_PLAQUE)
|
||||
@JvmField val YELLOW_PLAQUE = blockItem("yellow_plaque", CobblemonBlocks.YELLOW_PLAQUE)
|
||||
@JvmField val LIME_PLAQUE = blockItem("lime_plaque", CobblemonBlocks.LIME_PLAQUE)
|
||||
@JvmField val GREEN_PLAQUE = blockItem("green_plaque", CobblemonBlocks.GREEN_PLAQUE)
|
||||
@JvmField val CYAN_PLAQUE = blockItem("cyan_plaque", CobblemonBlocks.CYAN_PLAQUE)
|
||||
@JvmField val LIGHT_BLUE_PLAQUE = blockItem("light_blue_plaque", CobblemonBlocks.LIGHT_BLUE_PLAQUE)
|
||||
@JvmField val BLUE_PLAQUE = blockItem("blue_plaque", CobblemonBlocks.BLUE_PLAQUE)
|
||||
@JvmField val PURPLE_PLAQUE = blockItem("purple_plaque", CobblemonBlocks.PURPLE_PLAQUE)
|
||||
@JvmField val MAGENTA_PLAQUE = blockItem("magenta_plaque", CobblemonBlocks.MAGENTA_PLAQUE)
|
||||
@JvmField val PINK_PLAQUE = blockItem("pink_plaque", CobblemonBlocks.PINK_PLAQUE)
|
||||
|
||||
private val berries = mutableMapOf<ResourceLocation, BerryItem>()
|
||||
// Plants
|
||||
@JvmField val CHERI_BERRY = berryItem("cheri", StatusCuringBerryItem(CobblemonBlocks.CHERI_BERRY, Statuses.PARALYSIS))
|
||||
@@ -699,15 +716,15 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
val MOOMOO_MILK = create("moomoo_milk", MoomooMilk(Item.Properties().craftRemainder(Items.GLASS_BOTTLE).stacksTo((16))))
|
||||
|
||||
@JvmField
|
||||
val POTION = create("potion", PotionItem(PotionType.POTION))
|
||||
val POTION = create("potion", PotionItem(PotionType.POTION, CobblemonBlocks.POTION))
|
||||
@JvmField
|
||||
val SUPER_POTION = create("super_potion", PotionItem(PotionType.SUPER_POTION))
|
||||
val SUPER_POTION = create("super_potion", PotionItem(PotionType.SUPER_POTION, CobblemonBlocks.SUPER_POTION))
|
||||
@JvmField
|
||||
val HYPER_POTION = create("hyper_potion", PotionItem(PotionType.HYPER_POTION))
|
||||
val HYPER_POTION = create("hyper_potion", PotionItem(PotionType.HYPER_POTION, CobblemonBlocks.HYPER_POTION))
|
||||
@JvmField
|
||||
val MAX_POTION = create("max_potion", PotionItem(PotionType.MAX_POTION))
|
||||
val MAX_POTION = create("max_potion", PotionItem(PotionType.MAX_POTION, CobblemonBlocks.MAX_POTION))
|
||||
@JvmField
|
||||
val FULL_RESTORE = create("full_restore", PotionItem(PotionType.FULL_RESTORE))
|
||||
val FULL_RESTORE = create("full_restore", PotionItem(PotionType.FULL_RESTORE, CobblemonBlocks.FULL_RESTORE))
|
||||
|
||||
@JvmField
|
||||
val HEAL_POWDER = create("heal_powder", HealPowderItem())
|
||||
@@ -792,28 +809,27 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val SERIOUS_MINT = mintItem("serious_mint", MintItem(Natures.SERIOUS))
|
||||
|
||||
@JvmField val X_ACCURACY = create("x_${Stats.ACCURACY.identifier.path}", XStatItem(Stats.ACCURACY))
|
||||
@JvmField val X_ATTACK = create("x_${Stats.ATTACK.identifier.path}", XStatItem(Stats.ATTACK))
|
||||
@JvmField val X_DEFENSE = create("x_${Stats.DEFENCE.identifier.path}", XStatItem(Stats.DEFENCE))
|
||||
@JvmField val X_SP_ATK = create("x_${Stats.SPECIAL_ATTACK.identifier.path}", XStatItem(Stats.SPECIAL_ATTACK))
|
||||
@JvmField val X_SP_DEF = create("x_${Stats.SPECIAL_DEFENCE.identifier.path}", XStatItem(Stats.SPECIAL_DEFENCE))
|
||||
@JvmField val X_SPEED = create("x_${Stats.SPEED.identifier.path}", XStatItem(Stats.SPEED))
|
||||
@JvmField val X_ACCURACY = create("x_${Stats.ACCURACY.identifier.path}", XStatItem(Stats.ACCURACY, block = CobblemonBlocks.X_ACCURACY))
|
||||
@JvmField val X_ATTACK = create("x_${Stats.ATTACK.identifier.path}", XStatItem(Stats.ATTACK, block = CobblemonBlocks.X_ATTACK))
|
||||
@JvmField val X_DEFENSE = create("x_${Stats.DEFENCE.identifier.path}", XStatItem(Stats.DEFENCE, block = CobblemonBlocks.X_DEFENSE))
|
||||
@JvmField val X_SP_ATK = create("x_${Stats.SPECIAL_ATTACK.identifier.path}", XStatItem(Stats.SPECIAL_ATTACK, block = CobblemonBlocks.X_SP_ATK))
|
||||
@JvmField val X_SP_DEF = create("x_${Stats.SPECIAL_DEFENCE.identifier.path}", XStatItem(Stats.SPECIAL_DEFENCE, block = CobblemonBlocks.X_SP_DEF))
|
||||
@JvmField val X_SPEED = create("x_${Stats.SPEED.identifier.path}", XStatItem(Stats.SPEED, block = CobblemonBlocks.X_SPEED))
|
||||
|
||||
@JvmField val DIRE_HIT = create("dire_hit", DireHitItem())
|
||||
@JvmField val GUARD_SPEC = create("guard_spec", GuardSpecItem())
|
||||
@JvmField val DIRE_HIT = create("dire_hit", DireHitItem(CobblemonBlocks.DIRE_HIT))
|
||||
@JvmField val GUARD_SPEC = create("guard_spec", GuardSpecItem(CobblemonBlocks.GUARD_SPEC))
|
||||
|
||||
@JvmField val BURN_HEAL = create("burn_heal", StatusCureItem("item.cobblemon.burn_heal", Statuses.BURN))
|
||||
@JvmField val PARALYZE_HEAL = create("paralyze_heal", StatusCureItem("item.cobblemon.paralyze_heal", Statuses.PARALYSIS))
|
||||
@JvmField val ICE_HEAL = create("ice_heal", StatusCureItem("item.cobblemon.ice_heal", Statuses.FROZEN))
|
||||
@JvmField val ANTIDOTE = create("antidote", StatusCureItem("item.cobblemon.antidote", Statuses.POISON, Statuses.POISON_BADLY))
|
||||
@JvmField val AWAKENING = create("awakening", StatusCureItem("item.cobblemon.awakening", Statuses.SLEEP))
|
||||
@JvmField val FULL_HEAL = create("full_heal", StatusCureItem("item.cobblemon.full_heal", block = CobblemonBlocks.FULL_HEAL))
|
||||
@JvmField val ANTIDOTE = create("antidote", StatusCureItem("item.cobblemon.antidote", Statuses.POISON, Statuses.POISON_BADLY, block = CobblemonBlocks.ANTIDOTE))
|
||||
@JvmField val AWAKENING = create("awakening", StatusCureItem("item.cobblemon.awakening", Statuses.SLEEP, block = CobblemonBlocks.AWAKENING))
|
||||
@JvmField val BURN_HEAL = create("burn_heal", StatusCureItem("item.cobblemon.burn_heal", Statuses.BURN, block = CobblemonBlocks.BURN_HEAL))
|
||||
@JvmField val ICE_HEAL = create("ice_heal", StatusCureItem("item.cobblemon.ice_heal", Statuses.FROZEN, block = CobblemonBlocks.ICE_HEAL))
|
||||
@JvmField val PARALYZE_HEAL = create("paralyze_heal", StatusCureItem("item.cobblemon.paralyze_heal", Statuses.PARALYSIS, block = CobblemonBlocks.PARALYZE_HEAL))
|
||||
|
||||
@JvmField val FULL_HEAL = create("full_heal", StatusCureItem("item.cobblemon.full_heal"))
|
||||
|
||||
@JvmField val ETHER = create("ether", EtherItem(max = false))
|
||||
@JvmField val MAX_ETHER = create("max_ether", EtherItem(max = true))
|
||||
@JvmField val ELIXIR = create("elixir", ElixirItem(max = false))
|
||||
@JvmField val MAX_ELIXIR = create("max_elixir", ElixirItem(max = true))
|
||||
@JvmField val ETHER = create("ether", EtherItem(max = false, CobblemonBlocks.ETHER))
|
||||
@JvmField val MAX_ETHER = create("max_ether", EtherItem(max = true, CobblemonBlocks.MAX_ETHER))
|
||||
@JvmField val ELIXIR = create("elixir", ElixirItem(max = false, CobblemonBlocks.ELIXIR))
|
||||
@JvmField val MAX_ELIXIR = create("max_elixir", ElixirItem(max = true, CobblemonBlocks.MAX_ELIXIR))
|
||||
|
||||
@JvmField
|
||||
val ABILITY_CAPSULE = this.create("ability_capsule", AbilityChangeItem(AbilityChanger.COMMON_ABILITY))
|
||||
@@ -922,7 +938,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val BLACK_SLUDGE = heldItem("black_sludge")
|
||||
@JvmField
|
||||
val BLUNDER_POLICY = heldItem("blunder_policy")
|
||||
val BLUNDER_POLICY = itemNameBlockItem("blunder_policy", CobblemonBlocks.BLUNDER_POLICY)
|
||||
@JvmField
|
||||
val CELL_BATTERY = heldItem("cell_battery")
|
||||
@JvmField
|
||||
@@ -930,7 +946,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val CHOICE_SCARF = heldItem("choice_scarf")
|
||||
@JvmField
|
||||
val CLEANSE_TAG = heldItem("cleanse_tag")
|
||||
val CLEANSE_TAG = itemNameBlockItem("cleanse_tag", CobblemonBlocks.CLEANSE_TAG)
|
||||
@JvmField
|
||||
val CLEAR_AMULET = heldItem("clear_amulet")
|
||||
@JvmField
|
||||
@@ -1038,7 +1054,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val SOFT_SAND = heldItem("soft_sand")
|
||||
@JvmField
|
||||
val SPELL_TAG = heldItem("spell_tag")
|
||||
val SPELL_TAG = itemNameBlockItem("spell_tag", CobblemonBlocks.SPELL_TAG)
|
||||
@JvmField
|
||||
val SMOKE_BALL = heldItem("smoke_ball")
|
||||
@JvmField
|
||||
@@ -1056,7 +1072,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val UTILITY_UMBRELLA = heldItem("utility_umbrella")
|
||||
@JvmField
|
||||
val WEAKNESS_POLICY = heldItem("weakness_policy")
|
||||
val WEAKNESS_POLICY = itemNameBlockItem("weakness_policy", CobblemonBlocks.WEAKNESS_POLICY)
|
||||
@JvmField
|
||||
val WIDE_LENS = heldItem("wide_lens")
|
||||
@JvmField
|
||||
@@ -1553,6 +1569,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
private fun heldItem(name: String, item: Item, remappedName: String? = null) = create(
|
||||
name = name,
|
||||
entry = item.also {
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import com.cobblemon.mod.common.api.cooking.effects.CleanseAllEffect
|
||||
import com.cobblemon.mod.common.api.cooking.effects.CleanseNegativeEffect
|
||||
import com.cobblemon.mod.common.api.cooking.effects.MentalRestorationEffect
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
|
||||
object CobblemonMobEffects : PlatformRegistry<Registry<MobEffect>, ResourceKey<Registry<MobEffect>>, MobEffect>() {
|
||||
override val registry: Registry<MobEffect> = BuiltInRegistries.MOB_EFFECT
|
||||
override val resourceKey: ResourceKey<Registry<MobEffect>> = Registries.MOB_EFFECT
|
||||
|
||||
@JvmField
|
||||
val CLEANSE_NEGATIVE = create("cleanse_negative", CleanseNegativeEffect())
|
||||
|
||||
@JvmField
|
||||
val MENTAL_RESTORATION = create("mental_restoration", MentalRestorationEffect())
|
||||
|
||||
@JvmField
|
||||
val CLEANSE_ALL = create("cleanse_all", CleanseAllEffect())
|
||||
}
|
||||
@@ -304,7 +304,8 @@ open class PokemonBattle(
|
||||
.forEach{it.pokemon.heal()}
|
||||
actors.forEach { actor ->
|
||||
actor.pokemonList.forEach { battlePokemon ->
|
||||
battlePokemon.entity?.let { entity -> battlePokemon.postBattleEntityOperation(entity) }
|
||||
battlePokemon.postBattlePokemonOperations.forEach { it(battlePokemon) }
|
||||
battlePokemon.entity?.let { entity -> battlePokemon.postBattleEntityOperations.forEach { it(entity) } }
|
||||
if (battlePokemon.effectedPokemon.entity != null
|
||||
&& battlePokemon.effectedPokemon.entity?.beamMode == 0
|
||||
&& battlePokemon.effectedPokemon.entity?.platform != PlatformType.NONE) {
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cooking.effects
|
||||
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
import net.minecraft.world.effect.MobEffectCategory
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
class CleanseAllEffect : MobEffect(MobEffectCategory.BENEFICIAL, 0xFFFFFF) {
|
||||
override fun isInstantenous() = true
|
||||
override fun applyInstantenousEffect(source: Entity?, indirect: Entity?, target: LivingEntity, amplifier: Int, proximity: Double) {
|
||||
target.removeAllEffects()
|
||||
}
|
||||
override fun shouldApplyEffectTickThisTick(duration: Int, amplifier: Int) = false
|
||||
}
|
||||
+27
@@ -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.cooking.effects
|
||||
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
import net.minecraft.world.effect.MobEffectCategory
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
class CleanseNegativeEffect : MobEffect(MobEffectCategory.BENEFICIAL, 0xFFFFFF) {
|
||||
override fun isInstantenous() = true
|
||||
override fun applyInstantenousEffect(source: Entity?, indirect: Entity?, target: LivingEntity, amplifier: Int, proximity: Double) {
|
||||
val snapshot = target.activeEffects.toList()
|
||||
for (ei in snapshot) {
|
||||
if (ei.effect.value().category == MobEffectCategory.HARMFUL) {
|
||||
target.removeEffect(ei.effect)
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun shouldApplyEffectTickThisTick(duration: Int, amplifier: Int) = false
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.cooking.effects
|
||||
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.stats.Stats
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
import net.minecraft.world.effect.MobEffectCategory
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
class MentalRestorationEffect : MobEffect(MobEffectCategory.BENEFICIAL, 0xAA66FF) {
|
||||
override fun applyEffectTick(entity: LivingEntity, amplifier: Int): Boolean {
|
||||
if (entity is ServerPlayer) {
|
||||
val stats = entity.stats
|
||||
val statType = Stats.CUSTOM.get(Stats.TIME_SINCE_REST)
|
||||
val current = stats.getValue(statType)
|
||||
val reduction = 31 * (amplifier + 1)// reduce by half a minute every second per level (30 ticks removed per tick + 1 to account for the tick passing)
|
||||
val newValue = Math.max(current - reduction, 0)
|
||||
stats.setValue(entity, statType, newValue)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun shouldApplyEffectTickThisTick(duration: Int, amplifier: Int): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
+6
-3
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.events.battles
|
||||
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleContext
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
@@ -25,7 +26,8 @@ import com.cobblemon.mod.common.util.asArrayValue
|
||||
data class BattleFaintedEvent(
|
||||
override val battle: PokemonBattle,
|
||||
val killed: BattlePokemon,
|
||||
val context: BattleContext
|
||||
val context: BattleContext,
|
||||
val pnx: String
|
||||
) : BattleEvent {
|
||||
val structContext = mutableMapOf<String, MoValue>(
|
||||
"battle" to battle.struct,
|
||||
@@ -33,6 +35,7 @@ data class BattleFaintedEvent(
|
||||
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
|
||||
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct },
|
||||
"pokemon" to killed.struct,
|
||||
"context" to context.getStruct()
|
||||
"context" to context.getStruct(),
|
||||
"pnx" to StringValue(pnx)
|
||||
)
|
||||
}
|
||||
}
|
||||
+5
-3
@@ -25,7 +25,8 @@ import com.cobblemon.mod.common.util.asArrayValue
|
||||
data class FormeChangeEvent(
|
||||
override val battle: PokemonBattle,
|
||||
val pokemon: BattlePokemon,
|
||||
val formeName: String
|
||||
val formeName: String,
|
||||
val pnx: String
|
||||
) : BattleEvent {
|
||||
val context = mutableMapOf(
|
||||
"battle" to battle.struct,
|
||||
@@ -33,6 +34,7 @@ data class FormeChangeEvent(
|
||||
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
|
||||
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct },
|
||||
"pokemon" to pokemon.struct,
|
||||
"forme" to StringValue(formeName)
|
||||
"forme" to StringValue(formeName),
|
||||
"pnx" to StringValue(pnx)
|
||||
)
|
||||
}
|
||||
}
|
||||
+11
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.interaction
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
@@ -29,6 +30,11 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.util.LowerCaseEnumTypeAdapterFactory
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.level.biome.Biome
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.levelgen.structure.Structure
|
||||
import net.minecraft.world.level.material.Fluid
|
||||
|
||||
object PokemonInteractions : JsonDataRegistry<PokemonInteractionSet> {
|
||||
override val id = cobblemonResource("pokemon_interactions")
|
||||
@@ -43,6 +49,11 @@ object PokemonInteractions : JsonDataRegistry<PokemonInteractionSet> {
|
||||
.registerTypeAdapter(Requirement::class.java, CobblemonRequirementAdapter)
|
||||
.registerTypeAdapter(InteractionEffect::class.java, InteractionEffectAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, BiomeLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Block::class.java).type, BlockLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Structure::class.java).type, StructureLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Fluid::class.java).type, FluidLikeConditionAdapter)
|
||||
.registerTypeAdapter(IntRange::class.java, IntRangeAdapter)
|
||||
.registerTypeAdapterFactory(LowerCaseEnumTypeAdapterFactory())
|
||||
.setPrettyPrinting()
|
||||
|
||||
+19
-4
@@ -17,6 +17,7 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
|
||||
import com.cobblemon.mod.common.pokemon.adapters.CobblemonRequirementAdapter
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
@@ -143,11 +144,12 @@ class GiveItemEffect(val item: ResourceLocation, val amount: IntRange?) : Intera
|
||||
class PlaySoundEffect(
|
||||
val sound: ResourceLocation,
|
||||
val soundSource: SoundSource?,
|
||||
val playAround: Boolean = true,
|
||||
val distance: Double = 64.0,
|
||||
val volume: Float = 1.0F,
|
||||
val pitch: Float = 1.0F
|
||||
@SerializedName("playAround") private val _playAround: Boolean?,
|
||||
@SerializedName("distance") private val _distance: Double?,
|
||||
@SerializedName("volume") private val _volume: Float?,
|
||||
@SerializedName("pitch") private val _pitch: Float?,
|
||||
) : InteractionEffect {
|
||||
|
||||
override fun applyEffect(
|
||||
pokemon: PokemonEntity,
|
||||
player: ServerPlayer
|
||||
@@ -161,6 +163,7 @@ class PlaySoundEffect(
|
||||
volume,
|
||||
pitch
|
||||
)
|
||||
|
||||
if (playAround) {
|
||||
packet.sendToPlayersAround(pokemon.x, pokemon.y, pokemon.z, distance, pokemon.level().dimension())
|
||||
} else {
|
||||
@@ -168,6 +171,18 @@ class PlaySoundEffect(
|
||||
}
|
||||
}
|
||||
|
||||
val playAround: Boolean
|
||||
get() = _playAround != false
|
||||
|
||||
val distance: Double
|
||||
get() = _distance ?: 64.0
|
||||
|
||||
val volume: Float
|
||||
get() = _volume ?: 1.0F
|
||||
|
||||
val pitch: Float
|
||||
get() = _pitch ?: 1.0F
|
||||
|
||||
companion object {
|
||||
val ID = "play_sound"
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ object MoLangFunctions {
|
||||
runtime.environment.variable = params.environment.variable
|
||||
val args = params.params.subList(1, params.params.size)
|
||||
runtime.environment.context = ContextStruct(
|
||||
params.environment.context.map + args.mapIndexed { index, value -> "arg_${index + 1}" to value }.toMap()
|
||||
(params.environment.context?.map ?: emptyMap()) + args.mapIndexed { index, value -> "arg_${index + 1}" to value }.toMap()
|
||||
)
|
||||
val script = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
// store the args in the
|
||||
@@ -324,13 +324,24 @@ object MoLangFunctions {
|
||||
runtime.environment.context = params.environment.context
|
||||
val expression = params.getString(0).asExpressionLike()
|
||||
val delayInSeconds = params.getDoubleOrNull(1)?.toFloat() ?: 0.0f
|
||||
|
||||
fun evaluate(): MoValue {
|
||||
return try {
|
||||
runtime.resolve(expression)
|
||||
} catch (ex: Exception) {
|
||||
Cobblemon.LOGGER.warn("Failed to evaluate MoLang expression${if (delayInSeconds > 0.0f) " (delayed)" else ""}: $expression", ex)
|
||||
DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
|
||||
if (delayInSeconds > 0.0f) {
|
||||
val tracker = if (Cobblemon.implementation.environment() == Environment.SERVER) ServerTaskTracker else ClientTaskTracker
|
||||
tracker.after(delayInSeconds) {
|
||||
runtime.resolve(expression)
|
||||
evaluate()
|
||||
}
|
||||
DoubleValue.ONE
|
||||
} else {
|
||||
runtime.resolve(expression)
|
||||
evaluate()
|
||||
}
|
||||
},
|
||||
"system_time_millis" to java.util.function.Function { _ ->
|
||||
@@ -340,19 +351,19 @@ object MoLangFunctions {
|
||||
"date_local_time" to java.util.function.Function { _ ->
|
||||
val time = System.currentTimeMillis()
|
||||
val date = java.util.Date(time)
|
||||
val formatted = java.text.SimpleDateFormat("DD/MM/YYYY").format(date)
|
||||
val formatted = java.text.SimpleDateFormat("dd/MM/yyyy").format(date)
|
||||
StringValue(formatted)
|
||||
},
|
||||
"date_of" to java.util.function.Function { params ->
|
||||
val time = params.getDouble(0).toLong()
|
||||
val date = java.util.Date(time)
|
||||
val formatted = java.text.SimpleDateFormat("DD/MM/YYYY").format(date)
|
||||
val formatted = java.text.SimpleDateFormat("dd/MM/yyyy").format(date)
|
||||
StringValue(formatted)
|
||||
},
|
||||
"date_is_after" to java.util.function.Function { params ->
|
||||
val dateA = params.getString(0)
|
||||
val dateB = params.getString(1)
|
||||
val format = java.text.SimpleDateFormat("DD/MM/YYYY")
|
||||
val format = java.text.SimpleDateFormat("dd/MM/yyyy")
|
||||
val a = format.parse(dateA)
|
||||
val b = format.parse(dateB)
|
||||
DoubleValue(a.after(b))
|
||||
|
||||
+10
-8
@@ -80,7 +80,9 @@ open class ChoiceSpeciesFeatureProvider(
|
||||
|
||||
internal constructor(): this(emptyList())
|
||||
|
||||
override fun get(pokemon: Pokemon) = pokemon.getFeature<StringSpeciesFeature>(keys.first())
|
||||
override fun get(pokemon: Pokemon): StringSpeciesFeature? {
|
||||
return pokemon.features.filterIsInstance<StringSpeciesFeature>().find { it.name in keys }
|
||||
}
|
||||
|
||||
override fun invoke(pokemon: Pokemon): StringSpeciesFeature? {
|
||||
val existing = get(pokemon)
|
||||
@@ -101,15 +103,15 @@ open class ChoiceSpeciesFeatureProvider(
|
||||
}
|
||||
|
||||
override fun invoke(nbt: CompoundTag): StringSpeciesFeature? {
|
||||
return if (nbt.contains(keys.first())) {
|
||||
StringSpeciesFeature(keys.first(), "").also { it.loadFromNBT(nbt) }
|
||||
} else null
|
||||
val key = keys.find { nbt.contains(it) }
|
||||
if (key == null) return null
|
||||
return StringSpeciesFeature(key, "").also { it.loadFromNBT(nbt) }
|
||||
}
|
||||
|
||||
override fun invoke(json: JsonObject): StringSpeciesFeature? {
|
||||
return if (json.has(keys.first())) {
|
||||
StringSpeciesFeature(keys.first(), "").also { it.loadFromJSON(json) }
|
||||
} else null
|
||||
val key = keys.find { json.has(it) }
|
||||
if (key == null) return null
|
||||
return StringSpeciesFeature(key, "").also { it.loadFromJSON(json) }
|
||||
}
|
||||
|
||||
override fun fromString(value: String?): StringSpeciesFeature? {
|
||||
@@ -131,7 +133,7 @@ open class ChoiceSpeciesFeatureProvider(
|
||||
|
||||
override fun provide(properties: PokemonProperties): Set<String> {
|
||||
return if (isAspect) {
|
||||
val feature = properties.customProperties.filterIsInstance<StringSpeciesFeature>().find { it.name == keys.first() }
|
||||
val feature = properties.customProperties.filterIsInstance<StringSpeciesFeature>().find { it.name in keys }
|
||||
if (feature != null) {
|
||||
setOf(getAspect(feature))
|
||||
} else {
|
||||
|
||||
+23
-11
@@ -132,7 +132,9 @@ class FlagSpeciesFeatureProvider : SynchronizedSpeciesFeatureProvider<FlagSpecie
|
||||
|
||||
constructor(vararg keys: String) : this(keys.toList())
|
||||
|
||||
override fun get(pokemon: Pokemon) = pokemon.getFeature<FlagSpeciesFeature>(keys.first())
|
||||
override fun get(pokemon: Pokemon): FlagSpeciesFeature? {
|
||||
return pokemon.features.filterIsInstance<FlagSpeciesFeature>().find { it.name in keys }
|
||||
}
|
||||
|
||||
override fun invoke(pokemon: Pokemon): FlagSpeciesFeature? {
|
||||
return get(pokemon)
|
||||
@@ -144,15 +146,15 @@ class FlagSpeciesFeatureProvider : SynchronizedSpeciesFeatureProvider<FlagSpecie
|
||||
}
|
||||
|
||||
override fun invoke(nbt: CompoundTag): FlagSpeciesFeature? {
|
||||
return if (nbt.contains(keys.first())) {
|
||||
FlagSpeciesFeature(keys.first(), false).also { it.loadFromNBT(nbt) }
|
||||
} else null
|
||||
val key = keys.find { nbt.contains(it) }
|
||||
if (key == null) return null
|
||||
return FlagSpeciesFeature(key, false).also { it.loadFromNBT(nbt) }
|
||||
}
|
||||
|
||||
override fun invoke(json: JsonObject): FlagSpeciesFeature? {
|
||||
return if (json.has(keys.first())) {
|
||||
FlagSpeciesFeature(keys.first(), false).also { it.loadFromJSON(json) }
|
||||
} else null
|
||||
val key = keys.find { json.has(it) }
|
||||
if (key == null) return null
|
||||
return FlagSpeciesFeature(key, false).also { it.loadFromJSON(json) }
|
||||
}
|
||||
|
||||
override fun fromString(value: String?): FlagSpeciesFeature? {
|
||||
@@ -170,16 +172,26 @@ class FlagSpeciesFeatureProvider : SynchronizedSpeciesFeatureProvider<FlagSpecie
|
||||
}
|
||||
|
||||
override fun provide(pokemon: Pokemon): Set<String> {
|
||||
return if (isAspect && pokemon.getFeature<FlagSpeciesFeature>(keys.first())?.enabled == true) {
|
||||
setOf(keys.first())
|
||||
return if (isAspect) {
|
||||
val feature = pokemon.features.filterIsInstance<FlagSpeciesFeature>().find { it.name in keys }
|
||||
if (feature != null && feature.enabled) {
|
||||
setOf(keys.first())
|
||||
} else {
|
||||
emptySet()
|
||||
}
|
||||
} else {
|
||||
emptySet()
|
||||
}
|
||||
}
|
||||
|
||||
override fun provide(properties: PokemonProperties): Set<String> {
|
||||
return if (isAspect && properties.customProperties.filterIsInstance<FlagSpeciesFeature>().find { it.name == keys.first() }?.enabled == true) {
|
||||
setOf(keys.first())
|
||||
return if (isAspect) {
|
||||
val feature = properties.customProperties.filterIsInstance<FlagSpeciesFeature>().find { it.name in keys }
|
||||
if (feature != null && feature.enabled) {
|
||||
setOf(keys.first())
|
||||
} else {
|
||||
emptySet()
|
||||
}
|
||||
} else {
|
||||
emptySet()
|
||||
}
|
||||
|
||||
+6
-10
@@ -142,19 +142,15 @@ class IntSpeciesFeatureProvider : SynchronizedSpeciesFeatureProvider<IntSpeciesF
|
||||
}
|
||||
|
||||
override fun invoke(nbt: CompoundTag): IntSpeciesFeature? {
|
||||
return if (nbt.contains(keys.first())) {
|
||||
IntSpeciesFeature(keys.first(), nbt.getInt(keys.first()))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val key = keys.find { nbt.contains(it) }
|
||||
if (key == null) return null
|
||||
return IntSpeciesFeature(keys.first(), nbt.getInt(key));
|
||||
}
|
||||
|
||||
override fun invoke(json: JsonObject): IntSpeciesFeature? {
|
||||
return if (json.has(keys.first())) {
|
||||
IntSpeciesFeature(keys.first(), json.get(keys.first()).asInt)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val key = keys.find { json.has(it) }
|
||||
if (key == null) return null
|
||||
return IntSpeciesFeature(keys.first(), json.get(key).asInt)
|
||||
}
|
||||
|
||||
override fun get(pokemon: Pokemon) = pokemon.features.filterIsInstance<IntSpeciesFeature>().find { it.name in keys }
|
||||
|
||||
@@ -102,6 +102,12 @@ object SpeciesFeatures : JsonDataRegistry<SpeciesFeatureProvider<*>> {
|
||||
|
||||
@JvmStatic
|
||||
fun register(name: String, provider: SpeciesFeatureProvider<*>) = register(name, provider, isCoded = true)
|
||||
|
||||
@JvmStatic
|
||||
fun registerType(key: String, clazz: Class<out SpeciesFeatureProvider<*>>) {
|
||||
types[key] = clazz
|
||||
}
|
||||
|
||||
private fun registerFromAssets(identifier: ResourceLocation, provider: SpeciesFeatureProvider<*>) = register(identifier.path, provider, isCoded = false)
|
||||
|
||||
@JvmStatic
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.api.reactive
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
|
||||
open class EventObservable<T> : SimpleObservable<T>() {
|
||||
@JvmOverloads
|
||||
inline fun post(vararg events: T, then: (T) -> Unit = {}) {
|
||||
// Issuing generic-typed pass-throughs to varargs doesn't work
|
||||
// properly unless the source is a vararg as well, complicated story.
|
||||
|
||||
@@ -258,17 +258,22 @@ open class PartyStore(override val uuid: UUID) : PokemonStore<PartyPosition>() {
|
||||
|
||||
@JvmOverloads
|
||||
fun toBattleTeam(clone: Boolean = false, healPokemon: Boolean = false, leadingPokemon: UUID? = null) : List<BattlePokemon> {
|
||||
var leadingPokemonId = leadingPokemon
|
||||
val result = this.mapNotNull {
|
||||
return@mapNotNull if (clone) {
|
||||
BattlePokemon.safeCopyOf(it)
|
||||
BattlePokemon.safeCopyOf(it).also { copy ->
|
||||
if (leadingPokemon != null && it.uuid == leadingPokemonId) {
|
||||
leadingPokemonId = copy.uuid
|
||||
}
|
||||
}
|
||||
} else {
|
||||
BattlePokemon.playerOwned(it)
|
||||
}.also { if (healPokemon) it.effectedPokemon.heal() }
|
||||
}.toMutableList()
|
||||
|
||||
// reposition lead to front of the party
|
||||
if (leadingPokemon != null && result.first().uuid != leadingPokemon) {
|
||||
result.find { it.uuid == leadingPokemon }?.let { lead ->
|
||||
if (leadingPokemonId != null && result.first().uuid != leadingPokemonId) {
|
||||
result.find { it.uuid == leadingPokemonId }?.let { lead ->
|
||||
result.remove(lead)
|
||||
result.add(0, lead)
|
||||
}
|
||||
|
||||
+2
-2
@@ -154,12 +154,12 @@ open class PlayerPartyStore(
|
||||
|
||||
// Metabolism for Fullness
|
||||
if (pokemon.currentFullness > 0) {
|
||||
pokemon.tickMetabolism()
|
||||
pokemon.tickMetabolism(20)
|
||||
}
|
||||
|
||||
// Interaction Cooldown
|
||||
if (pokemon.interactionCooldowns.any()) {
|
||||
pokemon.tickInteractionCooldown()
|
||||
pokemon.tickInteractionCooldown(20)
|
||||
}
|
||||
|
||||
pokemon.features.filterIsInstance<TickingSpeciesFeature>().forEach { it.onSecondPassed(player.serverLevel(), pokemon, null) }
|
||||
|
||||
@@ -42,6 +42,7 @@ object CobblemonItemTags {
|
||||
@JvmField val DAWN_STONE_ORES = create("dawn_stone_ores")
|
||||
@JvmField val POTTERY_SHERDS = create("decorated_pot_sherds")
|
||||
@JvmField val DEEP_SEAS = create("deep_seas")
|
||||
@JvmField val DISPLAY_CASE_ITEMS = create("display_case_items")
|
||||
@JvmField val DUSK_STONE_ORES = create("dusk_stone_ores")
|
||||
@JvmField val ETHERS = create("ethers")
|
||||
@JvmField val EVOLUTION_ITEMS = create("evolution_items")
|
||||
@@ -57,6 +58,7 @@ object CobblemonItemTags {
|
||||
@JvmField val HANGING_SIGNS = create("hanging_signs")
|
||||
@JvmField val HERBS = create("herbs")
|
||||
@JvmField val ICE_STONE_ORES = create("ice_stone_ores")
|
||||
@JvmField val ITEM_BLOCKS = create("item_blocks")
|
||||
@JvmField val LEAF_STONE_ORES = create("leaf_stone_ores")
|
||||
@JvmField val MACHINES = create("machines")
|
||||
@JvmField val MINT_LEAF = create("mint_leaf")
|
||||
@@ -65,6 +67,7 @@ object CobblemonItemTags {
|
||||
@JvmField val MOCHIS = create("mochis")
|
||||
@JvmField val MOON_STONE_ORES = create("moon_stone_ores")
|
||||
@JvmField val MUTATED_BERRIES = create("mutated_berries")
|
||||
@JvmField val PLAQUES = create("plaques")
|
||||
@JvmField val PLANTS = create("plants")
|
||||
@JvmField val POKE_BALLS = create("poke_balls")
|
||||
@JvmField val POKE_RODS = create("poke_rods")
|
||||
|
||||
@@ -63,8 +63,8 @@ object BattleBuilder {
|
||||
): BattleStartResult {
|
||||
|
||||
val adjustLevel = battleFormat.adjustLevel
|
||||
val team1 = partyAccessor(player1).toBattleTeam(clone = cloneParties || adjustLevel > 0, healPokemon = healFirst, leadingPokemonPlayer1).sortedBy { it.health <= 0 }
|
||||
val team2 = partyAccessor(player2).toBattleTeam(clone = cloneParties || adjustLevel > 0, healPokemon = healFirst, leadingPokemonPlayer2).sortedBy { it.health <= 0 }
|
||||
val team1 = partyAccessor(player1).toBattleTeam(clone = cloneParties || adjustLevel > 0, healPokemon = healFirst, leadingPokemonPlayer1)
|
||||
val team2 = partyAccessor(player2).toBattleTeam(clone = cloneParties || adjustLevel > 0, healPokemon = healFirst, leadingPokemonPlayer2)
|
||||
|
||||
val battlePartyStores = mutableListOf<PlayerPartyStore>()
|
||||
|
||||
|
||||
@@ -105,12 +105,18 @@ data class BattleFormat(
|
||||
}
|
||||
|
||||
fun toFormatJSON(): String {
|
||||
/*
|
||||
Bag clause does not exist in showdown as a rule because showdown simply has no concept of a 'bag'.
|
||||
If we try sending it, the battle will error. So this simply omits that from ever getting sent.
|
||||
If we ever find a case where we are doing this for more than just bag clause, we should make a proper abstraction.
|
||||
*/
|
||||
val rulesToSendToShowdown = ruleSet.filter { it != BattleRules.BAG_CLAUSE }
|
||||
return """
|
||||
{
|
||||
"mod": "$mod",
|
||||
"gameType": "${battleType.name}",
|
||||
"gen": $gen,
|
||||
"ruleset": [${ruleSet.joinToString { "\"$it\"" }}],
|
||||
"ruleset": [${rulesToSendToShowdown.joinToString { "\"$it\"" }}],
|
||||
"effectType": "Format"
|
||||
}
|
||||
""".trimIndent().replace("\n", "")
|
||||
|
||||
@@ -12,6 +12,7 @@ object BattleRules {
|
||||
const val OBTAINABLE = "Obtainable"
|
||||
const val PAST = "+Past"
|
||||
const val UNOBTAINABLE = "+Unobtainable"
|
||||
const val BAG_CLAUSE = "Bag Clause"
|
||||
const val TEAM_PREVIEW = "Team Preview"
|
||||
const val ENDLESS_BATTLE_CLAUSE = "Endless Battle Clause"
|
||||
const val CANCEL_MOD = "Cancel Mod"
|
||||
|
||||
@@ -289,6 +289,8 @@ class ShowdownMoveset {
|
||||
var canDynamax = false
|
||||
var maxMoves: List<InBattleGimmickMove?>? = null
|
||||
var canTerastallize: String? = null
|
||||
/** This stores a list of gimmicks that have already been used this turn by a previous Pokemon, but the full turn has not been processed (ie. double battles). */
|
||||
val pendingGimmickUsedThisTurn = mutableListOf<Gimmick>()
|
||||
|
||||
fun saveToBuffer(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeSizedInt(IntSize.U_BYTE, moves.size)
|
||||
|
||||
@@ -300,4 +300,35 @@ object ShowdownInterpreter {
|
||||
} ?:
|
||||
MissingContext()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new update instruction parser.
|
||||
* @param id The ID of the instruction to register.
|
||||
* @param callback The callback function to create the instruction.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun registerUpdateInstructionParser(id: String, callback: (PokemonBattle, InstructionSet, BattleMessage, Iterator<BattleMessage>) -> InterpreterInstruction) {
|
||||
updateInstructionParser[id] = callback
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new split instruction parser.
|
||||
* @param id The ID of the instruction to register.
|
||||
* @param callback The callback function to create the instruction.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun registerSplitInstructionParser(id: String, callback: (PokemonBattle, BattleActor, InstructionSet, BattleMessage, BattleMessage, Iterator<BattleMessage>) -> InterpreterInstruction) {
|
||||
splitInstructionParser[id] = callback
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new side instruction parser.
|
||||
* @param id The ID of the instruction to register.
|
||||
* @param callback The callback function to create the instruction.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun registerSideInstructionParser(id: String, callback: (PokemonBattle, BattleActor, InstructionSet, BattleMessage) -> InterpreterInstruction) {
|
||||
sideInstructionParser[id] = callback
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import kotlin.collections.associateWith
|
||||
import kotlin.collections.partition
|
||||
import kotlin.math.absoluteValue
|
||||
|
||||
|
||||
/**
|
||||
* AI that tries to choose the best move for the given situations. Based off of the Pokemon Trainer Tournament Simulator Github
|
||||
* https://github.com/cRz-Shadows/Pokemon_Trainer_Tournament_Simulator/blob/main/pokemon-showdown/sim/examples/Simulation-test-1.ts#L330
|
||||
@@ -271,6 +272,11 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
}
|
||||
activeTrackerPokemon.firstTurn = false
|
||||
|
||||
// If HP is below 30% and not switching out, always use the most damaging move
|
||||
if (activeTrackerPokemon.currentHpPercent < 0.3 && !shouldSwitchOut(aiSide, battle, activeBattlePokemon, moveset)) {
|
||||
findAndUseMostDamagingMove(activeBattlePokemon, activeTrackerPokemon, opponents, availableMoves, moveset, battle, aiSide)?.let { return it }
|
||||
}
|
||||
|
||||
// Decision-making based on move availability and switch-out condition
|
||||
if (!shouldSwitchOut(aiSide, battle, activeBattlePokemon, moveset)) {
|
||||
val nRemainingMons = activeTracker.alliedSide.actors.sumOf { actor -> actor.party.filter { it.currentHpPercent > 0 }.size }
|
||||
@@ -521,6 +527,19 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
|
||||
val opponentActiveTracker = activeTracker.opponentSide.activePokemon
|
||||
val opponentSpeedEstimations = opponentActiveTracker.map { statEstimationActive(it, Stats.SPEED) }
|
||||
|
||||
|
||||
// Only switch if a switch-in is significantly better than the current Pokémon
|
||||
val currentScore = estimateMatchup(activeBattlePokemon, side, battle)
|
||||
val bestSwitchScore = availableSwitches.maxOfOrNull { estimateMatchup(activeBattlePokemon, side, battle, it) } ?: currentScore
|
||||
val improvementThreshold = currentScore.absoluteValue * 0.25 + 2
|
||||
if (bestSwitchScore <= currentScore + improvementThreshold) {
|
||||
return false
|
||||
}
|
||||
|
||||
if(bestSwitchScore < 1) {
|
||||
return false
|
||||
}
|
||||
// todo add some way to keep track of the player's boosting to see if it needs to switch out to something that can stop it
|
||||
|
||||
// if slower speed stat than the opposing pokemon and HP is less than 20% don't switch out
|
||||
@@ -548,6 +567,8 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
if (availableSwitches.isEmpty() || availableSwitches.none { estimateMatchup(activeBattlePokemon, side, battle, it) > 0 })
|
||||
return false
|
||||
|
||||
|
||||
|
||||
// ...and a 'good' reason to switch out
|
||||
if (opponentActiveTracker.any { it.boosts.getOrDefault(Stats.ACCURACY, 0) <= accuracySwitchThreshold } ||
|
||||
opponentActiveTracker.any { it.boosts.getOrDefault(Stats.DEFENCE, 0) <= -3 } ||
|
||||
|
||||
+8
-1
@@ -114,7 +114,14 @@ class ActivateInstruction(val instructionSet: InstructionSet, val message: Battl
|
||||
}
|
||||
"maxguard", "protect" -> battleLang("activate.protect", pokemonName)
|
||||
"shadowforce", "hyperspacefury", "hyperspacehole" -> battleLang("activate.phantomforce", pokemonName)
|
||||
else -> battleLang("activate.${effect.id}", pokemonName, sourceName, extraEffect)
|
||||
else -> {
|
||||
val msgVariant = message.optionalArgument("msg")
|
||||
if (msgVariant != null) {
|
||||
battleLang("activate.${effect.id}.$msgVariant", pokemonName, sourceName, extraEffect)
|
||||
} else {
|
||||
battleLang("activate.${effect.id}", pokemonName, sourceName, extraEffect)
|
||||
}
|
||||
}
|
||||
}
|
||||
battle.broadcastChatMessage(lang)
|
||||
//We check holds here so the chat msg + particle effect happen more concurrently, instead of sequentially
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ class FaintInstruction(battle: PokemonBattle, val message: BattleMessage) : Inte
|
||||
preamble.thenAccept {
|
||||
faintingPokemon.effectedPokemon.currentHealth = 0
|
||||
faintingPokemon.sendUpdate()
|
||||
CobblemonEvents.BATTLE_FAINTED.post(BattleFaintedEvent(battle, pokemon, context))
|
||||
CobblemonEvents.BATTLE_FAINTED.post(BattleFaintedEvent(battle, pokemon, context, pnx))
|
||||
battle.getActorAndActiveSlotFromPNX(pnx).second.battlePokemon = null
|
||||
faintingPokemon.contextManager.add(context)
|
||||
faintingPokemon.contextManager.clear(BattleContext.Type.STATUS, BattleContext.Type.VOLATILE, BattleContext.Type.BOOST, BattleContext.Type.UNBOOST)
|
||||
|
||||
+2
-1
@@ -26,6 +26,7 @@ import com.cobblemon.mod.common.util.battleLang
|
||||
class FormeChangeInstruction(val message: BattleMessage): InterpreterInstruction {
|
||||
|
||||
override fun invoke(battle: PokemonBattle) {
|
||||
val (pnx, _) = message.pnxAndUuid(0) ?: return
|
||||
val battlePokemon = message.battlePokemon(0, battle) ?: return
|
||||
val details = message.argumentAt(1)?.split(',')?.get(0)?.lowercase() ?: return
|
||||
val speciesName = details.substringBefore('-')
|
||||
@@ -37,7 +38,7 @@ class FormeChangeInstruction(val message: BattleMessage): InterpreterInstruction
|
||||
battle.dispatchWaiting {
|
||||
battle.minorBattleActions[battlePokemon.uuid] = message
|
||||
|
||||
CobblemonEvents.FORME_CHANGE.post(FormeChangeEvent(battle, battlePokemon, formName))
|
||||
CobblemonEvents.FORME_CHANGE.post(FormeChangeEvent(battle, battlePokemon, formName, pnx))
|
||||
val pokemonName = battlePokemon.getName()
|
||||
val lang = when(formName) {
|
||||
"busted", "hero", "complete" -> return@dispatchWaiting
|
||||
|
||||
+5
@@ -166,6 +166,11 @@ class SwitchInstruction(val instructionSet: InstructionSet, val battleActor: Bat
|
||||
// If we can't find the entity for some reason then we're going to skip the recall animation
|
||||
val sendOutFuture = CompletableFuture<Unit>()
|
||||
(pokemonEntity?.recallWithAnimation() ?: CompletableFuture.completedFuture(Unit)).thenApply {
|
||||
if (battle.ended) {
|
||||
sendOutFuture.complete(Unit)
|
||||
return@thenApply
|
||||
}
|
||||
|
||||
// Queue actual swap and send-in after the animation has ended
|
||||
actor.pokemonList.swap(actor.activePokemon.indexOf(activePokemon), actor.pokemonList.indexOf(newPokemon))
|
||||
activePokemon.battlePokemon = newPokemon
|
||||
|
||||
+8
-8
@@ -43,17 +43,17 @@ class WinInstruction(val message: BattleMessage): InterpreterInstruction {
|
||||
val losersText = losers.map { it.getName() }.reduce { acc, next -> acc + " & " + next }
|
||||
val wasCaught = battle.showdownMessages.any { "capture" in it }
|
||||
|
||||
battle.dispatch {
|
||||
// If the battle was a PvW battle, we need to set the killer of the wild Pokémon to the player
|
||||
if (battle.isPvW) {
|
||||
val nonPlayerActor = battle.actors.first { it.type == ActorType.WILD }
|
||||
val wildPokemon: BattlePokemon = nonPlayerActor.pokemonList.first()
|
||||
// If the battle was a PvW battle, we need to set the killer of the wild Pokémon to the player
|
||||
if (battle.isPvW) {
|
||||
val nonPlayerActor = battle.actors.first { it.type == ActorType.WILD }
|
||||
val wildPokemon: BattlePokemon = nonPlayerActor.pokemonList.first()
|
||||
|
||||
if (!wasCaught && losers.any { it.uuid == wildPokemon.uuid }) {
|
||||
wildPokemon.effectedPokemon.entity?.killer = (battle.actors.firstOrNull { it.type == ActorType.PLAYER } as? PlayerBattleActor)?.entity
|
||||
}
|
||||
if (!wasCaught && losers.any { it.uuid == wildPokemon.uuid }) {
|
||||
wildPokemon.effectedPokemon.entity?.killer = (battle.actors.firstOrNull { it.type == ActorType.PLAYER } as? PlayerBattleActor)?.entity
|
||||
}
|
||||
}
|
||||
|
||||
battle.dispatch {
|
||||
// broadcast victory / defeat
|
||||
if (!wasCaught) {
|
||||
val blackedOut = battle.isPvW && losers.any { it is PlayerBattleActor }
|
||||
|
||||
@@ -36,10 +36,18 @@ import java.util.function.Function
|
||||
open class BattlePokemon(
|
||||
val originalPokemon: Pokemon,
|
||||
val effectedPokemon: Pokemon = originalPokemon,
|
||||
val postBattleEntityOperation: (PokemonEntity) -> Unit = {}
|
||||
var postBattlePokemonOperations: MutableList<(BattlePokemon) -> Unit> = mutableListOf(),
|
||||
var postBattleEntityOperations: MutableList<(PokemonEntity) -> Unit> = mutableListOf()
|
||||
) {
|
||||
lateinit var actor: BattleActor
|
||||
|
||||
constructor(originalPokemon: Pokemon, effectedPokemon: Pokemon, postBattleEntityOperation: (PokemonEntity) -> Unit) : this(
|
||||
originalPokemon = originalPokemon,
|
||||
effectedPokemon = effectedPokemon,
|
||||
postBattlePokemonOperations = mutableListOf<(BattlePokemon) -> Unit>(),
|
||||
postBattleEntityOperations = mutableListOf(postBattleEntityOperation)
|
||||
)
|
||||
|
||||
companion object {
|
||||
fun safeCopyOf(pokemon: Pokemon): BattlePokemon {
|
||||
//TOOD figure out a closer registry access (might have to break some method signatures for this (1.7?)
|
||||
|
||||
@@ -19,6 +19,7 @@ import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.BlockItem
|
||||
import net.minecraft.world.item.context.BlockPlaceContext
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.LevelAccessor
|
||||
import net.minecraft.world.level.block.BaseEntityBlock
|
||||
@@ -110,6 +111,8 @@ class DisplayCaseBlock(settings: Properties) : BaseEntityBlock(settings) {
|
||||
|
||||
override fun getRenderShape(state: BlockState) = RenderShape.MODEL
|
||||
|
||||
override fun getShadeBrightness(state: BlockState, level: BlockGetter, pos: BlockPos): Float = 0.75F
|
||||
|
||||
override fun getAnalogOutputSignal(state: BlockState, world: Level, pos: BlockPos): Int {
|
||||
val stack = (world.getBlockEntity(pos) as DisplayCaseBlockEntity).getStack()
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import net.minecraft.world.level.block.SoundType
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateDefinition
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED
|
||||
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf
|
||||
import net.minecraft.world.level.block.state.properties.EnumProperty
|
||||
import net.minecraft.world.level.block.state.properties.IntegerProperty
|
||||
@@ -43,7 +44,6 @@ class HeartyGrainsBlock(settings: Properties) : CropBlock(settings), SimpleWater
|
||||
val CODEC = simpleCodec(::HeartyGrainsBlock)
|
||||
const val MATURE_AGE = 6
|
||||
const val AGE_AFTER_HARVEST = 3 // Last single block stage
|
||||
val WATERLOGGED = BlockStateProperties.WATERLOGGED
|
||||
val AGE: IntegerProperty = IntegerProperty.create("age", 0, MATURE_AGE)
|
||||
val HALF: EnumProperty<DoubleBlockHalf> = BlockStateProperties.DOUBLE_BLOCK_HALF
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.cobblemon.mod.common.util.isInBattle
|
||||
import com.cobblemon.mod.common.util.playSoundServer
|
||||
import com.cobblemon.mod.common.util.toVec3d
|
||||
import com.cobblemon.mod.common.util.voxelShape
|
||||
import com.cobblemon.mod.common.util.rotateShape
|
||||
import com.mojang.serialization.MapCodec
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
@@ -71,10 +72,10 @@ class PastureBlock(settings: Properties): BaseEntityBlock(settings), SimpleWater
|
||||
private val WEST_AABB_TOP = buildCollider(top = true, Direction.WEST)
|
||||
private val EAST_AABB_TOP = buildCollider(top = true, Direction.EAST)
|
||||
|
||||
private val SOUTH_AABB_BOTTOM = buildCollider(top = false, Direction.SOUTH)
|
||||
private val NORTH_AABB_BOTTOM = buildCollider(top = false, Direction.NORTH)
|
||||
private val WEST_AABB_BOTTOM = buildCollider(top = false, Direction.WEST)
|
||||
private val EAST_AABB_BOTTOM = buildCollider(top = false, Direction.EAST)
|
||||
private val SOUTH_AABB_BOTTOM = rotateShape(Direction.EAST, Direction.SOUTH, EAST_AABB_BOTTOM)
|
||||
private val NORTH_AABB_BOTTOM = rotateShape(Direction.EAST, Direction.NORTH, EAST_AABB_BOTTOM)
|
||||
private val WEST_AABB_BOTTOM = rotateShape(Direction.EAST, Direction.WEST, EAST_AABB_BOTTOM)
|
||||
|
||||
private fun buildCollider(top: Boolean, direction: Direction): VoxelShape {
|
||||
if (top) {
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.block
|
||||
|
||||
import com.cobblemon.mod.common.util.rotateShape
|
||||
import com.mojang.serialization.MapCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.world.item.context.BlockPlaceContext
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.LevelAccessor
|
||||
import net.minecraft.world.level.LevelReader
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.Blocks
|
||||
import net.minecraft.world.level.block.FaceAttachedHorizontalDirectionalBlock
|
||||
import net.minecraft.world.level.block.SimpleWaterloggedBlock
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateDefinition
|
||||
import net.minecraft.world.level.block.state.properties.AttachFace
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED
|
||||
import net.minecraft.world.level.material.FluidState
|
||||
import net.minecraft.world.level.material.Fluids
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
|
||||
class PlaqueBlock(properties : Properties) : FaceAttachedHorizontalDirectionalBlock(properties), SimpleWaterloggedBlock {
|
||||
companion object {
|
||||
val CODEC: MapCodec<PlaqueBlock> = RecordCodecBuilder.mapCodec {
|
||||
it.group(propertiesCodec()).apply(it, ::PlaqueBlock)
|
||||
}
|
||||
|
||||
val FLOOR_NORTH = Shapes.or(
|
||||
Shapes.box(0.0625, 0.25, 0.4375, 0.9375, 1.0, 0.5625),
|
||||
Shapes.box(0.125, 0.0, 0.4375, 0.25, 0.25, 0.5625),
|
||||
Shapes.box(0.75, 0.0, 0.4375, 0.875, 0.25, 0.5625),
|
||||
)
|
||||
val WALL_NORTH = Shapes.box(0.0625, 0.125, 0.9375, 0.9375, 0.875, 1.0)
|
||||
val CEILING_NORTH = Shapes.box(0.0625, 0.0, 0.4375, 0.9375, 0.75, 0.5625)
|
||||
}
|
||||
|
||||
init {
|
||||
registerDefaultState(stateDefinition.any()
|
||||
.setValue(FACING, Direction.NORTH)
|
||||
.setValue(FACE, AttachFace.WALL)
|
||||
.setValue(WATERLOGGED, false)
|
||||
)
|
||||
}
|
||||
|
||||
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
builder.add(FACING, FACE, WATERLOGGED)
|
||||
}
|
||||
|
||||
override fun getFluidState(blockState: BlockState): FluidState? {
|
||||
return if (blockState.getValue(WATERLOGGED)) Fluids.WATER.getSource(false) else super.getFluidState(blockState);
|
||||
}
|
||||
|
||||
override fun getStateForPlacement(context: BlockPlaceContext): BlockState? {
|
||||
val fluidState = context.level.getFluidState(context.clickedPos)
|
||||
for (direction in context.nearestLookingDirections) {
|
||||
val blockState: BlockState
|
||||
if (direction.getAxis() === Direction.Axis.Y) {
|
||||
blockState = (defaultBlockState()
|
||||
.setValue(FACE, if (direction == Direction.UP) AttachFace.CEILING else AttachFace.FLOOR) as BlockState)
|
||||
.setValue(FACING, context.horizontalDirection.opposite)
|
||||
.setValue(WATERLOGGED, fluidState.type === Fluids.WATER
|
||||
) as BlockState
|
||||
} else {
|
||||
blockState = (defaultBlockState()
|
||||
.setValue(FACE, AttachFace.WALL) as BlockState)
|
||||
.setValue(FACING, direction.opposite)
|
||||
.setValue(WATERLOGGED, fluidState.type === Fluids.WATER
|
||||
) as BlockState
|
||||
|
||||
}
|
||||
|
||||
if (blockState.canSurvive(context.getLevel(), context.getClickedPos())) {
|
||||
return blockState
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun codec(): MapCodec<PlaqueBlock> = CODEC
|
||||
|
||||
override fun getShape(state: BlockState, blockGetter: BlockGetter, pos: BlockPos, collisionContext: CollisionContext): VoxelShape {
|
||||
val direction = state.getValue(FACING)
|
||||
return when (state.getValue(FACE)) {
|
||||
AttachFace.FLOOR ->
|
||||
if (direction.axis === Direction.Axis.X) {
|
||||
rotateShape(Direction.NORTH, Direction.WEST, FLOOR_NORTH)
|
||||
} else FLOOR_NORTH
|
||||
AttachFace.WALL ->
|
||||
when (direction) {
|
||||
Direction.NORTH, Direction.UP, Direction.DOWN -> WALL_NORTH
|
||||
else -> rotateShape(Direction.NORTH, direction, WALL_NORTH)
|
||||
}
|
||||
AttachFace.CEILING ->
|
||||
if (direction.axis === Direction.Axis.X) {
|
||||
rotateShape(Direction.NORTH, Direction.WEST, CEILING_NORTH)
|
||||
} else CEILING_NORTH
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateShape(state: BlockState, direction: Direction, neighborState: BlockState, world: LevelAccessor, pos: BlockPos, neighborPos: BlockPos): BlockState {
|
||||
if (state.getValue(WATERLOGGED)) {
|
||||
world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world))
|
||||
}
|
||||
return if (getConnectedDirection(state).opposite == direction && !state.canSurvive(world, pos)) Blocks.AIR.defaultBlockState()
|
||||
else super.updateShape(state, direction, neighborState, world, pos, neighborPos)
|
||||
}
|
||||
|
||||
override fun canSurvive(state: BlockState, level: LevelReader, pos: BlockPos): Boolean {
|
||||
return if (state.getValue(FACE) == AttachFace.CEILING) {
|
||||
val direction = getConnectedDirection(state)
|
||||
canSupportCenter(level, pos.relative(direction.opposite), direction)
|
||||
} else {
|
||||
super.canSurvive(state, level, pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.block
|
||||
|
||||
import com.cobblemon.mod.common.util.rotateShape
|
||||
import com.mojang.serialization.MapCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.util.StringRepresentable
|
||||
import net.minecraft.world.item.context.BlockPlaceContext
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock
|
||||
import net.minecraft.world.level.block.SimpleWaterloggedBlock
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateDefinition
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties.HORIZONTAL_FACING
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED
|
||||
import net.minecraft.world.level.block.state.properties.IntegerProperty
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
import kotlin.math.min
|
||||
|
||||
class StackableItemBlock(settings: Properties, val type: StackableItemBlockType): HorizontalDirectionalBlock(settings), SimpleWaterloggedBlock {
|
||||
enum class StackableItemBlockType: StringRepresentable {
|
||||
BATTLE_ITEM,
|
||||
ETHER,
|
||||
MAX_POTION,
|
||||
POTION,
|
||||
STATUS_RESTORE;
|
||||
|
||||
override fun getSerializedName(): String = this.name.lowercase()
|
||||
|
||||
companion object {
|
||||
val CODEC = StringRepresentable.fromEnum(::values)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val MAX_AMOUNT: Int = 8
|
||||
val AMOUNT: IntegerProperty = IntegerProperty.create("amount", 1, MAX_AMOUNT)
|
||||
|
||||
val CODEC: MapCodec<StackableItemBlock> = RecordCodecBuilder.mapCodec { it.group(
|
||||
propertiesCodec(),
|
||||
StackableItemBlockType.CODEC.fieldOf("type").forGetter(StackableItemBlock::type)
|
||||
).apply(it, ::StackableItemBlock) }
|
||||
|
||||
val northShapeMap: Map<StackableItemBlockType, List<VoxelShape>> = mapOf(
|
||||
StackableItemBlockType.BATTLE_ITEM to listOf(
|
||||
Shapes.box(0.34375, 0.0, 0.34375, 0.65625, 0.4375, 0.65625),
|
||||
Shapes.or(
|
||||
Shapes.box(0.09375, 0.0, 0.34375, 0.40625, 0.4375, 0.65625),
|
||||
Shapes.box(0.59375, 0.0, 0.40625, 0.90625, 0.4375, 0.71875)
|
||||
),
|
||||
Shapes.or(
|
||||
Shapes.box(0.59375, 0.0, 0.59375, 0.90625, 0.4375, 0.90625),
|
||||
Shapes.box(0.09375, 0.0, 0.53125, 0.40625, 0.4375, 0.84375),
|
||||
Shapes.box(0.34375, 0.0, 0.09375, 0.65625, 0.4375, 0.40625)
|
||||
),
|
||||
Shapes.or(
|
||||
Shapes.box(0.09375, 0.0, 0.09375, 0.40625, 0.4375, 0.40625),
|
||||
Shapes.box(0.59375, 0.0, 0.15625, 0.90625, 0.4375, 0.46875),
|
||||
Shapes.box(0.65625, 0.0, 0.59375, 0.96875, 0.4375, 0.90625),
|
||||
Shapes.box(0.15625, 0.0, 0.53125, 0.46875, 0.4375, 0.84375)
|
||||
)
|
||||
),
|
||||
StackableItemBlockType.ETHER to listOf(
|
||||
Shapes.box(0.375, 0.0, 0.3125, 0.625, 0.5, 0.6875),
|
||||
Shapes.or(
|
||||
Shapes.box(0.625, 0.0, 0.375, 0.875, 0.5, 0.75),
|
||||
Shapes.box(0.125, 0.0, 0.3125, 0.375, 0.5, 0.6875)
|
||||
),
|
||||
Shapes.or(
|
||||
Shapes.box(0.375, 0.0, 0.125, 0.625, 0.5, 0.5),
|
||||
Shapes.box(0.125, 0.0, 0.5625, 0.375, 0.5, 0.9375),
|
||||
Shapes.box(0.625, 0.0, 0.625, 0.875, 0.5, 1.0)
|
||||
),
|
||||
Shapes.or(
|
||||
Shapes.box(0.125, 0.0, 0.0625, 0.375, 0.5, 0.4375),
|
||||
Shapes.box(0.625, 0.0, 0.125, 0.875, 0.5, 0.5),
|
||||
Shapes.box(0.6875, 0.0, 0.625, 0.9375, 0.5, 1.0),
|
||||
Shapes.box(0.1875, 0.0, 0.5625, 0.4375, 0.5, 0.9375)
|
||||
)
|
||||
),
|
||||
StackableItemBlockType.MAX_POTION to listOf(
|
||||
Shapes.box(0.34375, 0.0, 0.3125, 0.65625, 0.5, 0.6875),
|
||||
Shapes.or(
|
||||
Shapes.box(0.09375, 0.0, 0.3125, 0.40625, 0.5, 0.6875),
|
||||
Shapes.box(0.59375, 0.0, 0.375, 0.90625, 0.5, 0.75)
|
||||
),
|
||||
Shapes.or(
|
||||
Shapes.box(0.34375, 0.0, 0.0625, 0.65625, 0.5, 0.4375),
|
||||
Shapes.box(0.09375, 0.0, 0.5625, 0.40625, 0.5, 0.9375),
|
||||
Shapes.box(0.59375, 0.0, 0.625, 0.90625, 0.5, 1.0)
|
||||
),
|
||||
Shapes.or(
|
||||
Shapes.box(0.09375, 0.0, 0.0625, 0.40625, 0.5, 0.4375),
|
||||
Shapes.box(0.15625, 0.0, 0.5625, 0.46875, 0.5, 0.9375),
|
||||
Shapes.box(0.65625, 0.0, 0.625, 0.96875, 0.5, 1.0),
|
||||
Shapes.box(0.59375, 0.0, 0.125, 0.90625, 0.5, 0.5)
|
||||
).singleEncompassing()
|
||||
),
|
||||
StackableItemBlockType.POTION to listOf(
|
||||
Shapes.box(0.375, 0.0, 0.3125, 0.625, 0.5625, 0.75),
|
||||
Shapes.or(
|
||||
Shapes.box(0.125, 0.0, 0.3125, 0.375, 0.5625, 0.75),
|
||||
Shapes.box(0.625, 0.0, 0.375, 0.875, 0.5625, 0.8125)
|
||||
),
|
||||
Shapes.or(
|
||||
Shapes.box(0.375, 0.0, 0.0625, 0.625, 0.5625, 0.5),
|
||||
Shapes.box(0.625, 0.0, 0.5625, 0.875, 0.5625, 1.0),
|
||||
Shapes.box(0.125, 0.0, 0.5, 0.375, 0.5625, 0.9375)
|
||||
),
|
||||
Shapes.or(
|
||||
Shapes.box(0.125, 0.0, 0.0, 0.375, 0.5625, 0.4375),
|
||||
Shapes.box(0.625, 0.0, 0.0625, 0.875, 0.5625, 0.5),
|
||||
Shapes.box(0.6875, 0.0, 0.5625, 0.9375, 0.5625, 1.0),
|
||||
Shapes.box(0.1875, 0.0, 0.5, 0.4375, 0.5625, 0.9375)
|
||||
)
|
||||
),
|
||||
StackableItemBlockType.STATUS_RESTORE to listOf(
|
||||
Shapes.box(0.375, 0.0, 0.3125, 0.625, 0.4375, 0.6875),
|
||||
Shapes.or(
|
||||
Shapes.box(0.125, 0.0, 0.3125, 0.375, 0.4375, 0.75),
|
||||
Shapes.box(0.625, 0.0, 0.375, 0.875, 0.4375, 0.75)
|
||||
),
|
||||
Shapes.or(
|
||||
Shapes.box(0.125, 0.0, 0.5, 0.375, 0.4375, 0.875),
|
||||
Shapes.box(0.625, 0.0, 0.5625, 0.875, 0.4375, 0.9375),
|
||||
Shapes.box(0.375, 0.0, 0.0625, 0.625, 0.4375, 0.4375)
|
||||
),
|
||||
Shapes.or(
|
||||
Shapes.box(0.1875, 0.0, 0.5, 0.4375, 0.4375, 0.875),
|
||||
Shapes.box(0.125, 0.0, 0.0, 0.375, 0.4375, 0.375),
|
||||
Shapes.box(0.625, 0.0, 0.0625, 0.875, 0.4375, 0.4375),
|
||||
Shapes.box(0.6875, 0.0, 0.5625, 0.9375, 0.4375, 0.9375)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
fun getShape(type: StackableItemBlockType, count: Int): VoxelShape = northShapeMap[type]?.let { list -> list[(count - 1).coerceIn(0, list.lastIndex)] } ?: Shapes.block()
|
||||
fun getMaxAmount(type: StackableItemBlockType): Int = min(northShapeMap[type]?.size ?: 1 , MAX_AMOUNT)
|
||||
}
|
||||
|
||||
init {
|
||||
registerDefaultState(stateDefinition.any()
|
||||
.setValue(HORIZONTAL_FACING, Direction.NORTH)
|
||||
.setValue(AMOUNT, 1)
|
||||
.setValue(WATERLOGGED, false))
|
||||
}
|
||||
|
||||
override fun codec(): MapCodec<StackableItemBlock> = CODEC
|
||||
|
||||
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
builder.add(HORIZONTAL_FACING, AMOUNT, WATERLOGGED)
|
||||
}
|
||||
|
||||
override fun getCollisionShape(state: BlockState, level: BlockGetter, pos: BlockPos, context: CollisionContext): VoxelShape {
|
||||
val direction = state.getValue(HORIZONTAL_FACING)
|
||||
val count = state.getValue(AMOUNT)
|
||||
return rotateShape(Direction.NORTH, direction, getShape(type, count))
|
||||
}
|
||||
|
||||
override fun getShape(state: BlockState, level: BlockGetter, pos: BlockPos, context: CollisionContext): VoxelShape {
|
||||
return getCollisionShape(state, level, pos, context).singleEncompassing()
|
||||
}
|
||||
|
||||
override fun getStateForPlacement(context: BlockPlaceContext): BlockState? {
|
||||
val blockState = context.level.getBlockState(context.clickedPos)
|
||||
return if (blockState.`is`(this)) blockState.setValue(AMOUNT, min(getMaxAmount(type), (blockState.getValue(AMOUNT) + 1)))
|
||||
else super.getStateForPlacement(context)?.setValue(HORIZONTAL_FACING, context.horizontalDirection.opposite)
|
||||
}
|
||||
|
||||
override fun canBeReplaced(state: BlockState, useContext: BlockPlaceContext): Boolean {
|
||||
return if (
|
||||
!useContext.isSecondaryUseActive
|
||||
&& useContext.itemInHand.`is`(this.asItem())
|
||||
&& state.getValue(AMOUNT) <= getMaxAmount(type)
|
||||
) true else super.canBeReplaced(state, useContext)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.block
|
||||
|
||||
import com.mojang.serialization.MapCodec
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.world.item.context.BlockPlaceContext
|
||||
import net.minecraft.world.level.LevelAccessor
|
||||
import net.minecraft.world.level.LevelReader
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.Blocks
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock
|
||||
import net.minecraft.world.level.block.SimpleWaterloggedBlock
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateDefinition
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties.HORIZONTAL_FACING
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED
|
||||
import net.minecraft.world.level.material.FluidState
|
||||
import net.minecraft.world.level.material.Fluids
|
||||
|
||||
open class WallAttachedDirectionalBlock(settings: Properties): HorizontalDirectionalBlock(settings), SimpleWaterloggedBlock {
|
||||
companion object {
|
||||
val CODEC = simpleCodec(::WallAttachedDirectionalBlock)
|
||||
}
|
||||
|
||||
init {
|
||||
registerDefaultState(stateDefinition.any()
|
||||
.setValue(HORIZONTAL_FACING, Direction.NORTH)
|
||||
.setValue(WATERLOGGED, false))
|
||||
}
|
||||
|
||||
override fun codec(): MapCodec<out WallAttachedDirectionalBlock> = CODEC
|
||||
|
||||
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
builder.add(HORIZONTAL_FACING, WATERLOGGED)
|
||||
}
|
||||
|
||||
override fun getStateForPlacement(context: BlockPlaceContext): BlockState? {
|
||||
var direction = context.clickedFace
|
||||
if (direction === null || direction.axis === Direction.Axis.Y) {
|
||||
direction = context.horizontalDirection.opposite
|
||||
}
|
||||
|
||||
val fluidState = context.level.getFluidState(context.clickedPos)
|
||||
val blockState = this.defaultBlockState()
|
||||
.setValue(HORIZONTAL_FACING, direction)
|
||||
.setValue(WATERLOGGED, fluidState.type === Fluids.WATER
|
||||
) as BlockState
|
||||
|
||||
if (blockState.canSurvive(context.getLevel(), context.getClickedPos())) {
|
||||
return blockState
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getFluidState(blockState: BlockState): FluidState? = if (blockState.getValue(WATERLOGGED)) Fluids.WATER.getSource(false) else super.getFluidState(blockState)
|
||||
|
||||
override fun updateShape(state: BlockState, direction: Direction, neighborState: BlockState, world: LevelAccessor, pos: BlockPos, neighborPos: BlockPos): BlockState {
|
||||
if (state.getValue(WATERLOGGED)) {
|
||||
world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world))
|
||||
}
|
||||
return if (state.getValue(HORIZONTAL_FACING).opposite == direction && !state.canSurvive(world, pos)) Blocks.AIR.defaultBlockState()
|
||||
else super.updateShape(state, direction, neighborState, world, pos, neighborPos)
|
||||
}
|
||||
|
||||
override fun canSurvive(state: BlockState, level: LevelReader, pos: BlockPos): Boolean {
|
||||
return canAttach(level, pos, state.getValue(HORIZONTAL_FACING))
|
||||
}
|
||||
|
||||
fun canAttach(reader: LevelReader, pos: BlockPos, direction: Direction): Boolean {
|
||||
val blockPos = pos.relative(direction.opposite)
|
||||
return reader.getBlockState(blockPos).isFaceSturdy(reader, blockPos, direction)
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.block
|
||||
|
||||
import com.cobblemon.mod.common.util.rotateShape
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.MapCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
|
||||
class WallAttachedDirectionalShapeBlock(settings: Properties, val width: Int = 16, val height: Int = 16, val depth: Int = 16): WallAttachedDirectionalBlock(settings) {
|
||||
companion object {
|
||||
/**
|
||||
* Calculates a [VoxelShape] based on a center point of (8, 8, 16).
|
||||
*
|
||||
* The resulting shape is centered X horizontally and Y vertically
|
||||
* expanding inwards/North along the Z-axis from the South face (16).
|
||||
*
|
||||
* @param width The width of the shape from 0-16, along the X-axis.
|
||||
* @param height The height of the shape from 0-16 along the Y-axis.
|
||||
* @param depth The depth of the shape from 0-16 along the Z-axis, extending inwards from 16.
|
||||
* @return A VoxelShape.
|
||||
*/
|
||||
fun convertToShape(sizeX: Int, sizeY: Int, sizeZ: Int): VoxelShape {
|
||||
val x = sizeX.coerceIn(0, 16).toDouble()
|
||||
val y = sizeY.coerceIn(0, 16).toDouble()
|
||||
val z = sizeZ.coerceIn(0, 16).toDouble()
|
||||
|
||||
val minX = (8.0 - (x / 2.0)) / 16.0
|
||||
val maxX = (8.0 + (x / 2.0)) / 16.0
|
||||
|
||||
val minY = (8.0 - (y / 2.0)) / 16.0
|
||||
val maxY = (8.0 + (y / 2.0)) / 16.0
|
||||
|
||||
val minZ = (16.0 - z) / 16.0
|
||||
|
||||
return Shapes.box(minX, minY, minZ, maxX, maxY, 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
override fun codec(): MapCodec<WallAttachedDirectionalShapeBlock> = RecordCodecBuilder.mapCodec { instance ->
|
||||
instance.group(
|
||||
propertiesCodec(),
|
||||
Codec.INT.fieldOf("width").forGetter { it.width },
|
||||
Codec.INT.fieldOf("height").forGetter { it.height },
|
||||
Codec.INT.fieldOf("depth").forGetter { it.depth }
|
||||
).apply(instance, { properties, width, height, depth ->
|
||||
WallAttachedDirectionalShapeBlock(properties, width, height, depth)
|
||||
})
|
||||
}
|
||||
|
||||
override fun getShape(state: BlockState, level: BlockGetter, pos: BlockPos, context: CollisionContext): VoxelShape {
|
||||
val direction = state.getValue(FACING)
|
||||
return rotateShape(Direction.NORTH, direction, convertToShape(width, height, depth))
|
||||
}
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.block
|
||||
|
||||
import com.cobblemon.mod.common.block.StackableItemBlock.Companion.AMOUNT
|
||||
import com.cobblemon.mod.common.block.StackableItemBlock.Companion.MAX_AMOUNT
|
||||
import com.cobblemon.mod.common.util.rotateShape
|
||||
import com.mojang.serialization.MapCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.util.StringRepresentable
|
||||
import net.minecraft.world.item.context.BlockPlaceContext
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateDefinition
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties.HORIZONTAL_FACING
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
import kotlin.math.min
|
||||
|
||||
class WallAttachedStackableItemBlock(settings: Properties, val type: WallStackableItemBlockType): WallAttachedDirectionalBlock(settings) {
|
||||
enum class WallStackableItemBlockType: StringRepresentable {
|
||||
TAG;
|
||||
|
||||
override fun getSerializedName(): String = this.name.lowercase()
|
||||
|
||||
companion object {
|
||||
val CODEC = StringRepresentable.fromEnum(::values)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CODEC: MapCodec<WallAttachedStackableItemBlock> = RecordCodecBuilder.mapCodec { it.group(
|
||||
propertiesCodec(),
|
||||
WallStackableItemBlockType.CODEC.fieldOf("type").forGetter(WallAttachedStackableItemBlock::type)
|
||||
).apply(it, ::WallAttachedStackableItemBlock) }
|
||||
|
||||
val northShapeMap: Map<WallStackableItemBlockType, List<VoxelShape>> = mapOf(
|
||||
WallStackableItemBlockType.TAG to listOf(
|
||||
Shapes.box(0.375, 0.25, 0.9375, 0.625, 0.6875, 1.0),
|
||||
Shapes.box(0.375, 0.0625, 0.9375, 1.0, 0.6875, 1.0),
|
||||
Shapes.box(0.0, 0.0625, 0.9375, 1.0, 0.9375, 1.0),
|
||||
Shapes.box(0.0, 0.0625, 0.9375, 1.0, 1.0, 1.0),
|
||||
Shapes.box(0.0, 0.0, 0.9375, 1.0, 1.0, 1.0),
|
||||
Shapes.box(0.0, 0.0, 0.9375, 1.0, 1.0, 1.0),
|
||||
Shapes.box(0.0, 0.0, 0.9375, 1.0, 1.0, 1.0),
|
||||
Shapes.box(0.0, 0.0, 0.9375, 1.0, 1.0, 1.0)
|
||||
)
|
||||
)
|
||||
|
||||
fun getShape(type: WallStackableItemBlockType, count: Int): VoxelShape = northShapeMap[type]?.let { list -> list[(count - 1).coerceIn(0, list.lastIndex)] } ?: Shapes.block()
|
||||
fun getMaxAmount(type: WallStackableItemBlockType): Int = min(northShapeMap[type]?.size ?: 1 , MAX_AMOUNT)
|
||||
}
|
||||
|
||||
init {
|
||||
registerDefaultState(stateDefinition.any()
|
||||
.setValue(HORIZONTAL_FACING, Direction.NORTH)
|
||||
.setValue(AMOUNT, 1)
|
||||
.setValue(WATERLOGGED, false))
|
||||
}
|
||||
|
||||
override fun codec(): MapCodec<WallAttachedStackableItemBlock> = CODEC
|
||||
|
||||
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
super.createBlockStateDefinition(builder)
|
||||
builder.add(AMOUNT)
|
||||
}
|
||||
|
||||
override fun getShape(state: BlockState, level: BlockGetter, pos: BlockPos, context: CollisionContext): VoxelShape {
|
||||
val direction = state.getValue(HORIZONTAL_FACING)
|
||||
val count = state.getValue(AMOUNT)
|
||||
return rotateShape(Direction.NORTH, direction, getShape(type, count))
|
||||
}
|
||||
|
||||
override fun getStateForPlacement(context: BlockPlaceContext): BlockState? {
|
||||
val blockState = context.level.getBlockState(context.clickedPos)
|
||||
return if (blockState.`is`(this)) blockState.setValue(AMOUNT, min(getMaxAmount(type), (blockState.getValue(AMOUNT) + 1)))
|
||||
else super.getStateForPlacement(context)
|
||||
}
|
||||
|
||||
override fun canBeReplaced(state: BlockState, useContext: BlockPlaceContext): Boolean {
|
||||
return if (
|
||||
!useContext.isSecondaryUseActive
|
||||
&& useContext.itemInHand.`is`(this.asItem())
|
||||
&& state.getValue(AMOUNT) <= getMaxAmount(type)
|
||||
) true else super.canBeReplaced(state, useContext)
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -17,7 +17,6 @@ import com.cobblemon.mod.common.api.pasture.PastureLinkManager
|
||||
import com.cobblemon.mod.common.api.scheduling.afterOnServer
|
||||
import com.cobblemon.mod.common.api.text.italicise
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.text.textClickHandlers
|
||||
import com.cobblemon.mod.common.block.PastureBlock
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
|
||||
@@ -110,10 +109,10 @@ class PokemonPastureBlockEntity(pos: BlockPos, state: BlockState) :
|
||||
for (tetheredPokemon in tetheredPokemonList) {
|
||||
val pokemon = tetheredPokemon.getPokemon()!!
|
||||
if (pokemon.currentFullness > 0) {
|
||||
pokemon.tickMetabolism()
|
||||
pokemon.tickMetabolism(1)
|
||||
}
|
||||
if (pokemon.interactionCooldowns.any()) {
|
||||
pokemon.tickInteractionCooldown()
|
||||
pokemon.tickInteractionCooldown(1)
|
||||
}
|
||||
}
|
||||
blockEntity.togglePastureOn(blockEntity.getInRangeViewerCount(world, blockEntity.blockPos) > 0)
|
||||
|
||||
@@ -319,7 +319,48 @@ object CobblemonClient {
|
||||
CobblemonBlocks.PINK_CAMPFIRE_POT,
|
||||
CobblemonBlocks.RED_CAMPFIRE_POT,
|
||||
CobblemonBlocks.WHITE_CAMPFIRE_POT,
|
||||
CobblemonBlocks.YELLOW_CAMPFIRE_POT
|
||||
CobblemonBlocks.YELLOW_CAMPFIRE_POT,
|
||||
CobblemonBlocks.WHITE_PLAQUE,
|
||||
CobblemonBlocks.LIGHT_GRAY_PLAQUE,
|
||||
CobblemonBlocks.GRAY_PLAQUE,
|
||||
CobblemonBlocks.BLACK_PLAQUE,
|
||||
CobblemonBlocks.BROWN_PLAQUE,
|
||||
CobblemonBlocks.RED_PLAQUE,
|
||||
CobblemonBlocks.ORANGE_PLAQUE,
|
||||
CobblemonBlocks.YELLOW_PLAQUE,
|
||||
CobblemonBlocks.LIME_PLAQUE,
|
||||
CobblemonBlocks.GREEN_PLAQUE,
|
||||
CobblemonBlocks.CYAN_PLAQUE,
|
||||
CobblemonBlocks.LIGHT_BLUE_PLAQUE,
|
||||
CobblemonBlocks.BLUE_PLAQUE,
|
||||
CobblemonBlocks.PURPLE_PLAQUE,
|
||||
CobblemonBlocks.MAGENTA_PLAQUE,
|
||||
CobblemonBlocks.PINK_PLAQUE,
|
||||
CobblemonBlocks.BLUNDER_POLICY,
|
||||
CobblemonBlocks.WEAKNESS_POLICY,
|
||||
CobblemonBlocks.POTION,
|
||||
CobblemonBlocks.SUPER_POTION,
|
||||
CobblemonBlocks.HYPER_POTION,
|
||||
CobblemonBlocks.MAX_POTION,
|
||||
CobblemonBlocks.FULL_RESTORE,
|
||||
CobblemonBlocks.ANTIDOTE,
|
||||
CobblemonBlocks.AWAKENING,
|
||||
CobblemonBlocks.BURN_HEAL,
|
||||
CobblemonBlocks.ICE_HEAL,
|
||||
CobblemonBlocks.PARALYZE_HEAL,
|
||||
CobblemonBlocks.FULL_HEAL,
|
||||
CobblemonBlocks.ETHER,
|
||||
CobblemonBlocks.MAX_ETHER,
|
||||
CobblemonBlocks.ELIXIR,
|
||||
CobblemonBlocks.MAX_ELIXIR,
|
||||
CobblemonBlocks.DIRE_HIT,
|
||||
CobblemonBlocks.GUARD_SPEC,
|
||||
CobblemonBlocks.X_ACCURACY,
|
||||
CobblemonBlocks.X_ATTACK,
|
||||
CobblemonBlocks.X_DEFENSE,
|
||||
CobblemonBlocks.X_SP_ATK,
|
||||
CobblemonBlocks.X_SP_DEF,
|
||||
CobblemonBlocks.X_SPEED
|
||||
)
|
||||
|
||||
this.createBoatModelLayers()
|
||||
|
||||
@@ -11,10 +11,11 @@ package com.cobblemon.mod.common.client.battle
|
||||
import com.cobblemon.mod.common.CobblemonNetwork
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.battles.BattleFormat
|
||||
import com.cobblemon.mod.common.battles.ForcePassActionResponse
|
||||
import com.cobblemon.mod.common.battles.MoveActionResponse
|
||||
import com.cobblemon.mod.common.battles.PassActionResponse
|
||||
import com.cobblemon.mod.common.battles.ShowdownMoveset
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
@@ -61,8 +62,15 @@ class ClientBattle(
|
||||
if (index != -1) {
|
||||
while(index < pendingActionRequests.size) {
|
||||
val request = pendingActionRequests[index]
|
||||
if (request.response != PassActionResponse && request.response !is ForcePassActionResponse)
|
||||
if (request.response != PassActionResponse && request.response !is ForcePassActionResponse) {
|
||||
val response = request.response
|
||||
// If we're cancelling a turn that used a gimmick, we re-enable the ability for that gimmick to be used.
|
||||
if (response is MoveActionResponse && response.gimmickID != null) {
|
||||
val gimmick = ShowdownMoveset.Gimmick.entries.find { it.id == response.gimmickID }
|
||||
pendingActionRequests.forEach { it.moveSet?.pendingGimmickUsedThisTurn?.remove(gimmick) }
|
||||
}
|
||||
request.response = null
|
||||
}
|
||||
index++
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ class BattleMoveSelection(
|
||||
var moveTiles = baseTiles
|
||||
|
||||
val backButton = BattleBackButton(x - 11F, Minecraft.getInstance().window.guiScaledHeight - 22F)
|
||||
val gimmickButtons = moveSet.getGimmicks().mapIndexed { index, gimmick ->
|
||||
val gimmickButtons = moveSet.getGimmicks().filter { it !in moveSet.pendingGimmickUsedThisTurn }.mapIndexed { index, gimmick ->
|
||||
val initOff = BattleBackButton.WIDTH * 0.65F
|
||||
val xOff = initOff + BattleGimmickButton.SPACING * index
|
||||
BattleGimmickButton.create(gimmick, this, backButton.x + xOff, backButton.y)
|
||||
|
||||
+9
-1
@@ -17,6 +17,7 @@ import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.battles.InBattleGimmickMove
|
||||
import com.cobblemon.mod.common.battles.InBattleMove
|
||||
import com.cobblemon.mod.common.battles.MoveActionResponse
|
||||
import com.cobblemon.mod.common.battles.ShowdownMoveset
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.battle.ActiveClientBattlePokemon
|
||||
@@ -127,7 +128,7 @@ class BattleTargetSelection(
|
||||
private val isMultiTarget = multiTargetList?.firstOrNull { it.getPNX() == target.getPNX() } != null
|
||||
private val isCurrentPokemon = request.activePokemon.battlePokemon?.uuid == target.battlePokemon!!.uuid
|
||||
|
||||
open val response: MoveActionResponse get() = MoveActionResponse(targetSelection.move.id, responseTarget)
|
||||
open val response: MoveActionResponse get() = MoveActionResponse(targetSelection.move.id, responseTarget, gimmickID)
|
||||
val state = FloatingState()
|
||||
|
||||
open val selectable: Boolean get() = isMultiTarget || (responseTarget != null)
|
||||
@@ -311,6 +312,13 @@ class BattleTargetSelection(
|
||||
fun onClick() {
|
||||
if (!selectable) return
|
||||
targetSelection.playDownSound(Minecraft.getInstance().soundManager)
|
||||
// If a gimmick is used, remove the ability to use it on any pending action requests ahead of it
|
||||
if (response.gimmickID != null) {
|
||||
val gimmick = ShowdownMoveset.Gimmick.entries.first { it.id == response.gimmickID }
|
||||
CobblemonClient.battle?.pendingActionRequests?.forEach {
|
||||
it.moveSet?.pendingGimmickUsedThisTurn?.add(gimmick)
|
||||
}
|
||||
}
|
||||
targetSelection.battleGUI.selectAction(targetSelection.request, response)
|
||||
}
|
||||
}
|
||||
|
||||
+9
-9
@@ -143,18 +143,18 @@ object PartySendBinding : CobblemonBlockingKeyBinding(
|
||||
}
|
||||
|
||||
private fun canAttemptDismount(player: LocalPlayer, selectedPartyPokemon: Pokemon?): Boolean {
|
||||
if (player.vehicle !is PokemonEntity) return false
|
||||
val vehicle = player.vehicle as PokemonEntity
|
||||
if (player != vehicle.controllingPassenger) {
|
||||
return true
|
||||
}
|
||||
val vehicle = player.vehicle as? PokemonEntity ?: return false
|
||||
|
||||
if (player != vehicle.controllingPassenger) return true
|
||||
|
||||
val isAirRide = vehicle.ridingController?.context?.style == RidingStyle.AIR
|
||||
val hasLandRide = vehicle.rideProp.behaviours?.get(RidingStyle.LAND) != null
|
||||
return if (isAirRide && hasLandRide) {
|
||||
false
|
||||
} else {
|
||||
vehicle.pokemon.uuid == selectedPartyPokemon?.uuid
|
||||
|
||||
if (!Cobblemon.config.enableInFlightDismounting && isAirRide && hasLandRide) {
|
||||
return false
|
||||
}
|
||||
|
||||
return vehicle.pokemon.uuid == selectedPartyPokemon?.uuid
|
||||
}
|
||||
|
||||
private fun isRidingPokemon(player: LocalPlayer, ignoreControlling: Boolean = false): Boolean {
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ import net.minecraft.world.phys.Vec3
|
||||
|
||||
object CalculateSeatPositionsHandler : ClientNetworkPacketHandler<CalculateSeatPositionsPacket> {
|
||||
private const val FORMAT = "%.2f"
|
||||
private const val SEAT_PREFIX = "seat"
|
||||
private const val SEAT_PREFIX = "seat_"
|
||||
private const val SIMULATION_PERIOD_TICKS = 15 * 20F
|
||||
|
||||
class SeatRanges(
|
||||
|
||||
+1
@@ -160,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.`is`(CobblemonItemTags.PLAQUES) -> PositioningType.ITEM_MODEL
|
||||
stack.item is PokedexItem -> PositioningType.POKEDEX
|
||||
stack.item == CobblemonItems.RELIC_COIN_POUCH -> PositioningType.COIN_POUCH
|
||||
stack.item == CobblemonItems.PASTURE -> PositioningType.PASTURE
|
||||
|
||||
+6
-2
@@ -39,7 +39,11 @@ class PoseAdapter(
|
||||
override fun deserialize(json: JsonElement, type: Type, ctx: JsonDeserializationContext): Pose {
|
||||
val model = modelFinder()
|
||||
val obj = json as JsonObject
|
||||
val pose = JsonPose(model, obj)
|
||||
val pose = try {
|
||||
JsonPose(model, obj)
|
||||
} catch (e: Exception) {
|
||||
throw IllegalArgumentException("Failed to deserialize pose from JSON: $json", e)
|
||||
}
|
||||
|
||||
val conditionsList = mutableListOf<(PosableState) -> Boolean>()
|
||||
|
||||
@@ -100,4 +104,4 @@ class PoseAdapter(
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -206,7 +206,7 @@ fun generateAdditionalRideBoostsTooltip(stack: ItemStack): MutableList<Component
|
||||
val resultLines = mutableListOf<Component>()
|
||||
resultLines.add(rideBoostSeasoningHeader)
|
||||
|
||||
for ((stat, value) in boosts) {
|
||||
for ((stat, value) in boosts.toSortedMap()) {
|
||||
val statName = stat.displayName.also { it.style = it.style.withColor(stat.flavour.colour) }
|
||||
val valueText = if (value < 0) {
|
||||
Component.literal("$value").red()
|
||||
|
||||
@@ -329,6 +329,9 @@ class CobblemonConfig {
|
||||
@CobblemonConfigField(Category.Riding, lang = "remember_riding_camera", CLIENT)
|
||||
var rememberRidingCamera = false
|
||||
|
||||
@CobblemonConfigField(Category.Riding, lang = "enable_in_flight_dismounting", CLIENT)
|
||||
var enableInFlightDismounting = false
|
||||
|
||||
@CobblemonConfigField(Category.Debug, lang = "enable_debug_keys", CLIENT)
|
||||
var enableDebugKeys = false
|
||||
|
||||
|
||||
@@ -269,9 +269,6 @@ class OmniPathNavigation(val world: Level, val entity: Mob) : GroundPathNavigati
|
||||
// If we can fly and we're airborne, return the current Y position
|
||||
return vec.y
|
||||
}
|
||||
if (world.getBlockState(blockPos).block == CobblemonBlocks.SACCHARINE_LEAVES && pather.canPathThroughSaccLeaves()) {
|
||||
return vec.y + 0.5
|
||||
}
|
||||
return if ((canFloat()) && blockGetter.getFluidState(blockPos).`is`(FluidTags.WATER)) vec.y + 0.5 else super.getGroundY(vec)
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerEntity
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.tags.DamageTypeTags.BYPASSES_INVULNERABILITY
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.damagesource.DamageSource
|
||||
@@ -604,7 +605,7 @@ class NPCEntity(world: Level) : AgeableMob(CobblemonEntities.NPC, world), Posabl
|
||||
}
|
||||
|
||||
override fun isPushable() = isMovable ?: npc.isMovable
|
||||
override fun isInvulnerableTo(source: DamageSource) = isInvulnerable ?: npc.isInvulnerable
|
||||
override fun isInvulnerableTo(source: DamageSource) = (isInvulnerable ?: npc.isInvulnerable) && !source.`is`(BYPASSES_INVULNERABILITY)
|
||||
override fun canBeLeashed() = isLeashable ?: npc.isLeashable
|
||||
override fun canBeHitByProjectile() = allowProjectileHits ?: npc.allowProjectileHits
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import juuxel.adorn.block.variant.CompatBlockVariantSet
|
||||
|
||||
class AdornCompatibility : CompatBlockVariantSet() {
|
||||
override fun getWoodVariants(): List<BlockVariant?>? {
|
||||
return this.createVariants({ BlockVariant.Wood(it) }, "apricorn")
|
||||
return this.createVariants({ BlockVariant.Wood(it) }, "apricorn", "saccharine")
|
||||
}
|
||||
|
||||
override fun getModId(): String? {
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.advancement.criterion.PokemonInteractContext
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.battles.BagItemActionResponse
|
||||
import com.cobblemon.mod.common.battles.BagItems
|
||||
import com.cobblemon.mod.common.battles.BattleRules
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
@@ -41,7 +42,7 @@ interface BagItemLike {
|
||||
fun handleInteraction(player: ServerPlayer, battlePokemon: BattlePokemon, stack: ItemStack): Boolean {
|
||||
val battle = battlePokemon.actor.battle
|
||||
val bagItem = getBagItem(stack) ?: return false
|
||||
if (!battlePokemon.actor.canFitForcedAction()) {
|
||||
if (!battlePokemon.actor.canFitForcedAction() || battle.format.ruleSet.contains(BattleRules.BAG_CLAUSE)) {
|
||||
player.sendSystemMessage(battleLang("bagitem.cannot").red())
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -11,12 +11,13 @@ package com.cobblemon.mod.common.item.battle
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.item.CobblemonItem
|
||||
import net.minecraft.world.item.ItemNameBlockItem
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.level.block.Block
|
||||
|
||||
|
||||
class DireHitItem : CobblemonItem(Properties()), SimpleBagItemLike {
|
||||
class DireHitItem(block: Block) : ItemNameBlockItem(block, Properties()), SimpleBagItemLike {
|
||||
override val bagItem = object : BagItem {
|
||||
override val itemName = "item.cobblemon.dire_hit"
|
||||
override val returnItem = Items.AIR
|
||||
|
||||
@@ -11,11 +11,12 @@ package com.cobblemon.mod.common.item.battle
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.item.CobblemonItem
|
||||
import net.minecraft.world.item.ItemNameBlockItem
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.level.block.Block
|
||||
|
||||
class GuardSpecItem : CobblemonItem(Properties()), SimpleBagItemLike {
|
||||
class GuardSpecItem(block: Block) : ItemNameBlockItem(block, Properties()), SimpleBagItemLike {
|
||||
override val bagItem = object : BagItem {
|
||||
override val itemName = "item.cobblemon.guard_spec"
|
||||
override val returnItem = Items.AIR
|
||||
|
||||
@@ -12,11 +12,12 @@ import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.item.CobblemonItem
|
||||
import net.minecraft.world.item.ItemNameBlockItem
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.level.block.Block
|
||||
|
||||
class XStatItem(val stat: Stat, stages: Int = 2) : CobblemonItem(Properties()), SimpleBagItemLike {
|
||||
class XStatItem(val stat: Stat, stages: Int = 2, block: Block) : ItemNameBlockItem(block, Properties()), SimpleBagItemLike {
|
||||
override val bagItem = object : BagItem {
|
||||
override val itemName = "item.cobblemon.x_${stat.identifier.path}"
|
||||
override val returnItem = Items.AIR
|
||||
|
||||
@@ -66,6 +66,7 @@ object CobblemonItemGroups {
|
||||
@JvmStatic val EVOLUTION_ITEMS get() = BuiltInRegistries.CREATIVE_MODE_TAB.get(EVOLUTION_ITEMS_KEY)
|
||||
|
||||
@JvmStatic val BUILDING_BLOCKS_INJECTIONS = this.inject(ResourceKey.create(BuiltInRegistries.CREATIVE_MODE_TAB.key(), ResourceLocation.parse("building_blocks")), this::blocksInjections)
|
||||
@JvmStatic val COLORED_BLOCKS_INJECTIONS = this.inject(ResourceKey.create(BuiltInRegistries.CREATIVE_MODE_TAB.key(), ResourceLocation.parse("colored_blocks")), this::coloredBlocksInjections)
|
||||
@JvmStatic val FOOD_INJECTIONS = this.inject(ResourceKey.create(BuiltInRegistries.CREATIVE_MODE_TAB.key(), ResourceLocation.parse("food_and_drinks")), this::foodInjections)
|
||||
@JvmStatic val TOOLS_AND_UTILITIES_INJECTIONS = this.inject(ResourceKey.create(BuiltInRegistries.CREATIVE_MODE_TAB.key(), ResourceLocation.parse("tools_and_utilities")), this::toolsAndUtilitiesInjections)
|
||||
@JvmStatic val INGREDIENTS_INJECTIONS = this.inject(ResourceKey.create(BuiltInRegistries.CREATIVE_MODE_TAB.key(), ResourceLocation.parse("ingredients")), this::ingredientsInjections)
|
||||
@@ -381,6 +382,23 @@ object CobblemonItemGroups {
|
||||
entries.accept(CobblemonItems.THUNDER_STONE_BLOCK)
|
||||
entries.accept(CobblemonItems.WATER_STONE_BLOCK)
|
||||
|
||||
entries.accept(CobblemonItems.WHITE_PLAQUE)
|
||||
entries.accept(CobblemonItems.LIGHT_GRAY_PLAQUE)
|
||||
entries.accept(CobblemonItems.GRAY_PLAQUE)
|
||||
entries.accept(CobblemonItems.BLACK_PLAQUE)
|
||||
entries.accept(CobblemonItems.BROWN_PLAQUE)
|
||||
entries.accept(CobblemonItems.RED_PLAQUE)
|
||||
entries.accept(CobblemonItems.ORANGE_PLAQUE)
|
||||
entries.accept(CobblemonItems.YELLOW_PLAQUE)
|
||||
entries.accept(CobblemonItems.LIME_PLAQUE)
|
||||
entries.accept(CobblemonItems.GREEN_PLAQUE)
|
||||
entries.accept(CobblemonItems.CYAN_PLAQUE)
|
||||
entries.accept(CobblemonItems.LIGHT_BLUE_PLAQUE)
|
||||
entries.accept(CobblemonItems.BLUE_PLAQUE)
|
||||
entries.accept(CobblemonItems.PURPLE_PLAQUE)
|
||||
entries.accept(CobblemonItems.MAGENTA_PLAQUE)
|
||||
entries.accept(CobblemonItems.PINK_PLAQUE)
|
||||
|
||||
CobblemonItems.campfire_pots.forEach(entries::accept)
|
||||
}
|
||||
|
||||
@@ -765,6 +783,25 @@ object CobblemonItemGroups {
|
||||
}
|
||||
}
|
||||
|
||||
private fun coloredBlocksInjections(injector: Injector) {
|
||||
injector.putLast(CobblemonItems.WHITE_PLAQUE)
|
||||
injector.putAfter(CobblemonItems.LIGHT_GRAY_PLAQUE, CobblemonItems.WHITE_PLAQUE)
|
||||
injector.putAfter(CobblemonItems.GRAY_PLAQUE, CobblemonItems.LIGHT_GRAY_PLAQUE)
|
||||
injector.putAfter(CobblemonItems.BLACK_PLAQUE, CobblemonItems.GRAY_PLAQUE)
|
||||
injector.putAfter(CobblemonItems.BROWN_PLAQUE, CobblemonItems.BLACK_PLAQUE)
|
||||
injector.putAfter(CobblemonItems.RED_PLAQUE, CobblemonItems.BROWN_PLAQUE)
|
||||
injector.putAfter(CobblemonItems.ORANGE_PLAQUE, CobblemonItems.RED_PLAQUE)
|
||||
injector.putAfter(CobblemonItems.YELLOW_PLAQUE, CobblemonItems.ORANGE_PLAQUE)
|
||||
injector.putAfter(CobblemonItems.LIME_PLAQUE, CobblemonItems.YELLOW_PLAQUE)
|
||||
injector.putAfter(CobblemonItems.GREEN_PLAQUE, CobblemonItems.LIME_PLAQUE)
|
||||
injector.putAfter(CobblemonItems.CYAN_PLAQUE, CobblemonItems.GREEN_PLAQUE)
|
||||
injector.putAfter(CobblemonItems.LIGHT_BLUE_PLAQUE, CobblemonItems.CYAN_PLAQUE)
|
||||
injector.putAfter(CobblemonItems.BLUE_PLAQUE, CobblemonItems.LIGHT_BLUE_PLAQUE)
|
||||
injector.putAfter(CobblemonItems.PURPLE_PLAQUE, CobblemonItems.BLUE_PLAQUE)
|
||||
injector.putAfter(CobblemonItems.MAGENTA_PLAQUE, CobblemonItems.PURPLE_PLAQUE)
|
||||
injector.putAfter(CobblemonItems.PINK_PLAQUE, CobblemonItems.MAGENTA_PLAQUE)
|
||||
}
|
||||
|
||||
private fun foodInjections(injector: Injector) {
|
||||
injector.putAfter(CobblemonItems.TART_APPLE, Items.ENCHANTED_GOLDEN_APPLE)
|
||||
injector.putAfter(CobblemonItems.SWEET_APPLE, CobblemonItems.TART_APPLE)
|
||||
|
||||
@@ -13,7 +13,6 @@ import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
|
||||
import com.cobblemon.mod.common.api.item.PokemonSelectingItem
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.item.CobblemonItem
|
||||
import com.cobblemon.mod.common.item.battle.BagItem
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.giveOrDropItemStack
|
||||
@@ -25,8 +24,10 @@ import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.InteractionResultHolder
|
||||
import net.minecraft.world.item.ItemNameBlockItem
|
||||
import net.minecraft.world.item.Rarity
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
|
||||
/**
|
||||
* Items for recovering PP in all moves at once.
|
||||
@@ -34,9 +35,7 @@ import net.minecraft.world.level.Level
|
||||
* @author Hiroku
|
||||
* @since June 30th, 2023
|
||||
*/
|
||||
class ElixirItem(
|
||||
val max: Boolean
|
||||
) : CobblemonItem(Properties().apply {
|
||||
class ElixirItem(val max: Boolean, block: Block) : ItemNameBlockItem(block, Properties().apply {
|
||||
if (max) rarity(Rarity.UNCOMMON)
|
||||
}), PokemonSelectingItem {
|
||||
override val bagItem = object : BagItem {
|
||||
|
||||
@@ -14,7 +14,6 @@ import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
|
||||
import com.cobblemon.mod.common.api.item.PokemonAndMoveSelectingItem
|
||||
import com.cobblemon.mod.common.api.moves.Move
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.item.CobblemonItem
|
||||
import com.cobblemon.mod.common.item.battle.BagItem
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.giveOrDropItemStack
|
||||
@@ -26,8 +25,10 @@ import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.InteractionResultHolder
|
||||
import net.minecraft.world.item.ItemNameBlockItem
|
||||
import net.minecraft.world.item.Rarity
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
|
||||
/**
|
||||
* Item for recovering PP for a specific move in a Pokémon's move list. Opens a move selection GUI.
|
||||
@@ -35,9 +36,7 @@ import net.minecraft.world.level.Level
|
||||
* @author Hiroku
|
||||
* @since June 30th, 2023
|
||||
*/
|
||||
class EtherItem(
|
||||
val max: Boolean
|
||||
) : CobblemonItem(Properties().apply {
|
||||
class EtherItem(val max: Boolean, block: Block) : ItemNameBlockItem(block, Properties().apply {
|
||||
if (max) rarity(Rarity.UNCOMMON)
|
||||
}), PokemonAndMoveSelectingItem {
|
||||
override val bagItem = object : BagItem {
|
||||
|
||||
+2
-1
@@ -34,8 +34,9 @@ class FreshStartMochiItem : CobblemonItem(Properties()), PokemonSelectingItem {
|
||||
}
|
||||
|
||||
pokemon.feedPokemon(1)
|
||||
|
||||
pokemon.evs.forEach {
|
||||
pokemon.evs[it.key] = 0
|
||||
pokemon.setEV(it.key, 0)
|
||||
}
|
||||
|
||||
//pokemon.entity?.playSound(CobblemonSounds.MOCHI_USE, 1F, 1F) todo use mochi sounds for fullness levels and replace above
|
||||
|
||||
@@ -17,7 +17,6 @@ import com.cobblemon.mod.common.api.item.HealingSource
|
||||
import com.cobblemon.mod.common.api.item.PokemonSelectingItem
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.item.CobblemonItem
|
||||
import com.cobblemon.mod.common.item.battle.BagItem
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
@@ -31,12 +30,12 @@ import net.minecraft.world.item.Items
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.InteractionResultHolder
|
||||
import net.minecraft.world.item.ItemNameBlockItem
|
||||
import net.minecraft.world.item.Rarity
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
|
||||
class PotionItem(
|
||||
val type: PotionType
|
||||
) : CobblemonItem(Properties().apply {
|
||||
class PotionItem(val type: PotionType, block: Block) : ItemNameBlockItem(block, Properties().apply {
|
||||
when (type.name) {
|
||||
PotionType.MAX_POTION.name -> rarity(Rarity.UNCOMMON)
|
||||
PotionType.FULL_RESTORE.name -> rarity(Rarity.UNCOMMON)
|
||||
|
||||
+10
-3
@@ -35,9 +35,16 @@ class SinisterTeaItem : Item(
|
||||
val effectsComponent = stack.get(CobblemonItemComponents.MOB_EFFECTS)
|
||||
|
||||
if (effectsComponent != null) {
|
||||
for (effect in effectsComponent.mobEffects) {
|
||||
val effectCopy = MobEffectInstance(effect)
|
||||
user.addEffect(effectCopy)
|
||||
for (raw in effectsComponent.mobEffects) {
|
||||
val inst = MobEffectInstance(raw)
|
||||
val holder = inst.effect
|
||||
val effect = holder.value()
|
||||
|
||||
if (effect.isInstantenous) {
|
||||
effect.applyInstantenousEffect(user as? Player, null, user, inst.amplifier, 1.0)
|
||||
} else {
|
||||
user.addEffect(inst)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
|
||||
import com.cobblemon.mod.common.api.item.PokemonSelectingItem
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Status
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.item.CobblemonItem
|
||||
import com.cobblemon.mod.common.item.battle.BagItem
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.giveOrDropItemStack
|
||||
@@ -24,7 +23,9 @@ import net.minecraft.world.item.Items
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.InteractionResultHolder
|
||||
import net.minecraft.world.item.ItemNameBlockItem
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
|
||||
/**
|
||||
* An item that cures statuses. Based on the [status] parameter it can be either specific [Status]es or all statuses (none specified).
|
||||
@@ -32,7 +33,7 @@ import net.minecraft.world.level.Level
|
||||
* @author Hiroku
|
||||
* @since June 30th, 2023
|
||||
*/
|
||||
class StatusCureItem(val itemName: String, vararg val status: Status) : CobblemonItem(Properties()), PokemonSelectingItem {
|
||||
class StatusCureItem(val itemName: String, vararg val status: Status, block: Block) : ItemNameBlockItem(block, Properties()), PokemonSelectingItem {
|
||||
override val bagItem = object : BagItem {
|
||||
override val itemName = this@StatusCureItem.itemName
|
||||
override val returnItem = Items.AIR
|
||||
|
||||
+1
-2
@@ -29,8 +29,7 @@ class FormUpdatePacket(pokemon: () -> Pokemon?, form: FormData) : SingleUpdatePa
|
||||
val ID: ResourceLocation = cobblemonResource("packets/form-update")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): FormUpdatePacket {
|
||||
val pokemon = decodePokemon(buffer)
|
||||
val form = FormData()
|
||||
form.species = pokemon()!!.species
|
||||
val form = FormData().also { it.initialize(pokemon()!!.species) }
|
||||
form.decode(buffer)
|
||||
return FormUpdatePacket(pokemon, form)
|
||||
}
|
||||
|
||||
+7
-2
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.net.serverhandling.riding
|
||||
|
||||
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.net.messages.server.riding.DismountPokemonPacket
|
||||
import net.minecraft.server.MinecraftServer
|
||||
@@ -25,12 +26,16 @@ object DismountPokemonPacketHandler : ServerNetworkPacketHandler<DismountPokemon
|
||||
|
||||
val pokemon = player.vehicle as PokemonEntity
|
||||
if (!canPlayerStopRidingPokemon(pokemon, player)) return
|
||||
|
||||
val isRidingInAir = pokemon.ridingController?.context?.style == RidingStyle.AIR
|
||||
|
||||
if (pokemon.controllingPassenger == player) {
|
||||
pokemon.passengers.forEach { it.stopRiding() }
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
player.stopRiding()
|
||||
}
|
||||
|
||||
if (isRidingInAir) pokemon.setFlying(true)
|
||||
}
|
||||
|
||||
private fun canPlayerStopRidingPokemon(pokemon: PokemonEntity, player: ServerPlayer): Boolean {
|
||||
|
||||
@@ -199,6 +199,9 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
|
||||
var form = species.standardForm
|
||||
set(value) {
|
||||
// If nothing actually changed, avoid running heavy logic (e.g. updateMovesOnFormChange when the form hasn't really "changed")
|
||||
if (field == value) return
|
||||
|
||||
// Species updates already update HP but just a form change may require it
|
||||
// Moved to before the field was set else it won't actually do the hp calc proper <3
|
||||
val quotient = clamp(currentHealth / maxHealth.toFloat(), 0F, 1F)
|
||||
@@ -996,7 +999,7 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
this.currentFullness = max(0, this.currentFullness - value)
|
||||
}
|
||||
|
||||
// Amount of seconds that need to pass for the pokemon to lose 1 fullness value
|
||||
// Amount of ticks that need to pass for the pokemon to lose 1 fullness value
|
||||
fun getMetabolismRate(): Int {
|
||||
val speed = this.species.baseStats.getOrDefault(Stats.SPEED,0)
|
||||
|
||||
@@ -1009,16 +1012,12 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
//base berry count
|
||||
val baseBerryCount = 20
|
||||
|
||||
//rate of metabolism in seconds
|
||||
val metabolismRate = ((baseBerryCount.toDouble() - ((speed.toDouble() / BST.toDouble()) * baseBerryCount.toDouble()) * multiplier.toDouble()) * 60.0).toInt()
|
||||
|
||||
// returns value in seconds for the onSecondPassed function
|
||||
// check for below 0 value and set to minimum to 1 minute
|
||||
return if (metabolismRate <= 0) {
|
||||
1 * 60
|
||||
} else {
|
||||
metabolismRate
|
||||
var metabolismRateInSeconds = ((baseBerryCount.toDouble() - ((speed.toDouble() / BST.toDouble()) * baseBerryCount.toDouble()) * multiplier.toDouble()) * 60.0).toInt()
|
||||
if (metabolismRateInSeconds <= 0) {
|
||||
metabolismRateInSeconds = 1 * 60
|
||||
}
|
||||
|
||||
return metabolismRateInSeconds * 20
|
||||
}
|
||||
|
||||
// Boolean function that checks if a Pokemon can eat food based on fedTimes
|
||||
@@ -1037,13 +1036,18 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
this.interactionCooldowns.remove(group)
|
||||
}
|
||||
|
||||
open fun tickInteractionCooldown() {
|
||||
this.interactionCooldowns.entries.forEach { (key, value) ->
|
||||
val newValue = value - 1
|
||||
if(newValue <= 0)
|
||||
this.interactionCooldowns.remove(key)
|
||||
else
|
||||
this.interactionCooldowns.put(key, newValue)
|
||||
open fun tickInteractionCooldown(ticksPassed: Int) {
|
||||
val iterator = interactionCooldowns.entries.iterator()
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
val entry = iterator.next()
|
||||
val newValue = entry.value - ticksPassed.coerceAtLeast(1)
|
||||
|
||||
if (newValue <= 0) {
|
||||
iterator.remove()
|
||||
} else {
|
||||
entry.setValue(newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1054,9 +1058,8 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
/**
|
||||
* Called every second on Player owned and Pastured Pokémon for their fullness
|
||||
*/
|
||||
open fun tickMetabolism() {
|
||||
// have metabolism cycle increase each second
|
||||
metabolismCycle += 1
|
||||
open fun tickMetabolism(ticksPassed: Int) {
|
||||
metabolismCycle += ticksPassed.coerceAtLeast(1)
|
||||
|
||||
// if the metabolismCycle value equals the Pokemon's metabolism rate then decrease Fullness by 1
|
||||
if (metabolismCycle >= this.getMetabolismRate()) {
|
||||
@@ -2144,16 +2147,26 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
*/
|
||||
open fun self(): Pokemon = this
|
||||
|
||||
|
||||
/**
|
||||
* Function that sanitizes specific form-related moves when the form of this Pokémon changes.
|
||||
* We only want to sanitize `form_change` moves here so that intended illegalities from the user are preserved.
|
||||
*
|
||||
* E.g, Removing Overheat from Rotom when it is no longer Rotom-Heat and the target form is not compatible with Overheat.
|
||||
*/
|
||||
private fun updateMovesOnFormChange(newForm: FormData) {
|
||||
if (this.isClient) {
|
||||
return
|
||||
}
|
||||
if (this.isClient) return
|
||||
|
||||
val oldFormChangeMoves = this.form.moves.formChangeMoves.toSet()
|
||||
|
||||
// Only remove moves that were provided by the old form's form-change moves AND are not learnable by the new form
|
||||
for (i in 0 until MoveSet.MOVE_COUNT) {
|
||||
val move = this.moveSet[i]
|
||||
if (move != null && !LearnsetQuery.ANY.canLearn(move.template, newForm.moves)) {
|
||||
if (move != null && move.template in oldFormChangeMoves) {
|
||||
this.moveSet.setMove(i, null)
|
||||
}
|
||||
}
|
||||
|
||||
val benchedIterator = this.benchedMoves.iterator()
|
||||
while (benchedIterator.hasNext()) {
|
||||
val benchedMove = benchedIterator.next()
|
||||
@@ -2161,11 +2174,18 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
benchedIterator.remove()
|
||||
}
|
||||
}
|
||||
// Add form change moves
|
||||
|
||||
// Add new form's form-change moves
|
||||
newForm.moves.formChangeMoves.forEach { move ->
|
||||
// Under the hood these check if the moves already exist
|
||||
this.benchedMoves.add(BenchedMove(move, 0))
|
||||
if (this.moveSet.filterNotNull().none { it.template == move }) {
|
||||
if (this.moveSet.hasSpace()) {
|
||||
this.moveSet.add(move.create())
|
||||
} else {
|
||||
this.benchedMoves.add(BenchedMove(move, 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If moveset is empty try to find one valid move to fill it
|
||||
if (this.moveSet.filterNotNull().isEmpty()) {
|
||||
val benchedMove = this.benchedMoves.firstOrNull()
|
||||
|
||||
@@ -562,8 +562,8 @@ class OmniPathNodeMaker : NodeEvaluator() {
|
||||
//// PathType.WALKABLE
|
||||
//// } else if (blockState.canPathfindThrough(world, pos, NavigationType.AIR) && !blockStateBelow.isSideSolid(world, below, Direction.UP, SideShapeType.FULL)) {
|
||||
//// PathType.OPEN
|
||||
// } else if (blockState.`is`(BlockTags.LEAVES) && blockState.block == CobblemonBlocks.SACCHARINE_LEAVES && canPathThroughLeaves()) {
|
||||
// return PathType.OPEN
|
||||
if (canPathThroughLeaves() && blockState.block == CobblemonBlocks.SACCHARINE_LEAVES)
|
||||
return PathType.OPEN
|
||||
// } else PathType.BLOCKED
|
||||
|
||||
// This is the 1.6.1 logic but with some optimizations
|
||||
@@ -633,9 +633,6 @@ class OmniPathNodeMaker : NodeEvaluator() {
|
||||
pfContext, x, y, z, sizeX, sizeY, sizeZ, canOpenDoors, canPassDoors, set, PathType.BLOCKED, BlockPos(x, y, z), returnedEarlyPathType
|
||||
)
|
||||
|
||||
if (PathType.LEAVES in set) {
|
||||
return PathType.OPEN
|
||||
}
|
||||
|
||||
if (PathType.FENCE in set) {
|
||||
return PathType.FENCE
|
||||
@@ -755,7 +752,7 @@ class OmniPathNodeMaker : NodeEvaluator() {
|
||||
} else if (type == PathType.RAIL && block !is BaseRailBlock && pfContext.getCachedBlockState(pos.below()).block !is BaseRailBlock) {
|
||||
PathType.UNPASSABLE_RAIL
|
||||
} else if (type == PathType.LEAVES) {
|
||||
if (blockState.block === CobblemonBlocks.SACCHARINE_LEAVES && canPathThroughLeaves()) {
|
||||
if (canPathThroughLeaves() && blockState.block === CobblemonBlocks.SACCHARINE_LEAVES) {
|
||||
PathType.OPEN
|
||||
} else {
|
||||
PathType.BLOCKED
|
||||
|
||||
+4
-8
@@ -6,19 +6,15 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.properties.tags
|
||||
package com.cobblemon.mod.common.pokemon.properties
|
||||
|
||||
import com.cobblemon.mod.common.api.properties.CustomPokemonPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.StringProperty
|
||||
|
||||
object PokemonFlagProperty : CustomPokemonPropertyType<StringProperty> {
|
||||
|
||||
private const val KEY = "tag"
|
||||
|
||||
override val keys = setOf(KEY)
|
||||
object LabelProperty : CustomPokemonPropertyType<StringProperty> {
|
||||
override val keys = setOf("label", "tag")
|
||||
override val needsKey = true
|
||||
|
||||
override fun fromString(value: String?) = if (value == null) null else StringProperty(KEY, value, { _, _ -> }, { pokemon, underlyingValue -> pokemon.hasLabels(underlyingValue) })
|
||||
override fun fromString(value: String?) = if (value == null) null else StringProperty(keys.first(), value, { _, _ -> }, { pokemon, underlyingValue -> pokemon.hasLabels(underlyingValue) })
|
||||
|
||||
override fun examples() = emptySet<String>()
|
||||
}
|
||||
+15
-5
@@ -10,13 +10,14 @@ package com.cobblemon.mod.common.world.feature
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonBlocks
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonBiomeTags
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.core.Direction.UP
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.tags.BlockTags
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.world.item.component.CustomData
|
||||
import net.minecraft.world.level.WorldGenLevel
|
||||
import net.minecraft.world.level.block.Block.UPDATE_ALL
|
||||
import net.minecraft.world.level.block.Block.UPDATE_CLIENTS
|
||||
@@ -227,12 +228,20 @@ class SaccharineTreeFeature : Feature<BlockStateConfiguration>(BlockStateConfigu
|
||||
val i: Int = 2 + randomSource.nextInt(2)
|
||||
for (j in 0..<i) {
|
||||
if (isCombee > 0) {
|
||||
beehiveBlockEntity!!.storeBee(BeehiveBlockEntity.Occupant.create(randomSource.nextInt(599)))
|
||||
beehiveBlockEntity?.storeBee(BeehiveBlockEntity.Occupant.create(randomSource.nextInt(599)))
|
||||
} else {
|
||||
// We want to create a Pokemon entity here and turn it into a compound tag to store in the hive.
|
||||
// But creating a Pokemon entity during world generation can cause issues.
|
||||
// So instead we create custom compound tag that is a placeholder for an incomplete Pokemon.
|
||||
// This is caught and handled by BeeOccupantMixin.java, which turns it into a complete entity.
|
||||
val properties = "${POKEMON_ARGS} lvl=${LEVEL_RANGE.random()}"
|
||||
val pokemon = PokemonProperties.parse(properties)
|
||||
val entity = pokemon.createEntity(worldGenLevel.level)
|
||||
beehiveBlockEntity!!.addOccupant(entity)
|
||||
val compoundTag = CompoundTag()
|
||||
compoundTag.putString("id", POKEMON_PLACEHOLD_ID)
|
||||
compoundTag.putString("pokemonProperties", properties)
|
||||
val occupant = BeehiveBlockEntity.Occupant(
|
||||
CustomData.of(compoundTag), randomSource.nextInt(599), 600
|
||||
)
|
||||
beehiveBlockEntity?.storeBee(occupant)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -351,5 +360,6 @@ class SaccharineTreeFeature : Feature<BlockStateConfiguration>(BlockStateConfigu
|
||||
companion object {
|
||||
val POKEMON_ARGS = "combee"
|
||||
val LEVEL_RANGE = 5..15
|
||||
val POKEMON_PLACEHOLD_ID = "cobblemon_pokemon_entity_placeholder"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=north,amount=1": {
|
||||
"model": "cobblemon:block/antidote_0"
|
||||
},
|
||||
"facing=east,amount=1": {
|
||||
"model": "cobblemon:block/antidote_0",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=1": {
|
||||
"model": "cobblemon:block/antidote_0",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=1": {
|
||||
"model": "cobblemon:block/antidote_0",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=2": {
|
||||
"model": "cobblemon:block/antidote_1"
|
||||
},
|
||||
"facing=east,amount=2": {
|
||||
"model": "cobblemon:block/antidote_1",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=2": {
|
||||
"model": "cobblemon:block/antidote_1",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=2": {
|
||||
"model": "cobblemon:block/antidote_1",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=3": {
|
||||
"model": "cobblemon:block/antidote_2"
|
||||
},
|
||||
"facing=east,amount=3": {
|
||||
"model": "cobblemon:block/antidote_2",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=3": {
|
||||
"model": "cobblemon:block/antidote_2",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=3": {
|
||||
"model": "cobblemon:block/antidote_2",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=4": {
|
||||
"model": "cobblemon:block/antidote_3"
|
||||
},
|
||||
"facing=east,amount=4": {
|
||||
"model": "cobblemon:block/antidote_3",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=4": {
|
||||
"model": "cobblemon:block/antidote_3",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=4": {
|
||||
"model": "cobblemon:block/antidote_3",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=north,amount=1": {
|
||||
"model": "cobblemon:block/awakening_0"
|
||||
},
|
||||
"facing=east,amount=1": {
|
||||
"model": "cobblemon:block/awakening_0",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=1": {
|
||||
"model": "cobblemon:block/awakening_0",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=1": {
|
||||
"model": "cobblemon:block/awakening_0",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=2": {
|
||||
"model": "cobblemon:block/awakening_1"
|
||||
},
|
||||
"facing=east,amount=2": {
|
||||
"model": "cobblemon:block/awakening_1",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=2": {
|
||||
"model": "cobblemon:block/awakening_1",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=2": {
|
||||
"model": "cobblemon:block/awakening_1",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=3": {
|
||||
"model": "cobblemon:block/awakening_2"
|
||||
},
|
||||
"facing=east,amount=3": {
|
||||
"model": "cobblemon:block/awakening_2",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=3": {
|
||||
"model": "cobblemon:block/awakening_2",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=3": {
|
||||
"model": "cobblemon:block/awakening_2",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=4": {
|
||||
"model": "cobblemon:block/awakening_3"
|
||||
},
|
||||
"facing=east,amount=4": {
|
||||
"model": "cobblemon:block/awakening_3",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=4": {
|
||||
"model": "cobblemon:block/awakening_3",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=4": {
|
||||
"model": "cobblemon:block/awakening_3",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"variants": {
|
||||
"face=ceiling,facing=east": {
|
||||
"model": "cobblemon:block/black_plaque_hanging",
|
||||
"y": 90
|
||||
},
|
||||
"face=ceiling,facing=north": {
|
||||
"model": "cobblemon:block/black_plaque_hanging"
|
||||
},
|
||||
"face=ceiling,facing=south": {
|
||||
"model": "cobblemon:block/black_plaque_hanging",
|
||||
"y": 180
|
||||
},
|
||||
"face=ceiling,facing=west": {
|
||||
"model": "cobblemon:block/black_plaque_hanging",
|
||||
"y": 270
|
||||
},
|
||||
"face=floor,facing=east": {
|
||||
"model": "cobblemon:block/black_plaque_floor",
|
||||
"y": 90
|
||||
},
|
||||
"face=floor,facing=north": {
|
||||
"model": "cobblemon:block/black_plaque_floor"
|
||||
},
|
||||
"face=floor,facing=south": {
|
||||
"model": "cobblemon:block/black_plaque_floor",
|
||||
"y": 180
|
||||
},
|
||||
"face=floor,facing=west": {
|
||||
"model": "cobblemon:block/black_plaque_floor",
|
||||
"y": 270
|
||||
},
|
||||
"face=wall,facing=east": {
|
||||
"model": "cobblemon:block/black_plaque_wall",
|
||||
"y": 90
|
||||
},
|
||||
"face=wall,facing=north": {
|
||||
"model": "cobblemon:block/black_plaque_wall"
|
||||
},
|
||||
"face=wall,facing=south": {
|
||||
"model": "cobblemon:block/black_plaque_wall",
|
||||
"y": 180
|
||||
},
|
||||
"face=wall,facing=west": {
|
||||
"model": "cobblemon:block/black_plaque_wall",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"variants": {
|
||||
"face=ceiling,facing=east": {
|
||||
"model": "cobblemon:block/blue_plaque_hanging",
|
||||
"y": 90
|
||||
},
|
||||
"face=ceiling,facing=north": {
|
||||
"model": "cobblemon:block/blue_plaque_hanging"
|
||||
},
|
||||
"face=ceiling,facing=south": {
|
||||
"model": "cobblemon:block/blue_plaque_hanging",
|
||||
"y": 180
|
||||
},
|
||||
"face=ceiling,facing=west": {
|
||||
"model": "cobblemon:block/blue_plaque_hanging",
|
||||
"y": 270
|
||||
},
|
||||
"face=floor,facing=east": {
|
||||
"model": "cobblemon:block/blue_plaque_floor",
|
||||
"y": 90
|
||||
},
|
||||
"face=floor,facing=north": {
|
||||
"model": "cobblemon:block/blue_plaque_floor"
|
||||
},
|
||||
"face=floor,facing=south": {
|
||||
"model": "cobblemon:block/blue_plaque_floor",
|
||||
"y": 180
|
||||
},
|
||||
"face=floor,facing=west": {
|
||||
"model": "cobblemon:block/blue_plaque_floor",
|
||||
"y": 270
|
||||
},
|
||||
"face=wall,facing=east": {
|
||||
"model": "cobblemon:block/blue_plaque_wall",
|
||||
"y": 90
|
||||
},
|
||||
"face=wall,facing=north": {
|
||||
"model": "cobblemon:block/blue_plaque_wall"
|
||||
},
|
||||
"face=wall,facing=south": {
|
||||
"model": "cobblemon:block/blue_plaque_wall",
|
||||
"y": 180
|
||||
},
|
||||
"face=wall,facing=west": {
|
||||
"model": "cobblemon:block/blue_plaque_wall",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=north": {
|
||||
"model": "cobblemon:block/blunder_policy"
|
||||
},
|
||||
"facing=east": {
|
||||
"model": "cobblemon:block/blunder_policy",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south": {
|
||||
"model": "cobblemon:block/blunder_policy",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west": {
|
||||
"model": "cobblemon:block/blunder_policy",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"variants": {
|
||||
"face=ceiling,facing=east": {
|
||||
"model": "cobblemon:block/brown_plaque_hanging",
|
||||
"y": 90
|
||||
},
|
||||
"face=ceiling,facing=north": {
|
||||
"model": "cobblemon:block/brown_plaque_hanging"
|
||||
},
|
||||
"face=ceiling,facing=south": {
|
||||
"model": "cobblemon:block/brown_plaque_hanging",
|
||||
"y": 180
|
||||
},
|
||||
"face=ceiling,facing=west": {
|
||||
"model": "cobblemon:block/brown_plaque_hanging",
|
||||
"y": 270
|
||||
},
|
||||
"face=floor,facing=east": {
|
||||
"model": "cobblemon:block/brown_plaque_floor",
|
||||
"y": 90
|
||||
},
|
||||
"face=floor,facing=north": {
|
||||
"model": "cobblemon:block/brown_plaque_floor"
|
||||
},
|
||||
"face=floor,facing=south": {
|
||||
"model": "cobblemon:block/brown_plaque_floor",
|
||||
"y": 180
|
||||
},
|
||||
"face=floor,facing=west": {
|
||||
"model": "cobblemon:block/brown_plaque_floor",
|
||||
"y": 270
|
||||
},
|
||||
"face=wall,facing=east": {
|
||||
"model": "cobblemon:block/brown_plaque_wall",
|
||||
"y": 90
|
||||
},
|
||||
"face=wall,facing=north": {
|
||||
"model": "cobblemon:block/brown_plaque_wall"
|
||||
},
|
||||
"face=wall,facing=south": {
|
||||
"model": "cobblemon:block/brown_plaque_wall",
|
||||
"y": 180
|
||||
},
|
||||
"face=wall,facing=west": {
|
||||
"model": "cobblemon:block/brown_plaque_wall",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=north,amount=1": {
|
||||
"model": "cobblemon:block/burn_heal_0"
|
||||
},
|
||||
"facing=east,amount=1": {
|
||||
"model": "cobblemon:block/burn_heal_0",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=1": {
|
||||
"model": "cobblemon:block/burn_heal_0",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=1": {
|
||||
"model": "cobblemon:block/burn_heal_0",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=2": {
|
||||
"model": "cobblemon:block/burn_heal_1"
|
||||
},
|
||||
"facing=east,amount=2": {
|
||||
"model": "cobblemon:block/burn_heal_1",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=2": {
|
||||
"model": "cobblemon:block/burn_heal_1",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=2": {
|
||||
"model": "cobblemon:block/burn_heal_1",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=3": {
|
||||
"model": "cobblemon:block/burn_heal_2"
|
||||
},
|
||||
"facing=east,amount=3": {
|
||||
"model": "cobblemon:block/burn_heal_2",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=3": {
|
||||
"model": "cobblemon:block/burn_heal_2",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=3": {
|
||||
"model": "cobblemon:block/burn_heal_2",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=4": {
|
||||
"model": "cobblemon:block/burn_heal_3"
|
||||
},
|
||||
"facing=east,amount=4": {
|
||||
"model": "cobblemon:block/burn_heal_3",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=4": {
|
||||
"model": "cobblemon:block/burn_heal_3",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=4": {
|
||||
"model": "cobblemon:block/burn_heal_3",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=north,amount=1": {
|
||||
"model": "cobblemon:block/cleanse_tag_0"
|
||||
},
|
||||
"facing=east,amount=1": {
|
||||
"model": "cobblemon:block/cleanse_tag_0",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=1": {
|
||||
"model": "cobblemon:block/cleanse_tag_0",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=1": {
|
||||
"model": "cobblemon:block/cleanse_tag_0",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=2": {
|
||||
"model": "cobblemon:block/cleanse_tag_1"
|
||||
},
|
||||
"facing=east,amount=2": {
|
||||
"model": "cobblemon:block/cleanse_tag_1",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=2": {
|
||||
"model": "cobblemon:block/cleanse_tag_1",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=2": {
|
||||
"model": "cobblemon:block/cleanse_tag_1",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=3": {
|
||||
"model": "cobblemon:block/cleanse_tag_2"
|
||||
},
|
||||
"facing=east,amount=3": {
|
||||
"model": "cobblemon:block/cleanse_tag_2",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=3": {
|
||||
"model": "cobblemon:block/cleanse_tag_2",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=3": {
|
||||
"model": "cobblemon:block/cleanse_tag_2",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=4": {
|
||||
"model": "cobblemon:block/cleanse_tag_3"
|
||||
},
|
||||
"facing=east,amount=4": {
|
||||
"model": "cobblemon:block/cleanse_tag_3",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=4": {
|
||||
"model": "cobblemon:block/cleanse_tag_3",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=4": {
|
||||
"model": "cobblemon:block/cleanse_tag_3",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=5": {
|
||||
"model": "cobblemon:block/cleanse_tag_4"
|
||||
},
|
||||
"facing=east,amount=5": {
|
||||
"model": "cobblemon:block/cleanse_tag_4",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=5": {
|
||||
"model": "cobblemon:block/cleanse_tag_4",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=5": {
|
||||
"model": "cobblemon:block/cleanse_tag_4",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=6": {
|
||||
"model": "cobblemon:block/cleanse_tag_5"
|
||||
},
|
||||
"facing=east,amount=6": {
|
||||
"model": "cobblemon:block/cleanse_tag_5",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=6": {
|
||||
"model": "cobblemon:block/cleanse_tag_5",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=6": {
|
||||
"model": "cobblemon:block/cleanse_tag_5",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=7": {
|
||||
"model": "cobblemon:block/cleanse_tag_6"
|
||||
},
|
||||
"facing=east,amount=7": {
|
||||
"model": "cobblemon:block/cleanse_tag_6",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=7": {
|
||||
"model": "cobblemon:block/cleanse_tag_6",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=7": {
|
||||
"model": "cobblemon:block/cleanse_tag_6",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=8": {
|
||||
"model": "cobblemon:block/cleanse_tag_7"
|
||||
},
|
||||
"facing=east,amount=8": {
|
||||
"model": "cobblemon:block/cleanse_tag_7",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=8": {
|
||||
"model": "cobblemon:block/cleanse_tag_7",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=8": {
|
||||
"model": "cobblemon:block/cleanse_tag_7",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"variants": {
|
||||
"face=ceiling,facing=east": {
|
||||
"model": "cobblemon:block/cyan_plaque_hanging",
|
||||
"y": 90
|
||||
},
|
||||
"face=ceiling,facing=north": {
|
||||
"model": "cobblemon:block/cyan_plaque_hanging"
|
||||
},
|
||||
"face=ceiling,facing=south": {
|
||||
"model": "cobblemon:block/cyan_plaque_hanging",
|
||||
"y": 180
|
||||
},
|
||||
"face=ceiling,facing=west": {
|
||||
"model": "cobblemon:block/cyan_plaque_hanging",
|
||||
"y": 270
|
||||
},
|
||||
"face=floor,facing=east": {
|
||||
"model": "cobblemon:block/cyan_plaque_floor",
|
||||
"y": 90
|
||||
},
|
||||
"face=floor,facing=north": {
|
||||
"model": "cobblemon:block/cyan_plaque_floor"
|
||||
},
|
||||
"face=floor,facing=south": {
|
||||
"model": "cobblemon:block/cyan_plaque_floor",
|
||||
"y": 180
|
||||
},
|
||||
"face=floor,facing=west": {
|
||||
"model": "cobblemon:block/cyan_plaque_floor",
|
||||
"y": 270
|
||||
},
|
||||
"face=wall,facing=east": {
|
||||
"model": "cobblemon:block/cyan_plaque_wall",
|
||||
"y": 90
|
||||
},
|
||||
"face=wall,facing=north": {
|
||||
"model": "cobblemon:block/cyan_plaque_wall"
|
||||
},
|
||||
"face=wall,facing=south": {
|
||||
"model": "cobblemon:block/cyan_plaque_wall",
|
||||
"y": 180
|
||||
},
|
||||
"face=wall,facing=west": {
|
||||
"model": "cobblemon:block/cyan_plaque_wall",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=north,amount=1": {
|
||||
"model": "cobblemon:block/dire_hit_0"
|
||||
},
|
||||
"facing=east,amount=1": {
|
||||
"model": "cobblemon:block/dire_hit_0",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=1": {
|
||||
"model": "cobblemon:block/dire_hit_0",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=1": {
|
||||
"model": "cobblemon:block/dire_hit_0",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=2": {
|
||||
"model": "cobblemon:block/dire_hit_1"
|
||||
},
|
||||
"facing=east,amount=2": {
|
||||
"model": "cobblemon:block/dire_hit_1",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=2": {
|
||||
"model": "cobblemon:block/dire_hit_1",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=2": {
|
||||
"model": "cobblemon:block/dire_hit_1",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=3": {
|
||||
"model": "cobblemon:block/dire_hit_2"
|
||||
},
|
||||
"facing=east,amount=3": {
|
||||
"model": "cobblemon:block/dire_hit_2",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=3": {
|
||||
"model": "cobblemon:block/dire_hit_2",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=3": {
|
||||
"model": "cobblemon:block/dire_hit_2",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=4": {
|
||||
"model": "cobblemon:block/dire_hit_3"
|
||||
},
|
||||
"facing=east,amount=4": {
|
||||
"model": "cobblemon:block/dire_hit_3",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=4": {
|
||||
"model": "cobblemon:block/dire_hit_3",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=4": {
|
||||
"model": "cobblemon:block/dire_hit_3",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=north,amount=1": {
|
||||
"model": "cobblemon:block/elixir_0"
|
||||
},
|
||||
"facing=east,amount=1": {
|
||||
"model": "cobblemon:block/elixir_0",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=1": {
|
||||
"model": "cobblemon:block/elixir_0",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=1": {
|
||||
"model": "cobblemon:block/elixir_0",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=2": {
|
||||
"model": "cobblemon:block/elixir_1"
|
||||
},
|
||||
"facing=east,amount=2": {
|
||||
"model": "cobblemon:block/elixir_1",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=2": {
|
||||
"model": "cobblemon:block/elixir_1",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=2": {
|
||||
"model": "cobblemon:block/elixir_1",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=3": {
|
||||
"model": "cobblemon:block/elixir_2"
|
||||
},
|
||||
"facing=east,amount=3": {
|
||||
"model": "cobblemon:block/elixir_2",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=3": {
|
||||
"model": "cobblemon:block/elixir_2",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=3": {
|
||||
"model": "cobblemon:block/elixir_2",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=4": {
|
||||
"model": "cobblemon:block/elixir_3"
|
||||
},
|
||||
"facing=east,amount=4": {
|
||||
"model": "cobblemon:block/elixir_3",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=4": {
|
||||
"model": "cobblemon:block/elixir_3",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=4": {
|
||||
"model": "cobblemon:block/elixir_3",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=north,amount=1": {
|
||||
"model": "cobblemon:block/ether_0"
|
||||
},
|
||||
"facing=east,amount=1": {
|
||||
"model": "cobblemon:block/ether_0",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=1": {
|
||||
"model": "cobblemon:block/ether_0",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=1": {
|
||||
"model": "cobblemon:block/ether_0",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=2": {
|
||||
"model": "cobblemon:block/ether_1"
|
||||
},
|
||||
"facing=east,amount=2": {
|
||||
"model": "cobblemon:block/ether_1",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=2": {
|
||||
"model": "cobblemon:block/ether_1",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=2": {
|
||||
"model": "cobblemon:block/ether_1",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=3": {
|
||||
"model": "cobblemon:block/ether_2"
|
||||
},
|
||||
"facing=east,amount=3": {
|
||||
"model": "cobblemon:block/ether_2",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=3": {
|
||||
"model": "cobblemon:block/ether_2",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=3": {
|
||||
"model": "cobblemon:block/ether_2",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=4": {
|
||||
"model": "cobblemon:block/ether_3"
|
||||
},
|
||||
"facing=east,amount=4": {
|
||||
"model": "cobblemon:block/ether_3",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=4": {
|
||||
"model": "cobblemon:block/ether_3",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=4": {
|
||||
"model": "cobblemon:block/ether_3",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=north,amount=1": {
|
||||
"model": "cobblemon:block/full_heal_0"
|
||||
},
|
||||
"facing=east,amount=1": {
|
||||
"model": "cobblemon:block/full_heal_0",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=1": {
|
||||
"model": "cobblemon:block/full_heal_0",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=1": {
|
||||
"model": "cobblemon:block/full_heal_0",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=2": {
|
||||
"model": "cobblemon:block/full_heal_1"
|
||||
},
|
||||
"facing=east,amount=2": {
|
||||
"model": "cobblemon:block/full_heal_1",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=2": {
|
||||
"model": "cobblemon:block/full_heal_1",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=2": {
|
||||
"model": "cobblemon:block/full_heal_1",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=3": {
|
||||
"model": "cobblemon:block/full_heal_2"
|
||||
},
|
||||
"facing=east,amount=3": {
|
||||
"model": "cobblemon:block/full_heal_2",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=3": {
|
||||
"model": "cobblemon:block/full_heal_2",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=3": {
|
||||
"model": "cobblemon:block/full_heal_2",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=4": {
|
||||
"model": "cobblemon:block/full_heal_3"
|
||||
},
|
||||
"facing=east,amount=4": {
|
||||
"model": "cobblemon:block/full_heal_3",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=4": {
|
||||
"model": "cobblemon:block/full_heal_3",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=4": {
|
||||
"model": "cobblemon:block/full_heal_3",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=north,amount=1": {
|
||||
"model": "cobblemon:block/full_restore_0"
|
||||
},
|
||||
"facing=east,amount=1": {
|
||||
"model": "cobblemon:block/full_restore_0",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=1": {
|
||||
"model": "cobblemon:block/full_restore_0",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=1": {
|
||||
"model": "cobblemon:block/full_restore_0",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=2": {
|
||||
"model": "cobblemon:block/full_restore_1"
|
||||
},
|
||||
"facing=east,amount=2": {
|
||||
"model": "cobblemon:block/full_restore_1",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=2": {
|
||||
"model": "cobblemon:block/full_restore_1",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=2": {
|
||||
"model": "cobblemon:block/full_restore_1",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=3": {
|
||||
"model": "cobblemon:block/full_restore_2"
|
||||
},
|
||||
"facing=east,amount=3": {
|
||||
"model": "cobblemon:block/full_restore_2",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=3": {
|
||||
"model": "cobblemon:block/full_restore_2",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=3": {
|
||||
"model": "cobblemon:block/full_restore_2",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=4": {
|
||||
"model": "cobblemon:block/full_restore_3"
|
||||
},
|
||||
"facing=east,amount=4": {
|
||||
"model": "cobblemon:block/full_restore_3",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=4": {
|
||||
"model": "cobblemon:block/full_restore_3",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=4": {
|
||||
"model": "cobblemon:block/full_restore_3",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"variants": {
|
||||
"face=ceiling,facing=east": {
|
||||
"model": "cobblemon:block/gray_plaque_hanging",
|
||||
"y": 90
|
||||
},
|
||||
"face=ceiling,facing=north": {
|
||||
"model": "cobblemon:block/gray_plaque_hanging"
|
||||
},
|
||||
"face=ceiling,facing=south": {
|
||||
"model": "cobblemon:block/gray_plaque_hanging",
|
||||
"y": 180
|
||||
},
|
||||
"face=ceiling,facing=west": {
|
||||
"model": "cobblemon:block/gray_plaque_hanging",
|
||||
"y": 270
|
||||
},
|
||||
"face=floor,facing=east": {
|
||||
"model": "cobblemon:block/gray_plaque_floor",
|
||||
"y": 90
|
||||
},
|
||||
"face=floor,facing=north": {
|
||||
"model": "cobblemon:block/gray_plaque_floor"
|
||||
},
|
||||
"face=floor,facing=south": {
|
||||
"model": "cobblemon:block/gray_plaque_floor",
|
||||
"y": 180
|
||||
},
|
||||
"face=floor,facing=west": {
|
||||
"model": "cobblemon:block/gray_plaque_floor",
|
||||
"y": 270
|
||||
},
|
||||
"face=wall,facing=east": {
|
||||
"model": "cobblemon:block/gray_plaque_wall",
|
||||
"y": 90
|
||||
},
|
||||
"face=wall,facing=north": {
|
||||
"model": "cobblemon:block/gray_plaque_wall"
|
||||
},
|
||||
"face=wall,facing=south": {
|
||||
"model": "cobblemon:block/gray_plaque_wall",
|
||||
"y": 180
|
||||
},
|
||||
"face=wall,facing=west": {
|
||||
"model": "cobblemon:block/gray_plaque_wall",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"variants": {
|
||||
"face=ceiling,facing=east": {
|
||||
"model": "cobblemon:block/green_plaque_hanging",
|
||||
"y": 90
|
||||
},
|
||||
"face=ceiling,facing=north": {
|
||||
"model": "cobblemon:block/green_plaque_hanging"
|
||||
},
|
||||
"face=ceiling,facing=south": {
|
||||
"model": "cobblemon:block/green_plaque_hanging",
|
||||
"y": 180
|
||||
},
|
||||
"face=ceiling,facing=west": {
|
||||
"model": "cobblemon:block/green_plaque_hanging",
|
||||
"y": 270
|
||||
},
|
||||
"face=floor,facing=east": {
|
||||
"model": "cobblemon:block/green_plaque_floor",
|
||||
"y": 90
|
||||
},
|
||||
"face=floor,facing=north": {
|
||||
"model": "cobblemon:block/green_plaque_floor"
|
||||
},
|
||||
"face=floor,facing=south": {
|
||||
"model": "cobblemon:block/green_plaque_floor",
|
||||
"y": 180
|
||||
},
|
||||
"face=floor,facing=west": {
|
||||
"model": "cobblemon:block/green_plaque_floor",
|
||||
"y": 270
|
||||
},
|
||||
"face=wall,facing=east": {
|
||||
"model": "cobblemon:block/green_plaque_wall",
|
||||
"y": 90
|
||||
},
|
||||
"face=wall,facing=north": {
|
||||
"model": "cobblemon:block/green_plaque_wall"
|
||||
},
|
||||
"face=wall,facing=south": {
|
||||
"model": "cobblemon:block/green_plaque_wall",
|
||||
"y": 180
|
||||
},
|
||||
"face=wall,facing=west": {
|
||||
"model": "cobblemon:block/green_plaque_wall",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=north,amount=1": {
|
||||
"model": "cobblemon:block/guard_spec_0"
|
||||
},
|
||||
"facing=east,amount=1": {
|
||||
"model": "cobblemon:block/guard_spec_0",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=1": {
|
||||
"model": "cobblemon:block/guard_spec_0",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=1": {
|
||||
"model": "cobblemon:block/guard_spec_0",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=2": {
|
||||
"model": "cobblemon:block/guard_spec_1"
|
||||
},
|
||||
"facing=east,amount=2": {
|
||||
"model": "cobblemon:block/guard_spec_1",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=2": {
|
||||
"model": "cobblemon:block/guard_spec_1",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=2": {
|
||||
"model": "cobblemon:block/guard_spec_1",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=3": {
|
||||
"model": "cobblemon:block/guard_spec_2"
|
||||
},
|
||||
"facing=east,amount=3": {
|
||||
"model": "cobblemon:block/guard_spec_2",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=3": {
|
||||
"model": "cobblemon:block/guard_spec_2",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=3": {
|
||||
"model": "cobblemon:block/guard_spec_2",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=4": {
|
||||
"model": "cobblemon:block/guard_spec_3"
|
||||
},
|
||||
"facing=east,amount=4": {
|
||||
"model": "cobblemon:block/guard_spec_3",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=4": {
|
||||
"model": "cobblemon:block/guard_spec_3",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=4": {
|
||||
"model": "cobblemon:block/guard_spec_3",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=north,amount=1": {
|
||||
"model": "cobblemon:block/hyper_potion_0"
|
||||
},
|
||||
"facing=east,amount=1": {
|
||||
"model": "cobblemon:block/hyper_potion_0",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=1": {
|
||||
"model": "cobblemon:block/hyper_potion_0",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=1": {
|
||||
"model": "cobblemon:block/hyper_potion_0",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=2": {
|
||||
"model": "cobblemon:block/hyper_potion_1"
|
||||
},
|
||||
"facing=east,amount=2": {
|
||||
"model": "cobblemon:block/hyper_potion_1",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=2": {
|
||||
"model": "cobblemon:block/hyper_potion_1",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=2": {
|
||||
"model": "cobblemon:block/hyper_potion_1",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=3": {
|
||||
"model": "cobblemon:block/hyper_potion_2"
|
||||
},
|
||||
"facing=east,amount=3": {
|
||||
"model": "cobblemon:block/hyper_potion_2",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=3": {
|
||||
"model": "cobblemon:block/hyper_potion_2",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=3": {
|
||||
"model": "cobblemon:block/hyper_potion_2",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=4": {
|
||||
"model": "cobblemon:block/hyper_potion_3"
|
||||
},
|
||||
"facing=east,amount=4": {
|
||||
"model": "cobblemon:block/hyper_potion_3",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=4": {
|
||||
"model": "cobblemon:block/hyper_potion_3",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=4": {
|
||||
"model": "cobblemon:block/hyper_potion_3",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=north,amount=1": {
|
||||
"model": "cobblemon:block/ice_heal_0"
|
||||
},
|
||||
"facing=east,amount=1": {
|
||||
"model": "cobblemon:block/ice_heal_0",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=1": {
|
||||
"model": "cobblemon:block/ice_heal_0",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=1": {
|
||||
"model": "cobblemon:block/ice_heal_0",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=2": {
|
||||
"model": "cobblemon:block/ice_heal_1"
|
||||
},
|
||||
"facing=east,amount=2": {
|
||||
"model": "cobblemon:block/ice_heal_1",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=2": {
|
||||
"model": "cobblemon:block/ice_heal_1",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=2": {
|
||||
"model": "cobblemon:block/ice_heal_1",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=3": {
|
||||
"model": "cobblemon:block/ice_heal_2"
|
||||
},
|
||||
"facing=east,amount=3": {
|
||||
"model": "cobblemon:block/ice_heal_2",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=3": {
|
||||
"model": "cobblemon:block/ice_heal_2",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=3": {
|
||||
"model": "cobblemon:block/ice_heal_2",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=4": {
|
||||
"model": "cobblemon:block/ice_heal_3"
|
||||
},
|
||||
"facing=east,amount=4": {
|
||||
"model": "cobblemon:block/ice_heal_3",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=4": {
|
||||
"model": "cobblemon:block/ice_heal_3",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=4": {
|
||||
"model": "cobblemon:block/ice_heal_3",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"variants": {
|
||||
"face=ceiling,facing=east": {
|
||||
"model": "cobblemon:block/light_blue_plaque_hanging",
|
||||
"y": 90
|
||||
},
|
||||
"face=ceiling,facing=north": {
|
||||
"model": "cobblemon:block/light_blue_plaque_hanging"
|
||||
},
|
||||
"face=ceiling,facing=south": {
|
||||
"model": "cobblemon:block/light_blue_plaque_hanging",
|
||||
"y": 180
|
||||
},
|
||||
"face=ceiling,facing=west": {
|
||||
"model": "cobblemon:block/light_blue_plaque_hanging",
|
||||
"y": 270
|
||||
},
|
||||
"face=floor,facing=east": {
|
||||
"model": "cobblemon:block/light_blue_plaque_floor",
|
||||
"y": 90
|
||||
},
|
||||
"face=floor,facing=north": {
|
||||
"model": "cobblemon:block/light_blue_plaque_floor"
|
||||
},
|
||||
"face=floor,facing=south": {
|
||||
"model": "cobblemon:block/light_blue_plaque_floor",
|
||||
"y": 180
|
||||
},
|
||||
"face=floor,facing=west": {
|
||||
"model": "cobblemon:block/light_blue_plaque_floor",
|
||||
"y": 270
|
||||
},
|
||||
"face=wall,facing=east": {
|
||||
"model": "cobblemon:block/light_blue_plaque_wall",
|
||||
"y": 90
|
||||
},
|
||||
"face=wall,facing=north": {
|
||||
"model": "cobblemon:block/light_blue_plaque_wall"
|
||||
},
|
||||
"face=wall,facing=south": {
|
||||
"model": "cobblemon:block/light_blue_plaque_wall",
|
||||
"y": 180
|
||||
},
|
||||
"face=wall,facing=west": {
|
||||
"model": "cobblemon:block/light_blue_plaque_wall",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"variants": {
|
||||
"face=ceiling,facing=east": {
|
||||
"model": "cobblemon:block/light_gray_plaque_hanging",
|
||||
"y": 90
|
||||
},
|
||||
"face=ceiling,facing=north": {
|
||||
"model": "cobblemon:block/light_gray_plaque_hanging"
|
||||
},
|
||||
"face=ceiling,facing=south": {
|
||||
"model": "cobblemon:block/light_gray_plaque_hanging",
|
||||
"y": 180
|
||||
},
|
||||
"face=ceiling,facing=west": {
|
||||
"model": "cobblemon:block/light_gray_plaque_hanging",
|
||||
"y": 270
|
||||
},
|
||||
"face=floor,facing=east": {
|
||||
"model": "cobblemon:block/light_gray_plaque_floor",
|
||||
"y": 90
|
||||
},
|
||||
"face=floor,facing=north": {
|
||||
"model": "cobblemon:block/light_gray_plaque_floor"
|
||||
},
|
||||
"face=floor,facing=south": {
|
||||
"model": "cobblemon:block/light_gray_plaque_floor",
|
||||
"y": 180
|
||||
},
|
||||
"face=floor,facing=west": {
|
||||
"model": "cobblemon:block/light_gray_plaque_floor",
|
||||
"y": 270
|
||||
},
|
||||
"face=wall,facing=east": {
|
||||
"model": "cobblemon:block/light_gray_plaque_wall",
|
||||
"y": 90
|
||||
},
|
||||
"face=wall,facing=north": {
|
||||
"model": "cobblemon:block/light_gray_plaque_wall"
|
||||
},
|
||||
"face=wall,facing=south": {
|
||||
"model": "cobblemon:block/light_gray_plaque_wall",
|
||||
"y": 180
|
||||
},
|
||||
"face=wall,facing=west": {
|
||||
"model": "cobblemon:block/light_gray_plaque_wall",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"variants": {
|
||||
"face=ceiling,facing=east": {
|
||||
"model": "cobblemon:block/lime_plaque_hanging",
|
||||
"y": 90
|
||||
},
|
||||
"face=ceiling,facing=north": {
|
||||
"model": "cobblemon:block/lime_plaque_hanging"
|
||||
},
|
||||
"face=ceiling,facing=south": {
|
||||
"model": "cobblemon:block/lime_plaque_hanging",
|
||||
"y": 180
|
||||
},
|
||||
"face=ceiling,facing=west": {
|
||||
"model": "cobblemon:block/lime_plaque_hanging",
|
||||
"y": 270
|
||||
},
|
||||
"face=floor,facing=east": {
|
||||
"model": "cobblemon:block/lime_plaque_floor",
|
||||
"y": 90
|
||||
},
|
||||
"face=floor,facing=north": {
|
||||
"model": "cobblemon:block/lime_plaque_floor"
|
||||
},
|
||||
"face=floor,facing=south": {
|
||||
"model": "cobblemon:block/lime_plaque_floor",
|
||||
"y": 180
|
||||
},
|
||||
"face=floor,facing=west": {
|
||||
"model": "cobblemon:block/lime_plaque_floor",
|
||||
"y": 270
|
||||
},
|
||||
"face=wall,facing=east": {
|
||||
"model": "cobblemon:block/lime_plaque_wall",
|
||||
"y": 90
|
||||
},
|
||||
"face=wall,facing=north": {
|
||||
"model": "cobblemon:block/lime_plaque_wall"
|
||||
},
|
||||
"face=wall,facing=south": {
|
||||
"model": "cobblemon:block/lime_plaque_wall",
|
||||
"y": 180
|
||||
},
|
||||
"face=wall,facing=west": {
|
||||
"model": "cobblemon:block/lime_plaque_wall",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"variants": {
|
||||
"face=ceiling,facing=east": {
|
||||
"model": "cobblemon:block/magenta_plaque_hanging",
|
||||
"y": 90
|
||||
},
|
||||
"face=ceiling,facing=north": {
|
||||
"model": "cobblemon:block/magenta_plaque_hanging"
|
||||
},
|
||||
"face=ceiling,facing=south": {
|
||||
"model": "cobblemon:block/magenta_plaque_hanging",
|
||||
"y": 180
|
||||
},
|
||||
"face=ceiling,facing=west": {
|
||||
"model": "cobblemon:block/magenta_plaque_hanging",
|
||||
"y": 270
|
||||
},
|
||||
"face=floor,facing=east": {
|
||||
"model": "cobblemon:block/magenta_plaque_floor",
|
||||
"y": 90
|
||||
},
|
||||
"face=floor,facing=north": {
|
||||
"model": "cobblemon:block/magenta_plaque_floor"
|
||||
},
|
||||
"face=floor,facing=south": {
|
||||
"model": "cobblemon:block/magenta_plaque_floor",
|
||||
"y": 180
|
||||
},
|
||||
"face=floor,facing=west": {
|
||||
"model": "cobblemon:block/magenta_plaque_floor",
|
||||
"y": 270
|
||||
},
|
||||
"face=wall,facing=east": {
|
||||
"model": "cobblemon:block/magenta_plaque_wall",
|
||||
"y": 90
|
||||
},
|
||||
"face=wall,facing=north": {
|
||||
"model": "cobblemon:block/magenta_plaque_wall"
|
||||
},
|
||||
"face=wall,facing=south": {
|
||||
"model": "cobblemon:block/magenta_plaque_wall",
|
||||
"y": 180
|
||||
},
|
||||
"face=wall,facing=west": {
|
||||
"model": "cobblemon:block/magenta_plaque_wall",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=north,amount=1": {
|
||||
"model": "cobblemon:block/max_elixir_0"
|
||||
},
|
||||
"facing=east,amount=1": {
|
||||
"model": "cobblemon:block/max_elixir_0",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=1": {
|
||||
"model": "cobblemon:block/max_elixir_0",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=1": {
|
||||
"model": "cobblemon:block/max_elixir_0",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=2": {
|
||||
"model": "cobblemon:block/max_elixir_1"
|
||||
},
|
||||
"facing=east,amount=2": {
|
||||
"model": "cobblemon:block/max_elixir_1",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=2": {
|
||||
"model": "cobblemon:block/max_elixir_1",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=2": {
|
||||
"model": "cobblemon:block/max_elixir_1",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=3": {
|
||||
"model": "cobblemon:block/max_elixir_2"
|
||||
},
|
||||
"facing=east,amount=3": {
|
||||
"model": "cobblemon:block/max_elixir_2",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=3": {
|
||||
"model": "cobblemon:block/max_elixir_2",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=3": {
|
||||
"model": "cobblemon:block/max_elixir_2",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=4": {
|
||||
"model": "cobblemon:block/max_elixir_3"
|
||||
},
|
||||
"facing=east,amount=4": {
|
||||
"model": "cobblemon:block/max_elixir_3",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=4": {
|
||||
"model": "cobblemon:block/max_elixir_3",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=4": {
|
||||
"model": "cobblemon:block/max_elixir_3",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=north,amount=1": {
|
||||
"model": "cobblemon:block/max_ether_0"
|
||||
},
|
||||
"facing=east,amount=1": {
|
||||
"model": "cobblemon:block/max_ether_0",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=1": {
|
||||
"model": "cobblemon:block/max_ether_0",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=1": {
|
||||
"model": "cobblemon:block/max_ether_0",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=2": {
|
||||
"model": "cobblemon:block/max_ether_1"
|
||||
},
|
||||
"facing=east,amount=2": {
|
||||
"model": "cobblemon:block/max_ether_1",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=2": {
|
||||
"model": "cobblemon:block/max_ether_1",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=2": {
|
||||
"model": "cobblemon:block/max_ether_1",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=3": {
|
||||
"model": "cobblemon:block/max_ether_2"
|
||||
},
|
||||
"facing=east,amount=3": {
|
||||
"model": "cobblemon:block/max_ether_2",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=3": {
|
||||
"model": "cobblemon:block/max_ether_2",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=3": {
|
||||
"model": "cobblemon:block/max_ether_2",
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,amount=4": {
|
||||
"model": "cobblemon:block/max_ether_3"
|
||||
},
|
||||
"facing=east,amount=4": {
|
||||
"model": "cobblemon:block/max_ether_3",
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,amount=4": {
|
||||
"model": "cobblemon:block/max_ether_3",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,amount=4": {
|
||||
"model": "cobblemon:block/max_ether_3",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user