Compare commits

..
Author SHA1 Message Date
Apion d0cbc78b31 Configurable dance distance 2025-04-26 15:29:06 -04:00
Apion f2a03e40ed Make dancing pose driven instead of a molang condition 2025-04-26 15:08:39 -04:00
Landon Wills 87071bedbe Move dance behaviour to delegates 2025-04-15 07:59:40 -04:00
Landon ebe33e200c Remove debug code 2025-04-15 11:36:50 +00:00
Landon 15f30721b4 Rename dance pose 2025-04-15 06:12:03 +00:00
Landon Wills c3c4d6685e :catJAM: 2025-04-14 23:34:38 -04:00
196 changed files with 9227 additions and 32108 deletions
-20
View File
@@ -17,8 +17,6 @@
- Added cosmetics for Gurdurr, Conkeldurr, Squirtle Line, Sneasler, Sandle line, Treecko line, Braixen, Delphox, and Dragonite.
- Added `/transformmodelpart (position|rotation|scale) <modelPart> <transform: x y z>` command that can add transformations to a pokemon's model part.
- The player executing the command must be facing the target pokemon entity. Transformations are not persistent and will revert when resources are reloaded.
- Added lang keys for all moves and abilities up to Generation 9.
- Fixed Moon Ball moon phase logic to actually work correctly
### Pokémon Added
@@ -78,8 +76,6 @@
- Sneasler
- Braixen
- Delphox
- Cinderace
- Kangaskhan
### Model updates for the following Pokémon
- Gyarados
@@ -101,32 +97,18 @@
- Pidgeot
- Nosepass
- Probopass
- Kangaskhan
- Cinderace
- Magnezone
- Metagross
- Added Syrupy Apples.
### Changes
- Renamed `chargeGainedPerTick` config to `secondsToChargeHealingMachine`.
- Made Blocks of Gold count as Big Nuggets when held by a Pokémon (for Fling functionality)
- Players can now eat Sweet and Tart Apples, Whipped Dreams, and the Alcremie Sweets.
- Updated Sweet and Tart Apple sprites
- Updated the following recipes: Air Balloon, Assault Vest, Binding Band, Black Belt, Blunder Policy, Choice Band, Choice Scarf, Cleanse Tag, Covert Cloak, Destiny Knot, Eject Button, Expert Belt, Focus Band, Focus Sash, Magnet, Metronome, Muscle Band, Power Anklet, Power Band, Power Belt, Power Bracer, Power Lens, Power Weight, Protective Pads, Protein, Punching Glove, Reaper Cloth, Rocky Helmet, Room Service, Sachet, Safety Goggles, Silk Scarf, Spell Tag, Utility Umbrella, Weakness Policy, Zinc
- Added alternate ingredient options to the following recipes: Cell Battery, Charcoal Stick, Dragon Fang, Miracle Seed, Mystic Water, Never Melt Ice, Twisted Spoon, Damp Rock, Heat Rock, Icy Rock, Smooth Rock
- Grouped together some recipes within the Recipe Book. Groups include: the seven basic Poké Balls, the seven basic Ancient Poké Balls, Gilded Chests, Pokedexes, and the Weather Rocks.
- Updated some item tags to better integrate behaviours between Cobblemon, Vanilla Minecraft, and other mods
- Removed Cooked Meat, Raw Meat, Protein Ingredients, and Zinc Ingredients, the first two are now using `c` namespace tags, the latter have better integrated use of tags within their recipes which removes need for custom tags.
- Added our seeds tag into `#c:seeds`, which is now made use of for the Miracle Seed recipe.
- Tweaked the Natural Materials Vanilla file to fit with the changes to tags
- Substantially optimised spawning checks mainly by front-loading biome filtering.
- When using the `cobblemon` or `generation_9` capture calculators a critical capture with a single shake will always play for successful captures when you've already registered the Pokémon as caught in your Pokédex.
- Improved the performance of saving Pokédex and player data.
- Pokémon hitbox now scales with entity attribute `generic.scale`.
- Removed Shulker aspect and replaced it with cosmetic_item-shulker_shell.
- Shulker shell Forretress is now a cosmetic rather than a special evo and thus all shulker Forretress will revert back to normal until a shulker shell is put in their cosmetic slot.
- Updated `doPokemonSpawning` gamerule to support per-dimension configurations.
- The Pokedex now displays a form name of a "normal" Pokémon for when the base form is still a named form.
### Fixes
- Fixed Particles sometimes facing the wrong direction (looking at you, Swords Dance)
@@ -155,7 +137,6 @@
- Fixed Pokémon marked as silent still playing shiny sounds and effects.
- Fixed an issue with newer versions of Fabric API where underground Pokémon were spawning in The End.
- Fixed spawning not working well when you're at high points surrounded by lower altitude spawning areas, such as flying.
- Fixed certain Pokémon with forms not having appropriate stock Pokédex entries.
### Developer
- A finished battle now has winners and losers set inside of `PokemonBattle` instead of them always being empty.
@@ -192,7 +173,6 @@
- Added `pokemon` as an available Molang function for the `battleActor` functions.
- Fixed `heldItem` property inside spawn files not working and causing crashes
- Fixed `spawn_bedrock_particles` MoLang causing crashes when used in a server environment
- The Pokédex form lang key definition now follows `cobblemon.ui.pokedex.info.form.{species}-{formname}` instead of `cobblemon.ui.pokedex.info.form.{formname}`.
## [1.6.1 (January 26th, 2025)](#1-6-1)
@@ -1,30 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import net.minecraft.server.ServerInterface;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ServerLevel.class)
public abstract class MinecraftDedicatedServerMixin implements ServerInterface {
@Inject(method = "shouldDiscardEntity", at = @At(value = "HEAD"), cancellable = true)
public void cobblemon$allowPokemonSpawns(Entity entity, CallbackInfoReturnable<Boolean> callback) {
if (entity instanceof PokemonEntity) {
callback.setReturnValue(false);
}
}
}
@@ -0,0 +1,53 @@
/*
* 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.mixin;
import com.cobblemon.mod.common.Cobblemon;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.cobblemon.mod.common.entity.pokemon.PokemonServerDelegate;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.block.LevelEvent;
import net.minecraft.world.phys.AABB;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ServerLevel.class)
public abstract class ServerLevelMixin {
@Inject(method = "shouldDiscardEntity", at = @At(value = "HEAD"), cancellable = true)
public void cobblemon$allowPokemonSpawns(Entity entity, CallbackInfoReturnable<Boolean> callback) {
if (entity instanceof PokemonEntity) {
callback.setReturnValue(false);
}
}
@Inject(method = "levelEvent(Lnet/minecraft/world/entity/player/Player;ILnet/minecraft/core/BlockPos;I)V", at = @At(value = "HEAD"))
public void cobblemon$setPokemonDancing(Player player, int type, BlockPos pos, int data, CallbackInfo ci) {
if (type == LevelEvent.SOUND_PLAY_JUKEBOX_SONG || type == LevelEvent.SOUND_STOP_JUKEBOX_SONG) {
cobblemon$notifyNearbyEntities((ServerLevel) ((Object) this), pos, type == LevelEvent.SOUND_PLAY_JUKEBOX_SONG);
}
}
@Unique
private void cobblemon$notifyNearbyEntities(ServerLevel level, BlockPos pos, boolean playing) {
for (PokemonEntity pokemonEntity : level.getEntitiesOfClass(PokemonEntity.class, new AABB(pos).inflate(Cobblemon.config.getPokemonDanceDistance()))) {
PokemonServerDelegate delegate = (PokemonServerDelegate) pokemonEntity.getDelegate();
delegate.setDancing(playing);
delegate.setJukeboxPos(pos);
pokemonEntity.setRecordPlayingNearby(pos, playing);
}
}
}
@@ -8,24 +8,11 @@
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.api.orientation.OrientationController;
import com.cobblemon.mod.common.api.scheduling.ClientTaskTracker;
import com.cobblemon.mod.common.stadium.StadiumClientManager;
import com.cobblemon.mod.common.util.CameraExtensionsKt;
import net.minecraft.client.Camera;
import net.minecraft.client.DeltaTracker;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.Vec3;
import org.joml.Matrix4f;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@@ -33,17 +20,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(GameRenderer.class)
public class GameRendererMixin {
@Shadow @Final Minecraft minecraft;
@Shadow float renderDistance;
@Shadow @Final private LightTexture lightTexture;
@Shadow private boolean renderHand;
@Shadow private double getFov(Camera activeRenderInfo, float partialTicks, boolean useFOVSetting) { return 0.0; }
@Shadow public void resetProjectionMatrix(Matrix4f matrix) {}
@Shadow public Matrix4f getProjectionMatrix(double fov) { return new Matrix4f(); }
@Shadow private void renderItemInHand(Camera camera, float partialTick, Matrix4f projectionMatrix) {}
@Shadow public void pick(float partialTicks) {}
@Unique
long lastTime = -1;
@@ -66,54 +42,4 @@ public class GameRendererMixin {
lastTime = newTime;
}
@Inject(method = "renderLevel", at = @At(value = "HEAD"), cancellable = true)
public void renderLevel(DeltaTracker deltaTracker, CallbackInfo ci) {
if (StadiumClientManager.INSTANCE.shouldUseStadiumCamera()) {
float f = deltaTracker.getGameTimeDeltaPartialTick(true);
this.lightTexture.updateLightTexture(f);
if (this.minecraft.getCameraEntity() == null) {
this.minecraft.setCameraEntity(this.minecraft.player);
}
this.minecraft.getProfiler().push("camera");
Camera stadiumCamera = new Camera();
Entity entity = (Entity) this.minecraft.player;
stadiumCamera.setup(this.minecraft.level, entity, false, false, 1.0F);
//adjust camera
StadiumClientManager.INSTANCE.updateCameraData(f);
var position = StadiumClientManager.INSTANCE.getCameraPosition();
stadiumCamera.setPosition(position);
Quaternionf rotation = StadiumClientManager.INSTANCE.getCameraRotation();
var forwardVector = rotation.transform(Camera.FORWARDS, new Vector3f());
var upVector = rotation.transform(Camera.UP, new Vector3f());
var leftVector = rotation.transform(Camera.LEFT, new Vector3f());
stadiumCamera.rotation.set(rotation);
stadiumCamera.xRot = (float)Mth.wrapDegrees(-Math.toDegrees(Math.asin(forwardVector.y)));
stadiumCamera.yRot = Mth.wrapDegrees((float)-Math.toDegrees(Camera.FORWARDS.angleSigned(forwardVector, Camera.UP)) + 180);
stadiumCamera.forwards.set(forwardVector);
stadiumCamera.up.set(upVector);
stadiumCamera.left.set(leftVector);
this.renderDistance = (float)(this.minecraft.options.getEffectiveRenderDistance() * 16);
double d = this.getFov(stadiumCamera, f, true);
Matrix4f matrix4f = this.getProjectionMatrix(d);
this.resetProjectionMatrix(matrix4f);
Quaternionf quaternionf = stadiumCamera.rotation().conjugate(new Quaternionf());
Matrix4f matrix4f2 = (new Matrix4f()).rotation(quaternionf);
this.minecraft.levelRenderer.prepareCullFrustum(stadiumCamera.getPosition(), matrix4f2, this.getProjectionMatrix(Math.max(d, (double)(Integer)this.minecraft.options.fov().get())));
this.minecraft.levelRenderer.renderLevel(deltaTracker, false, stadiumCamera, (GameRenderer) (Object) this, this.lightTexture, matrix4f2, matrix4f);
this.minecraft.getProfiler().pop();
ci.cancel();
}
}
@Inject(method = "tick", at = @At(value = "TAIL"))
public void tick(CallbackInfo ci) {
// StadiumClientManager.INSTANCE.tickCameraManager();
}
}
@@ -36,9 +36,6 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
@JvmField
val PC: BlockEntityType<PCBlockEntity> = this.create("pc", BlockEntityType.Builder.of(::PCBlockEntity, CobblemonBlocks.PC).build(null))
@JvmField
val STADIUM: BlockEntityType<StadiumBlockEntity> = this.create("stadium_terminal", BlockEntityType.Builder.of(::StadiumBlockEntity, CobblemonBlocks.STADIUM).build(null))
@JvmField
val LECTERN: BlockEntityType<LecternBlockEntity> = this.create("lectern", BlockEntityType.Builder.of(::LecternBlockEntity, CobblemonBlocks.LECTERN).build(null))
@@ -354,9 +354,6 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
@JvmField
val PC = create("pc", PCBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F).noOcclusion().lightLevel { if ((it.getValue(PCBlock.ON) as Boolean) && (it.getValue(PCBlock.PART) == PCBlock.PCPart.TOP)) 10 else 0 }))
@JvmField
val STADIUM = create("stadium_terminal", StadiumBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F)))
@JvmField
val LECTERN = create("lectern", LecternBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).sound(SoundType.WOOD).strength(2.5F).ignitedByLava()))
@@ -272,8 +272,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val PC = blockItem("pc", CobblemonBlocks.PC)
@JvmField
val STADIUM = blockItem("stadium_terminal", CobblemonBlocks.STADIUM)
@JvmField
val PASTURE = blockItem("pasture", CobblemonBlocks.PASTURE)
@JvmField
val DISPLAY_CASE = blockItem("display_case", CobblemonBlocks.DISPLAY_CASE)
@@ -295,21 +293,20 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField val REAPER_CLOTH = noSettingsItem("reaper_cloth")
@JvmField val PRISM_SCALE = noSettingsItem("prism_scale")
@JvmField val SACHET = noSettingsItem("sachet")
@JvmField val WHIPPED_DREAM = create("whipped_dream", foodItem(8, 0.3f))
@JvmField val STRAWBERRY_SWEET = create("strawberry_sweet", foodItem(6, 0.125f))
@JvmField val LOVE_SWEET = create("love_sweet", foodItem(6, 0.125f))
@JvmField val BERRY_SWEET = create("berry_sweet", foodItem(6, 0.125f))
@JvmField val CLOVER_SWEET = create("clover_sweet", foodItem(6, 0.125f))
@JvmField val FLOWER_SWEET = create("flower_sweet", foodItem(6, 0.125f))
@JvmField val STAR_SWEET = create("star_sweet", foodItem(6, 0.125f))
@JvmField val RIBBON_SWEET = create("ribbon_sweet", foodItem(6, 0.125f))
@JvmField val WHIPPED_DREAM = noSettingsItem("whipped_dream")
@JvmField val STRAWBERRY_SWEET = noSettingsItem("strawberry_sweet")
@JvmField val LOVE_SWEET = noSettingsItem("love_sweet")
@JvmField val BERRY_SWEET = noSettingsItem("berry_sweet")
@JvmField val CLOVER_SWEET = noSettingsItem("clover_sweet")
@JvmField val FLOWER_SWEET = noSettingsItem("flower_sweet")
@JvmField val STAR_SWEET = noSettingsItem("star_sweet")
@JvmField val RIBBON_SWEET = noSettingsItem("ribbon_sweet")
@JvmField val CHIPPED_POT = noSettingsItem("chipped_pot")
@JvmField val CRACKED_POT = noSettingsItem("cracked_pot")
@JvmField val MASTERPIECE_TEACUP = noSettingsItem("masterpiece_teacup")
@JvmField val UNREMARKABLE_TEACUP = noSettingsItem("unremarkable_teacup")
@JvmField val SWEET_APPLE = create("sweet_apple", foodItem(4, 0.3f))
@JvmField val TART_APPLE = create("tart_apple", foodItem(4, 0.3f))
@JvmField val SYRUPY_APPLE = create("syrupy_apple", foodItem(4, 0.3f))
@JvmField val SWEET_APPLE = noSettingsItem("sweet_apple")
@JvmField val TART_APPLE = noSettingsItem("tart_apple")
@JvmField val GALARICA_CUFF = noSettingsItem("galarica_cuff")
@JvmField val GALARICA_WREATH = noSettingsItem("galarica_wreath")
@JvmField val BLACK_AUGURITE = noSettingsItem("black_augurite")
@@ -1361,7 +1358,4 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
return createdItem
}
private fun foodItem(nutrition: Int, saturationModifier: Float): Item {
return Item(Item.Properties().food(FoodProperties.Builder().nutrition(nutrition).saturationModifier(saturationModifier).build()))
}
}
@@ -218,10 +218,6 @@ import com.cobblemon.mod.common.net.serverhandling.trade.ChangeTradeAcceptanceHa
import com.cobblemon.mod.common.net.serverhandling.trade.OfferTradeHandler
import com.cobblemon.mod.common.net.serverhandling.trade.PerformTradeHandler
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler
import com.cobblemon.mod.common.stadium.StadiumCamerasSyncPacket
import com.cobblemon.mod.common.stadium.StadiumJoinHandler
import com.cobblemon.mod.common.stadium.StadiumJoinPacket
import com.cobblemon.mod.common.stadium.StadiumCameraManagersSyncPacket
import com.cobblemon.mod.common.util.server
import net.minecraft.server.level.ServerPlayer
@@ -378,8 +374,6 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(FlowRegistrySyncPacket.ID, FlowRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(CosmeticItemAssignmentSyncPacket.ID, CosmeticItemAssignmentSyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(MarkRegistrySyncPacket.ID, MarkRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(StadiumCamerasSyncPacket.ID, StadiumCamerasSyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(StadiumCameraManagersSyncPacket.ID, StadiumCameraManagersSyncPacket::decode, DataRegistrySyncPacketHandler()))
// Effects
list.add(PacketRegisterInfo(SpawnSnowstormParticlePacket.ID, SpawnSnowstormParticlePacket::decode, SpawnSnowstormParticleHandler))
@@ -442,9 +436,6 @@ object CobblemonNetwork {
// Riding
list.add(PacketRegisterInfo(ClientboundUpdateRidingStatePacket.ID, ClientboundUpdateRidingStatePacket::decode, ClientboundUpdateRidingStateHandler))
// Stadium packets
list.add(PacketRegisterInfo(StadiumJoinPacket.ID, StadiumJoinPacket::decode, StadiumJoinHandler))
return list
}
@@ -17,7 +17,11 @@ import com.bedrockk.molang.runtime.struct.VariableStruct
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.MoValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.*
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonActivities
import com.cobblemon.mod.common.CobblemonBlockEntities
import com.cobblemon.mod.common.CobblemonMemories
import com.cobblemon.mod.common.CobblemonUnlockableWallpapers
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
@@ -27,7 +31,13 @@ import com.cobblemon.mod.common.api.mark.Marks
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
import com.cobblemon.mod.common.api.moves.animations.ActionEffects
import com.cobblemon.mod.common.api.moves.animations.NPCProvider
import com.cobblemon.mod.common.api.pokedex.*
import com.cobblemon.mod.common.api.pokedex.AbstractPokedexManager
import com.cobblemon.mod.common.api.pokedex.CaughtCount
import com.cobblemon.mod.common.api.pokedex.CaughtPercent
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
import com.cobblemon.mod.common.api.pokedex.PokedexManager
import com.cobblemon.mod.common.api.pokedex.SeenCount
import com.cobblemon.mod.common.api.pokedex.SeenPercent
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.api.pokemon.stats.Stats
@@ -60,7 +70,35 @@ import com.cobblemon.mod.common.pokemon.Species
import com.cobblemon.mod.common.pokemon.evolution.variants.ItemInteractionEvolution
import com.cobblemon.mod.common.pokemon.evolution.variants.LevelUpEvolution
import com.cobblemon.mod.common.pokemon.evolution.variants.TradeEvolution
import com.cobblemon.mod.common.util.*
import com.cobblemon.mod.common.util.asArrayValue
import com.cobblemon.mod.common.util.asBlockPos
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import com.cobblemon.mod.common.util.asResource
import com.cobblemon.mod.common.util.asUUID
import com.cobblemon.mod.common.util.blockRegistry
import com.cobblemon.mod.common.util.cloneFrom
import com.cobblemon.mod.common.util.effectiveName
import com.cobblemon.mod.common.util.getBattleState
import com.cobblemon.mod.common.util.getBlockStatesWithPos
import com.cobblemon.mod.common.util.getBooleanOrNull
import com.cobblemon.mod.common.util.getDoubleOrNull
import com.cobblemon.mod.common.util.getIntOrNull
import com.cobblemon.mod.common.util.getIsSubmerged
import com.cobblemon.mod.common.util.getOrNull
import com.cobblemon.mod.common.util.getPlayer
import com.cobblemon.mod.common.util.getStringOrNull
import com.cobblemon.mod.common.util.isInBattle
import com.cobblemon.mod.common.util.isInt
import com.cobblemon.mod.common.util.isStandingOn
import com.cobblemon.mod.common.util.party
import com.cobblemon.mod.common.util.pc
import com.cobblemon.mod.common.util.pokedex
import com.cobblemon.mod.common.util.resolve
import com.cobblemon.mod.common.util.server
import com.cobblemon.mod.common.util.toProperties
import com.cobblemon.mod.common.util.withNPCValue
import com.cobblemon.mod.common.util.worldRegistry
import com.mojang.datafixers.util.Either
import net.minecraft.commands.arguments.EntityAnchorArgument
import net.minecraft.core.BlockPos
@@ -69,7 +107,11 @@ import net.minecraft.core.Registry
import net.minecraft.core.RegistryAccess
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.core.registries.Registries
import net.minecraft.nbt.*
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.DoubleTag
import net.minecraft.nbt.ListTag
import net.minecraft.nbt.StringTag
import net.minecraft.nbt.Tag
import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.MinecraftServer
@@ -78,7 +120,11 @@ import net.minecraft.server.level.ServerPlayer
import net.minecraft.tags.TagKey
import net.minecraft.world.damagesource.DamageSource
import net.minecraft.world.damagesource.DamageTypes
import net.minecraft.world.entity.*
import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.EntityType
import net.minecraft.world.entity.LightningBolt
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.PathfinderMob
import net.minecraft.world.entity.ai.behavior.BlockPosTracker
import net.minecraft.world.entity.ai.memory.MemoryModuleType
import net.minecraft.world.entity.ai.memory.MemoryStatus
@@ -93,7 +139,45 @@ import net.minecraft.world.level.dimension.DimensionType
import net.minecraft.world.level.levelgen.Heightmap
import net.minecraft.world.phys.AABB
import net.minecraft.world.phys.Vec3
import java.util.*
import java.util.UUID
import kotlin.collections.HashMap
import kotlin.collections.Map
import kotlin.collections.MutableList
import kotlin.collections.MutableSet
import kotlin.collections.any
import kotlin.collections.associate
import kotlin.collections.component1
import kotlin.collections.component2
import kotlin.collections.contains
import kotlin.collections.count
import kotlin.collections.emptyList
import kotlin.collections.filter
import kotlin.collections.filterIsInstance
import kotlin.collections.find
import kotlin.collections.flatMap
import kotlin.collections.forEach
import kotlin.collections.forEachIndexed
import kotlin.collections.getOrPut
import kotlin.collections.hashMapOf
import kotlin.collections.isNotEmpty
import kotlin.collections.iterator
import kotlin.collections.listOf
import kotlin.collections.map
import kotlin.collections.mapIndexed
import kotlin.collections.mapNotNull
import kotlin.collections.mapOf
import kotlin.collections.maxOfOrNull
import kotlin.collections.minByOrNull
import kotlin.collections.minOfOrNull
import kotlin.collections.mutableListOf
import kotlin.collections.mutableSetOf
import kotlin.collections.none
import kotlin.collections.random
import kotlin.collections.set
import kotlin.collections.setOf
import kotlin.collections.toList
import kotlin.collections.toMap
import kotlin.collections.toTypedArray
import kotlin.math.sqrt
import kotlin.random.Random
@@ -77,18 +77,18 @@ object CatchRateModifiers {
/**
* Used by [PokeBalls.MOON_BALL].
* Boosts the catch rate 1.5× during Moon Phases 2 and 6 between the times of 12000 – 24000.
* 2.5× during Moon Phases 1 and 7 between the times of 12000 – 24000.
* 4× during Moon Phase 0 between the times of 12000 – 24000.
* Boosts the catch rate 1.5× during Moon Phases 3 and 7 between the times of 12000 – 24000.
* 2.5× during Moon Phases 2 and 8 between the times of 12000 – 24000.
* 4× during Moon Phase 1 between the times of 12000 – 24000.
* 1× otherwise.
*/
val MOON_PHASES: CatchRateModifier = WorldStateModifier { _, entity ->
if (entity.level().gameTime in 12000..24000)
return@WorldStateModifier 1F
when (entity.level().moonPhase) {
2, 6 -> 1.5F
1, 7 -> 2.5F
0 -> 4F
3, 7 -> 1.5F
2, 8 -> 2.5F
1 -> 4F
else -> 1F
}
}
@@ -14,7 +14,6 @@ import com.cobblemon.mod.common.api.spawning.spawner.PlayerSpawnerFactory
import com.cobblemon.mod.common.platform.events.PlatformEvents
import com.cobblemon.mod.common.util.server
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
import net.minecraft.server.level.ServerLevel
import java.util.UUID
import net.minecraft.server.level.ServerPlayer
@@ -33,45 +32,24 @@ object CobblemonWorldSpawnerManager : SpawnerManager() {
init {
PlatformEvents.SERVER_PLAYER_LOGIN.subscribe { this.onPlayerLogin(it.player) }
PlatformEvents.SERVER_PLAYER_LOGOUT.subscribe { this.onPlayerLogout(it.player) }
PlatformEvents.CHANGE_DIMENSION.subscribe { this.onDimensionChange(it.player, it.origin, it.destination) }
}
fun onPlayerLogin(player: ServerPlayer) {
// Disables spawning
if (!Cobblemon.config.enableSpawning || player.level().gameRules.getBoolean(CobblemonGameRules.DO_POKEMON_SPAWNING) == false) {
if (!Cobblemon.config.enableSpawning || server()?.gameRules?.getBoolean(CobblemonGameRules.DO_POKEMON_SPAWNING) == false) {
return;
}
registerPlayerSpawner(player)
val spawner = PlayerSpawnerFactory.create(this, player)
spawnersForPlayers[player.uuid] = spawner
registerSpawner(spawner)
}
fun onPlayerLogout(player: ServerPlayer) {
unregisterPlayerSpawner(player)
}
fun onDimensionChange(player: ServerPlayer, origin: ServerLevel?, destination: ServerLevel?) {
fun getSpawnRule(level: ServerLevel?) = level?.gameRules?.getBoolean(CobblemonGameRules.DO_POKEMON_SPAWNING)
if (!Cobblemon.config.enableSpawning || getSpawnRule(origin) == getSpawnRule(destination)) {
return
}
val spawnerAction = if (destination?.gameRules?.getBoolean(CobblemonGameRules.DO_POKEMON_SPAWNING) == false) {
::unregisterPlayerSpawner
} else {
::registerPlayerSpawner
}
spawnerAction(player)
}
private fun unregisterPlayerSpawner(player: ServerPlayer) {
spawnersForPlayers.remove(player.uuid)?.let { unregisterSpawner(it) }
}
private fun registerPlayerSpawner(player: ServerPlayer) {
PlayerSpawnerFactory.create(this, player).also {
spawnersForPlayers[player.uuid] = it
registerSpawner(it)
val spawner = spawnersForPlayers[player.uuid]
if (spawner != null) {
spawnersForPlayers.remove(player.uuid)
unregisterSpawner(spawner)
}
}
}
@@ -71,15 +71,10 @@ open class SpawnerManager {
open fun onServerTick() {
// Disables spawning
if (!Cobblemon.config.enableSpawning) {
if (!Cobblemon.config.enableSpawning || server()?.gameRules?.getBoolean(DO_POKEMON_SPAWNING) == false) {
return
}
influences.removeIf { it.isExpired() }
getSpawnersOfType<TickingSpawner>().forEach {
if (it.getCauseEntity()?.level()?.gameRules?.getBoolean(DO_POKEMON_SPAWNING) == false) {
return@forEach
}
it.tick()
}
getSpawnersOfType<TickingSpawner>().forEach(TickingSpawner::tick)
}
}
@@ -1,133 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.block
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.text.red
import com.cobblemon.mod.common.api.text.text
import com.cobblemon.mod.common.block.entity.StadiumBlockEntity
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.InteractionResult
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.context.BlockPlaceContext
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.BaseEntityBlock
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.HorizontalDirectionalBlock
import net.minecraft.world.level.block.Mirror
import net.minecraft.world.level.block.RenderShape
import net.minecraft.world.level.block.Rotation
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.block.state.StateDefinition
import net.minecraft.world.phys.BlockHitResult
class StadiumBlock(properties: Properties): BaseEntityBlock(properties) {
companion object {
val CODEC = simpleCodec(::StadiumBlock)
}
init {
registerDefaultState(stateDefinition.any().setValue(HorizontalDirectionalBlock.FACING, Direction.NORTH))
}
override fun codec() = CODEC
override fun newBlockEntity(pos: BlockPos, state: BlockState): BlockEntity {
return StadiumBlockEntity(pos, state)
}
override fun getStateForPlacement(blockPlaceContext: BlockPlaceContext): BlockState {
return this.defaultBlockState().setValue(HorizontalDirectionalBlock.FACING, blockPlaceContext.horizontalDirection)
}
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
builder.add(HorizontalDirectionalBlock.FACING)
}
override fun rotate(blockState: BlockState, rotation: Rotation): BlockState {
return blockState.setValue(
HorizontalDirectionalBlock.FACING, rotation.rotate(blockState.getValue(
HorizontalDirectionalBlock.FACING)))
}
override fun mirror(blockState: BlockState, mirror: Mirror): BlockState {
return blockState.rotate(mirror.getRotation(blockState.getValue(HorizontalDirectionalBlock.FACING)))
}
override fun onRemove(state: BlockState, world: Level, pos: BlockPos, newState: BlockState, moved: Boolean) {
if (!state.`is`(newState.block)) super.onRemove(state, world, pos, newState, moved)
}
//TODO: override getTicker
override fun getRenderShape(state: BlockState) = RenderShape.MODEL
override fun useWithoutItem(
state: BlockState,
world: Level,
pos: BlockPos,
player: Player,
hitResult: BlockHitResult
): InteractionResult {
if (player !is ServerPlayer) return InteractionResult.SUCCESS
val blockEntity = world.getBlockEntity(pos)
if (blockEntity !is StadiumBlockEntity) return InteractionResult.SUCCESS
player.sendSystemMessage(text("Adding you to Battle").red())
blockEntity.addPlayer(player)
return InteractionResult.SUCCESS
}
/*
override fun useWithoutItem(
blockState: BlockState,
world: Level,
blockPos: BlockPos,
player: Player,
blockHitResult: BlockHitResult
): InteractionResult {
if (player !is ServerPlayer) return InteractionResult.SUCCESS
val blockEntity = world.getBlockEntity(blockPos)
if (blockEntity !is StadiumBlockEntity) return InteractionResult.SUCCESS
// Toggle isInUse state
blockEntity.isInUse = !blockEntity.isInUse
// debug
val activateMessage = if (blockEntity.isInUse) "Stadium Activated!" else "Stadium Deactivated!"
player.sendSystemMessage(text(activateMessage).red())
if (blockEntity.isInUse) {
// Generate flight path when activated
blockEntity.generateFlightPath(world, radiusX = 5.0, radiusZ = 3.0, height = 10.0, steps = 20)
} else {
// Clear path when deactivated
blockEntity.pathPoints.clear()
}
val message = "Stadium Pos: " + blockEntity.blockPos +
"\nPlayer 1 Pos: " + blockEntity.getPlayer1Pos() +
"\nPoke 1 Pos: " + blockEntity.getPoke1Pos() +
"\nPlayer 2 Pos: " + blockEntity.getPlayer2Pos() +
"\nPoke 2 Pos: " + blockEntity.getPoke2Pos()
player.sendSystemMessage(text(message).red())
blockEntity.setChanged()
world.sendBlockUpdated(blockPos, blockState, blockState, Block.UPDATE_CLIENTS)
return InteractionResult.SUCCESS
}
*/
}
@@ -1,143 +0,0 @@
package com.cobblemon.mod.common.block.entity
import com.cobblemon.mod.common.CobblemonBlockEntities
import com.cobblemon.mod.common.client.render.models.blockbench.drone.DroneState
import com.cobblemon.mod.common.stadium.StadiumSingleBattle
import net.minecraft.core.BlockPos
import net.minecraft.core.HolderLookup
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag
import net.minecraft.network.protocol.Packet
import net.minecraft.network.protocol.game.ClientGamePacketListener
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket
import net.minecraft.network.protocol.game.ClientboundPlayerLookAtPacket
import net.minecraft.network.protocol.game.ClientboundSetCarriedItemPacket
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.phys.Vec3
class StadiumBlockEntity(
pos: BlockPos,
blockState: BlockState
): BlockEntity(
CobblemonBlockEntities.STADIUM,
pos,
blockState
) {
var storedPlayers = mutableListOf<ServerPlayer>()
var battleDefenition = StadiumSingleBattle()
fun addPlayer(player: ServerPlayer) {
battleDefenition.addPlayer(player)
if (battleDefenition.readyForBattle()) battleDefenition.initializeBattle()
}
/*
var isInUse = false
val droneState = DroneState()
val pathPoints: MutableList<Vec3> = mutableListOf()
fun generateFlightPath(world: Level, radiusX: Double, radiusZ: Double, height: Double, steps: Int) {
pathPoints.clear()
for (i in 0 until steps) {
val angle = (i.toDouble() / steps) * Math.PI * 2
val xOffset = radiusX * Math.cos(angle)
val zOffset = radiusZ * Math.sin(angle)
val basePos = Vec3(blockPos.x + xOffset, blockPos.y + height, blockPos.z + zOffset)
val adjustedPos = getValidPoint(world, basePos)
pathPoints.add(adjustedPos)
}
}
private fun getValidPoint(world: Level, start: Vec3): Vec3 {
val maxHeight = 40 // Max height for drone path
val stepHeight = 1.0 // Step size for raycast
var adjustedHeight = start.y
for (h in 0..maxHeight step stepHeight.toInt()) {
val checkPos = BlockPos(start.x.toInt(), start.y.toInt() - h, start.z.toInt()) // Convert to BlockPos
if (!world.getBlockState(checkPos).isAir) { // Check if block is solid
return Vec3(start.x, start.y - h - 1, start.z) // Adjust position
}
}
return start // No obstruction found
}
fun getPlayer1Pos(): BlockPos {
return blockPos.north(10)
}
fun getPlayer2Pos(): BlockPos {
return blockPos.south(10)
}
fun getPoke1Pos(): BlockPos {
return blockPos.north(5)
}
fun getPoke2Pos(): BlockPos {
return blockPos.south(5)
}
/**
* Saves data to NBT.
*/
override fun saveAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
super.saveAdditional(tag, registries)
// Save the isInUse state
tag.putBoolean("IsInUse", isInUse)
// Save path points
val pathTag = ListTag()
for (point in pathPoints) {
val pointTag = CompoundTag()
pointTag.putDouble("x", point.x)
pointTag.putDouble("y", point.y)
pointTag.putDouble("z", point.z)
pathTag.add(pointTag)
}
tag.put("PathPoints", pathTag)
}
/**
* Loads data from NBT.
*/
override fun loadAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
super.loadAdditional(tag, registries)
// Load the isInUse state
isInUse = tag.getBoolean("IsInUse")
// Load path points
pathPoints.clear()
val pathTag = tag.getList("PathPoints", 10) // 10 is the ID for CompoundTag
for (i in 0 until pathTag.size) {
val pointTag = pathTag.getCompound(i)
val point = Vec3(pointTag.getDouble("x"), pointTag.getDouble("y"), pointTag.getDouble("z"))
pathPoints.add(point)
}
}
override fun getUpdatePacket(): Packet<ClientGamePacketListener>? {
//println("getUpdatePacket called for NestBlockEntity at $blockPos with egg: $eggComponent")
return ClientboundBlockEntityDataPacket.create(this)
}
override fun getUpdateTag(registryLookup: HolderLookup.Provider): CompoundTag {
val tag = saveWithoutMetadata(registryLookup)
//println("getUpdateTag called for NestBlockEntity at $blockPos with tag: $tag")
return tag
}
*/
}
@@ -26,7 +26,13 @@ import com.cobblemon.mod.common.client.gui.battle.BattleOverlay
import com.cobblemon.mod.common.client.particle.BedrockParticleOptionsRepository
import com.cobblemon.mod.common.client.render.ClientPlayerIcon
import com.cobblemon.mod.common.client.render.DeferredRenderer
import com.cobblemon.mod.common.client.render.block.*
import com.cobblemon.mod.common.client.render.block.BerryBlockRenderer
import com.cobblemon.mod.common.client.render.block.DisplayCaseRenderer
import com.cobblemon.mod.common.client.render.block.FossilAnalyzerRenderer
import com.cobblemon.mod.common.client.render.block.GildedChestBlockRenderer
import com.cobblemon.mod.common.client.render.block.HealingMachineRenderer
import com.cobblemon.mod.common.client.render.block.LecternBlockEntityRenderer
import com.cobblemon.mod.common.client.render.block.RestorationTankRenderer
import com.cobblemon.mod.common.client.render.boat.CobblemonBoatRenderer
import com.cobblemon.mod.common.client.render.entity.PokeBobberEntityRenderer
import com.cobblemon.mod.common.client.render.generic.GenericBedrockRenderer
@@ -54,7 +60,6 @@ import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.platform.events.PlatformEvents
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext
import com.cobblemon.mod.common.stadium.StadiumClientManager
import com.cobblemon.mod.common.util.isLookingAt
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.GuiGraphics
@@ -111,7 +116,6 @@ object CobblemonClient {
CobblemonDataProvider.canReload = true
DeferredRenderer.clearAll()
ClientPlayerIcon.clear()
StadiumClientManager.onLogout()
}
fun initialize(implementation: CobblemonClientImplementation) {
@@ -256,8 +260,7 @@ object CobblemonClient {
CobblemonBlocks.SKY_TUMBLESTONE_CLUSTER,
CobblemonBlocks.GIMMIGHOUL_CHEST,
CobblemonBlocks.DISPLAY_CASE,
CobblemonBlocks.LECTERN,
CobblemonBlocks.STADIUM
CobblemonBlocks.LECTERN
)
this.createBoatModelLayers()
@@ -291,7 +294,6 @@ object CobblemonClient {
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.GILDED_CHEST, ::GildedChestBlockRenderer)
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.DISPLAY_CASE, ::DisplayCaseRenderer)
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.LECTERN, ::LecternBlockEntityRenderer)
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.STADIUM, ::StadiumBlockRenderer)
}
private fun registerEntityRenderers() {
@@ -34,7 +34,11 @@ import com.cobblemon.mod.common.client.render.pokemon.PokemonRenderer.Companion.
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.net.messages.server.pokemon.update.ServerboundUpdateRidingStatePacket
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.*
import com.cobblemon.mod.common.util.MovingSoundInstance
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.resolve
import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.client.Minecraft
import net.minecraft.network.syncher.EntityDataAccessor
@@ -458,11 +458,10 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
formRightButton.render(context,mouseX, mouseY, delta)
val form = showableForms[selectedFormIndex]
val formName = if (form.displayForm.lowercase() == "normal") "" else "-${form.displayForm.lowercase().replace("-", "")}"
drawScaledTextJustifiedRight(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = lang("ui.pokedex.info.form.${species}${formName}").bold(),
text = lang("ui.pokedex.info.form.${form.displayForm.lowercase()}").bold(),
x = pX + 136,
y = pY + 15,
shadow = true
@@ -1,209 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.render.block
import com.cobblemon.mod.common.CobblemonBlocks
import com.cobblemon.mod.common.block.entity.StadiumBlockEntity
import com.cobblemon.mod.common.client.render.models.blockbench.drone.DroneModel
import com.cobblemon.mod.common.client.render.models.blockbench.drone.DroneState
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.util.cobblemonResource
import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.math.Axis
import net.minecraft.client.renderer.MultiBufferSource
import net.minecraft.client.renderer.RenderType
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
import net.minecraft.client.renderer.texture.OverlayTexture
import net.minecraft.core.Direction
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.level.block.HorizontalDirectionalBlock
import net.minecraft.world.level.block.state.BlockState
class StadiumBlockRenderer(ctx: BlockEntityRendererProvider.Context) : BlockEntityRenderer<StadiumBlockEntity> {
val context = RenderContext().also {
it.put(RenderContext.DO_QUIRKS, false)
it.put(RenderContext.RENDER_STATE, RenderContext.RenderState.BLOCK)
}
private var pathIndex = 0
private var animationTime = 0.0
private val droneSpeed = 0.10
override fun render(
blockEntity: StadiumBlockEntity,
partialTick: Float,
poseStack: PoseStack,
bufferSource: MultiBufferSource,
packedLight: Int,
packedOverlay: Int
) {
}
/*
override fun render(
blockEntity: StadiumBlockEntity,
tickDelta: Float,
poseStack: PoseStack,
multiBufferSource: MultiBufferSource,
light: Int,
overlay: Int
) {
val blockState = blockEntity.blockState
val yRot = blockState.getValue(HorizontalDirectionalBlock.FACING).toYRot()
val isClientSide = blockEntity.level?.isClientSide == true
if (!isClientSide) return
val stadiumBlockState = blockEntity.level?.getBlockState(blockEntity.blockPos) ?: return
if (stadiumBlockState.block != CobblemonBlocks.STADIUM) {
return
}
val droneState = blockEntity.droneState
poseStack.pushPose()
if (blockEntity.isInUse) {
if (blockEntity.pathPoints.isEmpty()) {
poseStack.popPose()
return
}
spawnDebugParticles(blockEntity) // debug particles
// Center the drone at the block's center
poseStack.translate(0.5, -3.0, 0.5)
//poseStack.mulPose(Axis.XP.rotationDegrees(180F))
//poseStack.mulPose(Axis.YP.rotationDegrees(180F))
val points = blockEntity.pathPoints
val nextIndex = (pathIndex + 1) % points.size
val currentPoint = points[pathIndex]
val nextPoint = points[nextIndex]
animationTime += tickDelta * droneSpeed
if (animationTime >= 1.0) {
animationTime = 0.0
pathIndex = nextIndex
}
val interpolatedPos = currentPoint.lerp(nextPoint, animationTime.toDouble())
println("DEBUG: Drone moving between points:")
println(" - Current Point: ${currentPoint}")
println(" - Next Point: ${nextPoint}")
println(" - Interpolated Position: $interpolatedPos")
poseStack.translate(interpolatedPos.x - blockEntity.blockPos.x,
interpolatedPos.y - blockEntity.blockPos.y,
interpolatedPos.z - blockEntity.blockPos.z)
println("DEBUG: Drone position interpolated to: $interpolatedPos")
poseStack.mulPose(Axis.YP.rotationDegrees(-yRot))
poseStack.mulPose(Axis.ZP.rotationDegrees(180F)) // flip the drone right side up
renderDrone(droneState, "sleep", tickDelta, poseStack, 1.0F, multiBufferSource, light)
} else {
val yRot = blockState.getValue(HorizontalDirectionalBlock.FACING).toYRot()
val poseEntry = poseStack.last()
val matrix = poseEntry.pose()
poseStack.translate(0.5, 0.0, 0.5)
poseStack.mulPose(Axis.YP.rotationDegrees(yRot))
val posX = matrix.m03()
val posY = matrix.m13()
val posZ = matrix.m23()
println("DEBUG: Drone is NOT in use. Rendering default position at: x=$posX, y=$posY, z=$posZ")
poseStack.mulPose(Axis.ZP.rotationDegrees(180F))
renderDrone(droneState, "sleep", tickDelta, poseStack, 1.0F, multiBufferSource, light)
}
poseStack.popPose()
}
fun renderDrone(
state: DroneState,
pose: String,
tickDelta: Float,
poseStack: PoseStack,
scale: Float = 1F,
multiBufferSource: MultiBufferSource,
light: Int,
) {
state.updatePartialTicks(tickDelta)
val droneResource: ResourceLocation = cobblemonResource("rotom_drone")
val model = VaryingModelRepository.getPoser(droneResource, state) as DroneModel
val texture = VaryingModelRepository.getTexture(droneResource, state)
val buffer = multiBufferSource.getBuffer(RenderType.entityCutout(texture))
model.bufferProvider = multiBufferSource
state.currentModel = model
state.setPose(pose)
model.context = context
context.put(RenderContext.TEXTURE, texture)
context.put(RenderContext.RENDER_STATE, RenderContext.RenderState.BLOCK)
context.put(RenderContext.POSABLE_STATE, state)
model.applyAnimations(
entity = null,
state = state,
headYaw = 0F,
headPitch = 0F,
limbSwing = 0F,
limbSwingAmount = 0F,
ageInTicks = state.animationSeconds * 20
)
poseStack.scale(scale, scale, scale)
// TODO: Make drone lighting dynamic (simply using the light arg makes the drone always appear dark)
model.withLayerContext(multiBufferSource, state, VaryingModelRepository.getLayers(droneResource, state)) {
model.render(context, poseStack, buffer, 200, OverlayTexture.NO_OVERLAY, -0x1)
}
model.setDefault()
}
private fun spawnDebugParticles(blockEntity: StadiumBlockEntity) {
val world = blockEntity.level ?: return
if (!world.isClientSide) return // Only run on the client-side
for (point in blockEntity.pathPoints) {
world.addParticle(
net.minecraft.core.particles.ParticleTypes.FLAME, // Test particle (changeable)
point.x, point.y, point.z, // Position of the particle
0.0, 0.02, 0.0 // Slight upward motion
)
}
// Spawn a special particle at the next interpolation point
if (blockEntity.pathPoints.isNotEmpty()) {
val nextPoint = blockEntity.pathPoints[(pathIndex + 1) % blockEntity.pathPoints.size]
world.addParticle(
net.minecraft.core.particles.ParticleTypes.END_ROD, // Different effect for next point
nextPoint.x, nextPoint.y, nextPoint.z,
0.0, 0.05, 0.0
)
}
}
*/
}
@@ -102,8 +102,7 @@ abstract class PosableState : Schedulable {
val allActiveAnimations: List<ActiveAnimation> get() = activeAnimations + quirks.flatMap { it.value.animations }
/** The tick-driven age of the state. Combines with [currentPartialTicks] to produce the animation seconds. */
var age = 0
protected set
protected var age = 0
/**
* The partial tick value of the state. Combines with [age] to produce the animation seconds. For entity-based state
* this will be consistently reset to a new value, whereas non-entity-based state will increment this value.
@@ -563,4 +562,4 @@ abstract class PosableState : Schedulable {
1F
}
}
}
}
@@ -198,11 +198,9 @@ data class BedrockAnimation(
boneTimelines.forEach { (boneName, timeline) ->
val part = relevantPartsByName[boneName] ?: if (boneName == "root_part") (rootPart as? ModelPart) else null
val isCamera = boneName == "locator_camera"
val scalar = if (isCamera) 1.0 else intensity.toDouble()
if (part !== null) {
if (!timeline.position.isEmpty()) {
val position = timeline.position.resolve(animationSeconds.toDouble(), runtime).scale(scalar)
val position = timeline.position.resolve(animationSeconds.toDouble(), runtime).scale(intensity.toDouble())
part.apply {
x += position.x.toFloat()
y += position.y.toFloat()
@@ -212,7 +210,7 @@ data class BedrockAnimation(
if (!timeline.rotation.isEmpty()) {
try {
val rotation = timeline.rotation.resolve(animationSeconds.toDouble(), runtime).scale(scalar)
val rotation = timeline.rotation.resolve(animationSeconds.toDouble(), runtime).scale(intensity.toDouble())
part.apply {
xRot += rotation.x.toFloat().toRadians()
yRot += rotation.y.toFloat().toRadians()
@@ -232,14 +230,14 @@ data class BedrockAnimation(
if (!timeline.scale.isEmpty()) {
var scale = timeline.scale.resolve(animationSeconds.toDouble(), runtime)
// If the goal is to make the invisible then kick that into gear after 0.5. Maybe could work better somehow else.
if (scale == Vec3.ZERO && scalar > 0.5) {
if (scale == Vec3.ZERO && intensity > 0.5) {
part.xScale *= scale.x.toFloat()
part.yScale *= scale.y.toFloat()
part.zScale *= scale.z.toFloat()
} else {
// The deviation from 1 is what we want to multiply by the intensity of the animation.
val deviation = scale.scale(-1.0).add(1.0, 1.0, 1.0)
val weakenedDeviation = deviation.scale(scalar)
val weakenedDeviation = deviation.scale(intensity.toDouble())
scale = weakenedDeviation.subtract(1.0, 1.0, 1.0).scale(-1.0)
part.xScale *= scale.x.toFloat()
part.yScale *= scale.y.toFloat()
@@ -396,4 +394,4 @@ enum class InterpolationType {
enum class Transformation {
POSITION, ROTATION, SCALE
}
}
@@ -1,39 +0,0 @@
/*
* Copyright (C) 2025 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.render.models.blockbench.drone
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.animation.PoseAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Bone
import com.cobblemon.mod.common.client.render.models.blockbench.quirk.ModelQuirk
import com.cobblemon.mod.common.entity.PoseType
import com.google.gson.annotations.SerializedName
import net.minecraft.client.model.geom.ModelPart
/**
* A model for rendering the Rotom drone used by the stadium block.
*
* @author Flarkinater
* @since February 14th, 2025
*/
class DroneModel(root: Bone) : PosableModel(root) {
@Transient
@SerializedName("So this name can be literally anything, huh?")
override val rootPart = (root as ModelPart).registerChildWithAllChildren(root.children.entries.first().key)
var droneAnimations: Array<PoseAnimation> = emptyArray()
var droneQuirks: Array<ModelQuirk<*>> = emptyArray()
override fun registerPoses() {
registerPose(
poseType = PoseType.SLEEP,
animations = droneAnimations,
quirks = droneQuirks
)
}
}
@@ -1,34 +0,0 @@
/*
* Copyright (C) 2025 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.render.models.blockbench.drone
import com.cobblemon.mod.common.api.scheduling.SchedulingTracker
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
/**
* State for a drone Rotom attached to a stadium block.
*
* @author Flarkinater
* @since February 12th, 2025
*/
class DroneState() : PosableState() {
init {
setPose("sleep")
age = 0
currentPartialTicks = 0F
}
override fun getEntity() = null
override fun updatePartialTicks(partialTicks: Float) {
currentPartialTicks += partialTicks / 2
}
override val schedulingTracker = SchedulingTracker()
}
@@ -0,0 +1,64 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen1
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class KangaskhanModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
override val rootPart = root.registerChildWithAllChildren("kangaskhan")
override val head = getPart("head")
override var portraitScale = 1.7F
override var portraitTranslation = Vec3(-0.15, 1.1, 0.0)
override var profileScale = 0.7F
override var profileTranslation = Vec3(0.0, 0.65, 0.0)
lateinit var standing: Pose
lateinit var walk: Pose
override fun registerPoses() {
val blink = quirk { bedrockStateful("kangaskhan", "blink")}
val blink2 = quirk { bedrockStateful("kangaskhan", "blink2")}
standing = registerPose(
poseName = "standing",
poseTypes = STATIONARY_POSES + UI_POSES,
transformTicks = 10,
quirks = arrayOf(blink, blink2),
animations = arrayOf(
singleBoneLook(),
bedrock("kangaskhan", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = MOVING_POSES,
transformTicks = 10,
quirks = arrayOf(blink, blink2),
animations = arrayOf(
singleBoneLook(),
bedrock("kangaskhan", "ground_idle")
//bedrock("kangaskhan", "ground_walk")
)
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PosableState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("kangaskhan", "faint") else null
}
@@ -8,11 +8,11 @@
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen3
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BimanualFrame
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
import com.cobblemon.mod.common.entity.PoseType
import net.minecraft.client.model.geom.ModelPart
@@ -38,6 +38,7 @@ class LudicoloModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame,
lateinit var floating: Pose
lateinit var swim: Pose
lateinit var sleep: Pose
lateinit var dance: Pose
override fun registerPoses() {
val blink = quirk { bedrockStateful("ludicolo", "blink") }
@@ -87,6 +88,17 @@ class LudicoloModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame,
)
)
dance = registerPose(
poseName = "dance",
poseType = PoseType.DANCE,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("ludicolo", "dance"),
)
)
}
override fun getFaintAnimation(state: PosableState) = if (state.isNotPosedIn(sleep)) bedrockStateful("ludicolo", "faint") else null
}
}
@@ -38,6 +38,7 @@ class AmbipomModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame, B
lateinit var walking: Pose
lateinit var sleep: Pose
lateinit var battleidle: Pose
lateinit var dancing: Pose
override val cryAnimation = CryProvider { bedrockStateful("ambipom", "cry") }
@@ -50,8 +51,7 @@ class AmbipomModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame, B
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
condition = { !it.isBattling },
poseTypes = PoseType.UI_POSES + PoseType.STAND,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
@@ -80,10 +80,20 @@ class AmbipomModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame, B
bedrock("ambipom", "ground_idle")
)
)
dancing = registerPose(
poseName = "dancing",
poseType = PoseType.DANCE,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("ambipom", "dance")
)
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PosableState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("ambipom", "faint") else null
}
}
@@ -19,7 +19,6 @@ import com.cobblemon.mod.common.client.render.models.blockbench.*
import com.cobblemon.mod.common.client.render.models.blockbench.bedrock.animation.BedrockAnimationRepository
import com.cobblemon.mod.common.client.render.models.blockbench.blockentity.BlockEntityModel
import com.cobblemon.mod.common.client.render.models.blockbench.fossil.FossilModel
import com.cobblemon.mod.common.client.render.models.blockbench.drone.DroneModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.AncientPokeBallModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.BeastBallModel
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.PokeBallModel
@@ -80,14 +79,12 @@ object VaryingModelRepository {
"poke_balls",
"generic",
"block_entities",
"drone"
)
val poserDirectories: List<Pair<String, Class<out PosableModel>>> = listOf(
"bedrock/posers" to PosableModel::class.java,
"bedrock/pokemon/posers" to PokemonPosableModel::class.java,
"bedrock/fossils/posers" to FossilModel::class.java,
"bedrock/drone/posers" to DroneModel::class.java,
"bedrock/block_entities/posers" to BlockEntityModel::class.java,
"bedrock/npcs/posers" to PosableModel::class.java,
"bedrock/poke_balls/posers" to PosableModel::class.java,
@@ -119,7 +116,6 @@ object VaryingModelRepository {
.registerTypeAdapter(PosableModel::class.java, JsonModelAdapter(::PosableModel))
.registerTypeAdapter(PokemonPosableModel::class.java, JsonModelAdapter(::PokemonPosableModel))
.registerTypeAdapter(FossilModel::class.java, JsonModelAdapter(::FossilModel))
.registerTypeAdapter(DroneModel::class.java, JsonModelAdapter(::DroneModel))
.registerTypeAdapter(BlockEntityModel::class.java, JsonModelAdapter(::BlockEntityModel))
.registerTypeAdapter(Pose::class.java, PoseAdapter { JsonModelAdapter.model!! })
.registerTypeAdapter(ModelPartTransformation::class.java, ModelPartTransformationAdapter)
@@ -291,6 +287,7 @@ object VaryingModelRepository {
inbuilt("kabuto", ::KabutoModel)
inbuilt("kabutops", ::KabutopsModel)
inbuilt("kadabra", ::KadabraModel)
inbuilt("kangaskhan", ::KangaskhanModel)
inbuilt("koffing", ::KoffingModel)
inbuilt("krabby", ::KrabbyModel)
inbuilt("lickitung", ::LickitungModel)
@@ -280,6 +280,9 @@ class CobblemonConfig {
@CobblemonConfigField(Category.Debug, lang = "enable_debug_keys")
var enableDebugKeys = false
@CobblemonConfigField(Category.Pokemon, lang="pokemon_dance_distance")
var pokemonDanceDistance = 3.0
fun clone(): CobblemonConfig {
val newConfig = CobblemonConfig()
CobblemonConfig::class.memberProperties.forEach { property ->
@@ -49,8 +49,6 @@ import com.cobblemon.mod.common.net.messages.client.data.UnlockReloadPacket
import com.cobblemon.mod.common.platform.events.PlatformEvents
import com.cobblemon.mod.common.pokemon.SpeciesAdditions
import com.cobblemon.mod.common.pokemon.properties.PropertiesCompletionProvider
import com.cobblemon.mod.common.stadium.StadiumCameraManagers
import com.cobblemon.mod.common.stadium.StadiumCameras
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.ifClient
import com.cobblemon.mod.common.util.server
@@ -99,8 +97,6 @@ object CobblemonDataProvider : DataProvider {
this.register(CobblemonCosmeticItems)
this.register(CobblemonFlows)
this.register(CobblemonUnlockableWallpapers)
this.register(StadiumCameras)
this.register(StadiumCameraManagers)
this.register(Marks)
CobblemonSpawnPools.load()
@@ -9,8 +9,9 @@
package com.cobblemon.mod.common.entity
import com.cobblemon.mod.common.util.cobblemonResource
import java.util.*
import net.minecraft.resources.ResourceLocation
import java.util.EnumSet
import java.util.Locale
/**
* The type of a pose. Used for normalizing pose swapping for all models.
@@ -27,6 +28,7 @@ enum class PoseType {
FLOAT,
SWIM,
GLIDE,
DANCE,
/** A pose for rendering on the left shoulder. Pose animations are given the player head yaw, pitch, and ageInTicks. */
SHOULDER_LEFT,
/** A pose for rendering on the right shoulder. Pose animations are given the player head yaw, pitch, and ageInTicks. */
@@ -50,7 +50,6 @@ import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviours
import com.cobblemon.mod.common.api.riding.events.SelectDriverEvent
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.api.riding.util.RidingAnimationData
import com.cobblemon.mod.common.api.riding.util.Vec3Spring
import com.cobblemon.mod.common.api.scheduling.Schedulable
import com.cobblemon.mod.common.api.scheduling.SchedulingTracker
import com.cobblemon.mod.common.api.scheduling.afterOnServer
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.entity.pokemon
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.OrientationControllable
import com.cobblemon.mod.common.api.entity.PokemonSender
@@ -29,8 +30,10 @@ import com.cobblemon.mod.common.util.asUUID
import com.cobblemon.mod.common.util.getIsSubmerged
import com.cobblemon.mod.common.util.math.geometry.toRadians
import com.cobblemon.mod.common.util.playSoundServer
import com.cobblemon.mod.common.util.toVec3d
import com.cobblemon.mod.common.util.update
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
import net.minecraft.core.BlockPos
import net.minecraft.network.chat.Component
import net.minecraft.network.syncher.EntityDataAccessor
import net.minecraft.server.level.ServerLevel
@@ -39,16 +42,20 @@ import net.minecraft.world.damagesource.DamageSource
import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.ai.attributes.Attributes
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.block.entity.JukeboxBlockEntity
import net.minecraft.world.level.pathfinder.PathType
import org.joml.Matrix3f
import org.joml.Vector3f
import java.util.*
import java.util.Optional
/** Handles purely server logic for a Pokémon */
class PokemonServerDelegate : PokemonSideDelegate {
lateinit var entity: PokemonEntity
var acknowledgedHPStat = -1
var dancing: Boolean = false
var jukeboxPos: BlockPos? = null
/** Mocked properties exposed to the client [PokemonEntity]. */
private val mock: PokemonProperties?
get() = entity.effects.mockEffect?.mock
@@ -265,6 +272,15 @@ class PokemonServerDelegate : PokemonSideDelegate {
val isPassenger = entity.isPassenger
val isUnderwater = entity.getIsSubmerged()
val isFlying = entity.getBehaviourFlag(PokemonBehaviourFlag.FLYING)
var isDancing = false
if (jukeboxPos != null) {
val level = entity.level()
val jukeboxBlockEntity = if (level.isLoaded(jukeboxPos!!)) level.getBlockEntity(jukeboxPos) as? JukeboxBlockEntity
else null
val distanceToJukebox = jukeboxPos?.toVec3d()?.distanceTo(entity.position())
isDancing = jukeboxBlockEntity?.songPlayer?.isPlaying == true && (distanceToJukebox ?: 100.0) < Cobblemon.config.pokemonDanceDistance
}
val poseType = when {
isPassenger -> PoseType.STAND
@@ -274,6 +290,7 @@ class PokemonServerDelegate : PokemonSideDelegate {
isMoving && isFlying -> PoseType.FLY
isFlying -> PoseType.HOVER
isMoving -> PoseType.WALK
isDancing -> PoseType.DANCE
else -> PoseType.STAND
}
@@ -238,7 +238,6 @@ object CobblemonItemGroups {
entries.accept(CobblemonItems.PC)
entries.accept(CobblemonItems.HEALING_MACHINE)
entries.accept(CobblemonItems.PASTURE)
entries.accept(CobblemonItems.STADIUM)
entries.accept(CobblemonItems.GILDED_CHEST)
entries.accept(CobblemonItems.YELLOW_GILDED_CHEST)
@@ -354,18 +353,6 @@ object CobblemonItemGroups {
entries.accept(CobblemonItems.LEEK_AND_POTATO_STEW)
entries.accept(CobblemonItems.BRAISED_VIVICHOKE)
entries.accept(CobblemonItems.VIVICHOKE_DIP)
entries.accept(CobblemonItems.TART_APPLE)
entries.accept(CobblemonItems.SWEET_APPLE)
entries.accept(CobblemonItems.SYRUPY_APPLE)
entries.accept(CobblemonItems.WHIPPED_DREAM)
entries.accept(CobblemonItems.STRAWBERRY_SWEET)
entries.accept(CobblemonItems.LOVE_SWEET)
entries.accept(CobblemonItems.BERRY_SWEET)
entries.accept(CobblemonItems.CLOVER_SWEET)
entries.accept(CobblemonItems.FLOWER_SWEET)
entries.accept(CobblemonItems.STAR_SWEET)
entries.accept(CobblemonItems.RIBBON_SWEET)
entries.accept(CobblemonItems.BERRY_JUICE)
entries.accept(CobblemonItems.REMEDY)
entries.accept(CobblemonItems.FINE_REMEDY)
@@ -488,7 +475,6 @@ object CobblemonItemGroups {
entries.accept(CobblemonItems.WHIPPED_DREAM)
entries.accept(CobblemonItems.TART_APPLE)
entries.accept(CobblemonItems.SWEET_APPLE)
entries.accept(CobblemonItems.SYRUPY_APPLE)
entries.accept(CobblemonItems.CRACKED_POT)
entries.accept(CobblemonItems.CHIPPED_POT)
entries.accept(CobblemonItems.MASTERPIECE_TEACUP)
@@ -658,23 +644,9 @@ object CobblemonItemGroups {
}
private fun foodInjections(injector: Injector) {
injector.putAfter(CobblemonItems.TART_APPLE, Items.ENCHANTED_GOLDEN_APPLE)
injector.putAfter(CobblemonItems.SWEET_APPLE, CobblemonItems.TART_APPLE)
injector.putAfter(CobblemonItems.SYRUPY_APPLE, CobblemonItems.SWEET_APPLE)
injector.putAfter(CobblemonItems.MEDICINAL_LEEK, Items.POISONOUS_POTATO)
injector.putAfter(CobblemonItems.ROASTED_LEEK, CobblemonItems.MEDICINAL_LEEK)
injector.putAfter(CobblemonItems.BRAISED_VIVICHOKE, CobblemonItems.ROASTED_LEEK)
injector.putAfter(CobblemonItems.WHIPPED_DREAM, Items.PUMPKIN_PIE)
injector.putAfter(CobblemonItems.STRAWBERRY_SWEET, CobblemonItems.WHIPPED_DREAM)
injector.putAfter(CobblemonItems.LOVE_SWEET, CobblemonItems.STRAWBERRY_SWEET)
injector.putAfter(CobblemonItems.BERRY_SWEET, CobblemonItems.LOVE_SWEET)
injector.putAfter(CobblemonItems.CLOVER_SWEET, CobblemonItems.BERRY_SWEET)
injector.putAfter(CobblemonItems.FLOWER_SWEET, CobblemonItems.CLOVER_SWEET)
injector.putAfter(CobblemonItems.STAR_SWEET, CobblemonItems.FLOWER_SWEET)
injector.putAfter(CobblemonItems.RIBBON_SWEET, CobblemonItems.STAR_SWEET)
injector.putAfter(CobblemonItems.LEEK_AND_POTATO_STEW, Items.RABBIT_STEW)
injector.putAfter(CobblemonItems.VIVICHOKE_DIP, CobblemonItems.LEEK_AND_POTATO_STEW)
}
@@ -10,17 +10,10 @@ package com.cobblemon.mod.common.item.interactive
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.item.PokemonSelectingItem
import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
import com.cobblemon.mod.common.client.render.models.blockbench.animation.PrimaryAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.bedrock.animation.BedrockActiveAnimation
import com.cobblemon.mod.common.item.CobblemonItem
import com.cobblemon.mod.common.pokemon.Nature
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.stadium.StadiumClientManager
import com.cobblemon.mod.common.stadium.deserialize
import com.cobblemon.mod.common.util.*
import com.cobblemon.mod.common.util.lang
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraft.server.level.ServerPlayer
@@ -52,21 +45,9 @@ class MintItem(val nature: Nature) : CobblemonItem(Properties()), PokemonSelecti
}
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
// if (user is ServerPlayer) {
// return use(user, user.getItemInHand(hand))
// }
if (!world.isClientSide) return InteractionResultHolder.fail(user.getItemInHand(hand))
val pokemon = CobblemonClient.storage.myParty.first { it?.entity != null } ?: return InteractionResultHolder.fail(user.getItemInHand(hand))
val entity = pokemon.entity ?: return InteractionResultHolder.fail(user.getItemInHand(hand))
val delegate = entity.delegate as? PokemonClientDelegate ?: return InteractionResultHolder.fail(user.getItemInHand(hand))
val bedrockAnimation = when (pokemon.species.name) {
"Tinkaton" -> (delegate.runtime.resolve("q.bedrock_primary('tinkaton', 'signature')".asExpression()).value() as ObjectValue<*>).obj as PrimaryAnimation
"Tandemaus" -> (delegate.runtime.resolve("q.bedrock_primary('tandemaus', 'faint')".asExpression()).value() as ObjectValue<*>).obj as PrimaryAnimation
else -> (delegate.runtime.resolve("q.bedrock_primary('ceruledge', 'battle_cry')".asExpression()).value() as ObjectValue<*>).obj as PrimaryAnimation
if (user is ServerPlayer) {
return use(user, user.getItemInHand(hand))
}
delegate.addPrimaryAnimation(bedrockAnimation)
StadiumClientManager.playAnimation(entity, bedrockAnimation)
return InteractionResultHolder.success(user.getItemInHand(hand))
}
}
}
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common.platform.events
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
class ChangeDimensionEvent(val player: ServerPlayer, val origin: ServerLevel?, val destination: ServerLevel?)
class ChangeDimensionEvent(val player: ServerPlayer)
@@ -1,32 +0,0 @@
package com.cobblemon.mod.common.stadium
import com.cobblemon.mod.common.util.adapters.Vec3dAdapter
import com.google.gson.GsonBuilder
import net.minecraft.world.phys.Vec3
import org.joml.Vector3f
val gson = GsonBuilder()
.setPrettyPrinting()
.disableHtmlEscaping()
.registerTypeAdapter(Vec3::class.java, Vec3dAdapter)
.create()
fun deserialize(data: String): CameraAnimation {
return gson.fromJson(data, CameraAnimation::class.java)
}
data class CameraAnimation(
val length: Double,
val origin: CameraOrigin,
val timeline: Timeline
)
data class Timeline(
val position: Map<Double, Vec3>,
val rotation: Map<Double, Vec3>,
)
data class CameraOrigin(
val position: Vec3,
val rotation: Vec3,
)
@@ -1,25 +0,0 @@
package com.cobblemon.mod.common.stadium
import net.minecraft.server.level.ServerPlayer
import java.util.*
abstract class StadiumBattleDefenition {
var stadiumBattleID: UUID = UUID.randomUUID()
var participants: MutableList<UUID> = mutableListOf<UUID>()
var spectators: MutableList<UUID> = mutableListOf<UUID>()
var cameras: MutableList<StadiumCameraEntry> = mutableListOf<StadiumCameraEntry>()
abstract fun readyForBattle(): Boolean
abstract fun canAddPlayer(player: ServerPlayer): Boolean
abstract fun addPlayer(player: ServerPlayer)
abstract fun getPlayers(): MutableList<ServerPlayer>
abstract fun initializeBattle()
abstract fun getCurrentCamera(): StadiumCameraEntry
}
@@ -1,192 +0,0 @@
package com.cobblemon.mod.common.stadium
import com.bedrockk.molang.Expression
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.util.*
import com.google.gson.JsonArray
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import net.fabricmc.loader.impl.lib.sat4j.core.Vec
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.phys.Vec3
import org.joml.Vector3f
import java.lang.reflect.Type
import kotlin.math.abs
import kotlin.math.atan
import kotlin.math.atan2
class StadiumCameraEntry(
var id: ResourceLocation,
val length: Double = 0.0,
val positionTimeline: MutableMap<String, CameraKeyFrame> = mutableMapOf(),
val targetPositionTimeline: MutableMap<String, CameraKeyFrame> = mutableMapOf(),
val move: String = ""
) {
fun resolvePosition(time: Double): Vec3 {
return resolvePosition(time, positionTimeline)
}
private fun resolvePosition(time: Double, map: MutableMap<String, CameraKeyFrame>): Vec3 {
val runtime = StadiumClientManager.runtime
runtime.environment.setSimpleVariable("anim_time", DoubleValue(time))
var frame1: CameraKeyFrame? = null
var frame2: CameraKeyFrame? = null
var time1 = -1.0
var time2 = -1.0
for (keyframe in map) {
if (time >= keyframe.key.toDouble()) {
if (time1 == -1.0 || abs(time - keyframe.key.toDouble()) < abs(time - time1)) {
frame1 = keyframe.value
time1 = keyframe.key.toDouble()
}
}
if (time < keyframe.key.toDouble()) {
if (time2 == -1.0 || abs(time - keyframe.key.toDouble()) < abs(time - time2)) {
frame2 = keyframe.value
time2 = keyframe.key.toDouble()
}
}
}
val difference = (time - time1) / (time2 - time1)
if (frame1 != null && frame1.interpolation == CameraInterpolation.STEP) {
frame2 = null
}
if (frame1 == null && frame2 == null) {
return Vec3.ZERO
}
else if (frame1 == null) {
frame2!!
val x = runtime.resolveDouble(frame2.x)
val y = runtime.resolveDouble(frame2.y)
val z = runtime.resolveDouble(frame2.z)
return Vec3(x,y,z)
}
else if (frame2 == null) {
val x = runtime.resolveDouble(frame1.x)
val y = runtime.resolveDouble(frame1.y)
val z = runtime.resolveDouble(frame1.z)
return Vec3(x,y,z)
}
else {
val x1 = runtime.resolveDouble(frame1.x)
val y1 = runtime.resolveDouble(frame1.y)
val z1 = runtime.resolveDouble(frame1.z)
val vec1 = Vec3(x1,y1,z1)
val x2 = runtime.resolveDouble(frame2.x)
val y2 = runtime.resolveDouble(frame2.y)
val z2 = runtime.resolveDouble(frame2.z)
val vec2 = Vec3(x2,y2,z2)
return vec1.lerp(vec2, difference)
}
}
fun resolveRotation(time: Double): Vector3f {
val position = resolvePosition(time, positionTimeline)
val target = resolvePosition(time, targetPositionTimeline)
val offset = target.subtract(position)
val xRot = -atan(offset.y.toFloat()/offset.horizontalDistance().toFloat()) * (180F / Math.PI.toFloat())
val yRot = -atan2(offset.x.toFloat(),offset.z.toFloat()) * (180F / Math.PI.toFloat())
return Vector3f(xRot, yRot, 0.0F)
}
fun encode(buf: RegistryFriendlyByteBuf) {
buf.writeIdentifier(id)
buf.writeDouble(length)
buf.writeMap(positionTimeline, {_, key -> buf.writeString(key)}, {_, value ->
buf.writeString(value.x.getString())
buf.writeString(value.y.getString())
buf.writeString(value.z.getString())
buf.writeEnum(value.interpolation)
})
buf.writeMap(targetPositionTimeline, {_, key -> buf.writeString(key)}, {_, value ->
buf.writeString(value.x.getString())
buf.writeString(value.y.getString())
buf.writeString(value.z.getString())
buf.writeEnum(value.interpolation)
})
buf.writeString(move)
}
companion object {
fun decode(buf: RegistryFriendlyByteBuf) : StadiumCameraEntry {
val id = buf.readIdentifier()
val length = buf.readDouble()
val positionTimeline = buf.readMap({_ -> buf.readString()}, {_ ->
CameraKeyFrame(buf.readString().asExpression(), buf.readString().asExpression(), buf.readString().asExpression(), buf.readEnum(CameraInterpolation::class.java))
}).toMutableMap()
val targetPositionTimeline = buf.readMap({_ -> buf.readString()}, {_ ->
CameraKeyFrame(buf.readString().asExpression(), buf.readString().asExpression(), buf.readString().asExpression(), buf.readEnum(CameraInterpolation::class.java))
}).toMutableMap()
val move = buf.readString()
return StadiumCameraEntry(id, length, positionTimeline, targetPositionTimeline, move)
}
}
data class CameraKeyFrame (
val x: Expression,
val y: Expression,
val z: Expression,
val interpolation: CameraInterpolation
)
enum class CameraInterpolation {
LINEAR,
STEP
}
object CameraEntryAdapter: JsonDeserializer<StadiumCameraEntry> {
override fun deserialize(
json: JsonElement?,
typeOfT: Type?,
context: JsonDeserializationContext?
): StadiumCameraEntry {
if (json is JsonObject) {
val length = json["length"]?.asDouble ?: 0.0
val positionTimeline = mutableMapOf<String, CameraKeyFrame>()
json["positions"]?.asJsonObject?.entrySet()?.forEach { (name, position) ->
val xyz = position.asJsonObject["xyz"]
var x = "0.0".asExpression()
var y = "0.0".asExpression()
var z = "0.0".asExpression()
if (xyz != null && xyz.isJsonArray && xyz.asJsonArray.size() == 3) {
x = xyz.asJsonArray[0].asString.asExpression()
y = xyz.asJsonArray[1].asString.asExpression()
z = xyz.asJsonArray[2].asString.asExpression()
}
val interpolation = when (position.asJsonObject["interpolation"]?.asString) {
"linear" -> CameraInterpolation.LINEAR
"step" -> CameraInterpolation.STEP
else -> CameraInterpolation.LINEAR
}
positionTimeline[name] = CameraKeyFrame(x, y, z, interpolation)
}
val targetPositionTimeline = mutableMapOf<String, CameraKeyFrame>()
json["targetPositions"]?.asJsonObject?.entrySet()?.forEach { (name, position) ->
val xyz = position.asJsonObject["xyz"]
var x = "0.0".asExpression()
var y = "0.0".asExpression()
var z = "0.0".asExpression()
if (xyz != null && xyz.isJsonArray && xyz.asJsonArray.size() == 3) {
x = xyz.asJsonArray[0].asString.asExpression()
y = xyz.asJsonArray[1].asString.asExpression()
z = xyz.asJsonArray[2].asString.asExpression()
}
val interpolation = when (position.asJsonObject["interpolation"]?.asString) {
"linear" -> CameraInterpolation.LINEAR
"step" -> CameraInterpolation.STEP
else -> CameraInterpolation.LINEAR
}
targetPositionTimeline[name] = CameraKeyFrame(x, y, z, interpolation)
}
val move = json["move"]?.asString ?: ""
}
throw IllegalStateException("Stadium Camera could not be parsed")
}
}
}
@@ -1,119 +0,0 @@
package com.cobblemon.mod.common.stadium
import com.bedrockk.molang.Expression
import com.cobblemon.mod.common.util.*
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import java.lang.reflect.Type
class StadiumCameraManagerEntry(
var id: ResourceLocation,
val states: MutableMap<String, StadiumCameraState>,
val startingState: String
) {
fun encode(buf: RegistryFriendlyByteBuf) {
buf.writeIdentifier(id)
buf.writeMap(states, {_, key -> buf.writeString(key)}, {_, value -> value.encode(buf)})
buf.writeString(startingState)
}
companion object {
fun decode(buf: RegistryFriendlyByteBuf): StadiumCameraManagerEntry {
val id = buf.readIdentifier()
val states = buf.readMap({buf.readString()}, {StadiumCameraState.decode(buf)}).toMutableMap()
val startState = buf.readString()
return StadiumCameraManagerEntry(id, states, startState)
}
}
}
class StadiumCameraState(
val camera: Expression,
val target: StadiumCameraTarget,
val listOfTransitions: MutableList<StadiumCameraTransition>,
val loop: Boolean
) {
fun encode(buf: RegistryFriendlyByteBuf) {
buf.writeString(camera.originalString)
buf.writeEnum(target)
buf.writeCollection(listOfTransitions) {_, transition -> transition.encode(buf)}
buf.writeBoolean(loop)
}
companion object {
fun decode(buf: RegistryFriendlyByteBuf): StadiumCameraState {
val camera = buf.readString().asExpression()
val target = buf.readEnum(StadiumCameraTarget::class.java)
val listOfTransitions = buf.readList { StadiumCameraTransition.decode(buf) }.toMutableList()
val loop = buf.readBoolean()
return StadiumCameraState(camera, target, listOfTransitions, loop)
}
}
}
class StadiumCameraTransition(
val targetState: String,
val checkOnEnd: Boolean,
val condition: Expression
) {
fun encode(buf: RegistryFriendlyByteBuf) {
buf.writeString(targetState)
buf.writeBoolean(checkOnEnd)
buf.writeString(condition.originalString)
}
companion object {
fun decode(buf: RegistryFriendlyByteBuf): StadiumCameraTransition {
val targetState = buf.readString()
val checkOnEnd = buf.readBoolean()
val condition = buf.readString().asExpression()
return StadiumCameraTransition(targetState, checkOnEnd, condition)
}
}
}
enum class StadiumCameraTarget {
CENTRE,
ACTIVE_POKEMON,
ENEMY_POKEMON,
TRAINER
}
object StadiumCameraManagerAdapter: JsonDeserializer<StadiumCameraManagerEntry> {
override fun deserialize(
json: JsonElement?,
typeOfT: Type?,
context: JsonDeserializationContext?
): StadiumCameraManagerEntry {
if (json is JsonObject) {
val states = mutableMapOf<String, StadiumCameraState>()
json["states"]?.asJsonObject?.entrySet()?.forEach { (name, state) ->
val camera = state.asJsonObject["camera"]?.asString?.asExpression() ?: "".asExpression()
val target = when (state.asJsonObject["target"]?.asString) {
"CENTRE" -> StadiumCameraTarget.CENTRE
"ACTIVE_POKEMON" -> StadiumCameraTarget.ACTIVE_POKEMON
"ENEMY_POKEMON" -> StadiumCameraTarget.ENEMY_POKEMON
"TRAINER" -> StadiumCameraTarget.TRAINER
else -> StadiumCameraTarget.CENTRE
}
val listOfTransitions = mutableListOf<StadiumCameraTransition>()
state.asJsonObject["transitions"]?.asJsonArray?.forEach {
val targetState = it.asJsonObject["targetState"]?.asString ?: ""
val checkOnEnd = it.asJsonObject["checkOnEnd"]?.asBoolean ?: false
val condition = it.asJsonObject["condition"]?.asString?.asExpression() ?: "0.0".asExpression()
listOfTransitions.add(StadiumCameraTransition(targetState, checkOnEnd, condition))
}
val loop = state.asJsonObject["loop"]?.asBoolean ?: false
states[name] = StadiumCameraState(camera, target, listOfTransitions, loop)
}
val startingState = json["startingState"].asString ?: ""
return StadiumCameraManagerEntry(cobblemonResource(""), states, startingState)
}
throw IllegalStateException("StadiumCameraManager could not be parsed")
}
}
@@ -1,46 +0,0 @@
package com.cobblemon.mod.common.stadium
import com.bedrockk.molang.Expression
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.util.adapters.ExpressionAdapter
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType
object StadiumCameraManagers: JsonDataRegistry<StadiumCameraManagerEntry> {
override val id = cobblemonResource("stadium_managers")
override val type = PackType.SERVER_DATA
override val gson: Gson = GsonBuilder()
.disableHtmlEscaping()
.setPrettyPrinting()
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
.registerTypeAdapter(StadiumCameraManagerEntry::class.java, StadiumCameraManagerAdapter)
.create()
override val typeToken: TypeToken<StadiumCameraManagerEntry> = TypeToken.get(StadiumCameraManagerEntry::class.java)
override val resourcePath = "stadium_managers"
val managers = mutableMapOf<ResourceLocation, StadiumCameraManagerEntry>()
override fun reload(data: Map<ResourceLocation, StadiumCameraManagerEntry>) {
managers.clear()
data.forEach { location, manager ->
manager.id = location
managers[location] = manager
}
observable.emit(this)
}
override val observable = SimpleObservable<StadiumCameraManagers>()
override fun sync(player: ServerPlayer) {
StadiumCameraManagersSyncPacket(managers.values).sendToPlayer(player)
}
}
@@ -1,27 +0,0 @@
package com.cobblemon.mod.common.stadium
import com.cobblemon.mod.common.net.messages.client.data.DataRegistrySyncPacket
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.network.RegistryFriendlyByteBuf
class StadiumCameraManagersSyncPacket(managers: Collection<StadiumCameraManagerEntry>) :
DataRegistrySyncPacket<StadiumCameraManagerEntry, StadiumCameraManagersSyncPacket>(managers) {
override fun encodeEntry(buffer: RegistryFriendlyByteBuf, entry: StadiumCameraManagerEntry) {
entry.encode(buffer)
}
override fun decodeEntry(buffer: RegistryFriendlyByteBuf): StadiumCameraManagerEntry? {
return StadiumCameraManagerEntry.decode(buffer)
}
override fun synchronizeDecoded(entries: Collection<StadiumCameraManagerEntry>) {
StadiumCameraManagers.reload(entries.associateBy { it.id })
}
override val id = ID
companion object {
val ID = cobblemonResource("stadium_camera_managers_sync")
fun decode(buffer: RegistryFriendlyByteBuf) = StadiumCameraManagersSyncPacket(emptyList()).apply { decodeBuffer(buffer) }
}
}
@@ -1,48 +0,0 @@
package com.cobblemon.mod.common.stadium
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType
object StadiumCameras: JsonDataRegistry<StadiumCameraEntry> {
override val id = cobblemonResource("stadium_cameras")
override val type = PackType.SERVER_DATA
override val gson: Gson = GsonBuilder()
.disableHtmlEscaping()
.setPrettyPrinting()
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
.registerTypeAdapter(StadiumCameraEntry::class.java, StadiumCameraEntry.CameraEntryAdapter)
.create()
override val typeToken: TypeToken<StadiumCameraEntry> = TypeToken.get(StadiumCameraEntry::class.java)
override val resourcePath = "stadium_cameras"
val cameras = mutableMapOf<ResourceLocation, StadiumCameraEntry>()
override fun reload(data: Map<ResourceLocation, StadiumCameraEntry>) {
cameras.clear()
data.forEach { location, camera ->
camera.id = location
cameras[location] = camera
}
observable.emit(this)
}
override val observable = SimpleObservable<StadiumCameras>()
override fun sync(player: ServerPlayer) {
StadiumCamerasSyncPacket(cameras.values).sendToPlayer(player)
}
fun getMoveCamera(move: String): StadiumCameraEntry? {
return cameras.values.firstOrNull { it.move == move }
}
}
@@ -1,27 +0,0 @@
package com.cobblemon.mod.common.stadium
import com.cobblemon.mod.common.net.messages.client.data.DataRegistrySyncPacket
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.network.RegistryFriendlyByteBuf
class StadiumCamerasSyncPacket(cameras: Collection<StadiumCameraEntry>) :
DataRegistrySyncPacket<StadiumCameraEntry, StadiumCamerasSyncPacket>(cameras) {
override fun encodeEntry(buffer: RegistryFriendlyByteBuf, entry: StadiumCameraEntry) {
entry.encode(buffer)
}
override fun decodeEntry(buffer: RegistryFriendlyByteBuf): StadiumCameraEntry? {
return StadiumCameraEntry.decode(buffer)
}
override fun synchronizeDecoded(entries: Collection<StadiumCameraEntry>) {
StadiumCameras.reload(entries.associateBy { it.id })
}
override val id = ID
companion object {
val ID = cobblemonResource("stadium_cameras_sync")
fun decode(buffer: RegistryFriendlyByteBuf) = StadiumCamerasSyncPacket(emptyList()).apply { decodeBuffer(buffer) }
}
}
@@ -1,232 +0,0 @@
package com.cobblemon.mod.common.stadium
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.MoValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunctions
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
import com.cobblemon.mod.common.client.ClientMoLangFunctions.setupClient
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.MountedPokemonAnimationRenderController
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
import com.cobblemon.mod.common.client.render.models.blockbench.animation.PrimaryAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.bedrock.animation.linearLerpAlpha
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.asResource
import com.cobblemon.mod.common.util.math.fromEulerXYZ
import com.cobblemon.mod.common.util.math.geometry.toRadians
import com.cobblemon.mod.common.util.math.toEulerXYZ
import com.cobblemon.mod.common.util.resolveBoolean
import com.cobblemon.mod.common.util.resolveString
import com.cobblemon.mod.common.util.toVec3d
import net.minecraft.resources.ResourceLocation
import net.minecraft.util.Mth
import net.minecraft.world.phys.Vec3
import org.joml.Matrix4f
import org.joml.Quaternionf
import org.joml.Vector3f
import java.util.*
import java.util.function.Function
import com.cobblemon.mod.common.util.plus
import net.minecraft.client.Minecraft
object StadiumClientManager {
//Molang
fun MoLangRuntime.setupCameraFunctions(): MoLangRuntime {
environment.query.addFunctions(
hashMapOf(
"moveCamera" to Function { params ->
if (params.get<MoValue>(0) !is StringValue) {
return@Function Unit
}
val camera = StadiumCameras.getMoveCamera(params.get<MoValue>(0).asString())
return@Function camera?.id?.toString() ?: ""
}
)
)
return this
}
val runtime = MoLangRuntime().setup().setupClient().setupCameraFunctions()
var currentStadiumBattleUUID: UUID? = null
var Instruction = "DEFAULT"
var InstructionChangeTime = 0.0
var InstructionJustChanged = false
fun updateState(newState: String) {
Instruction = newState
InstructionChangeTime = 0.0
InstructionJustChanged = true
}
fun onLogout() {
currentStadiumBattleUUID = null
}
fun handleJoin(battleUUID: UUID, cameraManager: ResourceLocation) {
currentStadiumBattleUUID = battleUUID
activeCameraManager = cameraManager
cameraTimer = 0.0
currentCameraState = StadiumCameraManagers.managers[cameraManager]!!.startingState
cameraPosition = Vec3.ZERO
cameraRotation = Quaternionf()
updateCameraData(0.0)
}
fun inStadiumBattle(): Boolean {
return currentStadiumBattleUUID != null
}
fun shouldUseStadiumCamera(): Boolean {
return animation != null
}
//Molang Data
fun updateMolangVar() {
val environment = runtime.environment
environment.setSimpleVariable("instruction", StringValue(Instruction))
//environment.setSimpleVariable("instructionChangeTime", DoubleValue(InstructionChangeTime))
environment.setSimpleVariable("instructionJustChanged", DoubleValue(InstructionJustChanged))
val isSpectating = CobblemonClient.battle?.spectating ?: false
environment.setSimpleVariable("isBattling", DoubleValue(!isSpectating))
environment.setSimpleVariable("isSpectating", DoubleValue(isSpectating))
}
fun instructionUpdate(newState: String, additionalValues: MutableMap<String, MoValue>) {
val environment = runtime.environment
Instruction = newState
InstructionChangeTime = 0.0
InstructionJustChanged = true
for (value in additionalValues) {
environment.setSimpleVariable(value.key, value.value)
}
}
//Camera Manager
var activeCameraManager: ResourceLocation? = null
var cameraTimer: Double = 0.0
var currentCameraState: String = ""
var nextCameraState: String = ""
var calculateNextState: Boolean = true
fun tickCameraManager() {
if (!shouldUseStadiumCamera()) return
//Molang Variables
val environment = runtime.environment
if (CobblemonClient.battle != null) {
environment.setSimpleVariable("selectingMove", DoubleValue(CobblemonClient.battle!!.mustChoose))
}
else {
environment.setSimpleVariable("selectingMove", DoubleValue(0.0))
}
val currentManager = StadiumCameraManagers.managers[activeCameraManager]!!
val currentState = currentManager.states[currentCameraState]!!
val currentCamera = StadiumCameras.cameras[runtime.resolveString(currentState.camera).asResource()]
InstructionChangeTime += 0.05
if (currentCamera != null) {
cameraTimer += 0.05
if (cameraTimer > currentCamera.length) {
if (currentState.loop) {
cameraTimer -= currentCamera.length
}
else {
cameraTimer = currentCamera.length
}
}
}
if (!calculateNextState) {
currentCameraState = nextCameraState
calculateNextState = true
cameraTimer = if (currentCamera != null && currentCamera.length != 0.0) cameraTimer - currentCamera.length else 0.0
}
else {
updateMolangVar()
environment.setSimpleVariable("instructionChangeTime", DoubleValue(InstructionChangeTime))
val endOfAnim = if (currentCamera != null) cameraTimer + 1/20 >= currentCamera.length else true
val nextState = evaluateTransitions(currentState, endOfAnim)
if (nextState != null) {
nextCameraState = nextState.targetState
while (true) {
val newState = currentManager.states[nextCameraState]!!
val newCamera = StadiumCameras.cameras[runtime.resolveString(newState.camera).asResource()]
val newEndOfAnim = if (newCamera != null) newCamera.length == 0.0 else true
val newNextState = evaluateTransitions(newState, newEndOfAnim)
if (newNextState == null) {
break
}
else {
nextCameraState = newNextState.targetState
}
}
calculateNextState = false
}
}
if (InstructionJustChanged) {
InstructionJustChanged = false
Instruction = "NONE"
}
}
private fun evaluateTransitions(state: StadiumCameraState, checkEnd: Boolean) : StadiumCameraTransition? {
var nextState = state.listOfTransitions.firstOrNull { !it.checkOnEnd && runtime.resolveBoolean(it.condition) }
if (nextState == null && checkEnd) {
nextState = state.listOfTransitions.firstOrNull { it.checkOnEnd && runtime.resolveBoolean(it.condition) }
}
return nextState
}
var cameraPosition: Vec3 = Vec3.ZERO
var cameraRotation: Quaternionf = Quaternionf()
var startTime = 0.0
var startPosition: Vec3? = null
var startRotation: Vector3f? = null
var attackAnimationPokemon: PokemonEntity? = null
var animation: PrimaryAnimation? = null
var oldFov: Int = 0
fun playAnimation(pokemon: PokemonEntity, animation: PrimaryAnimation) {
if (startTime != 0.0) return
attackAnimationPokemon = pokemon
this.animation = animation
this.oldFov = Minecraft.getInstance().options.fov().get()
animation.afterAction += {
cameraPosition = Vec3.ZERO
cameraRotation = Quaternionf()
attackAnimationPokemon = null
this.animation = null
Minecraft.getInstance().options.fov().set(oldFov)
}
}
fun updateCameraData(delta: Double) {
val pokemon = attackAnimationPokemon ?: return
val delegate = pokemon.delegate as? PokemonClientDelegate ?: return
delegate.updatePartialTicks(delta.toFloat())
MountedPokemonAnimationRenderController.reset()
MountedPokemonAnimationRenderController.setup(pokemon, delta.toFloat())
val locator = delegate.locatorStates["camera"] ?: return
cameraPosition = locator.position.add(locator.matrix.getTranslation(Vector3f()).toVec3d())
cameraRotation = locator.matrix.getUnnormalizedRotation(Quaternionf()).normalize()
val cameraPart = delegate.currentModel?.getPart("locator_camera") ?: return
val fov = cameraPart.zScale.toInt()
if (Minecraft.getInstance().options.fov().get() != fov) {
Minecraft.getInstance().options.fov().set(fov)
}
}
}
@@ -1,4 +0,0 @@
package com.cobblemon.mod.common.stadium
class StadiumFormat {
}
@@ -1,13 +0,0 @@
package com.cobblemon.mod.common.stadium
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
import net.minecraft.client.Minecraft
import net.minecraft.server.MinecraftServer
import net.minecraft.server.level.ServerPlayer
object StadiumJoinHandler: ClientNetworkPacketHandler<StadiumJoinPacket> {
override fun handle(packet: StadiumJoinPacket, client: Minecraft) {
StadiumClientManager.handleJoin(packet.joiningBattle, packet.cameraManager)
}
}
@@ -1,24 +0,0 @@
package com.cobblemon.mod.common.stadium
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.readIdentifier
import com.cobblemon.mod.common.util.writeIdentifier
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import java.util.*
class StadiumJoinPacket(
val joiningBattle: UUID,
val cameraManager: ResourceLocation
): NetworkPacket<StadiumJoinPacket> {
override val id = ID
override fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeUUID(this.joiningBattle)
buffer.writeIdentifier(cameraManager)
}
companion object {
val ID = cobblemonResource("stadium_join")
fun decode(buffer: RegistryFriendlyByteBuf) = StadiumJoinPacket(buffer.readUUID(), buffer.readIdentifier())
}
}
@@ -1,34 +0,0 @@
package com.cobblemon.mod.common.stadium
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import java.util.UUID
object StadiumServerManager {
val activeStadiumBattles = mutableMapOf<UUID, StadiumBattleInstance>()
fun createNewStadiumBattle(battle: UUID, managerResource: ResourceLocation, participants: MutableList<UUID> = mutableListOf<UUID>()) {
val newInstance = StadiumBattleInstance(battle, managerResource)
newInstance.participants = participants
activeStadiumBattles[battle] = newInstance
}
fun terminateNewStadiumBattle(battle: UUID) {
activeStadiumBattles.remove(battle)
}
fun addPlayerToStadiumBattle(battle: UUID, player: UUID) {
val instance = activeStadiumBattles[battle]
if (instance != null) {
if (!instance.participants.contains(player)) instance.participants.add(player)
}
}
}
class StadiumBattleInstance(
val stadiumBattleId: UUID,
val managerResource: ResourceLocation
){
var participants = mutableListOf<UUID>()
}
@@ -1,63 +0,0 @@
package com.cobblemon.mod.common.stadium
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.battles.BattleBuilder
import com.cobblemon.mod.common.battles.SuccessfulBattleStart
import com.cobblemon.mod.common.util.getPlayer
import com.cobblemon.mod.common.util.party
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.phys.Vec3
class StadiumSingleBattle: StadiumBattleDefenition() {
@JvmField
val MAX_PLAYERS = 2
var player1Position = Vec3(0.0,0.0,0.0)
var player2Position = Vec3(0.0,0.0,0.0)
var player1PokemonPosition = Vec3(0.0,0.0,0.0)
var player2PokemonPosition = Vec3(0.0,0.0,0.0)
var activeBattle: PokemonBattle? = null
override fun readyForBattle(): Boolean {
return this.getPlayers().count() == MAX_PLAYERS
}
override fun canAddPlayer(player: ServerPlayer): Boolean {
val party = player.party()
return party.occupied() > 0
}
override fun addPlayer(player: ServerPlayer) {
if (canAddPlayer(player)) {
participants.add(player.uuid)
player.sendPacket(StadiumJoinPacket(player.uuid, StadiumCameraManagers.managers.keys.first()))
}
}
override fun getPlayers(): MutableList<ServerPlayer> {
return participants.mapNotNull { it.getPlayer() }.toMutableList()
}
override fun initializeBattle() {
if (!readyForBattle()) return
val players = getPlayers()
val player1 = players[0]
val player2 = players[1]
val battleResult = BattleBuilder.pvp1v1(player1, player2)
var errored = false
battleResult.ifErrored { errored = true }
if (errored) return
val battle = (battleResult as SuccessfulBattleStart).battle
}
override fun getCurrentCamera(): StadiumCameraEntry {
TODO("Not yet implemented")
}
}
@@ -1,15 +0,0 @@
package com.cobblemon.mod.common.util
import com.cobblemon.mod.common.util.math.geometry.toDegrees
import com.cobblemon.mod.common.util.math.toEulerXYZ
import net.minecraft.client.Camera
import org.joml.Quaternionf
fun Camera.setRotation(pitch: Float, yaw: Float, roll: Float) {
this.xRot = pitch.toDegrees()
this.yRot = yaw.toDegrees()
this.rotation.rotationYXZ(yaw, pitch, roll)
Camera.FORWARDS.rotate(this.rotation, this.forwards)
Camera.UP.rotate(this.rotation, this.up)
Camera.LEFT.rotate(this.rotation, this.left)
}
@@ -1,41 +0,0 @@
{
"format_version": "1.8.0",
"animations": {
"animation.rotom_drone.sleep": {
"loop": true,
"bones": {
"body": {
"rotation": [
"math.sin(query.anim_time * 120) * 6",
0,
"math.cos(query.anim_time * 100) * 4"
],
"position": [
0,
"18 + math.sin(query.anim_time * 90) * 1",
0
]
},
"head": {
"relative_to": {
"rotation": "entity"
},
"rotation": [
0,
0,
0.01
]
}
}
},
"animation.rotom_drone.circle": {
"loop": true,
"bones": {
"rotom_drone": {
"rotation": [30, "90 - q.anim_time*90", 0],
"position": ["48*math.cos(q.anim_time*90)", 64, "48*math.sin(q.anim_time*90)"]
}
}
}
}
}
@@ -1,208 +0,0 @@
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.drone_rotom",
"texture_width": 64,
"texture_height": 32,
"visible_bounds_width": 8,
"visible_bounds_height": 6.5,
"visible_bounds_offset": [0, 2.75, 0]
},
"bones": [
{
"name": "rotom_drone",
"pivot": [0, 0, 0]
},
{
"name": "body",
"parent": "rotom_drone",
"pivot": [0, 8, 0]
},
{
"name": "head",
"parent": "body",
"pivot": [0, 6.5, 0],
"cubes": [
{"origin": [-5.5, 6.5, -3.5], "size": [11, 6, 7], "uv": [0, 0]}
]
},
{
"name": "eyes",
"parent": "head",
"pivot": [0.5, 6.5, -2.5]
},
{
"name": "eye_right",
"parent": "eyes",
"pivot": [-2.9, 9.5, -3.5],
"rotation": [0, 0, -7.5],
"cubes": [
{"origin": [-3.9, 7.5, -3.5], "size": [2, 4, 0], "inflate": 0.01, "uv": [0, 0], "mirror": true},
{"origin": [-3.9, 9, -3.5], "size": [2, 1, 0], "inflate": 0.02, "uv": [0, 6], "mirror": true}
]
},
{
"name": "pupil_right",
"parent": "eye_right",
"pivot": [-2.9, 9.5, -3.5],
"cubes": [
{"origin": [-3.4, 8, -3.5], "size": [1, 3, 0], "inflate": 0.03, "uv": [5, 0], "mirror": true}
]
},
{
"name": "eye_left",
"parent": "eyes",
"pivot": [2.9, 9.5, -3.5],
"rotation": [0, 0, 7.5],
"cubes": [
{"origin": [1.9, 7.5, -3.5], "size": [2, 4, 0], "inflate": 0.01, "uv": [0, 13]},
{"origin": [1.9, 9, -3.5], "size": [2, 1, 0], "inflate": 0.02, "uv": [0, 5]}
]
},
{
"name": "pupil_left",
"parent": "eye_left",
"pivot": [2.9, 9.5, -3.5],
"cubes": [
{"origin": [2.4, 8, -3.5], "size": [1, 3, 0], "inflate": 0.03, "uv": [6, 13]}
]
},
{
"name": "mouth_smile",
"parent": "head",
"pivot": [0, 7.55, -3.5],
"cubes": [
{"origin": [-1, 6.95, -3.5], "size": [2, 1, 0], "inflate": 0.02, "uv": [36, 7]},
{"origin": [-1.5, 7.25, -3.5], "size": [1, 1, 0], "inflate": 0.01, "uv": [40, 7]},
{"origin": [0.5, 7.25, -3.5], "size": [1, 1, 0], "inflate": 0.01, "uv": [42, 7]}
]
},
{
"name": "mouth_closed",
"parent": "head",
"pivot": [0, 7.45, -3.4],
"cubes": [
{"origin": [-0.5, 6.95, -3.4], "size": [1, 1, 0], "inflate": 0.02, "uv": [38, 8]}
]
},
{
"name": "mouth_open",
"parent": "head",
"pivot": [0, 7.45, -3.4],
"cubes": [
{"origin": [-0.5, 6.95, -3.4], "size": [1, 1, 0], "inflate": 0.02, "uv": [36, 8]}
]
},
{
"name": "mouth_sad",
"parent": "head",
"pivot": [0, 7.6, -3.3],
"cubes": [
{"origin": [-1, 7.3, -3.3], "size": [2, 1, 0], "inflate": 0.02, "uv": [36, 9]},
{"origin": [-1.5, 7, -3.3], "size": [1, 1, 0], "inflate": 0.01, "uv": [40, 9]},
{"origin": [0.5, 7, -3.3], "size": [1, 1, 0], "inflate": 0.01, "uv": [42, 9]}
]
},
{
"name": "head_spike1",
"parent": "head",
"pivot": [0, 12.5, 0],
"cubes": [
{"origin": [-1.5, 11.5, -1.5], "size": [3, 4, 3], "uv": [29, 0]}
]
},
{
"name": "head_spike2",
"parent": "head_spike1",
"pivot": [0, 15.5, 0],
"cubes": [
{"origin": [-1, 14.5, -1], "size": [2, 4, 2], "uv": [8, 13]}
]
},
{
"name": "head_spike3",
"parent": "head_spike2",
"pivot": [0, 18.5, 0],
"cubes": [
{"origin": [-0.5, 17.5, -0.5], "size": [1, 3, 1], "uv": [44, 6]}
]
},
{
"name": "torso",
"parent": "body",
"pivot": [0, 7, 0],
"cubes": [
{"origin": [-2, 3, -1.5], "size": [4, 4, 3], "uv": [34, 10]}
]
},
{
"name": "camera",
"parent": "torso",
"pivot": [0, 4.65, -1.25],
"cubes": [
{"origin": [-1, 3.65, -2.75], "size": [2, 2, 2], "uv": [24, 13]},
{"origin": [-0.5, 4.15, -2.75], "size": [1, 1, 0], "inflate": 0.01, "uv": [38, 0]}
]
},
{
"name": "propeller_front_right",
"parent": "torso",
"pivot": [-1.5, 5, -1],
"rotation": [0, 45, 0],
"cubes": [
{"origin": [-2, 5, -3.5], "size": [1, 0, 3], "uv": [37, 0]},
{"origin": [-5.5, 5, -11.5], "size": [8, 0, 8], "uv": [40, 0]}
]
},
{
"name": "propeller_front_left",
"parent": "torso",
"pivot": [1.5, 5, -1],
"rotation": [0, -45, 0],
"cubes": [
{"origin": [1, 5, -3.5], "size": [1, 0, 3], "uv": [27, 0]},
{"origin": [-2.5, 5, -11.5], "size": [8, 0, 8], "uv": [40, 0]}
]
},
{
"name": "propeller_back_right",
"parent": "torso",
"pivot": [-1.5, 5, 1],
"rotation": [0, -45, 0],
"cubes": [
{"origin": [-2, 5, 0.5], "size": [1, 0, 3], "uv": [39, 0]},
{"origin": [-5.5, 5, 3.5], "size": [8, 0, 8], "uv": [40, 0]}
]
},
{
"name": "propeller_back_left",
"parent": "torso",
"pivot": [1.5, 5, 1],
"rotation": [0, 45, 0],
"cubes": [
{"origin": [1, 5, 0.5], "size": [1, 0, 3], "uv": [42, 3]},
{"origin": [-2.5, 5, 3.5], "size": [8, 0, 8], "uv": [40, 0]}
]
},
{
"name": "tail1",
"parent": "torso",
"pivot": [0, 3, 0],
"cubes": [
{"origin": [-1, 1, -1], "size": [2, 3, 2], "uv": [16, 13]}
]
},
{
"name": "tail2",
"parent": "tail1",
"pivot": [0, 1, 0],
"cubes": [
{"origin": [-0.5, -1, -0.5], "size": [1, 3, 1], "uv": [41, 3]}
]
}
]
}
]
}
@@ -1,8 +0,0 @@
{
"poses": {
"sleep": {
"poseTypes": ["SLEEP"],
"animations": ["q.bedrock('rotom_drone', 'sleep')"]
}
}
}
@@ -1,13 +0,0 @@
{
"name": "cobblemon:rotom_drone",
"order": 0,
"variations": [
{
"aspects": [],
"poser": "cobblemon:rotom_drone",
"model": "cobblemon:rotom_drone.geo",
"texture": "cobblemon:textures/drone/rotom_drone.png",
"layers": []
}
]
}
@@ -458,21 +458,8 @@
"2.125": [0, -42.5, 0],
"2.3333": [0, -47.5, 0]
}
},
"locator_camera": {
"relative_to": {
"rotation": "entity"
},
"position": {
"0.0": [-24, 12, -23],
"0.91667": [20, 11, -15]
},
"rotation": {
"0.0": [0, -145, 0],
"0.91667": [0, -215, 0]
}
}
}
}
}
}
}
@@ -1343,27 +1343,6 @@
"2.2083": {"pre": [0, 0, 0], "post": [-0.1, 0, -0.1]},
"2.3333": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]}
}
},
"locator_camera": {
"relative_to": {
"rotation": "entity"
},
"position": {
"0.0": [0, 45, -42],
"0.125": [0, 16, -42],
"1.20833": [0, 16, -42],
"1.41667": [0, 66, -26],
"2.20833": [0, 72, -11],
"2.33333": [0, 26, -37]
},
"rotation": {
"0.0": [197.5, 2.5, -180],
"0.125": [172.5, 2.5, -180],
"1.20833": [172.5, 2.5, -180],
"1.41667": [227.5, 2.5, -180],
"2.20833": [245, 2.5, -180],
"2.33333": [185, 2.5, -180]
}
}
},
"sound_effects": {
@@ -3653,27 +3632,6 @@
"0.2083": {"pre": [0, 0, 0], "post": [-0.1, 0, -0.1]},
"1.375": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]}
}
},
"locator_camera": {
"relative_to": {
"rotation": "entity"
},
"position": {
"0.0": [0, 22, -44],
"0.25": [-41, 22, -25],
"1.20833": [-41, 22, -25],
"1.45833": [40, 22, -28],
"2": [40, 22, -28],
"2.20833": [0, 22, -61]
},
"rotation": {
"0.0": [0, 180, 0],
"0.25": [0, 227.5, 0],
"1.20833": [0, 227.5, 0],
"1.45833": [0, 127.5, 0],
"2": [0, 127.5, 0],
"2.20833": [0, 180, 0]
}
}
},
"sound_effects": {
@@ -5952,4 +5910,4 @@
}
}
}
}
}
@@ -237,16 +237,8 @@
"cubes": [
{"origin": [10, 2, -1], "size": [2, 2, 2], "inflate": -0.001, "uv": [8, 36]}
]
},
{
"name": "locator_camera",
"parent": "tandemaus",
"pivot": [0, 0, 0],
"locators": {
"camera": [0, 0, 0]
}
}
]
}
]
}
}
@@ -601,16 +601,8 @@
"cubes": [
{"origin": [-2.33, -1, -2.65], "size": [2, 2, 2], "inflate": 0.02, "pivot": [-1.3, 0, -1.65], "rotation": [0, -45, 0], "uv": [52, 36], "mirror": true}
]
},
{
"name": "locator_camera",
"parent": "ceruledge",
"pivot": [0, 0, 0],
"locators": {
"camera": [0, 0, 0]
}
}
]
}
]
}
}
@@ -25,14 +25,9 @@
"parent": "body_hammer",
"pivot": [0, 4, 0]
},
{
"name": "arms_hammer",
"parent": "torso_hammer",
"pivot": [0, 7, 0]
},
{
"name": "arm_hammer_right",
"parent": "arms_hammer",
"parent": "torso_hammer",
"pivot": [-1.5, 6.5, 0]
},
{
@@ -311,14 +306,9 @@
{"origin": [5.5, -2.75, -4.5], "size": [0, 4, 9], "uv": [0, 0]}
]
},
{
"name": "arms",
"parent": "torso",
"pivot": [0, 7, 0]
},
{
"name": "arm_left",
"parent": "arms",
"parent": "torso",
"pivot": [1.5, 6.5, 0],
"cubes": [
{"origin": [1.5, 5.5, -1.5], "size": [3, 2, 3], "uv": [94, 16]}
@@ -379,7 +369,7 @@
},
{
"name": "arm_right",
"parent": "arms",
"parent": "torso",
"pivot": [-1.5, 6.5, 0],
"cubes": [
{"origin": [-4.5, 5.5, -1.5], "size": [3, 2, 3], "uv": [58, 93]}
@@ -469,16 +459,8 @@
"cubes": [
{"origin": [0.25, 0, -1], "size": [2, 2, 2], "inflate": 0.2, "uv": [38, 54]}
]
},
{
"name": "locator_camera",
"parent": "tinkaton",
"pivot": [0, 0, 0],
"locators": {
"camera": [0, 0, 0]
}
}
]
}
]
}
}
@@ -1,63 +0,0 @@
{
"portraitScale": 0.89,
"portraitTranslation": [-0.17,2.04,0],
"profileScale": 0.37,
"profileTranslation": [0,1.14,0],
"rootBone": "kangaskhan",
"animations": {
"cry": "q.bedrock_stateful('kangaskhan', 'cry')",
"recoil": "q.bedrock_stateful('kangaskhan', 'recoil')"
},
"poses": {
"battle-standing": {
"poseTypes": [
"STAND"
],
"isBattle": true,
"animations": [
"q.look('kid_head')",
"q.bedrock('kangaskhan', 'battle_idle')"
],
"quirks": [
"q.bedrock_quirk('kangaskhan', 'blink')"
]
},
"standing": {
"poseTypes": [
"STAND",
"NONE",
"PORTRAIT",
"PROFILE"
],
"isBattle": false,
"animations": [
"q.look('kid_head')",
"q.bedrock('kangaskhan', 'ground_idle')"
],
"quirks": [
"q.bedrock_quirk('kangaskhan', 'blink')"
]
},
"walking": {
"poseTypes": [
"WALK",
"SWIM"
],
"animations": [
"q.look('kid_head')",
"q.bedrock('kangaskhan', 'ground_walk')"
],
"quirks": [
"q.bedrock_quirk('kangaskhan', 'blink')"
]
},
"sleep": {
"poseTypes": [
"SLEEP"
],
"animations": [
"q.bedrock('kangaskhan', 'sleep')"
]
}
}
}
@@ -33,6 +33,7 @@
"poseName": "standing",
"poseTypes": ["STAND", "NONE", "PORTRAIT", "PROFILE"],
"isBattle": false,
"condition": "!q.is_dancing",
"animations": [
"q.look('head')",
"q.bedrock('empoleon', 'ground_idle_old')"
@@ -120,6 +121,13 @@
"rotation": [0, 12.5, -52.5]
}
]
},
"dancing": {
"poseName": "dancing",
"isBattle": false,
"poseTypes": ["DANCE"],
"animations": ["q.bedrock('empoleon', 'dance')"],
"quirks": ["q.bedrock_quirk('empoleon', 'blink')"]
}
}
}
@@ -1,58 +1,28 @@
{
"portraitScale": 1.5,
"portraitTranslation": [-0.13, 2.74, 0],
"profileScale": 0.37,
"profileTranslation": [0, 1.22, 0],
"rootBone": "cinderace",
"animations": {
"faint": "q.bedrock_primary('cinderace', math.random(0, 1) < 0.25 ? 'faint2' : 'faint', q.curve('one'))",
"cry": "q.bedrock_stateful('cinderace', 'cry')",
"recoil": "q.bedrock_stateful('cinderace', 'recoil')",
"physical": "q.bedrock_primary('cinderace', 'physical', q.curve('symmetrical'))",
"special": "q.bedrock_primary('cinderace', 'special', q.curve('symmetrical'))",
"status": "q.bedrock_primary('cinderace', 'status', q.curve('symmetrical'))"
"portraitScale": 1.7,
"portraitTranslation": [-0.07, 2.95, 0],
"profileScale": 0.33,
"profileTranslation": [0, 1.23, 0],
"rootBone": "cinderace",
"animations": {
"cry": "q.bedrock_stateful('cinderace', 'cry')"
},
"poses": {
"standing": {
"poseName": "standing",
"poseTypes": ["STAND", "FLOAT", "PORTRAIT", "PROFILE", "NONE"],
"animations": ["q.bedrock('cinderace', 'ground_idle')"],
"quirks": ["q.bedrock_quirk('cinderace', 'blink')"]
},
"poses": {
"battle-standing": {
"poseTypes": ["STAND"],
"isBattle": true,
"animations": [
"q.look('head')",
"q.bedrock('cinderace', 'battle_idle')"
],
"namedAnimations": {
"cry": "q.bedrock_primary('cinderace', 'battle_cry', q.curve('one'))"
},
"quirks": ["q.bedrock_quirk('cinderace', 'blink')"]
},
"standing": {
"poseTypes": ["STAND", "NONE", "PORTRAIT", "PROFILE"],
"isBattle": false,
"animations": [
"q.look('head')",
"q.bedrock('cinderace', 'ground_idle')"
],
"quirks": [
"q.bedrock_quirk('cinderace', 'blink')"
],
"transitions": {
"battle-standing": "q.bedrock_primary('cinderace', 'battle_intro'), q.curve('symmetrical'))"
}
},
"walking": {
"poseTypes": ["WALK"],
"animations": [
"q.look('head')",
"q.bedrock('cinderace', 'ground_walk')"
],
"quirks": ["q.bedrock_quirk('cinderace', 'blink')"]
},
"sleeping": {
"poseTypes": ["SLEEP"],
"namedAnimations": {
"cry": "q.bedrock_stateful('dummy', 'cry')"
},
"animations": ["q.bedrock('cinderace', 'sleep')"]
}
"walking": {
"poseName": "walking",
"poseTypes": ["WALK", "SWIM"],
"animations": [
"q.bedrock('cinderace', 'ground_idle')",
"q.biped_walk(0.66, 0.6, 'leg_left0', 'leg_right0')",
"q.bimanual_swing(0.66, 0.6, 'arm_left', 'arm_right')"
],
"quirks": ["q.bedrock_quirk('cinderace', 'blink')"]
}
}
}
}
@@ -1,19 +1,17 @@
{
"species": "cobblemon:kangaskhan",
"order": 0,
"variations": [
{
"aspects": [],
"poser": "cobblemon:kangaskhan",
"model": "cobblemon:kangaskhan.geo",
"texture": "cobblemon:textures/pokemon/0115_kangaskhan/kangaskhan.png",
"layers": []
},
{
"aspects": [
"shiny"
],
"texture": "cobblemon:textures/pokemon/0115_kangaskhan/kangaskhan_shiny.png"
}
]
}
"species": "cobblemon:kangaskhan",
"order": 0,
"variations": [
{
"aspects": [],
"poser": "cobblemon:kangaskhan",
"model": "cobblemon:kangaskhan.geo",
"texture": "cobblemon:textures/pokemon/0115_kangaskhan/kangaskhan.png",
"layers": []
},
{
"aspects": ["shiny"],
"texture": "cobblemon:textures/pokemon/0115_kangaskhan/kangaskhan_shiny.png"
}
]
}
@@ -7,20 +7,11 @@
"poser": "cobblemon:cinderace",
"model": "cobblemon:cinderace.geo",
"texture": "cobblemon:textures/pokemon/0815_cinderace/cinderace.png",
"layers": [
{
"name": "emissive",
"emissive": true,
"texture": "cobblemon:textures/pokemon/0815_cinderace/cinderace_emissive.png",
"translucent": true
}
]
"layers": []
},
{
"aspects": [
"shiny"
],
"aspects": ["shiny"],
"texture": "cobblemon:textures/pokemon/0815_cinderace/cinderace_shiny.png"
}
]
}
}
@@ -1,7 +0,0 @@
{
"variants": {
"": {
"model": "cobblemon:block/stadium_terminal"
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,6 +0,0 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "cobblemon:block/stadium_terminal"
}
}
@@ -1,3 +0,0 @@
{
"parent": "cobblemon:block/stadium_terminal"
}
@@ -1,6 +0,0 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/evolution/syrupy_apple"
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 404 B

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 435 B

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 777 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

@@ -119,15 +119,3 @@ transitive-accessible class net/minecraft/client/renderer/RenderStateShard$Light
transitive-accessible field net/minecraft/world/entity/LivingEntity jumping Z
transitive-accessible field net/minecraft/world/entity/Entity FLAG_SHIFT_KEY_DOWN I
transitive-accessible field net/minecraft/world/entity/Entity DATA_SHARED_FLAGS_ID Lnet/minecraft/network/syncher/EntityDataAccessor;
transitive-accessible method net/minecraft/client/Camera setPosition (Lnet/minecraft/world/phys/Vec3;)V
transitive-accessible field net/minecraft/client/Camera FORWARDS Lorg/joml/Vector3f;
transitive-accessible field net/minecraft/client/Camera UP Lorg/joml/Vector3f;
transitive-accessible field net/minecraft/client/Camera LEFT Lorg/joml/Vector3f;
transitive-accessible field net/minecraft/client/Camera forwards Lorg/joml/Vector3f;
transitive-accessible field net/minecraft/client/Camera up Lorg/joml/Vector3f;
transitive-accessible field net/minecraft/client/Camera left Lorg/joml/Vector3f;
transitive-accessible field net/minecraft/client/Camera xRot F
transitive-accessible field net/minecraft/client/Camera yRot F
transitive-accessible field net/minecraft/client/Camera rotation Lorg/joml/Quaternionf;
transitive-accessible method net/minecraft/client/Camera setRotation (FF)V
@@ -6,8 +6,6 @@
"cobblemon:braised_vivichoke",
"cobblemon:leek_and_potato_stew",
"cobblemon:vivichoke_dip",
"cobblemon:energy_root",
"cobblemon:whipped_dream",
"#cobblemon:sweets"
"cobblemon:energy_root"
]
}
@@ -1,6 +0,0 @@
{
"replace": false,
"values": [
"#cobblemon:berries"
]
}
@@ -1,7 +1,7 @@
{
"parent": "cobblemon:recipes/root",
"criteria": {
"has_stone": {
"has_fire": {
"conditions": {
"items": [
{
@@ -13,18 +13,6 @@
},
"trigger": "minecraft:inventory_changed"
},
"has_gem": {
"conditions": {
"items": [
{
"items": [
"cobblemon:fire_gem"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "cobblemon:charcoal_stick"
@@ -34,8 +22,7 @@
},
"requirements": [
[
"has_stone",
"has_gem",
"has_fire",
"has_the_recipe"
]
],
@@ -13,18 +13,6 @@
},
"trigger": "minecraft:inventory_changed"
},
"has_gem": {
"conditions": {
"items": [
{
"items": [
"cobblemon:water_gem"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "cobblemon:damp_rock"
@@ -35,7 +23,6 @@
"requirements": [
[
"has_stone",
"has_gem",
"has_the_recipe"
]
],
@@ -13,18 +13,6 @@
},
"trigger": "minecraft:inventory_changed"
},
"has_gem": {
"conditions": {
"items": [
{
"items": [
"cobblemon:dragon_gem"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "cobblemon:dragon_fang"
@@ -35,7 +23,6 @@
"requirements": [
[
"has_breath",
"has_gem",
"has_the_recipe"
]
],
@@ -6,25 +6,13 @@
"items": [
{
"items": [
"cobblemon:fire_stone"
"cobblemon:water_stone"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_gem": {
"conditions": {
"items": [
{
"items": [
"cobblemon:fire_gem"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "cobblemon:heat_rock"
@@ -35,7 +23,6 @@
"requirements": [
[
"has_stone",
"has_gem",
"has_the_recipe"
]
],
@@ -13,18 +13,6 @@
},
"trigger": "minecraft:inventory_changed"
},
"has_gem": {
"conditions": {
"items": [
{
"items": [
"cobblemon:ice_gem"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "cobblemon:icy_rock"
@@ -35,7 +23,6 @@
"requirements": [
[
"has_stone",
"has_gem",
"has_the_recipe"
]
],
@@ -1,7 +1,7 @@
{
"parent": "cobblemon:recipes/root",
"criteria": {
"has_stone": {
"has_water": {
"conditions": {
"items": [
{
@@ -13,18 +13,6 @@
},
"trigger": "minecraft:inventory_changed"
},
"has_gem": {
"conditions": {
"items": [
{
"items": [
"cobblemon:water_gem"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "cobblemon:mystic_water"
@@ -34,8 +22,7 @@
},
"requirements": [
[
"has_stone",
"has_gem",
"has_water",
"has_the_recipe"
]
],
@@ -13,30 +13,6 @@
},
"trigger": "minecraft:inventory_changed"
},
"has_gem": {
"conditions": {
"items": [
{
"items": [
"cobblemon:ice_gem"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_stone": {
"conditions": {
"items": [
{
"items": [
"cobblemon:ice_stone"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "cobblemon:never_melt_ice"
@@ -47,8 +23,6 @@
"requirements": [
[
"has_ice",
"has_stone",
"has_gem",
"has_the_recipe"
]
],
@@ -0,0 +1,34 @@
{
"parent": "cobblemon:recipes/root",
"criteria": {
"has_ice": {
"conditions": {
"items": [
{
"items": [
"cobblemon:ice_stone"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "cobblemon:never_melt_ice_using_stone"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_ice",
"has_the_recipe"
]
],
"rewards": {
"recipes": [
"cobblemon:never_melt_ice", "cobblemon:never_melt_ice_using_stone"
]
}
}
@@ -13,30 +13,6 @@
},
"trigger": "minecraft:inventory_changed"
},
"has_rock_gem": {
"conditions": {
"items": [
{
"items": [
"cobblemon:rock_gem"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_ground_gem": {
"conditions": {
"items": [
{
"items": [
"cobblemon:ground_gem"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "cobblemon:smooth_rock"
@@ -47,8 +23,6 @@
"requirements": [
[
"has_stone",
"has_rock_gem",
"has_ground_gem",
"has_the_recipe"
]
],
@@ -1,13 +0,0 @@
{
"type": "minecraft:block",
"pools": [{
"rolls": 1,
"entries": [{
"type": "minecraft:item",
"name": "cobblemon:stadium_terminal"
}],
"conditions": [{
"condition": "minecraft:survives_explosion"
}]
}]
}
@@ -1,63 +0,0 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0,
"conditions": [
{
"condition": "minecraft:inverted",
"term": {
"condition": "minecraft:any_of",
"terms": [
{
"condition": "minecraft:match_tool",
"predicate": {
"items": "minecraft:shears"
}
},
{
"condition": "minecraft:match_tool",
"predicate": {
"predicates": {
"minecraft:enchantments": [
{
"enchantments": "minecraft:silk_touch",
"levels": {
"min": 1
}
}
]
}
}
}
]
}
}
],
"entries": [
{
"type": "minecraft:item",
"conditions": [
{
"condition": "minecraft:survives_explosion"
},
{
"chances": [
0.005,
0.0055555557,
0.00625,
0.008333334,
0.025
],
"condition": "minecraft:table_bonus",
"enchantment": "minecraft:fortune"
}
],
"name": "cobblemon:tart_apple"
}
],
"rolls": 1
}
],
"random_sequence": "minecraft:blocks/dark_oak_leaves"
}

Some files were not shown because too many files have changed in this diff Show More