Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f3be80e0c0 | ||
|
|
5287b4c5d3 | ||
|
|
a1be064863 |
@@ -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,8 +97,6 @@
|
||||
- Pidgeot
|
||||
- Nosepass
|
||||
- Probopass
|
||||
- Kangaskhan
|
||||
- Cinderace
|
||||
- Magnezone
|
||||
- Metagross
|
||||
- Added Syrupy Apples.
|
||||
@@ -126,7 +120,6 @@
|
||||
- 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 +148,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 +184,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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -24,12 +24,16 @@ import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
|
||||
import com.cobblemon.mod.common.api.dialogue.PlayerDialogueFaceProvider
|
||||
import com.cobblemon.mod.common.api.dialogue.ReferenceDialogueFaceProvider
|
||||
import com.cobblemon.mod.common.api.mark.Marks
|
||||
import com.cobblemon.mod.common.api.moves.MoveTemplate
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
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.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
|
||||
import com.cobblemon.mod.common.api.pokemon.moves.Learnset
|
||||
import com.cobblemon.mod.common.api.pokemon.moves.LearnsetQuery
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
|
||||
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
|
||||
@@ -782,6 +786,26 @@ object MoLangFunctions {
|
||||
}
|
||||
struct
|
||||
}
|
||||
map.put("learnset") { pokemon.form.moves.asMoLangValue() }
|
||||
map.put("can_learn") { params ->
|
||||
val moveId = params.getString(0)
|
||||
val move = Moves.getByName(moveId) ?: return@put DoubleValue.ZERO
|
||||
val learnType = params.getStringOrNull(1) ?: return@put DoubleValue(
|
||||
LearnsetQuery.ANY.canLearn(move, pokemon.form.moves)
|
||||
)
|
||||
|
||||
val query = when (learnType) {
|
||||
"tm" -> LearnsetQuery.TM_MOVE
|
||||
"egg" -> LearnsetQuery.EGG_MOVE
|
||||
"tutor" -> LearnsetQuery.TUTOR_MOVES
|
||||
"level" -> LearnsetQuery.ANY_LEVEL
|
||||
"form_change" -> LearnsetQuery.FORM_CHANGE
|
||||
"evolution" -> LearnsetQuery.EVOLUTION
|
||||
else -> LearnsetQuery.ANY
|
||||
}
|
||||
|
||||
DoubleValue(query.canLearn(move, pokemon.form.moves))
|
||||
}
|
||||
map.put("is_wild") { DoubleValue(pokemon.entity?.let { it.ownerUUID == null } == true) }
|
||||
map.put("is_shiny") { DoubleValue(pokemon.shiny) }
|
||||
map.put("species") { pokemon.species.struct }
|
||||
@@ -1114,11 +1138,43 @@ object MoLangFunctions {
|
||||
map.put("hitbox_height") { DoubleValue(species.hitbox.height) }
|
||||
map.put("hitbox_fixed") { DoubleValue(species.hitbox.fixed) }
|
||||
map.put("catch_rate") { DoubleValue(species.catchRate) }
|
||||
map.put("learnset") { species.moves.asMoLangValue() }
|
||||
|
||||
map
|
||||
}
|
||||
)
|
||||
|
||||
val learnsetFunctions: MutableList<(Learnset) -> HashMap<String, java.util.function.Function<MoParams, Any>>> = mutableListOf(
|
||||
{ learnset ->
|
||||
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
|
||||
map.put("tutor_moves") { learnset.tutorMoves.map { it.struct }.asArrayValue() }
|
||||
map.put("egg_moves") { learnset.eggMoves.map { it.struct }.asArrayValue() }
|
||||
map.put("tm_moves") { learnset.tmMoves.map { it.struct }.asArrayValue() }
|
||||
map.put("evolution_moves") { learnset.evolutionMoves.map { it.struct }.asArrayValue() }
|
||||
map.put("form_change_moves") { learnset.formChangeMoves.map { it.struct }.asArrayValue() }
|
||||
|
||||
map.put("get_level_up_moves_to") { params ->
|
||||
val level = params.getIntOrNull(0) ?: 0
|
||||
learnset.getLevelUpMovesUpTo(level).map { it.struct }.asArrayValue()
|
||||
}
|
||||
|
||||
map.put("level_up_moves") {
|
||||
val struct = QueryStruct(hashMapOf())
|
||||
for (level in learnset.levelUpMoves.keys) {
|
||||
struct.addFunction("$level") {
|
||||
learnset.levelUpMoves[level]?.map { it.struct }?.asArrayValue() ?: ArrayStruct()
|
||||
}
|
||||
}
|
||||
struct
|
||||
}
|
||||
|
||||
map
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
|
||||
val pokemonPropertiesFunctions: MutableList<(PokemonProperties) -> HashMap<String, java.util.function.Function<MoParams, Any>>> = mutableListOf(
|
||||
{ props ->
|
||||
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
@@ -1283,6 +1339,18 @@ object MoLangFunctions {
|
||||
return value
|
||||
}
|
||||
|
||||
fun Learnset.asMoLangValue(): ObjectValue<Learnset> {
|
||||
val value = ObjectValue(
|
||||
obj = this,
|
||||
stringify = { it.toString() }
|
||||
)
|
||||
|
||||
value.addFunctions(learnsetFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
|
||||
|
||||
return value
|
||||
|
||||
}
|
||||
|
||||
fun PokemonEntity.asMoLangValue(): ObjectValue<PokemonEntity> {
|
||||
val value = ObjectValue(
|
||||
obj = this,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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')"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"parent": "minecraft:block/cube_all",
|
||||
"textures": {
|
||||
"all": "cobblemon:block/stadium_terminal"
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"parent": "cobblemon:block/stadium_terminal"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 291 B |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 777 B |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.1 KiB |
|
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
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [{
|
||||
"rolls": 1,
|
||||
"entries": [{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:stadium_terminal"
|
||||
}],
|
||||
"conditions": [{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
@@ -42,25 +42,13 @@
|
||||
"catchRate": 45,
|
||||
"eggCycles": 20,
|
||||
"baseFriendship": 50,
|
||||
"baseScale": 0.9,
|
||||
"baseScale": 1.4,
|
||||
"hitbox": {
|
||||
"width": 2,
|
||||
"height": 3.2,
|
||||
"width": 1.2,
|
||||
"height": 1.9,
|
||||
"fixed": false
|
||||
},
|
||||
"standingEyeHeight": 0.85,
|
||||
"behaviour": {
|
||||
"moving": {
|
||||
"walk": {
|
||||
"walkSpeed": 0.23
|
||||
}
|
||||
},
|
||||
"resting": {
|
||||
"canSleep": true,
|
||||
"willSleepOnBed": false
|
||||
}
|
||||
},
|
||||
"drops": {
|
||||
"drops": {
|
||||
"amount": 1,
|
||||
"entries": [
|
||||
{
|
||||
|
||||
@@ -48,18 +48,6 @@
|
||||
"height": 3,
|
||||
"fixed": false
|
||||
},
|
||||
"standingEyeHeight": 0.85,
|
||||
"behaviour": {
|
||||
"moving": {
|
||||
"walk": {
|
||||
"walkSpeed": 0.29
|
||||
}
|
||||
},
|
||||
"resting": {
|
||||
"canSleep": true,
|
||||
"willSleepOnBed": false
|
||||
}
|
||||
},
|
||||
"drops": {
|
||||
"amount": 6,
|
||||
"entries": [
|
||||
|
||||