mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-21 22:56:23 -04:00
Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8899f1bd08 | ||
|
|
70c7b1d739 | ||
|
|
0dbfc1b119 | ||
|
|
850962b7f1 | ||
|
|
7c54c7815f | ||
|
|
614d2dbe70 |
+39
-20
@@ -1,41 +1,60 @@
|
||||
# Changelog
|
||||
## [1.8.1 (September 13th, 2026)](#1-8-1)
|
||||
## [1.8.1 (MONTH Xth, 2026)](#1-8-1)
|
||||
|
||||
### Additions
|
||||
|
||||
### New rideable Pokémon
|
||||
|
||||
### Pokémon Added
|
||||
|
||||
### Model updates for the following Pokémon
|
||||
|
||||
### Animation updates for the following Pokémon
|
||||
- Flapple, Appletun, Dipplin, Hydrapple (placeholder animations only).
|
||||
|
||||
### Changes
|
||||
|
||||
### Fixes
|
||||
- Fixed a potential world generation stall caused by Type Gem clusters.
|
||||
- Fixed Pokémon on shoulders not animating if they are visibly holding a held item.
|
||||
- Fixed NPCs getting their own TM progress file.
|
||||
- Fixed odd NeoForge crash due to a dependency being outdated. It will now correctly flag the dependency for being outdated.
|
||||
- Fixed the TM Machine refusing move selections that the `unlockAllMoveDexMovesByDefault` config had made visible, leaving the move slot blank and the craft button unresponsive.
|
||||
- Fixed the `stat_compare` and `stat_equal` evolution requirements crashing the game when given `special_attack` or `special_defence`, and made them treat any non-permanent stat as a failed requirement instead of crashing.
|
||||
- Fixed the Beast Ball not applying its 0.1× penalty to Pokémon that are not Ultra Beasts.
|
||||
- Fixed the Moon Ball reading the world's total elapsed time instead of the time of day, so its bonus applied during the day instead.
|
||||
- Fixed the Love Ball never awarding its 2.5× opposite gender bonus, and matching species by display name instead of identifier.
|
||||
- Fixed the Timer Ball being weaker than a regular Poké Ball on early turns and only reaching 4× on turn 14 instead of turn 10.
|
||||
- Fixed the Luxury Ball only doubling Friendship gains of 1, leaving level up and berry gains unaffected.
|
||||
- Fixed NPCs getting their own TM progress file.
|
||||
- Fixed the TM Machine refusing move selections that the `unlockAllMoveDexMovesByDefault` config had made visible, leaving the move slot blank and the craft button unresponsive.
|
||||
- Fixed Rufflet, Braviary, and Hisuian Braviary flooding logs with errors about missing sound events.
|
||||
- Fixed Pokémon property typos in Pangoro and Dedenne herd spawn files.
|
||||
- Fixed form typo in Rockruff dusk spawn entry.
|
||||
- Fixed a potential world gen stall with the Type Gem clusters.
|
||||
- Fixed Rowap and Jacoba berries not correctly altering Pokémon sizes when used as bait
|
||||
- Fixed Ampharos' eyes not emitting particles
|
||||
- Fixed Alolan Raticate's cry not playing
|
||||
- Fixed unintentional watermelon cosmetic for Hisuian Electrode.
|
||||
- Fixed Blastoise having an unintentional passenger seat.
|
||||
- Fixed Blastoise having an unintentional passenger seat
|
||||
- Fixed odd NeoForge crash due to a dependency being outdated. It will now flag the dependency for being outdated correctly.
|
||||
- Fixed form typo in Rockruff-Dusk spawn, preventing it from being able to spawn.
|
||||
- Fixed the `stat_compare` and `stat_equal` evolution requirements crashing the game when given `special_attack` or `special_defence`, and made them treat any non-permanent stat as a failed requirement instead of crashing.
|
||||
- Fixed a potential world gen stall caused by Type Gem clusters.
|
||||
- Fixed Rowap and Jacoba berries not correctly altering Pokémon sizes when used as bait.
|
||||
- Fixed Ampharos' eyes not emitting particles.
|
||||
- Fixed Alolan Raticate's cry not playing.
|
||||
- Fixed odd NeoForge crash due to a dependency being outdated. It will now correctly flag the dependency for being outdated.
|
||||
- Fixed several incorrect light-based spawning conditions for ghosts and bugs.
|
||||
- Removed unused, placeholder habitat pools.
|
||||
- Fixed Mantyke, Mantine, and Quaxly getting stuck in a recoil 'expression' during battles due to having an expression assigned as a recoil animation.
|
||||
- Fixed Lucario's aura particles not emitting.
|
||||
- Fixed Lycanroc's head movement.
|
||||
- Added head movement to Archaludon.
|
||||
- Fixed Duraludon line not having their sleep animations.
|
||||
- Fixed Diglett line not having their faint animations.
|
||||
- Fixed Kingambit moving its legs while walking.
|
||||
- Fixed Mantyke, Mantine, and Quaxly getting stuck in a recoil 'expression' during battles due to a having an expression mistakenly assigned as a recoil animation.
|
||||
- Fixed Pokémon on shoulders not animating if they are visibly holding a held item.
|
||||
- Fixed Mantyke, Mantine, and Quaxly getting stuck in a recoil 'expression' during battles due to a having an expression mistakenly assigned as a recoil animation.
|
||||
- Fixed Lycanroc's head movement
|
||||
- Added head movement to Archaludon
|
||||
- Fixed Duraludon line not having their sleep animations
|
||||
- Fixed Diglett line not having their faint animations
|
||||
- Fixed Kingambit moving its legs while walking
|
||||
|
||||
|
||||
### Developer
|
||||
|
||||
### Molang & Datapacks
|
||||
|
||||
### Particles
|
||||
|
||||
### Localization
|
||||
- Updated translations for:
|
||||
- Brazilian Portuguese
|
||||
- Simplified Chinese
|
||||
- Japanese
|
||||
- Updated translations for:
|
||||
@@ -1,9 +1,9 @@
|
||||
|
||||
import utilities.isSnapshot
|
||||
import utilities.version
|
||||
import java.time.OffsetDateTime
|
||||
import java.time.ZoneOffset
|
||||
import java.time.format.DateTimeFormatter
|
||||
import utilities.isSnapshot
|
||||
import utilities.version
|
||||
|
||||
/*
|
||||
*
|
||||
@@ -32,6 +32,7 @@ repositories {
|
||||
maven(url = "https://api.modrinth.com/maven")
|
||||
maven(url = "https://maven.neoforged.net/releases")
|
||||
maven(url = "https://maven.gegy.dev")
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
}
|
||||
|
||||
@@ -40,6 +41,7 @@ dependencies {
|
||||
modImplementation(libs.fabric.loader)
|
||||
modApi(libs.molang)
|
||||
|
||||
|
||||
// Integrations
|
||||
compileOnlyApi(libs.jei.api)
|
||||
modCompileOnly(libs.bundles.common.integrations.compileOnly) {
|
||||
@@ -62,14 +64,19 @@ dependencies {
|
||||
|
||||
// Unit Testing
|
||||
testImplementation(libs.bundles.unitTesting)
|
||||
testImplementation(libs.graal.sdk)
|
||||
testRuntimeOnly(libs.bundles.graal)
|
||||
}
|
||||
|
||||
tasks.withType<Test> {
|
||||
useJUnitPlatform()
|
||||
// Static GL mocks must not load a graphics driver on headless CI.
|
||||
systemProperty("org.lwjgl.opengl.explicitInit", "true")
|
||||
testLogging {
|
||||
setEvents(listOf("failed"))
|
||||
setExceptionFormat("full")
|
||||
}
|
||||
System.getProperty("camera.benchmark")?.let { systemProperty("camera.benchmark", it) }
|
||||
}
|
||||
|
||||
tasks.processResources {
|
||||
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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.camera;
|
||||
|
||||
import com.cobblemon.mod.common.client.render.camera.CameraFeedHandler;
|
||||
import com.cobblemon.mod.common.client.util.compat.SodiumCompat;
|
||||
import com.cobblemon.mod.common.platform.events.ClientChunkEvent;
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.LightLayer;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public final class CameraClientChunkCacheExtension {
|
||||
private static final Long2ObjectOpenHashMap<LevelChunk> CHUNKS = new Long2ObjectOpenHashMap<>();
|
||||
|
||||
private CameraClientChunkCacheExtension() {}
|
||||
|
||||
public static boolean shouldKeepChunk(ChunkPos chunkPos) {
|
||||
int renderDistance = Minecraft.getInstance().options.renderDistance().get();
|
||||
return CameraChunkVisibilityManager.shouldKeepChunk(chunkPos, renderDistance)
|
||||
|| CameraFeedHandler.shouldAddChunk(chunkPos, renderDistance);
|
||||
}
|
||||
|
||||
public static void retain(LevelChunk chunk) {
|
||||
synchronized (CHUNKS) {
|
||||
CHUNKS.put(chunk.getPos().toLong(), chunk);
|
||||
}
|
||||
}
|
||||
|
||||
public static LevelChunk take(ClientLevel level, int x, int z) {
|
||||
synchronized (CHUNKS) {
|
||||
long position = ChunkPos.asLong(x, z);
|
||||
LevelChunk chunk = CHUNKS.get(position);
|
||||
return chunk != null && chunk.getLevel() == level ? CHUNKS.remove(position) : null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void drop(ClientLevel level, ChunkPos chunkPos) {
|
||||
LevelChunk chunk = take(level, chunkPos.x, chunkPos.z);
|
||||
if (chunk != null) {
|
||||
unload(level, chunk);
|
||||
}
|
||||
}
|
||||
|
||||
public static LevelChunk getChunk(int x, int z) {
|
||||
synchronized (CHUNKS) {
|
||||
return CHUNKS.get(ChunkPos.asLong(x, z));
|
||||
}
|
||||
}
|
||||
|
||||
public static LevelChunk replaceWithPacketData(ClientLevel level, int x, int z, FriendlyByteBuf packetData, CompoundTag chunkTag, Consumer<ClientboundLevelChunkPacketData.BlockEntityTagOutput> tagOutput) {
|
||||
if (!Minecraft.getInstance().isSameThread()) {
|
||||
throw new IllegalStateException("Camera chunk packet applied off the client thread");
|
||||
}
|
||||
ChunkPos chunkPos = new ChunkPos(x, z);
|
||||
LevelChunk chunk = getChunk(x, z);
|
||||
if (chunk == null || chunk.getLevel() != level) {
|
||||
chunk = new LevelChunk(level, chunkPos);
|
||||
}
|
||||
chunk.replaceWithPacketData(packetData, chunkTag, tagOutput);
|
||||
retain(chunk);
|
||||
level.onChunkLoaded(chunkPos);
|
||||
SodiumCompat.getInstance().notifyChunkAdded(level, x, z);
|
||||
PlatformEvents.CLIENT_CHUNK_LOAD.postEvents(new ClientChunkEvent.Load(chunk, level));
|
||||
return chunk;
|
||||
}
|
||||
|
||||
public static void prune(ClientLevel level) {
|
||||
for (LevelChunk chunk : snapshot()) {
|
||||
if (chunk.getLevel() == level && !shouldKeepChunk(chunk.getPos())) {
|
||||
try {
|
||||
drop(level, chunk.getPos());
|
||||
} finally {
|
||||
queueLightRemoval(level, chunk.getPos());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
ArrayList<LevelChunk> removed;
|
||||
synchronized (CHUNKS) {
|
||||
removed = new ArrayList<>(CHUNKS.values());
|
||||
CHUNKS.clear();
|
||||
}
|
||||
RuntimeException failure = null;
|
||||
for (LevelChunk chunk : removed) {
|
||||
ClientLevel level = (ClientLevel) chunk.getLevel();
|
||||
try {
|
||||
try {
|
||||
unload(level, chunk);
|
||||
} finally {
|
||||
queueLightRemoval(level, chunk.getPos());
|
||||
}
|
||||
} catch (RuntimeException exception) {
|
||||
if (failure == null) failure = exception;
|
||||
else if (failure != exception) failure.addSuppressed(exception);
|
||||
}
|
||||
}
|
||||
if (failure != null) throw failure;
|
||||
}
|
||||
|
||||
public static ArrayList<LevelChunk> snapshot() {
|
||||
synchronized (CHUNKS) {
|
||||
return new ArrayList<>(CHUNKS.values());
|
||||
}
|
||||
}
|
||||
|
||||
private static void queueLightRemoval(ClientLevel level, ChunkPos position) {
|
||||
level.queueLightUpdate(() -> {
|
||||
LevelLightEngine lightEngine = level.getLightEngine();
|
||||
lightEngine.setLightEnabled(position, false);
|
||||
for (int y = lightEngine.getMinLightSection(); y < lightEngine.getMaxLightSection(); y++) {
|
||||
SectionPos section = SectionPos.of(position, y);
|
||||
lightEngine.queueSectionData(LightLayer.BLOCK, section, null);
|
||||
lightEngine.queueSectionData(LightLayer.SKY, section, null);
|
||||
}
|
||||
for (int y = level.getMinSection(); y < level.getMaxSection(); y++) {
|
||||
lightEngine.updateSectionStatus(SectionPos.of(position, y), true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void unload(ClientLevel level, LevelChunk chunk) {
|
||||
ChunkPos position = chunk.getPos();
|
||||
try {
|
||||
SodiumCompat.getInstance().notifyChunkRemoved(level, position.x, position.z);
|
||||
} finally {
|
||||
try {
|
||||
PlatformEvents.CLIENT_CHUNK_UNLOAD.postEvents(new ClientChunkEvent.Unload(chunk, level));
|
||||
} finally {
|
||||
level.unload(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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.camera;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.longs.LongSet;
|
||||
import net.minecraft.client.renderer.chunk.SectionRenderDispatcher;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class CameraViewAreaExtension {
|
||||
private static final Long2ObjectOpenHashMap<SectionRenderDispatcher.RenderSection> SECTIONS = new Long2ObjectOpenHashMap<>();
|
||||
private static final Map<UUID, LongSet> OWNERS = new HashMap<>();
|
||||
private static SectionRenderDispatcher sectionRenderDispatcher;
|
||||
private static final AtomicLong REVISION = new AtomicLong();
|
||||
private static final AtomicLong GRAPH_REVISION = new AtomicLong();
|
||||
private static final Set<SectionRenderDispatcher.RenderSection> CAMERA_SECTIONS = Collections.synchronizedSet(Collections.newSetFromMap(new WeakHashMap<>()));
|
||||
private static int minSectionY;
|
||||
private static int maxSectionY;
|
||||
|
||||
private CameraViewAreaExtension() {
|
||||
}
|
||||
|
||||
public static void allChanged(SectionRenderDispatcher dispatcher, Level level) {
|
||||
clear();
|
||||
sectionRenderDispatcher = dispatcher;
|
||||
minSectionY = level.getMinSection();
|
||||
maxSectionY = level.getMaxSection();
|
||||
}
|
||||
|
||||
public static SectionRenderDispatcher.RenderSection rawFetch(int cx, int cy, int cz, boolean generateNew) {
|
||||
if (sectionRenderDispatcher == null || cy < minSectionY || cy >= maxSectionY) {
|
||||
return null;
|
||||
}
|
||||
|
||||
long sectionPos = SectionPos.asLong(cx, cy, cz);
|
||||
return generateNew ? provideSection(sectionPos) : SECTIONS.get(sectionPos);
|
||||
}
|
||||
|
||||
public static void setDirty(int cx, int cy, int cz, boolean playerChanged) {
|
||||
SectionRenderDispatcher.RenderSection section = rawFetch(cx, cy, cz, false);
|
||||
if (section != null) {
|
||||
section.setDirty(playerChanged);
|
||||
}
|
||||
}
|
||||
|
||||
public static void onChunkUnload(int sectionX, int sectionZ) {
|
||||
REVISION.incrementAndGet();
|
||||
Collection<SectionRenderDispatcher.RenderSection> removed = new ArrayList<>();
|
||||
for (int sectionY = minSectionY; sectionY < maxSectionY; sectionY++) {
|
||||
long sectionPos = SectionPos.asLong(sectionX, sectionY, sectionZ);
|
||||
SectionRenderDispatcher.RenderSection section = SECTIONS.remove(sectionPos);
|
||||
|
||||
if (section != null) {
|
||||
removed.add(section);
|
||||
}
|
||||
}
|
||||
releaseBuffers(removed);
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
REVISION.incrementAndGet();
|
||||
sectionRenderDispatcher = null;
|
||||
minSectionY = 0;
|
||||
maxSectionY = 0;
|
||||
OWNERS.clear();
|
||||
Collection<SectionRenderDispatcher.RenderSection> removed = new ArrayList<>(SECTIONS.values());
|
||||
SECTIONS.clear();
|
||||
releaseBuffers(removed);
|
||||
}
|
||||
|
||||
public static long revision() {
|
||||
return REVISION.get();
|
||||
}
|
||||
|
||||
public static long graphRevision() {
|
||||
return GRAPH_REVISION.get();
|
||||
}
|
||||
|
||||
public static boolean onSectionCompiled(SectionRenderDispatcher.RenderSection section) {
|
||||
// Late camera uploads must not enter the player's graph after their buffers have been released.
|
||||
if (!CAMERA_SECTIONS.contains(section)) return false;
|
||||
GRAPH_REVISION.incrementAndGet();
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void retainSections(UUID cameraId, Collection<SectionRenderDispatcher.RenderSection> sections) {
|
||||
LongSet positions = new LongOpenHashSet();
|
||||
for (SectionRenderDispatcher.RenderSection section : sections) {
|
||||
positions.add(SectionPos.asLong(section.getOrigin()));
|
||||
}
|
||||
LongSet previous = OWNERS.put(cameraId, positions);
|
||||
releaseUnownedSections(previous);
|
||||
}
|
||||
|
||||
public static void releaseSections(UUID cameraId) {
|
||||
releaseUnownedSections(OWNERS.remove(cameraId));
|
||||
}
|
||||
|
||||
private static void releaseUnownedSections(LongSet positions) {
|
||||
if (positions == null) return;
|
||||
Collection<SectionRenderDispatcher.RenderSection> removed = new ArrayList<>();
|
||||
for (long position : positions) {
|
||||
if (OWNERS.values().stream().anyMatch(owner -> owner.contains(position))) continue;
|
||||
SectionRenderDispatcher.RenderSection section = SECTIONS.remove(position);
|
||||
if (section != null) removed.add(section);
|
||||
}
|
||||
releaseBuffers(removed);
|
||||
}
|
||||
|
||||
private static void releaseBuffers(Collection<SectionRenderDispatcher.RenderSection> sections) {
|
||||
RuntimeException failure = null;
|
||||
for (SectionRenderDispatcher.RenderSection section : sections) {
|
||||
try {
|
||||
section.releaseBuffers();
|
||||
} catch (RuntimeException exception) {
|
||||
if (failure == null) failure = exception;
|
||||
else if (failure != exception) failure.addSuppressed(exception);
|
||||
}
|
||||
}
|
||||
if (failure != null) throw failure;
|
||||
}
|
||||
|
||||
private static SectionRenderDispatcher.RenderSection provideSection(long sectionPos) {
|
||||
return SECTIONS.computeIfAbsent(sectionPos, CameraViewAreaExtension::createSection);
|
||||
}
|
||||
|
||||
private static SectionRenderDispatcher.RenderSection createSection(long sectionPos) {
|
||||
if (sectionRenderDispatcher == null) {
|
||||
throw new IllegalStateException("SectionRenderDispatcher not initialised");
|
||||
}
|
||||
BlockPos origin = SectionPos.of(sectionPos).origin();
|
||||
SectionRenderDispatcher.RenderSection section = sectionRenderDispatcher.new RenderSection(0, origin.getX(), origin.getY(), origin.getZ());
|
||||
CAMERA_SECTIONS.add(section);
|
||||
return section;
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* 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.camera.accessor;
|
||||
|
||||
public interface CameraFeedRenderState {
|
||||
boolean cobblemonRenderHand();
|
||||
boolean cobblemonRenderBlockOutline();
|
||||
}
|
||||
@@ -8,6 +8,9 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.api.cinematic.runtime.CinematicManager;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import com.cobblemon.mod.common.CobblemonNetwork;
|
||||
import com.cobblemon.mod.common.OrientationControllable;
|
||||
import com.cobblemon.mod.common.api.orientation.OrientationController;
|
||||
import com.cobblemon.mod.common.api.pokemon.effect.ShoulderEffectRegistry;
|
||||
@@ -17,6 +20,7 @@ import com.cobblemon.mod.common.api.riding.behaviour.types.liquid.SubmarineBehav
|
||||
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate;
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.net.messages.server.orientation.ServerboundUpdateOrientationPacket;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
@@ -130,6 +134,16 @@ public abstract class LivingEntityMixin extends Entity implements OrientationCon
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z", at = @At("HEAD"), cancellable = true)
|
||||
private void cobblemon$cancelDamageDuringCinematicTakeover(DamageSource source, float amount, CallbackInfoReturnable<Boolean> cir) {
|
||||
final LivingEntity self = (LivingEntity) (Object) this;
|
||||
if (self instanceof ServerPlayer serverPlayer) {
|
||||
if (CinematicManager.INSTANCE.isPlayerUnderImmuneTakeover(serverPlayer.getUUID())) {
|
||||
cir.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "decreaseAirSupply", at = @At("HEAD"), cancellable = true)
|
||||
private void cobblemon$conditionalWaterBreathing(
|
||||
int currentAir,
|
||||
|
||||
@@ -11,9 +11,12 @@ package com.cobblemon.mod.common.mixin.accessor;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
@Mixin(Entity.class)
|
||||
public interface AccessorEntity {
|
||||
@Invoker("updateFluidOnEyes")
|
||||
void cobblemonUpdateFluidOnEyes();
|
||||
|
||||
@Accessor("eyeHeight")
|
||||
void standingEyeHeight(float standingEyeHeight);
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.accessor;
|
||||
|
||||
import net.minecraft.client.Camera;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(Camera.class)
|
||||
public interface CameraAccessor {
|
||||
@Accessor("detached")
|
||||
void setDetached(boolean detached);
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.accessor;
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientChunkCache;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReferenceArray;
|
||||
|
||||
@Mixin(ClientChunkCache.Storage.class)
|
||||
public interface CameraChunkStorageAccessor {
|
||||
@Accessor("chunks")
|
||||
AtomicReferenceArray<LevelChunk> cobblemon$getChunks();
|
||||
|
||||
@Accessor("chunkRadius")
|
||||
int cobblemon$getChunkRadius();
|
||||
|
||||
@Accessor("chunkCount")
|
||||
int cobblemon$getChunkCount();
|
||||
|
||||
@Accessor("chunkCount")
|
||||
void cobblemon$setChunkCount(int count);
|
||||
|
||||
@Accessor("viewCenterX")
|
||||
int cobblemon$getViewCenterX();
|
||||
|
||||
@Accessor("viewCenterZ")
|
||||
int cobblemon$getViewCenterZ();
|
||||
|
||||
@Invoker("getIndex")
|
||||
int cobblemon$getIndex(int x, int z);
|
||||
}
|
||||
+2
@@ -10,7 +10,9 @@ package com.cobblemon.mod.common.mixin.accessor;
|
||||
|
||||
import net.minecraft.client.gui.components.StateSwitchingButton;
|
||||
import net.minecraft.client.gui.screens.recipebook.RecipeBookComponent;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Mutable;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(RecipeBookComponent.class)
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.accessor;
|
||||
|
||||
import net.minecraft.server.level.ServerEntity;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(ServerEntity.class)
|
||||
public interface ServerEntityEntityAccessor {
|
||||
@Accessor("entity")
|
||||
Entity getEntity();
|
||||
}
|
||||
+7
-1
@@ -9,10 +9,13 @@
|
||||
package com.cobblemon.mod.common.mixin.accessor;
|
||||
|
||||
import net.minecraft.server.level.ServerEntity;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.network.ServerPlayerConnection;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Mixin(targets = "net.minecraft.server.level.ChunkMap$TrackedEntity")
|
||||
@@ -22,4 +25,7 @@ public interface TrackedEntityAccessor {
|
||||
|
||||
@Accessor("serverEntity")
|
||||
ServerEntity getServerEntity();
|
||||
}
|
||||
|
||||
@Invoker("updatePlayers")
|
||||
void cobblemon$updatePlayers(List<ServerPlayer> players);
|
||||
}
|
||||
|
||||
+2
-1
@@ -15,9 +15,11 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.world.Containers;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.alchemy.PotionBrewing;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.item.crafting.RecipeManager;
|
||||
@@ -32,7 +34,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Mixin(BrewingStandBlockEntity.class)
|
||||
public class BrewingStandBlockEntityMixin {
|
||||
|
||||
|
||||
@@ -9,11 +9,17 @@
|
||||
package com.cobblemon.mod.common.mixin.brewing;
|
||||
|
||||
import com.cobblemon.mod.common.duck.RecipeAwareSlot;
|
||||
import com.cobblemon.mod.common.item.crafting.brewingstand.BrewingStandRecipe;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.BrewingStandMenu;
|
||||
import net.minecraft.world.inventory.ContainerData;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.item.crafting.brewingstand.BrewingStandRecipe;
|
||||
import net.minecraft.world.inventory.BrewingStandMenu;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeManager;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.cinematic;
|
||||
|
||||
import com.cobblemon.mod.common.api.cinematic.runtime.CinematicViewerScopedEntity;
|
||||
import com.cobblemon.mod.common.mixin.accessor.ServerEntityEntityAccessor;
|
||||
import com.cobblemon.mod.common.mixin.accessor.TrackedEntityAccessor;
|
||||
import net.minecraft.server.level.ServerEntity;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@Mixin(targets = "net.minecraft.server.level.ChunkMap$TrackedEntity")
|
||||
public abstract class TrackedEntityMixin {
|
||||
|
||||
// Cancellation must also unpair existing viewers, or they keep receiving updates after the scope narrows.
|
||||
@Inject(method = "updatePlayer", at = @At("HEAD"), cancellable = true)
|
||||
private void cobblemon$filterViewerScopedEntity(ServerPlayer player, CallbackInfo ci) {
|
||||
final TrackedEntityAccessor self = (TrackedEntityAccessor) this;
|
||||
final ServerEntity serverEntity = self.getServerEntity();
|
||||
if (serverEntity == null) return;
|
||||
final Entity entity = ((ServerEntityEntityAccessor) serverEntity).getEntity();
|
||||
if (entity == null) return;
|
||||
|
||||
if (entity instanceof CinematicViewerScopedEntity scoped) {
|
||||
final Set<UUID> allowed = scoped.getCobblemonSceneViewers();
|
||||
if (allowed != null && !allowed.contains(player.getUUID())) {
|
||||
if (self.getSeenBy().remove(player.connection)) {
|
||||
serverEntity.removePairing(player);
|
||||
}
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.camera.CameraClientChunkCacheExtension;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||
import net.minecraft.network.protocol.game.ClientboundForgetLevelChunkPacket;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ClientPacketListener.class)
|
||||
public abstract class CameraClientPacketListenerMixin {
|
||||
@Shadow
|
||||
private ClientLevel level;
|
||||
|
||||
@Inject(method = "queueLightRemoval", at = @At("HEAD"), cancellable = true)
|
||||
private void cobblemon$keepCameraLight(ClientboundForgetLevelChunkPacket packet, CallbackInfo ci) {
|
||||
ChunkPos position = packet.pos();
|
||||
LevelChunk retained = CameraClientChunkCacheExtension.getChunk(position.x, position.z);
|
||||
if (retained != null && retained.getLevel() == level) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.camera.CameraClientChunkCacheExtension;
|
||||
import com.cobblemon.mod.common.client.render.camera.CameraFeedHandler;
|
||||
import com.cobblemon.mod.common.client.render.camera.CameraViewAreaExtension;
|
||||
import com.cobblemon.mod.common.client.util.compat.SodiumCompat;
|
||||
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.ViewArea;
|
||||
import net.minecraft.client.renderer.chunk.SectionRenderDispatcher;
|
||||
import net.minecraft.client.renderer.culling.Frustum;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(value = LevelRenderer.class, priority = 1100)
|
||||
public abstract class CameraLevelRendererMixin {
|
||||
private static final int CINEMATIC_RENDER_DISTANCE_CHUNKS = 32;
|
||||
private static final float CINEMATIC_FOG_DISTANCE = CINEMATIC_RENDER_DISTANCE_CHUNKS * 16;
|
||||
|
||||
@Shadow
|
||||
private SectionRenderDispatcher sectionRenderDispatcher;
|
||||
@Shadow
|
||||
private ClientLevel level;
|
||||
|
||||
@WrapWithCondition(method = "setupRender", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ViewArea;repositionCamera(DD)V"))
|
||||
private boolean cobblemon$shouldRepositionCamera(ViewArea viewArea, double x, double z) {
|
||||
return !CameraFeedHandler.isCapturing();
|
||||
}
|
||||
|
||||
// Sodium owns its setup pipeline even while vanilla feed sections are substituted.
|
||||
@Inject(method = "setupRender", at = @At("HEAD"), cancellable = true)
|
||||
private void cobblemon$onSetupRender(Camera camera, Frustum frustum, boolean hasCapturedFrustum, boolean isSpectator, CallbackInfo ci) {
|
||||
if (CameraFeedHandler.isCapturing() && !SodiumCompat.getInstance().isActive()) {
|
||||
CameraFeedHandler.prepareVisibleSections(frustum);
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "setLevel", at = @At("HEAD"))
|
||||
private void cobblemon$onSetLevel(ClientLevel level, CallbackInfo ci) {
|
||||
try {
|
||||
if (this.level != level) {
|
||||
CameraClientChunkCacheExtension.clear();
|
||||
}
|
||||
} finally {
|
||||
CameraViewAreaExtension.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "allChanged", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SectionOcclusionGraph;waitAndReset(Lnet/minecraft/client/renderer/ViewArea;)V"))
|
||||
private void cobblemon$onAllChanged(CallbackInfo ci) {
|
||||
CameraViewAreaExtension.allChanged(sectionRenderDispatcher, level);
|
||||
}
|
||||
|
||||
@Inject(method = "addRecentlyCompiledSection", at = @At("HEAD"), cancellable = true)
|
||||
private void cobblemon$onSectionCompiled(SectionRenderDispatcher.RenderSection section, CallbackInfo ci) {
|
||||
if (CameraViewAreaExtension.onSectionCompiled(section)) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "isSectionCompiled", at = @At("HEAD"), cancellable = true)
|
||||
private void cobblemon$onIsSectionCompiled(BlockPos pos, CallbackInfoReturnable<Boolean> cir) {
|
||||
if (CameraFeedHandler.isCapturing()) {
|
||||
SectionPos sectionPos = SectionPos.of(pos);
|
||||
SectionRenderDispatcher.RenderSection section = CameraViewAreaExtension.rawFetch(sectionPos.x(), sectionPos.y(), sectionPos.z(), false);
|
||||
|
||||
if (section != null && section.getCompiled() != SectionRenderDispatcher.CompiledSection.UNCOMPILED) {
|
||||
cir.setReturnValue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ModifyVariable(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/FogRenderer;setupColor(Lnet/minecraft/client/Camera;FLnet/minecraft/client/multiplayer/ClientLevel;IF)V"), ordinal = 1)
|
||||
private float cobblemon$modifyFogRenderDistance(float original) {
|
||||
if (CameraFeedHandler.isCapturing())
|
||||
return CINEMATIC_FOG_DISTANCE;
|
||||
|
||||
return original;
|
||||
}
|
||||
|
||||
// A Marker camera otherwise excludes the local player from vanilla entity rendering.
|
||||
@WrapOperation(
|
||||
method = "renderLevel",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Camera;getEntity()Lnet/minecraft/world/entity/Entity;")
|
||||
)
|
||||
private Entity cobblemon$getCameraEntityDuringCapture(Camera camera, Operation<Entity> original) {
|
||||
if (CameraFeedHandler.isCapturing()) {
|
||||
Entity player = Minecraft.getInstance().player;
|
||||
if (player != null) return player;
|
||||
}
|
||||
return original.call(camera);
|
||||
}
|
||||
|
||||
@WrapOperation(
|
||||
method = "renderLevel",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Camera;isDetached()Z")
|
||||
)
|
||||
private boolean cobblemon$isCameraDetachedDuringCapture(Camera camera, Operation<Boolean> original) {
|
||||
if (CameraFeedHandler.isCapturing()) {
|
||||
return true;
|
||||
}
|
||||
return original.call(camera);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,8 +8,12 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.api.camera.CameraRotation;
|
||||
import com.cobblemon.mod.common.api.orientation.OrientationController;
|
||||
import com.cobblemon.mod.common.api.riding.Rideable;
|
||||
import com.cobblemon.mod.common.client.MountedPokemonAnimationRenderController;
|
||||
import com.cobblemon.mod.common.client.camera.ClientCameraController;
|
||||
import com.cobblemon.mod.common.client.render.camera.CameraFeedHandler;
|
||||
import com.cobblemon.mod.common.client.render.camera.MountedCameraRenderer;
|
||||
import com.cobblemon.mod.common.duck.CameraDuck;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
@@ -19,11 +23,15 @@ import net.minecraft.client.Camera;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import java.util.UUID;
|
||||
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.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(Camera.class)
|
||||
public abstract class CameraMixin implements CameraDuck {
|
||||
@@ -31,6 +39,7 @@ public abstract class CameraMixin implements CameraDuck {
|
||||
@Shadow private float eyeHeightOld;
|
||||
@Shadow private BlockGetter level;
|
||||
@Shadow private Entity entity;
|
||||
@Final @Shadow private Quaternionf rotation;
|
||||
@Final @Shadow private Vector3f forwards;
|
||||
@Final @Shadow private Vector3f up;
|
||||
@Final @Shadow private Vector3f left;
|
||||
@@ -42,6 +51,7 @@ public abstract class CameraMixin implements CameraDuck {
|
||||
@Override public BlockGetter cobblemon$getLevel() {
|
||||
return level;
|
||||
}
|
||||
@Shadow protected abstract void setRotation(float yRot, float xRot);
|
||||
|
||||
@Override public Entity cobblemon$getEntity() {
|
||||
return entity;
|
||||
@@ -85,4 +95,29 @@ public abstract class CameraMixin implements CameraDuck {
|
||||
MountedCameraRenderer.INSTANCE.setSmoothRotation(null);
|
||||
original.call(instance, x, y, z);
|
||||
}
|
||||
|
||||
// Apply after vanilla third-person and sleeping offsets so authored transforms remain exact.
|
||||
@Inject(method = "setup", at = @At("RETURN"))
|
||||
private void cobblemon$applyCinematicTransform(BlockGetter level, Entity entity, boolean detached, boolean thirdPersonReverse, float partialTick, CallbackInfo ci) {
|
||||
UUID capturedId = CameraFeedHandler.getCurrentlyCapturedCamera();
|
||||
CameraFeedHandler.FeedContext context = capturedId != null ? CameraFeedHandler.getFeedContext(capturedId) : null;
|
||||
float roll;
|
||||
if (context != null) {
|
||||
setPosition(context.getPosition());
|
||||
setRotation(context.getYaw(), context.getPitch());
|
||||
roll = context.getRoll();
|
||||
} else {
|
||||
if (!ClientCameraController.shouldUseCinematicCamera()) return;
|
||||
ClientCameraController.ActiveTransform transform = ClientCameraController.getCameraTransform();
|
||||
if (transform == null) return;
|
||||
CameraRotation rotation = transform.getRotation();
|
||||
setPosition(transform.getPosition());
|
||||
setRotation(rotation.getYaw(), rotation.getPitch());
|
||||
roll = transform.getRoll();
|
||||
}
|
||||
this.rotation.rotateZ((float) Math.toRadians(roll));
|
||||
OrientationController.Companion.getFORWARDS().rotate(this.rotation, this.forwards);
|
||||
OrientationController.Companion.getUP().rotate(this.rotation, this.up);
|
||||
OrientationController.Companion.getLEFT().rotate(this.rotation, this.left);
|
||||
}
|
||||
}
|
||||
|
||||
+178
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.camera.CameraClientChunkCacheExtension;
|
||||
import com.cobblemon.mod.common.mixin.accessor.CameraChunkStorageAccessor;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.minecraft.client.multiplayer.ClientChunkCache;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
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;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReferenceArray;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Mixin(value = ClientChunkCache.class, priority = 1100)
|
||||
public abstract class ClientChunkCacheMixin {
|
||||
@Shadow
|
||||
volatile ClientChunkCache.Storage storage;
|
||||
@Shadow
|
||||
@Final
|
||||
ClientLevel level;
|
||||
@Shadow
|
||||
@Final
|
||||
private LevelChunk emptyChunk;
|
||||
|
||||
@Inject(method = "drop", at = @At("HEAD"), cancellable = true)
|
||||
private void cobblemon$onDrop(ChunkPos chunkPos, CallbackInfo ci) {
|
||||
if (CameraClientChunkCacheExtension.shouldKeepChunk(chunkPos)) {
|
||||
CameraChunkStorageAccessor access = (CameraChunkStorageAccessor) (Object) storage;
|
||||
int index = access.cobblemon$getIndex(chunkPos.x, chunkPos.z);
|
||||
LevelChunk chunk = access.cobblemon$getChunks().get(index);
|
||||
if (chunk != null && chunk.getPos().equals(chunkPos)) {
|
||||
cobblemon$retain(access, index, chunk);
|
||||
}
|
||||
ci.cancel();
|
||||
} else {
|
||||
CameraClientChunkCacheExtension.drop(level, chunkPos);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "updateViewCenter", at = @At("HEAD"))
|
||||
private void cobblemon$onViewCenter(int x, int z, CallbackInfo ci) {
|
||||
CameraChunkStorageAccessor access = (CameraChunkStorageAccessor) (Object) storage;
|
||||
cobblemon$retainOutsideRange(access, x, z, access.cobblemon$getChunkRadius());
|
||||
}
|
||||
|
||||
@Inject(method = "updateViewRadius", at = @At("HEAD"))
|
||||
private void cobblemon$onViewRadius(int radius, CallbackInfo ci) {
|
||||
CameraChunkStorageAccessor access = (CameraChunkStorageAccessor) (Object) storage;
|
||||
cobblemon$retainOutsideRange(access, access.cobblemon$getViewCenterX(), access.cobblemon$getViewCenterZ(), Math.max(2, radius) + 3);
|
||||
}
|
||||
|
||||
@Inject(method = "updateViewCenter", at = @At("TAIL"))
|
||||
private void cobblemon$afterViewCenter(int x, int z, CallbackInfo ci) {
|
||||
cobblemon$promoteCameraChunks((CameraChunkStorageAccessor) (Object) storage);
|
||||
}
|
||||
|
||||
@Inject(method = "updateViewRadius", at = @At("TAIL"))
|
||||
private void cobblemon$afterViewRadius(int radius, CallbackInfo ci) {
|
||||
cobblemon$promoteCameraChunks((CameraChunkStorageAccessor) (Object) storage);
|
||||
}
|
||||
|
||||
@Inject(method = "tick", at = @At("HEAD"))
|
||||
private void cobblemon$onTick(BooleanSupplier hasTimeLeft, boolean tickChunks, CallbackInfo ci) {
|
||||
CameraClientChunkCacheExtension.prune(level);
|
||||
}
|
||||
|
||||
@Inject(method = "replaceWithPacketData", at = @At("HEAD"), cancellable = true)
|
||||
private void cobblemon$onReplaceWithPacketData(int x, int z, FriendlyByteBuf buffer, CompoundTag chunkTag, Consumer<ClientboundLevelChunkPacketData.BlockEntityTagOutput> tagOutputConsumer, CallbackInfoReturnable<LevelChunk> cir) {
|
||||
if (!storage.inRange(x, z)) {
|
||||
if (CameraClientChunkCacheExtension.shouldKeepChunk(new ChunkPos(x, z))) {
|
||||
cir.setReturnValue(CameraClientChunkCacheExtension.replaceWithPacketData(level, x, z, buffer, chunkTag, tagOutputConsumer));
|
||||
}
|
||||
return;
|
||||
}
|
||||
CameraChunkStorageAccessor access = (CameraChunkStorageAccessor) (Object) storage;
|
||||
int index = access.cobblemon$getIndex(x, z);
|
||||
LevelChunk previous = access.cobblemon$getChunks().get(index);
|
||||
if (previous != null && (previous.getPos().x != x || previous.getPos().z != z)
|
||||
&& CameraClientChunkCacheExtension.shouldKeepChunk(previous.getPos())) {
|
||||
cobblemon$retain(access, index, previous);
|
||||
}
|
||||
}
|
||||
|
||||
@WrapOperation(method = "replaceWithPacketData", at = @At(value = "NEW", target = "(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/ChunkPos;)Lnet/minecraft/world/level/chunk/LevelChunk;"))
|
||||
private LevelChunk cobblemon$reuseCameraChunk(Level level, ChunkPos position, Operation<LevelChunk> original) {
|
||||
LevelChunk retained = CameraClientChunkCacheExtension.take(this.level, position.x, position.z);
|
||||
return retained != null ? retained : original.call(level, position);
|
||||
}
|
||||
|
||||
@Inject(method = "replaceBiomes", at = @At("HEAD"), cancellable = true)
|
||||
private void cobblemon$onReplaceBiomes(int x, int z, FriendlyByteBuf buffer, CallbackInfo ci) {
|
||||
LevelChunk chunk = CameraClientChunkCacheExtension.getChunk(x, z);
|
||||
if (chunk != null && chunk.getLevel() == level) {
|
||||
chunk.replaceBiomes(buffer);
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "getChunk(IILnet/minecraft/world/level/chunk/status/ChunkStatus;Z)Lnet/minecraft/world/level/chunk/LevelChunk;", at = @At("RETURN"), cancellable = true)
|
||||
private void cobblemon$onGetChunk(int x, int z, ChunkStatus chunkStatus, boolean requireChunk, CallbackInfoReturnable<LevelChunk> cir) {
|
||||
if (cir.getReturnValue() == null || cir.getReturnValue() == emptyChunk) {
|
||||
LevelChunk chunk = CameraClientChunkCacheExtension.getChunk(x, z);
|
||||
if (chunk != null && chunk.getLevel() == level) {
|
||||
cir.setReturnValue(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void cobblemon$promoteCameraChunks(CameraChunkStorageAccessor access) {
|
||||
AtomicReferenceArray<LevelChunk> chunks = access.cobblemon$getChunks();
|
||||
for (LevelChunk chunk : CameraClientChunkCacheExtension.snapshot()) {
|
||||
ChunkPos position = chunk.getPos();
|
||||
if (chunk.getLevel() != level
|
||||
|| Math.abs(position.x - access.cobblemon$getViewCenterX()) > access.cobblemon$getChunkRadius()
|
||||
|| Math.abs(position.z - access.cobblemon$getViewCenterZ()) > access.cobblemon$getChunkRadius()) continue;
|
||||
int index = access.cobblemon$getIndex(position.x, position.z);
|
||||
LevelChunk previous = chunks.get(index);
|
||||
if (previous != null && CameraClientChunkCacheExtension.shouldKeepChunk(previous.getPos())) {
|
||||
cobblemon$retain(access, index, previous);
|
||||
previous = null;
|
||||
}
|
||||
CameraClientChunkCacheExtension.take(level, position.x, position.z);
|
||||
chunks.set(index, chunk);
|
||||
if (previous == null) {
|
||||
access.cobblemon$setChunkCount(access.cobblemon$getChunkCount() + 1);
|
||||
} else {
|
||||
CameraClientChunkCacheExtension.unload(level, previous);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void cobblemon$retainOutsideRange(CameraChunkStorageAccessor access, int centerX, int centerZ, int radius) {
|
||||
AtomicReferenceArray<LevelChunk> chunks = access.cobblemon$getChunks();
|
||||
for (int index = 0; index < chunks.length(); index++) {
|
||||
LevelChunk chunk = chunks.get(index);
|
||||
if (chunk == null) continue;
|
||||
ChunkPos position = chunk.getPos();
|
||||
if ((Math.abs(position.x - centerX) > radius || Math.abs(position.z - centerZ) > radius)
|
||||
&& CameraClientChunkCacheExtension.shouldKeepChunk(position)) {
|
||||
cobblemon$retain(access, index, chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void cobblemon$retain(CameraChunkStorageAccessor access, int index, LevelChunk chunk) {
|
||||
// Detach before loader unload callbacks: lighting and block entities belong to this same LevelChunk.
|
||||
if (access.cobblemon$getChunks().compareAndSet(index, chunk, null)) {
|
||||
access.cobblemon$setChunkCount(access.cobblemon$getChunkCount() - 1);
|
||||
CameraClientChunkCacheExtension.retain(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,9 @@ package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonRecipeCategories;
|
||||
import com.cobblemon.mod.common.item.crafting.CookingPotBookCategory;
|
||||
import com.cobblemon.mod.common.item.crafting.CookingPotRecipe;
|
||||
import com.cobblemon.mod.common.item.crafting.CookingPotRecipeBase;
|
||||
import com.cobblemon.mod.common.item.crafting.CookingPotShapelessRecipe;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
+122
-15
@@ -9,43 +9,142 @@
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.api.scheduling.ClientTaskTracker;
|
||||
import com.cobblemon.mod.common.client.camera.GameCamera;
|
||||
import com.cobblemon.mod.common.client.camera.ClientCameraController;
|
||||
import com.cobblemon.mod.common.client.cinematic.ClientSceneSessionManager;
|
||||
import com.cobblemon.mod.common.client.render.camera.accessor.CameraFeedRenderState;
|
||||
import com.cobblemon.mod.common.client.render.camera.CameraFeedHandler;
|
||||
import com.cobblemon.mod.common.client.render.camera.compositor.CompositorManager;
|
||||
import net.minecraft.client.Camera;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import net.minecraft.client.DeltaTracker;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Mutable;
|
||||
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;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
import java.util.UUID;
|
||||
|
||||
@Mixin(GameRenderer.class)
|
||||
public class GameRendererMixin {
|
||||
@Unique
|
||||
long lastTime = -1;
|
||||
public abstract class GameRendererMixin implements CameraFeedRenderState {
|
||||
|
||||
@Inject(
|
||||
method = "render",
|
||||
at = @At(value = "TAIL")
|
||||
)
|
||||
public void render(DeltaTracker counter, boolean tick, CallbackInfo ci) {
|
||||
@Shadow private boolean renderHand;
|
||||
@Shadow private boolean renderBlockOutline;
|
||||
|
||||
@Override public boolean cobblemonRenderHand() { return renderHand; }
|
||||
@Override public boolean cobblemonRenderBlockOutline() { return renderBlockOutline; }
|
||||
|
||||
@Shadow @Final @Mutable
|
||||
private Camera mainCamera;
|
||||
|
||||
@Unique
|
||||
private Camera cobblemon$playerCamera;
|
||||
|
||||
@Unique
|
||||
private final GameCamera cobblemon$gameCamera = new GameCamera();
|
||||
|
||||
@Unique
|
||||
private boolean cobblemon$usingCinematic;
|
||||
|
||||
@Unique
|
||||
private long cobblemon$lastTime = -1;
|
||||
|
||||
@Inject(method = "render", at = @At("HEAD"))
|
||||
private void cobblemon$swapCamera(DeltaTracker counter, boolean tick, CallbackInfo ci) {
|
||||
Minecraft client = Minecraft.getInstance();
|
||||
long newTime = System.currentTimeMillis();
|
||||
// Don't play scheduled animations when the game is paused
|
||||
if (client.isPaused()) {
|
||||
lastTime = newTime;
|
||||
if (client.level == null) {
|
||||
cobblemon$restoreCamera();
|
||||
return;
|
||||
}
|
||||
|
||||
if (lastTime != -1) {
|
||||
ClientTaskTracker.INSTANCE.update((newTime - lastTime) / 1000F);
|
||||
ClientCameraController.advanceFrame(client.isPaused() ? 0f : counter.getRealtimeDeltaTicks() / 20f);
|
||||
|
||||
ClientSceneSessionManager.INSTANCE.getAllSessions().forEach(session -> session.refreshCompositor());
|
||||
|
||||
if (ClientCameraController.shouldUseCinematicCamera()) {
|
||||
if (!cobblemon$usingCinematic) {
|
||||
cobblemon$playerCamera = mainCamera;
|
||||
mainCamera = cobblemon$gameCamera;
|
||||
cobblemon$usingCinematic = true;
|
||||
}
|
||||
cobblemon$gameCamera.prepare(client, counter.getGameTimeDeltaPartialTick(tick));
|
||||
} else if (cobblemon$usingCinematic) {
|
||||
cobblemon$restoreCamera();
|
||||
}
|
||||
lastTime = newTime;
|
||||
}
|
||||
|
||||
// WrapOperation allows Iris/Sodium to share this call site; Redirect claims it exclusively.
|
||||
@WrapOperation(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;renderLevel(Lnet/minecraft/client/DeltaTracker;)V"))
|
||||
private void cobblemon$skipVanillaRenderLevel(GameRenderer instance, DeltaTracker deltaTracker, Operation<Void> original) {
|
||||
if (!CompositorManager.isFullscreenActive()) {
|
||||
original.call(instance, deltaTracker);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;tryTakeScreenshotIfNeeded()V"))
|
||||
private void cobblemon$afterLevelRendering(DeltaTracker deltaTracker, boolean renderLevel, CallbackInfo ci) {
|
||||
boolean compositorNeedsFeeds = CompositorManager.isFullscreenActive()
|
||||
|| !CompositorManager.INSTANCE.getRequiredFeeds().isEmpty();
|
||||
if (compositorNeedsFeeds && CameraFeedHandler.hasFeeds()) {
|
||||
CameraFeedHandler.captureFeeds(deltaTracker);
|
||||
}
|
||||
if (CompositorManager.isFullscreenActive()) {
|
||||
CompositorManager.INSTANCE.compositeAll();
|
||||
CompositorManager.renderFullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "pick", at = @At("HEAD"), cancellable = true)
|
||||
private void cobblemon$preventFramePick(float partialTicks, CallbackInfo ci) {
|
||||
if (CameraFeedHandler.isCapturing())
|
||||
ci.cancel();
|
||||
}
|
||||
|
||||
@Inject(method = "getFov", at = @At("HEAD"), cancellable = true)
|
||||
private void cobblemon$overrideCinematicFov(Camera camera, float partialTicks, boolean useFovSetting, CallbackInfoReturnable<Double> cir) {
|
||||
UUID capturedId = CameraFeedHandler.getCurrentlyCapturedCamera();
|
||||
Float fov;
|
||||
if (capturedId != null) {
|
||||
CameraFeedHandler.FeedContext context = CameraFeedHandler.getFeedContext(capturedId);
|
||||
fov = context != null ? context.getFov() : null;
|
||||
} else {
|
||||
if (camera != cobblemon$gameCamera || !ClientCameraController.shouldUseCinematicCamera()) return;
|
||||
fov = ClientCameraController.getPrimaryFovOverride();
|
||||
}
|
||||
if (fov != null) {
|
||||
cir.setReturnValue(fov.doubleValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "render", at = @At(value = "TAIL"))
|
||||
private void cobblemon$afterRender(DeltaTracker counter, boolean tick, CallbackInfo ci) {
|
||||
Minecraft client = Minecraft.getInstance();
|
||||
|
||||
long newTime = System.currentTimeMillis();
|
||||
|
||||
if (client.isPaused()) {
|
||||
cobblemon$lastTime = newTime;
|
||||
return;
|
||||
}
|
||||
|
||||
if (cobblemon$lastTime != -1) {
|
||||
float delta = (newTime - cobblemon$lastTime) / 1000F;
|
||||
ClientTaskTracker.INSTANCE.update(delta);
|
||||
}
|
||||
cobblemon$lastTime = newTime;
|
||||
}
|
||||
|
||||
@ModifyArg(
|
||||
@@ -60,4 +159,12 @@ public class GameRendererMixin {
|
||||
return (entityX) -> !(entity.getVehicle() == entityX && entityX instanceof PokemonEntity) && original.test(entityX);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void cobblemon$restoreCamera() {
|
||||
if (cobblemon$usingCinematic) {
|
||||
mainCamera = cobblemon$playerCamera;
|
||||
cobblemon$playerCamera = null;
|
||||
cobblemon$usingCinematic = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.OrientationControllable;
|
||||
import com.cobblemon.mod.common.client.camera.ClientCameraController;
|
||||
import com.cobblemon.mod.common.item.PokedexItem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -28,6 +29,11 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
public class ItemInHandRendererMixin {
|
||||
@Inject(method = "renderArmWithItem", at = @At(value = "HEAD"), cancellable = true)
|
||||
private void cobblemon$renderArmWithItem(AbstractClientPlayer abstractClientPlayer, float f, float g, InteractionHand interactionHand, float h, ItemStack itemStack, float i, PoseStack poseStack, MultiBufferSource multiBufferSource, int j, CallbackInfo ci) {
|
||||
if (ClientCameraController.shouldUseCinematicCamera()) {
|
||||
ci.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
if (abstractClientPlayer.isUsingItem() && abstractClientPlayer.getUseItem().getItem() instanceof PokedexItem) {
|
||||
ci.cancel();
|
||||
}
|
||||
|
||||
@@ -8,11 +8,14 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.camera.ClientCameraController;
|
||||
import com.cobblemon.mod.common.client.render.ClientPlayerIcon;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.CameraType;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.model.PlayerModel;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
@@ -31,11 +34,34 @@ public abstract class PlayerRendererMixin extends LivingEntityRenderer<AbstractC
|
||||
super(context, model, shadowRadius);
|
||||
}
|
||||
|
||||
@WrapOperation(
|
||||
method = "render(Lnet/minecraft/client/player/AbstractClientPlayer;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/CameraType;isFirstPerson()Z"
|
||||
)
|
||||
)
|
||||
private boolean cobblemon$allowBodyRenderInCinematic(CameraType instance, Operation<Boolean> original) {
|
||||
if (ClientCameraController.shouldUseCinematicCamera() && ClientCameraController.shouldRenderPlayerBody()) {
|
||||
return false;
|
||||
}
|
||||
return original.call(instance);
|
||||
}
|
||||
|
||||
@Inject(method = "render", at = @At(value = "TAIL"))
|
||||
public void renderPlayer(AbstractClientPlayer player, float f, float g, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, CallbackInfo ci) {
|
||||
ClientPlayerIcon.Companion.onRenderPlayer(player);
|
||||
}
|
||||
|
||||
@Inject(method = "render(Lnet/minecraft/client/player/AbstractClientPlayer;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At("HEAD"), cancellable = true)
|
||||
private void cobblemon$hideCinematicPlayer(AbstractClientPlayer player, float yaw, float partialTick, PoseStack poseStack, MultiBufferSource buffers, int light, CallbackInfo ci) {
|
||||
if (player != Minecraft.getInstance().player) return;
|
||||
if (ClientCameraController.shouldUseCinematicCamera() && !ClientCameraController.shouldRenderPlayerBody()) {
|
||||
ci.cancel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@WrapOperation(method = "getRenderOffset(Lnet/minecraft/client/player/AbstractClientPlayer;F)Lnet/minecraft/world/phys/Vec3;", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/AbstractClientPlayer;isCrouching()Z"))
|
||||
private boolean cobblemon$disableCrouchOffset(AbstractClientPlayer instance, Operation<Boolean> original) {
|
||||
if (instance.isPassenger() && instance.getVehicle() instanceof PokemonEntity) {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.render.RenderAlphaScope;
|
||||
import net.minecraft.client.renderer.RenderStateShard;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(RenderStateShard.class)
|
||||
public abstract class RenderStateShardMixin {
|
||||
@Inject(method = "setupRenderState", at = @At("RETURN"))
|
||||
private void cobblemon$applyScopedAlpha(CallbackInfo ci) {
|
||||
if ((Object) this instanceof RenderType) RenderAlphaScope.afterMaterialSetup();
|
||||
}
|
||||
|
||||
@Inject(method = "clearRenderState", at = @At("RETURN"))
|
||||
private void cobblemon$restoreScopedAlpha(CallbackInfo ci) {
|
||||
if ((Object) this instanceof RenderType) RenderAlphaScope.afterMaterialClear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.render.camera.CameraViewAreaExtension;
|
||||
import net.minecraft.client.renderer.ViewArea;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ViewArea.class)
|
||||
public class ViewAreaMixin {
|
||||
@Inject(method = "setDirty", at = @At("HEAD"))
|
||||
private void cobblemon$markCinematicDirty(int cx, int cy, int cz, boolean reRenderOnMainThread, CallbackInfo ci) {
|
||||
CameraViewAreaExtension.setDirty(cx, cy, cz, reRenderOnMainThread);
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@
|
||||
package com.cobblemon.mod.common.mixin.entity;
|
||||
|
||||
import com.cobblemon.mod.common.OrientationControllable;
|
||||
import com.cobblemon.mod.common.api.cinematic.runtime.CinematicViewerScopedEntity;
|
||||
import com.cobblemon.mod.common.api.cinematic.runtime.pathfinding.NativeMotionEntity;
|
||||
import com.cobblemon.mod.common.duck.RidePassenger;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon;
|
||||
@@ -25,6 +27,8 @@ import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@@ -35,11 +39,35 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@Mixin(Entity.class)
|
||||
public abstract class EntityMixin {
|
||||
public abstract class EntityMixin implements CinematicViewerScopedEntity {
|
||||
|
||||
@Unique
|
||||
@Nullable
|
||||
private Set<UUID> cobblemon$sceneViewers = null;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Set<UUID> getCobblemonSceneViewers() {
|
||||
return cobblemon$sceneViewers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCobblemonSceneViewers(@Nullable Set<UUID> viewers) {
|
||||
this.cobblemon$sceneViewers = viewers;
|
||||
}
|
||||
|
||||
@Shadow @Nullable public abstract Entity getVehicle();
|
||||
|
||||
@WrapOperation(method = "move", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/Block;stepOn(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/entity/Entity;)V"))
|
||||
private void cobblemon$skipSimulatedFootsteps(Block block, Level level, BlockPos pos, BlockState state,
|
||||
Entity entity, Operation<Void> original) {
|
||||
if (!(entity instanceof NativeMotionEntity)) original.call(block, level, pos, state, entity);
|
||||
}
|
||||
|
||||
@Inject(method = "updateInWaterStateAndDoWaterCurrentPushing", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/Entity;wasTouchingWater:Z", ordinal = 1), cancellable = true)
|
||||
public void cobblemon$verifyActuallyTouchingWater(CallbackInfo ci) {
|
||||
if(this.getVehicle() instanceof PokemonEntity) {
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.api.cinematic.registry.SceneBuiltinSources
|
||||
import com.cobblemon.mod.common.net.serverhandling.editor.EditorPreviewSessionRegistry
|
||||
import com.cobblemon.mod.common.api.cinematic.runtime.CinematicManager
|
||||
import com.cobblemon.mod.common.api.molangui.MolangUiService
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBuildDetails.smallCommitHash
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
import com.cobblemon.mod.common.api.SeasonResolver
|
||||
@@ -76,6 +81,8 @@ import com.cobblemon.mod.common.battles.BattleSide
|
||||
import com.cobblemon.mod.common.battles.ShowdownThread
|
||||
import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.battles.stadium.StadiumBattleRegistry
|
||||
import com.cobblemon.mod.common.battles.stadium.StadiumSpectating
|
||||
import com.cobblemon.mod.common.block.dispenser.DispenserBehaviorRegistry
|
||||
import com.cobblemon.mod.common.client.CobblemonPack
|
||||
import com.cobblemon.mod.common.command.argument.*
|
||||
@@ -97,10 +104,10 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.aspects.ALPHA_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.aspects.CHARACTERISTIC_RAINBOW_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.aspects.COSMETIC_SLOT_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.aspects.FORM_ASPECTS
|
||||
import com.cobblemon.mod.common.pokemon.aspects.GENDER_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.aspects.MARK_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.aspects.SHINY_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.BlockClickEvolution
|
||||
import com.cobblemon.mod.common.pokemon.feature.SlowpokeTailRegrowthSpeciesFeature
|
||||
import com.cobblemon.mod.common.pokemon.feature.SlowpokeTailRegrowthSpeciesFeatureProvider
|
||||
import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver
|
||||
@@ -115,7 +122,6 @@ import com.cobblemon.mod.common.pokemon.properties.NoAIProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.UnaspectPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
|
||||
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
|
||||
import com.cobblemon.mod.common.pokemon.transformation.triggers.BlockClickTrigger
|
||||
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.world.feature.CobblemonPlacedFeatures
|
||||
@@ -260,6 +266,9 @@ object Cobblemon {
|
||||
playerDataManager.onPlayerDisconnect(it.player)
|
||||
RequestManager.onLogoff(it.player)
|
||||
serverPlayerStructs.remove(it.player.uuid)
|
||||
MolangUiService.closeAllForPlayer(it.player.uuid)
|
||||
CinematicManager.onPlayerDisconnect(it.player.uuid)
|
||||
EditorPreviewSessionRegistry.onPlayerDisconnect(it.player.uuid)
|
||||
}
|
||||
PlatformEvents.PLAYER_DEATH.subscribe {
|
||||
PCLinkManager.removeLink(it.player.uuid)
|
||||
@@ -274,8 +283,13 @@ object Cobblemon {
|
||||
PlatformEvents.RIGHT_CLICK_BLOCK.subscribe { event ->
|
||||
val player = event.player
|
||||
val block = player.level().getBlockState(event.pos).block
|
||||
val context = BlockClickTrigger.Context(block, player.level())
|
||||
player.party().forEach { pokemon -> pokemon.triggerTransformations<BlockClickTrigger>(context) }
|
||||
player.party().forEach { pokemon ->
|
||||
pokemon.lockedEvolutions
|
||||
.filterIsInstance<BlockClickEvolution>()
|
||||
.forEach { evolution ->
|
||||
evolution.attemptEvolution(pokemon, BlockClickEvolution.BlockInteractionContext(block, player.level()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PlatformEvents.CHANGE_DIMENSION.subscribe {
|
||||
@@ -297,6 +311,7 @@ object Cobblemon {
|
||||
HeldItemProvider.register(CobblemonHeldItemManager, Priority.LOWEST)
|
||||
}
|
||||
|
||||
|
||||
fun sendServerSettingsPacketToPlayer(player: ServerPlayer) {
|
||||
ServerSettingsPacket(
|
||||
this.config.preventCompletePartyDeposit,
|
||||
@@ -319,7 +334,6 @@ object Cobblemon {
|
||||
|
||||
SHINY_ASPECT.register()
|
||||
GENDER_ASPECT.register()
|
||||
FORM_ASPECTS.register()
|
||||
COSMETIC_SLOT_ASPECT.register()
|
||||
CHARACTERISTIC_RAINBOW_ASPECT.register()
|
||||
ALPHA_ASPECT.register()
|
||||
@@ -350,6 +364,8 @@ object Cobblemon {
|
||||
CustomPokemonProperty.register(NoAIProperty)
|
||||
CustomPokemonProperty.register(HeldItemVisibleProperty)
|
||||
|
||||
SceneBuiltinSources.register()
|
||||
|
||||
CobblemonEvents.POKEMON_PROPERTY_INITIALISED.emit(Unit)
|
||||
|
||||
CallbackHandler.setup()
|
||||
@@ -446,7 +462,14 @@ object Cobblemon {
|
||||
)
|
||||
}
|
||||
|
||||
PlatformEvents.SERVER_STOPPING.subscribe {
|
||||
StadiumSpectating.clear()
|
||||
// Release temporary actor AI/gravity settings before the final world save.
|
||||
CinematicManager.clear()
|
||||
}
|
||||
PlatformEvents.SERVER_STOPPED.subscribe {
|
||||
StadiumBattleRegistry.clearDynamic()
|
||||
MolangUiService.closeAll()
|
||||
storage.unregisterAll(it.server.registryAccess())
|
||||
playerDataManager.saveAllStores()
|
||||
playerDataManager.saveExecutor.shutdown()
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.CobblemonBehaviours.autoPokemonBehaviours
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.ai.CobblemonBehaviour
|
||||
import com.cobblemon.mod.common.api.ai.config.BehaviourConfig
|
||||
@@ -20,7 +19,16 @@ import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.net.messages.client.data.BehaviourSyncPacket
|
||||
import com.cobblemon.mod.common.util.adapters.*
|
||||
import com.cobblemon.mod.common.util.adapters.ActivityAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.BehaviourConfigAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionOrEntityVariableAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.MemoryModuleTypeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.SensorTypeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.TaskConfigAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.TranslatedTextAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.endsWith
|
||||
import com.google.gson.Gson
|
||||
|
||||
@@ -109,4 +109,10 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
|
||||
"poke_snack",
|
||||
BlockEntityType.Builder.of(::PokeSnackBlockEntity, CobblemonBlocks.POKE_SNACK, CobblemonBlocks.POKE_CAKE).build(null)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val STADIUM_BLOCK: BlockEntityType<StadiumBlockEntity> = this.create(
|
||||
"stadium_block",
|
||||
BlockEntityType.Builder.of(::StadiumBlockEntity, CobblemonBlocks.STADIUM_BLOCK).build(null)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -682,6 +682,9 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val HEALING_MACHINE = create("healing_machine", HealingMachineBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F).noOcclusion().lightLevel { if (it.getValue(HealingMachineBlock.CHARGE_LEVEL) >= HealingMachineBlock.MAX_CHARGE_LEVEL) 12 else 5 }))
|
||||
|
||||
@JvmField
|
||||
val STADIUM_BLOCK = create("stadium_block", StadiumBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).strength(3.5F, 6.0F).noOcclusion().pushReaction(PushReaction.BLOCK)))
|
||||
|
||||
@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)) 13 else 0 }))
|
||||
|
||||
|
||||
@@ -15,7 +15,11 @@ import net.minecraft.commands.CommandSourceStack
|
||||
import net.minecraft.commands.Commands
|
||||
|
||||
object CobblemonCommands {
|
||||
fun register(dispatcher: CommandDispatcher<CommandSourceStack>, registry: CommandBuildContext, selection: Commands.CommandSelection) {
|
||||
fun register(
|
||||
dispatcher: CommandDispatcher<CommandSourceStack>,
|
||||
registry: CommandBuildContext,
|
||||
selection: Commands.CommandSelection
|
||||
) {
|
||||
SpawnPokemon.register(dispatcher)
|
||||
SpawnNPCCommand.register(dispatcher)
|
||||
GivePokemon.register(dispatcher)
|
||||
@@ -41,8 +45,6 @@ object CobblemonCommands {
|
||||
HeldItemCommand.register(dispatcher, registry)
|
||||
PcCommand.register(dispatcher)
|
||||
SpawnPokemonFromPool.register(dispatcher)
|
||||
SpawnMeteorCommand.register(dispatcher)
|
||||
SetMegaBondCommand.register(dispatcher)
|
||||
PokeboxCommand.register(dispatcher)
|
||||
PokedexCommand.register(dispatcher)
|
||||
TestStoreCommand.register(dispatcher)
|
||||
@@ -63,7 +65,6 @@ object CobblemonCommands {
|
||||
ChangeBoxWallpaperCommand.register(dispatcher)
|
||||
RunMolangCommand.register(dispatcher)
|
||||
RunMolangScriptCommand.register(dispatcher)
|
||||
SpectateBattleCommand.register(dispatcher)
|
||||
CobblemonConfigCommand.register(dispatcher)
|
||||
UnlockPCBoxWallpaperCommand.register(dispatcher)
|
||||
BehaviourEditCommand.register(dispatcher)
|
||||
@@ -79,5 +80,8 @@ object CobblemonCommands {
|
||||
// Possibly lock down registration if and only if under dev environment or running in an environment
|
||||
// with a certain system environment variable set
|
||||
CobblemonInfoCommand.register(dispatcher)
|
||||
CinematicCommand.register(dispatcher)
|
||||
StadiumBattleCommand.register(dispatcher)
|
||||
MolangUiCommand.register(dispatcher)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,10 @@ import com.cobblemon.mod.common.entity.boat.CobblemonBoatEntity
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonChestBoatEntity
|
||||
import com.cobblemon.mod.common.entity.fishing.PokeRodFishingBobberEntity
|
||||
import com.cobblemon.mod.common.entity.generic.GenericBedrockEntity
|
||||
import com.cobblemon.mod.common.entity.stadium.StadiumCameraDroneEntity
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.projectile.FallingStarEntity
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.core.Registry
|
||||
@@ -82,6 +82,12 @@ object CobblemonEntities : PlatformRegistry<Registry<EntityType<*>>, ResourceKey
|
||||
@JvmField
|
||||
val GENERIC_BEDROCK_ENTITY_KEY = cobblemonResource("generic_bedrock")
|
||||
@JvmField
|
||||
val STADIUM_CAMERA_DRONE: EntityType<StadiumCameraDroneEntity> = this.create(
|
||||
"stadium_camera_drone",
|
||||
EntityType.Builder.of(::StadiumCameraDroneEntity, MobCategory.MISC)
|
||||
.build(cobblemonResource("stadium_camera_drone").toString())
|
||||
)
|
||||
@JvmField
|
||||
val GENERIC_BEDROCK_ENTITY: EntityType<GenericBedrockEntity> = this.create(
|
||||
GENERIC_BEDROCK_ENTITY_KEY.path,
|
||||
EntityType.Builder.of({ _, world -> GenericBedrockEntity(world) }, MobCategory.MISC)
|
||||
@@ -96,17 +102,8 @@ object CobblemonEntities : PlatformRegistry<Registry<EntityType<*>>, ResourceKey
|
||||
EntityType.Builder.of({ _, world -> NPCEntity(world) }, MobCategory.CREATURE).build("$NPC_KEY")
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val FALLING_STAR_KEY = cobblemonResource("falling_star")
|
||||
@JvmField
|
||||
val FALLING_STAR: EntityType<FallingStarEntity> = create(
|
||||
FALLING_STAR_KEY.path,
|
||||
EntityType.Builder.of(::FallingStarEntity, MobCategory.MISC).sized(0.5F, 0.5F).clientTrackingRange(8)
|
||||
.build(FALLING_STAR_KEY.toString())
|
||||
)
|
||||
|
||||
fun registerAttributes(consumer: (EntityType<out LivingEntity>, AttributeSupplier.Builder) -> Unit) {
|
||||
consumer(POKEMON, PokemonEntity.createAttributes())
|
||||
consumer(NPC, NPCEntity.createAttributes())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.server.packs.resources.PreparableReloadListener
|
||||
import net.minecraft.tags.TagKey
|
||||
import net.minecraft.world.inventory.MenuType
|
||||
import net.minecraft.world.level.GameRules
|
||||
import net.minecraft.world.level.ItemLike
|
||||
import net.minecraft.world.level.biome.Biome
|
||||
|
||||
@@ -33,12 +33,6 @@ object CobblemonItemComponents : PlatformRegistry<Registry<DataComponentType<*>>
|
||||
.networkSynchronized(HeldItemEffectComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
@JvmField
|
||||
val MEGA_BOND: DataComponentType<MegaBondComponent> = create("mega_bond", DataComponentType.builder<MegaBondComponent>()
|
||||
.persistent(MegaBondComponent.CODEC)
|
||||
.networkSynchronized(MegaBondComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
@JvmField
|
||||
val BAIT: DataComponentType<RodBaitComponent> = create("bait", DataComponentType.builder<RodBaitComponent>()
|
||||
.persistent(RodBaitComponent.CODEC)
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.cobblemon.mod.common.item.berry.StatusCuringBerryItem
|
||||
import com.cobblemon.mod.common.item.food.SinisterTeaItem
|
||||
import com.cobblemon.mod.common.item.interactive.*
|
||||
import com.cobblemon.mod.common.item.interactive.ability.AbilityChangeItem
|
||||
import com.cobblemon.mod.common.item.stadium.StadiumPlacementWandItem
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import com.cobblemon.mod.common.pokeball.PokeBall
|
||||
import com.cobblemon.mod.common.pokemon.IVs
|
||||
@@ -74,6 +75,9 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val NPC_EDITOR = create("npc_editor", CobblemonItem(Item.Properties().stacksTo(1)))
|
||||
|
||||
@JvmField
|
||||
val STADIUM_PLACEMENT_WAND = create("stadium_placement_wand", StadiumPlacementWandItem())
|
||||
|
||||
@JvmField
|
||||
val pokeBalls = mutableListOf<PokeBallItem>()
|
||||
@JvmField
|
||||
@@ -465,6 +469,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
val PASTURE = blockItem("pasture", CobblemonBlocks.PASTURE)
|
||||
@JvmField
|
||||
val DISPLAY_CASE = blockItem("display_case", CobblemonBlocks.DISPLAY_CASE)
|
||||
@JvmField
|
||||
val STADIUM_BLOCK = blockItem("stadium_block", CobblemonBlocks.STADIUM_BLOCK)
|
||||
// @JvmField
|
||||
// val INCENSE_SWEET = blockItem("incense_sweet", CobblemonBlocks.INCENSE_SWEET) // TODO after 1.7
|
||||
|
||||
@@ -914,10 +920,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
val THUNDER_STONE = noSettingsItem("thunder_stone")
|
||||
@JvmField
|
||||
val WATER_STONE = noSettingsItem("water_stone")
|
||||
@JvmField
|
||||
val MEGA_SHARD = noSettingsItem("mega_shard")
|
||||
@JvmField
|
||||
val DORMANT_MEGA_STONE = heldItem("dormant_mega_stone")
|
||||
|
||||
val wearables = mutableListOf<WearableItem>()
|
||||
//Wearable items (these items should have a corresponding 3D model)
|
||||
@@ -936,34 +938,14 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val ABILITY_SHIELD = heldItem("ability_shield")
|
||||
@JvmField
|
||||
val ABOMASITE = heldItem("abomasite")
|
||||
@JvmField
|
||||
val ABSOLITE = heldItem("absolite")
|
||||
@JvmField
|
||||
val ABSORB_BULB = heldItem("absorb_bulb")
|
||||
@JvmField
|
||||
val AERODACTYLITE = heldItem("aerodactylite")
|
||||
@JvmField
|
||||
val AGGRONITE = heldItem("aggronite")
|
||||
@JvmField
|
||||
val AIR_BALLOON = heldItem("air_balloon")
|
||||
@JvmField
|
||||
val ALAKAZITE = heldItem("alakazite")
|
||||
@JvmField
|
||||
val ALTARIANITE = heldItem("altarianite")
|
||||
@JvmField
|
||||
val AMPHAROSITE = heldItem("ampharosite")
|
||||
@JvmField
|
||||
val ASSAULT_VEST = heldItem("assault_vest")
|
||||
@JvmField
|
||||
val BIG_ROOT = compostableBlockItem("big_root", CobblemonBlocks.BIG_ROOT, 0.30f)
|
||||
@JvmField
|
||||
val AUDINITE = heldItem("audinite")
|
||||
@JvmField
|
||||
val BANETTITE = heldItem("banettite")
|
||||
@JvmField
|
||||
val BEEDRILLITE = heldItem("beedrillite")
|
||||
@JvmField
|
||||
val BINDING_BAND = heldItem("binding_band")
|
||||
@JvmField
|
||||
val BLACK_BELT = heldItem("black_belt")
|
||||
@@ -972,20 +954,10 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val BLUNDER_POLICY = itemNameBlockItem("blunder_policy", CobblemonBlocks.BLUNDER_POLICY)
|
||||
@JvmField
|
||||
val BLASTOISINITE = heldItem("blastoisinite")
|
||||
@JvmField
|
||||
val BLAZIKENITE = heldItem("blazikenite")
|
||||
@JvmField
|
||||
val CAMERUPTITE = heldItem("cameruptite")
|
||||
@JvmField
|
||||
val CELL_BATTERY = heldItem("cell_battery")
|
||||
@JvmField
|
||||
val CHARCOAL = heldItem("charcoal_stick", remappedName = "charcoal")
|
||||
@JvmField
|
||||
val CHARIZARDITE_X = heldItem("charizardite_x")
|
||||
@JvmField
|
||||
val CHARIZARDITE_Y = heldItem("charizardite_y")
|
||||
@JvmField
|
||||
val CHOICE_SCARF = heldItem("choice_scarf")
|
||||
@JvmField
|
||||
val CLEANSE_TAG = itemNameBlockItem("cleanse_tag", CobblemonBlocks.CLEANSE_TAG)
|
||||
@@ -996,8 +968,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val DESTINY_KNOT = heldItem("destiny_knot")
|
||||
@JvmField
|
||||
val DIANCITE = heldItem("diancite")
|
||||
@JvmField
|
||||
val DRAGON_FANG = heldItem("dragon_fang")
|
||||
@JvmField
|
||||
val EJECT_BUTTON = heldItem("eject_button")
|
||||
@@ -1020,42 +990,20 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val FOCUS_SASH = heldItem("focus_sash")
|
||||
@JvmField
|
||||
val GALLADITE = heldItem("galladite")
|
||||
@JvmField
|
||||
val GARCHOMPITE = heldItem("garchompite")
|
||||
@JvmField
|
||||
val GARDEVOIRITE = heldItem("gardevoirite")
|
||||
@JvmField
|
||||
val GENGARITE = heldItem("gengarite")
|
||||
@JvmField
|
||||
val GLALITITE = heldItem("glalitite")
|
||||
@JvmField
|
||||
val GRASSY_SEED = heldItem("grassy_seed")
|
||||
@JvmField
|
||||
val GRIP_CLAW = heldItem("grip_claw")
|
||||
@JvmField
|
||||
val GYARADOSITE = heldItem("gyaradosite")
|
||||
@JvmField
|
||||
val HARD_STONE = heldItem("hard_stone")
|
||||
@JvmField
|
||||
val HEAVY_DUTY_BOOTS = heldItem("heavy_duty_boots")
|
||||
@JvmField
|
||||
val HERACRONITE = heldItem("heracronite")
|
||||
@JvmField
|
||||
val HOUNDOOMINITE = heldItem("houndoominite")
|
||||
@JvmField
|
||||
val IRON_BALL = heldItem("iron_ball")
|
||||
@JvmField
|
||||
val KANGASKHANITE = heldItem("kangaskhanite")
|
||||
@JvmField
|
||||
val LAGGING_TAIL = heldItem("lagging_tail")
|
||||
@JvmField
|
||||
val LEFTOVERS = compostableHeldItem("leftovers", null, 0.50f)
|
||||
@JvmField
|
||||
val LATIASITE = heldItem("latiasite")
|
||||
@JvmField
|
||||
val LATIOSITE = heldItem("latiosite")
|
||||
@JvmField
|
||||
val LIFE_ORB = heldItem("life_orb")
|
||||
@JvmField
|
||||
val LIGHT_BALL = heldItem("light_ball")
|
||||
@@ -1064,40 +1012,20 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val LOADED_DICE = heldItem("loaded_dice")
|
||||
@JvmField
|
||||
val LOPUNNITE = heldItem("lopunnite")
|
||||
@JvmField
|
||||
val LUCARIONITE = heldItem("lucarionite")
|
||||
@JvmField
|
||||
val LUCKY_EGG = heldItem("lucky_egg")
|
||||
@JvmField
|
||||
val LUMINOUS_MOSS = heldItem("luminous_moss")
|
||||
@JvmField
|
||||
val MAGNET = heldItem("magnet")
|
||||
@JvmField
|
||||
val MANECTITE = heldItem("manectite")
|
||||
@JvmField
|
||||
val MAWILITE = heldItem("mawilite")
|
||||
@JvmField
|
||||
val MEDICHAMITE = heldItem("medichamite")
|
||||
@JvmField
|
||||
val METAGROSSITE = heldItem("metagrossite")
|
||||
@JvmField
|
||||
val METRONOME = heldItem("metronome")
|
||||
@JvmField
|
||||
val MEWTWONITE_X = heldItem("mewtwonite_x")
|
||||
@JvmField
|
||||
val MEWTWONITE_Y = heldItem("mewtwonite_y")
|
||||
@JvmField
|
||||
val MIRACLE_SEED = heldItem("miracle_seed")
|
||||
@JvmField
|
||||
val MYSTIC_WATER = heldItem("mystic_water")
|
||||
@JvmField
|
||||
val NEVER_MELT_ICE = heldItem("never_melt_ice")
|
||||
@JvmField
|
||||
val PIDGEOTITE = heldItem("pidgeotite")
|
||||
@JvmField
|
||||
val PINSIRITE = heldItem("pinsirite")
|
||||
@JvmField
|
||||
val POISON_BARB = heldItem("poison_barb")
|
||||
@JvmField
|
||||
val POWER_ANKLET = heldItem("power_anklet")
|
||||
@@ -1126,20 +1054,10 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val ROOM_SERVICE = heldItem("room_service")
|
||||
@JvmField
|
||||
val SABLENITE = heldItem("sablenite")
|
||||
@JvmField
|
||||
val SALAMENCITE = heldItem("salamencite")
|
||||
@JvmField
|
||||
val SCEPTILITE = heldItem("sceptilite")
|
||||
@JvmField
|
||||
val SCIZORITE = heldItem("scizorite")
|
||||
@JvmField
|
||||
val SCOPE_LENS = heldItem("scope_lens")
|
||||
@JvmField
|
||||
val SHARP_BEAK = heldItem("sharp_beak")
|
||||
@JvmField
|
||||
val SHARPEDONITE = heldItem("sharpedonite")
|
||||
@JvmField
|
||||
val SHED_SHELL = heldItem("shed_shell")
|
||||
@JvmField
|
||||
val SHELL_BELL = heldItem("shell_bell")
|
||||
@@ -1148,8 +1066,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val SILVER_POWDER = heldItem("silver_powder")
|
||||
@JvmField
|
||||
val SLOWBRONITE = heldItem("slowbronite")
|
||||
@JvmField
|
||||
val SOFT_SAND = heldItem("soft_sand")
|
||||
@JvmField
|
||||
val SPELL_TAG = itemNameBlockItem("spell_tag", CobblemonBlocks.SPELL_TAG)
|
||||
@@ -1158,12 +1074,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val SOOTHE_BELL = heldItem("soothe_bell")
|
||||
@JvmField
|
||||
val STEELIXITE = heldItem("steelixite")
|
||||
@JvmField
|
||||
val STICKY_BARB = heldItem("sticky_barb")
|
||||
@JvmField
|
||||
val SWAMPERTITE = heldItem("swampertite")
|
||||
@JvmField
|
||||
val TERRAIN_EXTENDER = heldItem("terrain_extender")
|
||||
@JvmField
|
||||
val THROAT_SPRAY = heldItem("throat_spray")
|
||||
@@ -1172,14 +1084,10 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val TWISTED_SPOON = heldItem("twisted_spoon")
|
||||
@JvmField
|
||||
val TYRANITARITE = heldItem("tyranitarite")
|
||||
@JvmField
|
||||
val UTILITY_UMBRELLA = heldItem("utility_umbrella")
|
||||
@JvmField
|
||||
val WEAKNESS_POLICY = itemNameBlockItem("weakness_policy", CobblemonBlocks.WEAKNESS_POLICY)
|
||||
@JvmField
|
||||
val VENUSAURITE = heldItem("venusaurite")
|
||||
@JvmField
|
||||
val WIDE_LENS = heldItem("wide_lens")
|
||||
@JvmField
|
||||
val ZOOM_LENS = heldItem("zoom_lens")
|
||||
@@ -1854,4 +1762,4 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
private fun foodItem(nutrition: Int, saturationModifier: Float): Item {
|
||||
return CobblemonItem(Item.Properties().food(FoodProperties.Builder().nutrition(nutrition).saturationModifier(saturationModifier).build()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,12 @@ import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.ListCodec
|
||||
import com.mojang.serialization.codecs.PrimitiveCodec
|
||||
import java.util.Optional
|
||||
import java.util.UUID
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.GlobalPos
|
||||
import net.minecraft.core.UUIDUtil
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import java.util.*
|
||||
|
||||
object CobblemonMemories {
|
||||
val memories = mutableMapOf<String, MemoryModuleType<*>>()
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
|
||||
import com.cobblemon.mod.common.api.molangui.container.MolangContainerMenu
|
||||
import com.cobblemon.mod.common.block.campfirepot.CookingPotMenu
|
||||
import com.cobblemon.mod.common.block.tmmachine.TMMachineMenu
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
@@ -16,15 +17,17 @@ import net.minecraft.core.Registry
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.world.flag.FeatureFlags
|
||||
import net.minecraft.world.inventory.MenuType
|
||||
|
||||
object CobblemonMenuType : PlatformRegistry<Registry<MenuType<*>>, ResourceKey<Registry<MenuType<*>>>, MenuType<*>>() {
|
||||
|
||||
val COOKING_POT = MenuType.register("cooking_pot_menu", ::CookingPotMenu)
|
||||
val TM_MACHINE = MenuType.register("tm_machine_menu", ::TMMachineMenu)
|
||||
val MOLANG_UI = create("molang_ui", MenuType(::MolangContainerMenu, FeatureFlags.DEFAULT_FLAGS))
|
||||
|
||||
override val registry: Registry<MenuType<*>>
|
||||
get() = BuiltInRegistries.MENU
|
||||
override val resourceKey: ResourceKey<Registry<MenuType<*>>>
|
||||
get() = Registries.MENU
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,20 @@ import com.cobblemon.mod.common.client.net.battle.*
|
||||
import com.cobblemon.mod.common.client.net.callback.move.OpenMoveCallbackHandler
|
||||
import com.cobblemon.mod.common.client.net.callback.party.OpenPartyCallbackHandler
|
||||
import com.cobblemon.mod.common.client.net.callback.partymove.OpenPartyMoveCallbackHandler
|
||||
import com.cobblemon.mod.common.client.net.cinematic.BeatChangeHandler
|
||||
import com.cobblemon.mod.common.client.net.cinematic.FeedAssignmentHandler
|
||||
import com.cobblemon.mod.common.client.net.cinematic.FeedTransformHandler
|
||||
import com.cobblemon.mod.common.client.net.cinematic.SceneEndHandler
|
||||
import com.cobblemon.mod.common.client.net.cinematic.SceneStartHandler
|
||||
import com.cobblemon.mod.common.client.net.editor.EditorPreviewAckHandler
|
||||
import com.cobblemon.mod.common.client.net.editor.EditorPreviewStateHandler
|
||||
import com.cobblemon.mod.common.client.net.editor.EditorRouteResultHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.editor.EditorRouteResultS2CPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.editor.EditorRouteRequestC2SPacket
|
||||
import com.cobblemon.mod.common.net.serverhandling.editor.EditorRouteRequestHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.editor.EditorPreviewStateS2CPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.editor.EditorPreviewControlC2SPacket
|
||||
import com.cobblemon.mod.common.net.serverhandling.editor.EditorPreviewControlHandler
|
||||
import com.cobblemon.mod.common.client.net.cooking.ToggleCookingPotLidHandler
|
||||
import com.cobblemon.mod.common.client.net.data.CobblemonMechanicsSyncHandler
|
||||
import com.cobblemon.mod.common.client.net.data.DataRegistrySyncPacketHandler
|
||||
@@ -32,6 +46,10 @@ import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormParticleHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.ExpGainedDataPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.InteractPokemonUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.PokedexUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.molangui.MolangUiCloseHandler
|
||||
import com.cobblemon.mod.common.client.net.molangui.MolangUiCompatibilityRequestHandler
|
||||
import com.cobblemon.mod.common.client.net.molangui.MolangUiOpenHandler
|
||||
import com.cobblemon.mod.common.client.net.molangui.MolangUiUpdateHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.SetActiveTMPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.SetTMMachineContainerDataPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.SummaryUIPacketHandler
|
||||
@@ -53,6 +71,16 @@ import com.cobblemon.mod.common.client.net.riding.ClientboundUpdateDriverInputHa
|
||||
import com.cobblemon.mod.common.client.net.settings.OpenCobblemonConfigEditorHandler
|
||||
import com.cobblemon.mod.common.client.net.settings.ServerSettingsPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.sound.UnvalidatedPlaySoundS2CPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.stadium.OpenStadiumConfigHandler
|
||||
import com.cobblemon.mod.common.client.net.stadium.StadiumConfigResultHandler
|
||||
import com.cobblemon.mod.common.client.net.stadium.StadiumSpectateStateHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.stadium.StadiumSpectateStatePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.stadium.StadiumSpectatePacket
|
||||
import com.cobblemon.mod.common.net.serverhandling.stadium.StadiumSpectateHandler
|
||||
import com.cobblemon.mod.common.client.net.stadium.StadiumCinematicHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.stadium.StadiumCinematicPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.stadium.EditStadiumCinematicPacket
|
||||
import com.cobblemon.mod.common.net.serverhandling.stadium.EditStadiumCinematicHandler
|
||||
import com.cobblemon.mod.common.client.net.spawn.SpawnExtraDataEntityHandler
|
||||
import com.cobblemon.mod.common.client.net.starter.StarterUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.RemoveClientPokemonHandler
|
||||
@@ -72,17 +100,30 @@ import com.cobblemon.mod.common.client.net.trade.TradeProcessStartedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeStartedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeUpdatedHandler
|
||||
import com.cobblemon.mod.common.net.PacketRegisterInfo
|
||||
import com.cobblemon.mod.common.net.serverhandling.stadium.RequestStadiumPlacementWandHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.stadium.UpdateStadiumBlockHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.CalculateSeatPositionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.OpenBehaviourEditorPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.SetClientPlayerDataPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.*
|
||||
import com.cobblemon.mod.common.net.messages.client.cinematic.BeatChangePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.cinematic.FeedAssignmentPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.cinematic.FeedTransformPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.cinematic.SceneEndPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.cinematic.SceneStartPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.editor.EditorPreviewAckS2CPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.callback.OpenMoveCallbackPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyCallbackPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyMoveCallbackPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.cooking.SeasoningRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.cooking.ToggleCookingPotLidPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.data.*
|
||||
import com.cobblemon.mod.common.net.messages.client.molangui.MolangUiClosePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.molangui.MolangUiCompatibilityRequestPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.molangui.MolangUiOpenPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.molangui.MolangUiUpdatePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.debug.RequestOpenRidingStatsDebugGUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueClosedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueOpenedPacket
|
||||
@@ -107,14 +148,14 @@ import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.Add
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.ClearEvolutionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.ClientboundSeatAssignmentPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.RemoveEvolutionPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.form.AddFormPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.form.ClearFormsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.form.RemoveFormPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.settings.OpenCobblemonConfigScreenPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.stadium.OpenStadiumConfigPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.stadium.StadiumConfigResultPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.stadium.RequestStadiumPlacementWandPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.stadium.UpdateStadiumBlockPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnGenericBedrockPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnFallingStarPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnNPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokeballPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokemonPacket
|
||||
@@ -161,6 +202,8 @@ import com.cobblemon.mod.common.net.messages.server.RequestPlayerInteractionsPac
|
||||
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.StadiumPreviewChoicePacket
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.StadiumPreviewChoiceHandler
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamLeavePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamRequestPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamResponsePacket
|
||||
@@ -180,10 +223,15 @@ import com.cobblemon.mod.common.net.messages.server.debug.OpenRidingStatsDebugGU
|
||||
import com.cobblemon.mod.common.net.messages.server.debug.ServerboundUpdateRidingSettingsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.debug.ServerboundUpdateRidingStatRangePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.debug.ServerboundUpdateRidingStatsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.editor.EditorPreviewStartC2SPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.editor.EditorPreviewStopC2SPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.dialogue.EscapeDialoguePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.dialogue.InputToDialoguePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.molangui.MolangUiActionPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.molangui.MolangUiClosedPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.habitat.SaveHabitatBlockSettingsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.npc.SaveNPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.molangui.MolangUiCompatibilityResponsePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.orientation.ServerboundUpdateOrientationPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.PasturePokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.SetPastureConflictPacket
|
||||
@@ -198,8 +246,6 @@ import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetItemHidden
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetMarkingsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetNicknamePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.evolution.AcceptEvolutionPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.form.AcceptFormPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.form.RevertFormPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.riding.DismountPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdateDriverInputPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdatePassengerPositionPacket
|
||||
@@ -217,11 +263,9 @@ import com.cobblemon.mod.common.net.messages.server.trade.ChangeTradeAcceptanceP
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.PerformTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket
|
||||
import com.cobblemon.mod.common.net.serverhandling.AcceptFormHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.ChallengeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.ChallengeResponseHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.RequestInteractionsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.RevertFormHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.BattleSelectActionsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.RemoveSpectatorHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
|
||||
@@ -242,11 +286,16 @@ import com.cobblemon.mod.common.net.serverhandling.debug.RequestOpenRidingStatsD
|
||||
import com.cobblemon.mod.common.net.serverhandling.debug.ServerboundUpdateRidingSettingsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.debug.ServerboundUpdateRidingStatRangeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.debug.ServerboundUpdateRidingStatsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.editor.EditorPreviewStartHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.editor.EditorPreviewStopHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.dialogue.EscapeDialogueHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.dialogue.InputToDialogueHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.molangui.MolangUiActionHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.molangui.MolangUiClosedHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.evolution.AcceptEvolutionHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.habitat.SaveHabitatBlockSettingsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.npc.SaveNPCHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.molangui.MolangUiCompatibilityResponseHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.orientation.ServerboundUpdateOrientationHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.PasturePokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.SetPastureConflictHandler
|
||||
@@ -395,6 +444,7 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(BattleEndPacket.ID, BattleEndPacket::decode, BattleEndHandler))
|
||||
list.add(PacketRegisterInfo(BattleInitializePacket.ID, BattleInitializePacket::decode, BattleInitializeHandler))
|
||||
list.add(PacketRegisterInfo(BattleQueueRequestPacket.ID, BattleQueueRequestPacket::decode, BattleQueueRequestHandler))
|
||||
list.add(PacketRegisterInfo(StadiumBattleStatePacket.ID, StadiumBattleStatePacket::decode, StadiumBattleStateHandler))
|
||||
list.add(PacketRegisterInfo(BattleFaintPacket.ID, BattleFaintPacket::decode, BattleFaintHandler))
|
||||
list.add(PacketRegisterInfo(BattleMakeChoicePacket.ID, BattleMakeChoicePacket::decode, BattleMakeChoiceHandler))
|
||||
list.add(PacketRegisterInfo(BattleHealthChangePacket.ID, BattleHealthChangePacket::decode, BattleHealthChangeHandler))
|
||||
@@ -411,9 +461,37 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(BattlePersistentStatusPacket.ID, BattlePersistentStatusPacket::decode, BattlePersistentStatusHandler))
|
||||
list.add(PacketRegisterInfo(BattleMadeInvalidChoicePacket.ID, BattleMadeInvalidChoicePacket::decode, BattleMadeInvalidChoiceHandler))
|
||||
list.add(PacketRegisterInfo(BattleMusicPacket.ID, BattleMusicPacket::decode, BattleMusicHandler))
|
||||
list.add(PacketRegisterInfo(BattleChallengeExpiredPacket.ID, BattleChallengeExpiredPacket::decode, BattleChallengeExpiredHandler))
|
||||
list.add(PacketRegisterInfo(BattleReplacePokemonPacket.ID, BattleReplacePokemonPacket::decode, BattleReplacePokemonHandler))
|
||||
list.add(PacketRegisterInfo(BattleTransformPokemonPacket.ID, BattleTransformPokemonPacket::decode, BattleTransformPokemonHandler))
|
||||
list.add(
|
||||
PacketRegisterInfo(
|
||||
BattleChallengeExpiredPacket.ID,
|
||||
BattleChallengeExpiredPacket::decode,
|
||||
BattleChallengeExpiredHandler
|
||||
)
|
||||
)
|
||||
list.add(
|
||||
PacketRegisterInfo(
|
||||
BattleReplacePokemonPacket.ID,
|
||||
BattleReplacePokemonPacket::decode,
|
||||
BattleReplacePokemonHandler
|
||||
)
|
||||
)
|
||||
list.add(
|
||||
PacketRegisterInfo(
|
||||
BattleTransformPokemonPacket.ID,
|
||||
BattleTransformPokemonPacket::decode,
|
||||
BattleTransformPokemonHandler
|
||||
)
|
||||
)
|
||||
|
||||
list.add(PacketRegisterInfo(SceneStartPacket.ID, SceneStartPacket::decode, SceneStartHandler))
|
||||
list.add(PacketRegisterInfo(SceneEndPacket.ID, SceneEndPacket::decode, SceneEndHandler))
|
||||
list.add(PacketRegisterInfo(FeedTransformPacket.ID, FeedTransformPacket::decode, FeedTransformHandler))
|
||||
list.add(PacketRegisterInfo(FeedAssignmentPacket.ID, FeedAssignmentPacket::decode, FeedAssignmentHandler))
|
||||
list.add(PacketRegisterInfo(BeatChangePacket.ID, BeatChangePacket::decode, BeatChangeHandler))
|
||||
|
||||
list.add(PacketRegisterInfo(EditorPreviewAckS2CPacket.ID, EditorPreviewAckS2CPacket::decode, EditorPreviewAckHandler))
|
||||
list.add(PacketRegisterInfo(EditorPreviewStateS2CPacket.ID, EditorPreviewStateS2CPacket::decode, EditorPreviewStateHandler))
|
||||
list.add(PacketRegisterInfo(EditorRouteResultS2CPacket.ID, EditorRouteResultS2CPacket::decode, EditorRouteResultHandler))
|
||||
|
||||
// MultiBattleTeam Packets
|
||||
list.add(PacketRegisterInfo(TeamRequestNotificationPacket.ID, TeamRequestNotificationPacket::decode, TeamRequestNotificationHandler))
|
||||
@@ -453,6 +531,11 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(RideSettingsSyncPacket.ID, RideSettingsSyncPacket::decode, RideSettingsSyncHandler))
|
||||
list.add(PacketRegisterInfo(TechnicalMachineRegistrySyncPacket.ID, TechnicalMachineRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
|
||||
list.add(PacketRegisterInfo(MolangUiOpenPacket.ID, MolangUiOpenPacket::decode, MolangUiOpenHandler))
|
||||
list.add(PacketRegisterInfo(MolangUiClosePacket.ID, MolangUiClosePacket::decode, MolangUiCloseHandler))
|
||||
list.add(PacketRegisterInfo(MolangUiUpdatePacket.ID, MolangUiUpdatePacket::decode, MolangUiUpdateHandler))
|
||||
list.add(PacketRegisterInfo(MolangUiCompatibilityRequestPacket.ID, MolangUiCompatibilityRequestPacket::decode, MolangUiCompatibilityRequestHandler))
|
||||
|
||||
// Effects
|
||||
list.add(PacketRegisterInfo(SpawnSnowstormParticlePacket.ID, SpawnSnowstormParticlePacket::decode, SpawnSnowstormParticleHandler))
|
||||
list.add(PacketRegisterInfo(SpawnSnowstormEntityParticlePacket.ID, SpawnSnowstormEntityParticlePacket::decode, SpawnSnowstormEntityParticleHandler))
|
||||
@@ -465,7 +548,6 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(SpawnPokemonPacket.ID, SpawnPokemonPacket::decode, SpawnExtraDataEntityHandler()))
|
||||
list.add(PacketRegisterInfo(SpawnPokeballPacket.ID, SpawnPokeballPacket::decode, SpawnExtraDataEntityHandler()))
|
||||
list.add(PacketRegisterInfo(SpawnGenericBedrockPacket.ID, SpawnGenericBedrockPacket::decode, SpawnExtraDataEntityHandler()))
|
||||
list.add(PacketRegisterInfo(SpawnFallingStarPacket.ID, SpawnFallingStarPacket::decode, SpawnExtraDataEntityHandler()))
|
||||
list.add(PacketRegisterInfo(SpawnNPCPacket.ID, SpawnNPCPacket::decode, SpawnExtraDataEntityHandler()))
|
||||
list.add(PacketRegisterInfo(ToastPacket.ID, ToastPacket::decode, ToastPacketHandler))
|
||||
|
||||
@@ -483,8 +565,25 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(OpenPasturePacket.ID, OpenPasturePacket::decode, OpenPastureHandler))
|
||||
list.add(PacketRegisterInfo(ClosePasturePacket.ID, ClosePasturePacket::decode, ClosePastureHandler))
|
||||
list.add(PacketRegisterInfo(PokemonPasturedPacket.ID, PokemonPasturedPacket::decode, PokemonPasturedHandler))
|
||||
list.add(PacketRegisterInfo(PokemonUnpasturedPacket.ID, PokemonUnpasturedPacket::decode, PokemonUnpasturedHandler))
|
||||
list.add(PacketRegisterInfo(UpdatePastureConflictFlagPacket.ID, UpdatePastureConflictFlagPacket::decode, UpdatePastureConflictFlagHandler))
|
||||
list.add(
|
||||
PacketRegisterInfo(
|
||||
PokemonUnpasturedPacket.ID,
|
||||
PokemonUnpasturedPacket::decode,
|
||||
PokemonUnpasturedHandler
|
||||
)
|
||||
)
|
||||
list.add(
|
||||
PacketRegisterInfo(
|
||||
UpdatePastureConflictFlagPacket.ID,
|
||||
UpdatePastureConflictFlagPacket::decode,
|
||||
UpdatePastureConflictFlagHandler
|
||||
)
|
||||
)
|
||||
|
||||
list.add(PacketRegisterInfo(OpenStadiumConfigPacket.ID, OpenStadiumConfigPacket::decode, OpenStadiumConfigHandler))
|
||||
list.add(PacketRegisterInfo(StadiumConfigResultPacket.ID, StadiumConfigResultPacket::decode, StadiumConfigResultHandler))
|
||||
list.add(PacketRegisterInfo(StadiumSpectateStatePacket.ID, StadiumSpectateStatePacket::decode, StadiumSpectateStateHandler))
|
||||
list.add(PacketRegisterInfo(StadiumCinematicPacket.ID, StadiumCinematicPacket::decode, StadiumCinematicHandler))
|
||||
|
||||
// Orientation
|
||||
list.add(PacketRegisterInfo(ClientboundUpdateOrientationPacket.ID, ClientboundUpdateOrientationPacket::decode, ClientboundUpdateOrientationHandler))
|
||||
@@ -515,11 +614,6 @@ object CobblemonNetwork {
|
||||
// Pokédex scanning
|
||||
list.add(PacketRegisterInfo(ServerConfirmedRegisterPacket.ID, ServerConfirmedRegisterPacket::decode, ServerConfirmedRegisterHandler))
|
||||
|
||||
// Form packets
|
||||
list.add(PacketRegisterInfo(AddFormPacket.ID, AddFormPacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(ClearFormsPacket.ID, ClearFormsPacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(RemoveFormPacket.ID, RemoveFormPacket::decode, PokemonUpdatePacketHandler()))
|
||||
|
||||
// Riding
|
||||
list.add(PacketRegisterInfo(ClientboundUpdateRidingStatePacket.ID, ClientboundUpdateRidingStatePacket::decode, ClientboundUpdateRidingStateHandler))
|
||||
list.add(PacketRegisterInfo(ClientboundUpdateDriverInputPacket.ID, ClientboundUpdateDriverInputPacket::decode, ClientboundUpdateDriverInputHandler))
|
||||
@@ -587,6 +681,7 @@ object CobblemonNetwork {
|
||||
|
||||
// Battle packets
|
||||
list.add(PacketRegisterInfo(BattleSelectActionsPacket.ID, BattleSelectActionsPacket::decode, BattleSelectActionsHandler))
|
||||
list.add(PacketRegisterInfo(StadiumPreviewChoicePacket.ID, StadiumPreviewChoicePacket::decode, StadiumPreviewChoiceHandler))
|
||||
list.add(PacketRegisterInfo(SpectateBattlePacket.ID, SpectateBattlePacket::decode, SpectateBattleHandler))
|
||||
list.add(PacketRegisterInfo(RemoveSpectatorPacket.ID, RemoveSpectatorPacket::decode, RemoveSpectatorHandler))
|
||||
|
||||
@@ -635,10 +730,6 @@ object CobblemonNetwork {
|
||||
// NPC packets
|
||||
list.add(PacketRegisterInfo(SaveNPCPacket.ID, SaveNPCPacket::decode, SaveNPCHandler))
|
||||
|
||||
// Form Packets
|
||||
list.add(PacketRegisterInfo(AcceptFormPacket.ID, AcceptFormPacket::decode, AcceptFormHandler))
|
||||
list.add(PacketRegisterInfo(RevertFormPacket.ID, RevertFormPacket::decode, RevertFormHandler))
|
||||
|
||||
// Riding packet(s)
|
||||
list.add(PacketRegisterInfo(ServerboundUpdateOrientationPacket.ID, ServerboundUpdateOrientationPacket::decode, ServerboundUpdateOrientationHandler))
|
||||
list.add(PacketRegisterInfo(ServerboundUpdateRidingStatePacket.ID, ServerboundUpdateRidingStatePacket::decode, ServerboundUpdateRidingStateHandler))
|
||||
@@ -658,8 +749,29 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(SetTMMachineContainerDataPacket.ID, SetTMMachineContainerDataPacket::decode, SetTMMachineContainerDataPacketHandler))
|
||||
|
||||
// Behaviour Packets
|
||||
list.add(PacketRegisterInfo(SetEntityBehaviourPacket.ID, SetEntityBehaviourPacket::decode, SetEntityBehaviourHandler))
|
||||
list.add(PacketRegisterInfo(DamageOnCollisionPacket.ID, DamageOnCollisionPacket::decode, DamageOnCollisionPacketHandler))
|
||||
list.add(
|
||||
PacketRegisterInfo(
|
||||
SetEntityBehaviourPacket.ID,
|
||||
SetEntityBehaviourPacket::decode,
|
||||
SetEntityBehaviourHandler
|
||||
)
|
||||
)
|
||||
list.add(
|
||||
PacketRegisterInfo(
|
||||
DamageOnCollisionPacket.ID,
|
||||
DamageOnCollisionPacket::decode,
|
||||
DamageOnCollisionPacketHandler
|
||||
)
|
||||
)
|
||||
|
||||
list.add(PacketRegisterInfo(UpdateStadiumBlockPacket.ID, UpdateStadiumBlockPacket::decode, UpdateStadiumBlockHandler))
|
||||
list.add(PacketRegisterInfo(EditStadiumCinematicPacket.ID, EditStadiumCinematicPacket::decode, EditStadiumCinematicHandler))
|
||||
list.add(PacketRegisterInfo(RequestStadiumPlacementWandPacket.ID, RequestStadiumPlacementWandPacket::decode, RequestStadiumPlacementWandHandler))
|
||||
list.add(PacketRegisterInfo(StadiumSpectatePacket.ID, StadiumSpectatePacket::decode, StadiumSpectateHandler))
|
||||
|
||||
list.add(PacketRegisterInfo(MolangUiActionPacket.ID, MolangUiActionPacket::decode, MolangUiActionHandler))
|
||||
list.add(PacketRegisterInfo(MolangUiClosedPacket.ID, MolangUiClosedPacket::decode, MolangUiClosedHandler))
|
||||
list.add(PacketRegisterInfo(MolangUiCompatibilityResponsePacket.ID, MolangUiCompatibilityResponsePacket::decode, MolangUiCompatibilityResponseHandler))
|
||||
|
||||
// Habitat blocks
|
||||
list.add(PacketRegisterInfo(SaveHabitatBlockSettingsPacket.ID, SaveHabitatBlockSettingsPacket::decode, SaveHabitatBlockSettingsHandler))
|
||||
@@ -667,6 +779,10 @@ object CobblemonNetwork {
|
||||
// Debug / cheats
|
||||
list.add(PacketRegisterInfo(RequestOpenRidingStatsDebugGUIPacket.ID, RequestOpenRidingStatsDebugGUIPacket::decode, RequestOpenRidingStatsDebugGUIHandler))
|
||||
|
||||
list.add(PacketRegisterInfo(EditorPreviewStartC2SPacket.ID, EditorPreviewStartC2SPacket::decode, EditorPreviewStartHandler))
|
||||
list.add(PacketRegisterInfo(EditorRouteRequestC2SPacket.ID, EditorRouteRequestC2SPacket::decode, EditorRouteRequestHandler))
|
||||
list.add(PacketRegisterInfo(EditorPreviewStopC2SPacket.ID, EditorPreviewStopC2SPacket::decode, EditorPreviewStopHandler))
|
||||
list.add(PacketRegisterInfo(EditorPreviewControlC2SPacket.ID, EditorPreviewControlC2SPacket::decode, EditorPreviewControlHandler))
|
||||
|
||||
return list
|
||||
}
|
||||
@@ -674,4 +790,4 @@ object CobblemonNetwork {
|
||||
fun sendPacketToPlayer(player: ServerPlayer, packet: NetworkPacket<*>) {
|
||||
Cobblemon.implementation.networkManager.sendPacketToPlayer(player, packet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.sensors.*
|
||||
import com.cobblemon.mod.common.pokemon.ai.PokemonDisturbancesSensor
|
||||
import com.cobblemon.mod.common.entity.sensor.BattlingPokemonSensor
|
||||
import com.cobblemon.mod.common.entity.sensor.NPCBattlingSensor
|
||||
import com.cobblemon.mod.common.pokemon.ai.PokemonDisturbancesSensor
|
||||
import java.util.function.Supplier
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.ai.sensing.Sensor
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import java.util.Optional
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.world.entity.Entity
|
||||
@@ -19,6 +18,7 @@ import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.item.trading.ItemCost
|
||||
import net.minecraft.world.item.trading.MerchantOffer
|
||||
import java.util.Optional
|
||||
|
||||
/**
|
||||
* A generator for various trade offers in the mod.
|
||||
|
||||
+1
-1
@@ -11,10 +11,10 @@ package com.cobblemon.mod.common.advancement.criterion
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import java.util.Optional
|
||||
import net.minecraft.advancements.critereon.ContextAwarePredicate
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import java.util.Optional
|
||||
|
||||
class AspectCriterion(
|
||||
playerCtx: Optional<ContextAwarePredicate>,
|
||||
|
||||
+1
-1
@@ -14,8 +14,8 @@ import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import java.util.Optional
|
||||
import net.minecraft.advancements.critereon.ContextAwarePredicate
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class CastPokeRodContext(val baitId: ResourceLocation)
|
||||
|
||||
|
||||
+1
-1
@@ -10,10 +10,10 @@ package com.cobblemon.mod.common.advancement.criterion
|
||||
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import java.util.Optional
|
||||
import net.minecraft.advancements.critereon.ContextAwarePredicate
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import java.util.Optional
|
||||
|
||||
/**
|
||||
* A context that is used when you require a [CountableContext] along with some type string.
|
||||
|
||||
+1
-1
@@ -14,8 +14,8 @@ import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import java.util.Optional
|
||||
import net.minecraft.advancements.critereon.ContextAwarePredicate
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class ReelInPokemonContext(val species : ResourceLocation, val baitId: ResourceLocation)
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common.api.abilities
|
||||
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
import com.cobblemon.mod.common.api.data.ShowdownIdentifiable
|
||||
import com.cobblemon.mod.common.util.codec.CodecUtils
|
||||
import com.google.gson.JsonObject
|
||||
import com.mojang.serialization.Codec
|
||||
@@ -26,7 +25,7 @@ class AbilityTemplate(
|
||||
var builder: (AbilityTemplate, forced: Boolean, priority: Priority) -> Ability = { template, forced, priority -> Ability(template, forced, priority) },
|
||||
val displayName: String = "cobblemon.ability.$name",
|
||||
val description: String = "cobblemon.ability.$name.desc"
|
||||
) : ShowdownIdentifiable {
|
||||
) {
|
||||
/**
|
||||
* Returns the Ability or if applicable the extension connected to this template
|
||||
*/
|
||||
@@ -46,8 +45,6 @@ class AbilityTemplate(
|
||||
*/
|
||||
fun create(json: JsonObject) = create().loadFromJSON(json)
|
||||
|
||||
override fun showdownId(): String = ShowdownIdentifiable.REGEX.replace(this.name.lowercase(), "")
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ import com.cobblemon.mod.common.api.molang.MoLangFunctions.addStandardFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
|
||||
import com.cobblemon.mod.common.entity.MoLangScriptingEntity
|
||||
import com.cobblemon.mod.common.util.activityRegistry
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.api.ai.config.BehaviourConfig
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.util.getBooleanOrNull
|
||||
import com.cobblemon.mod.common.util.getDoubleOrNull
|
||||
import kotlin.math.sqrt
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
|
||||
/**
|
||||
* Used to maintain some settings around how the entity should wander this tick. The idea is you
|
||||
|
||||
@@ -8,12 +8,16 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
|
||||
@@ -11,8 +11,13 @@ package com.cobblemon.mod.common.api.ai.config.task
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.weightedSelection
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
+2
@@ -8,10 +8,12 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask.Companion.wrapped
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.util.mainThreadRuntime
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
|
||||
+2
@@ -10,6 +10,8 @@ package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.StopBeingAngryIfTargetDead
|
||||
|
||||
+2
@@ -9,7 +9,9 @@
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.Difficulty
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
|
||||
+1
@@ -15,6 +15,7 @@ import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.npc.ai.SwitchToBattleTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class SwitchToNPCBattleTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = emptyList<MoLangConfigVariable>()
|
||||
|
||||
+2
@@ -10,6 +10,8 @@ package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
+2
@@ -10,6 +10,8 @@ package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
+1
@@ -25,6 +25,7 @@ import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.memory.MemoryStatus
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -22,7 +22,6 @@ import com.cobblemon.mod.common.util.mainThreadRuntime
|
||||
import com.cobblemon.mod.common.util.resolveFloat
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import kotlin.math.ceil
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
@@ -35,6 +34,7 @@ import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.level.material.Fluids
|
||||
import net.minecraft.world.level.pathfinder.PathType
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import kotlin.math.ceil
|
||||
|
||||
class WaterWanderTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(WANDER, "water_wanders", true).asExpressible()
|
||||
|
||||
+32
-17
@@ -35,6 +35,7 @@ import com.cobblemon.mod.common.battles.ActiveBattlePokemon
|
||||
import com.cobblemon.mod.common.battles.BattleCaptureAction
|
||||
import com.cobblemon.mod.common.battles.BattleFormat
|
||||
import com.cobblemon.mod.common.battles.BattleRegistry
|
||||
import com.cobblemon.mod.common.battles.stadium.StadiumBattleSession
|
||||
import com.cobblemon.mod.common.battles.BattleSide
|
||||
import com.cobblemon.mod.common.battles.FleeAttemptActionResponse
|
||||
import com.cobblemon.mod.common.battles.ForfeitActionResponse
|
||||
@@ -54,9 +55,9 @@ import com.cobblemon.mod.common.net.messages.client.battle.BattleEndPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMakeChoicePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMessagePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleQueueRequestPacket
|
||||
import com.cobblemon.mod.common.pokemon.transformation.progress.DefeatTransformationProgress
|
||||
import com.cobblemon.mod.common.pokemon.transformation.progress.LastBattleCriticalHitsTransformationProgress
|
||||
import com.cobblemon.mod.common.pokemon.transformation.requirements.DefeatRequirement
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.DefeatEvolutionProgress
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.LastBattleCriticalHitsEvolutionProgress
|
||||
import com.cobblemon.mod.common.pokemon.requirements.DefeatRequirement
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.getPlayer
|
||||
import com.cobblemon.mod.common.util.giveOrDropItemStack
|
||||
@@ -80,14 +81,18 @@ import net.minecraft.world.item.ItemStack
|
||||
open class PokemonBattle(
|
||||
val format: BattleFormat,
|
||||
val side1: BattleSide,
|
||||
val side2: BattleSide
|
||||
val side2: BattleSide,
|
||||
initializeProgress: Boolean = true
|
||||
) {
|
||||
/** Whether logging will be silenced for this battle. */
|
||||
var mute = !CobblemonBuildDetails.SNAPSHOT
|
||||
val struct = this.asMoLangValue()
|
||||
val runtime = MoLangRuntime().also { it.environment.query = struct }
|
||||
val runtime = MoLangRuntime().also {
|
||||
it.environment.query = struct
|
||||
}
|
||||
|
||||
val onEndHandlers: MutableList<(PokemonBattle) -> Unit> = mutableListOf()
|
||||
var stadiumSession: StadiumBattleSession? = null
|
||||
|
||||
val battlePartyStores = mutableListOf<PlayerPartyStore>()
|
||||
|
||||
@@ -96,9 +101,15 @@ open class PokemonBattle(
|
||||
side2.battle = this
|
||||
this.actors.forEach { actor ->
|
||||
actor.battle = this
|
||||
}
|
||||
if (initializeProgress) resetEvolutionProgress()
|
||||
}
|
||||
|
||||
internal fun resetEvolutionProgress() {
|
||||
actors.forEach { actor ->
|
||||
actor.pokemonList.forEach { battlePokemon ->
|
||||
battlePokemon.effectedPokemon.requirementProgress
|
||||
.filterIsInstance<LastBattleCriticalHitsTransformationProgress>()
|
||||
battlePokemon.effectedPokemon.evolutionProxy.current().progress()
|
||||
.filterIsInstance<LastBattleCriticalHitsEvolutionProgress>()
|
||||
.forEach { it.reset() }
|
||||
}
|
||||
}
|
||||
@@ -237,7 +248,9 @@ open class PokemonBattle(
|
||||
}
|
||||
|
||||
fun turn(newTurnNumber: Int) {
|
||||
actors.forEach { it.turn() }
|
||||
// Prepare all actors before notifying synchronous AI, or its first response can clear other actors' requests.
|
||||
actors.forEach { it.prepareTurn() }
|
||||
actors.forEach { it.fireChoiceRequest() }
|
||||
// TODO: If a pokemon switches in the same turn another pokemon is KO'd it will not receive exp for the KO
|
||||
for (side in sides) {
|
||||
val opposite = side.getOppositeSide()
|
||||
@@ -250,6 +263,7 @@ open class PokemonBattle(
|
||||
}
|
||||
|
||||
fun end() {
|
||||
if (ended) return
|
||||
ended = true
|
||||
val awardToFainted = Cobblemon.config.awardExperienceToFaintedPokemon
|
||||
val awardOnLoss = Cobblemon.config.awardExperienceOnBattleLoss
|
||||
@@ -271,13 +285,12 @@ open class PokemonBattle(
|
||||
val facedFainted = opponentPokemon.facedOpponents.contains(faintedPokemon)
|
||||
val pokemon = opponentPokemon.effectedPokemon
|
||||
if (facedFainted) {
|
||||
if (pokemon.hasMatchingRequirement<DefeatRequirement>({ it.target.matches(faintedPokemon.effectedPokemon) })) {
|
||||
val requiredPokemonProperties = pokemon.getRelevantRequirements<DefeatRequirement> { it.target.matches(faintedPokemon.effectedPokemon) }
|
||||
.map { it.target }
|
||||
.distinctBy { it.asString() }
|
||||
for (props in requiredPokemonProperties) {
|
||||
val progress = pokemon.progressFirstOrCreate({ it is DefeatTransformationProgress && it.currentProgress().target.asString().equals(props.asString(), ignoreCase = true) }, ::DefeatTransformationProgress)
|
||||
progress.updateProgress(DefeatTransformationProgress.Progress(props.copy(), progress.currentProgress().amount + 1))
|
||||
pokemon.lockedEvolutions.forEach { evolution ->
|
||||
evolution.requirements.filterIsInstance<DefeatRequirement>().forEach { defeatRequirement ->
|
||||
if (defeatRequirement.target.matches(faintedPokemon.effectedPokemon)) {
|
||||
val progress = pokemon.evolutionProxy.current().progressFirstOrCreate({ it is DefeatEvolutionProgress && it.currentProgress().target == defeatRequirement.target }) { DefeatEvolutionProgress() }
|
||||
progress.updateProgress(DefeatEvolutionProgress.Progress(defeatRequirement.target, progress.currentProgress().amount + 1))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -465,7 +478,7 @@ open class PokemonBattle(
|
||||
val message = battleLang("crash").red()
|
||||
this.actors.filterIsInstance<PlayerBattleActor>().forEach { it.entity?.sendSystemMessage(message) }
|
||||
this.saveBattleLog()
|
||||
this.stop()
|
||||
if (stadiumSession != null) BattleRegistry.abortStadiumBattle(battleId) else this.stop()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -473,6 +486,7 @@ open class PokemonBattle(
|
||||
ticks++
|
||||
if (isPvW && !ended && dispatches.isEmpty()) checkFlee()
|
||||
}
|
||||
stadiumSession?.tick()
|
||||
}
|
||||
|
||||
open fun checkFlee() {
|
||||
@@ -508,6 +522,7 @@ open class PokemonBattle(
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
if (ended) return
|
||||
writeShowdownAction(">forcetie") // This will terminate the Showdown connection
|
||||
end()
|
||||
}
|
||||
@@ -584,4 +599,4 @@ open class PokemonBattle(
|
||||
queryStruct.addFunction("has_rule") { params -> DoubleValue(params.getString(0) in format.ruleSet) }
|
||||
return queryStruct
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+33
-28
@@ -11,8 +11,9 @@ package com.cobblemon.mod.common.api.battles.model.actor
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.api.battles.model.ai.BattleAI
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.battles.DefaultActionResponse
|
||||
import com.cobblemon.mod.common.battles.ForcePassActionResponse
|
||||
import com.cobblemon.mod.common.battles.PassActionResponse
|
||||
import com.cobblemon.mod.common.battles.ShowdownActionResponse
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.exception.IllegalActionChoiceException
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleFaintPacket
|
||||
@@ -49,36 +50,40 @@ abstract class AIBattleActor(
|
||||
* Called when the AI is requested to make a choice.
|
||||
*/
|
||||
open fun onChoiceRequested() {
|
||||
val req = request
|
||||
if (req == null) {
|
||||
responses.clear()
|
||||
expectingPassActions.clear()
|
||||
mustChoose = false
|
||||
battle.checkForInputDispatch()
|
||||
return
|
||||
}
|
||||
val passActions = expectingPassActions.toList()
|
||||
try {
|
||||
request?.let {
|
||||
setActionResponses(it.iterate(this.activePokemon) { battleMon, moveset, forceSwitch ->
|
||||
battleAI.choose(battleMon, battle, getSide(), moveset, forceSwitch)
|
||||
})
|
||||
pokemonList.forEach { pokemon ->
|
||||
pokemon.willBeSwitchedIn = false
|
||||
}
|
||||
} ?: {
|
||||
val response = mutableListOf<ShowdownActionResponse>()
|
||||
repeat(activePokemon.size) {
|
||||
response.add(PassActionResponse)
|
||||
}
|
||||
setActionResponses(response)
|
||||
LOGGER.warn("AI requested choice, but no request was set. Returning PassActionResponses.")
|
||||
}
|
||||
setActionResponses(req.iterate(this.activePokemon) { battleMon, moveset, forceSwitch ->
|
||||
battleAI.choose(battleMon, battle, getSide(), moveset, forceSwitch)
|
||||
})
|
||||
} catch (exception: IllegalActionChoiceException) {
|
||||
// Validation may have consumed forced passes and accepted a prefix before rejecting a later slot.
|
||||
responses.clear()
|
||||
expectingPassActions.clear()
|
||||
expectingPassActions.addAll(passActions)
|
||||
if (req.forceSwitch.any { it }) {
|
||||
LOGGER.error("AI could not choose replacements; using Showdown's default choices", exception)
|
||||
setActionResponses(req.iterate(activePokemon) { _, _, _ -> DefaultActionResponse() })
|
||||
return
|
||||
}
|
||||
LOGGER.error("AI was unable to choose an action, we're going to need to pass!")
|
||||
exception.printStackTrace()
|
||||
request?.let {
|
||||
setActionResponses(it.iterate(this.activePokemon) { _, _ , _->
|
||||
PassActionResponse
|
||||
})
|
||||
} ?: {
|
||||
val response = mutableListOf<ShowdownActionResponse>()
|
||||
repeat(activePokemon.size) {
|
||||
response.add(PassActionResponse)
|
||||
}
|
||||
setActionResponses(response)
|
||||
}
|
||||
var forcedPasses = passActions.size
|
||||
setActionResponses(req.iterate(this.activePokemon) { _, moveset, forceSwitch ->
|
||||
if (!forceSwitch && moveset != null && forcedPasses > 0) {
|
||||
forcedPasses--
|
||||
ForcePassActionResponse()
|
||||
} else PassActionResponse
|
||||
})
|
||||
} finally {
|
||||
pokemonList.forEach { it.willBeSwitchedIn = false }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+27
-14
@@ -22,10 +22,11 @@ import com.cobblemon.mod.common.item.battle.BagItem
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleApplyPassResponsePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMakeChoicePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMessagePacket
|
||||
import java.util.UUID
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import java.util.UUID
|
||||
|
||||
abstract class BattleActor(
|
||||
val uuid: UUID,
|
||||
@@ -52,6 +53,8 @@ abstract class BattleActor(
|
||||
var itemsUsed = mutableListOf<BagItem>()
|
||||
/** For when battles start, it's the number of Pokémon that are still in the process of being sent out (animation wise) */
|
||||
var stillSendingOutCount = 0
|
||||
/** Positions follow active slot order: slot a is index 0. */
|
||||
var stadiumSendOutPositions: List<Vec3>? = null
|
||||
|
||||
abstract val type: ActorType
|
||||
|
||||
@@ -71,21 +74,31 @@ abstract class BattleActor(
|
||||
open fun isForPlayer(serverPlayerEntity: ServerPlayer) = serverPlayerEntity.uuid in getPlayerUUIDs()
|
||||
open fun isForPokemon(pokemonEntity: PokemonEntity) = activePokemon.any { it.battlePokemon?.effectedPokemon?.entity == pokemonEntity }
|
||||
|
||||
fun turn() {
|
||||
val request = request ?: return
|
||||
responses.clear()
|
||||
if (activePokemon.any { it.isAlive() }) {
|
||||
mustChoose = true
|
||||
sendUpdate(BattleMakeChoicePacket())
|
||||
}
|
||||
|
||||
|
||||
val requestActive = request.active
|
||||
if (requestActive == null || requestActive.isEmpty() || request.wait) {
|
||||
this.request = null
|
||||
/** Prepare every actor before notifying any AI, since synchronous choices can dispatch immediately. */
|
||||
fun prepareTurn() {
|
||||
mustChoose = false
|
||||
val req = request ?: run {
|
||||
responses.clear()
|
||||
expectingPassActions.clear()
|
||||
return
|
||||
}
|
||||
responses.clear()
|
||||
if (activePokemon.any { it.isAlive() }) {
|
||||
mustChoose = true
|
||||
}
|
||||
val requestActive = req.active
|
||||
if (req.wait || (requestActive.isNullOrEmpty() && req.forceSwitch.none { it })) {
|
||||
this.request = null
|
||||
expectingPassActions.clear()
|
||||
mustChoose = false
|
||||
} else if (req.forceSwitch.any { it }) {
|
||||
mustChoose = true
|
||||
}
|
||||
}
|
||||
|
||||
/** Call only after every actor has been prepared for this turn. */
|
||||
fun fireChoiceRequest() {
|
||||
if (mustChoose) sendUpdate(BattleMakeChoicePacket())
|
||||
}
|
||||
|
||||
fun postUpdate() {
|
||||
@@ -162,4 +175,4 @@ abstract class BattleActor(
|
||||
|
||||
open fun win(otherWinners: List<BattleActor>, losers: List<BattleActor>) {}
|
||||
open fun lose(winners: List<BattleActor>, otherLosers: List<BattleActor>) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import com.cobblemon.mod.common.util.adapters.*
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import java.awt.Color
|
||||
import net.minecraft.advancements.critereon.MinMaxBounds
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
@@ -31,6 +30,7 @@ import net.minecraft.tags.TagKey
|
||||
import net.minecraft.world.level.biome.Biome
|
||||
import net.minecraft.world.phys.AABB
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import java.awt.Color
|
||||
|
||||
/**
|
||||
* The data registry for [Berry].
|
||||
|
||||
@@ -26,10 +26,10 @@ import com.cobblemon.mod.common.util.writeBox
|
||||
import com.cobblemon.mod.common.util.writeEnumConstant
|
||||
import com.cobblemon.mod.common.util.writeIdentifier
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import java.awt.Color
|
||||
import java.util.EnumSet
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import java.awt.Color
|
||||
import java.util.EnumSet
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.tags.TagKey
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.camera
|
||||
|
||||
/** Minecraft yaw and pitch, in degrees. */
|
||||
data class CameraRotation(
|
||||
val yaw: Float,
|
||||
val pitch: Float
|
||||
)
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.camera.model
|
||||
|
||||
// Air bubbles have no separate vanilla call that Fabric can cancel.
|
||||
enum class HudElement(val id: String) {
|
||||
CROSSHAIR("crosshair"),
|
||||
HOTBAR("hotbar"),
|
||||
EXPERIENCE_BAR("experience_bar"),
|
||||
PLAYER_HEALTH("player_health"),
|
||||
ARMOR("armor"),
|
||||
FOOD("food"),
|
||||
EFFECTS("effects"),
|
||||
BOSS_BAR("boss_bar"),
|
||||
SCOREBOARD("scoreboard"),
|
||||
CHAT("chat"),
|
||||
PLAYER_LIST("player_list"),
|
||||
SELECTED_ITEM_NAME("selected_item_name"),
|
||||
COBBLEMON_OVERLAY("cobblemon_overlay");
|
||||
|
||||
companion object {
|
||||
val ALL: Set<HudElement> = entries.toSet()
|
||||
|
||||
private val BY_ID = entries.associateBy { it.id }
|
||||
|
||||
fun fromId(id: String): HudElement? = BY_ID[id]
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.camera.model
|
||||
|
||||
data class ParameterDefinition(
|
||||
val type: ParameterType,
|
||||
val description: String? = null,
|
||||
val default: ParameterDefault? = null
|
||||
)
|
||||
|
||||
enum class ParameterType {
|
||||
NUMBER,
|
||||
VEC3,
|
||||
STRING
|
||||
}
|
||||
|
||||
sealed class ParameterDefault {
|
||||
data class NumberDefault(val value: Double) : ParameterDefault()
|
||||
data class Vec3Default(val x: Double, val y: Double, val z: Double) : ParameterDefault()
|
||||
data class StringDefault(val value: String) : ParameterDefault()
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.camera.model
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
import com.google.gson.JsonElement
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
data class PositionExpression(
|
||||
val x: CoordinateValue,
|
||||
val y: CoordinateValue,
|
||||
val z: CoordinateValue
|
||||
) {
|
||||
fun toVec3(
|
||||
context: Map<String, MoValue> = emptyMap(),
|
||||
runtime: MoLangRuntime,
|
||||
origin: Vec3 = Vec3.ZERO,
|
||||
isRelative: Boolean = false
|
||||
): Vec3 {
|
||||
val base = Vec3(
|
||||
x.evaluate(context, runtime),
|
||||
y.evaluate(context, runtime),
|
||||
z.evaluate(context, runtime)
|
||||
)
|
||||
|
||||
return if (isRelative) base.add(origin) else base
|
||||
}
|
||||
|
||||
fun isFinite(context: Map<String, MoValue>, runtime: MoLangRuntime): Boolean {
|
||||
val vec = toVec3(context, runtime)
|
||||
return vec.x.isFinite() && vec.y.isFinite() && vec.z.isFinite()
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun fromJson(element: JsonElement): PositionExpression {
|
||||
return when {
|
||||
element.isJsonObject -> {
|
||||
val obj = element.asJsonObject
|
||||
PositionExpression(
|
||||
x = deserializeCoordinate(obj.get("x")),
|
||||
y = deserializeCoordinate(obj.get("y")),
|
||||
z = deserializeCoordinate(obj.get("z"))
|
||||
)
|
||||
}
|
||||
element.isJsonArray -> {
|
||||
val arr = element.asJsonArray
|
||||
if (arr.size() != 3) {
|
||||
throw IllegalArgumentException("Position array must have exactly 3 elements [x, y, z], got ${arr.size()}")
|
||||
}
|
||||
PositionExpression(
|
||||
x = deserializeCoordinate(arr[0]),
|
||||
y = deserializeCoordinate(arr[1]),
|
||||
z = deserializeCoordinate(arr[2])
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
throw IllegalArgumentException("Position must be either an object {x, y, z} or array [x, y, z]")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun deserializeCoordinate(element: JsonElement?): CoordinateValue {
|
||||
if (element == null) {
|
||||
return CoordinateValue.Static(0.0)
|
||||
}
|
||||
|
||||
return when {
|
||||
element.isJsonPrimitive && element.asJsonPrimitive.isNumber -> {
|
||||
CoordinateValue.Static(element.asDouble)
|
||||
}
|
||||
element.isJsonPrimitive && element.asJsonPrimitive.isString -> {
|
||||
CoordinateValue.Dynamic(element.asString.asExpressionLike())
|
||||
}
|
||||
element.isJsonObject -> {
|
||||
val obj = element.asJsonObject
|
||||
val type = obj.get("type")?.asString
|
||||
val expression = obj.get("expression")?.asString
|
||||
|
||||
when (type) {
|
||||
"expression" -> {
|
||||
if (expression == null) {
|
||||
throw IllegalArgumentException("Expression coordinate missing 'expression' field")
|
||||
}
|
||||
CoordinateValue.Dynamic(expression.asExpressionLike())
|
||||
}
|
||||
else -> {
|
||||
throw IllegalArgumentException("Unknown coordinate type: $type")
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
throw IllegalArgumentException("Invalid coordinate value: $element")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class CoordinateValue {
|
||||
data class Static(val value: Double) : CoordinateValue() {
|
||||
init { require(value.isFinite()) { "Static coordinate must be finite" } }
|
||||
}
|
||||
data class Dynamic(val expression: ExpressionLike) : CoordinateValue()
|
||||
|
||||
fun evaluate(
|
||||
context: Map<String, MoValue>,
|
||||
runtime: MoLangRuntime
|
||||
): Double {
|
||||
return when (this) {
|
||||
is Static -> value
|
||||
is Dynamic -> runtime.resolve(expression, context).asDouble().also {
|
||||
require(it.isFinite()) { "Dynamic coordinate must evaluate to a finite value" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.camera.result
|
||||
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
data class ValidationError(
|
||||
val path: String,
|
||||
val message: Component,
|
||||
val severity: Severity = Severity.ERROR
|
||||
) {
|
||||
enum class Severity { WARNING, ERROR }
|
||||
|
||||
override fun toString(): String = "[$severity] $path: ${message.string}"
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.Entity
|
||||
|
||||
sealed class ActorBinding {
|
||||
abstract val kind: ActorKind
|
||||
|
||||
/** Visible player actors override server position and suppress movement packets. */
|
||||
data class Player(
|
||||
val player: ServerPlayer,
|
||||
val fallbackPokemon: PokemonProperties? = null
|
||||
) : ActorBinding() {
|
||||
override val kind: ActorKind = ActorKind.PlayerTakeover
|
||||
}
|
||||
|
||||
data class Real(val entity: Entity) : ActorBinding() {
|
||||
override val kind: ActorKind = ActorKind.RealEntity
|
||||
}
|
||||
|
||||
data class SynthPokemon(
|
||||
val properties: PokemonProperties,
|
||||
val aspects: Set<String> = emptySet()
|
||||
) : ActorBinding() {
|
||||
override val kind: ActorKind = ActorKind.SynthesizedPokemon
|
||||
}
|
||||
|
||||
data class SynthBedrock(
|
||||
val category: ResourceLocation,
|
||||
val aspects: Set<String> = emptySet(),
|
||||
val scale: Float = 1.0f
|
||||
) : ActorBinding() {
|
||||
override val kind: ActorKind = ActorKind.SynthesizedBedrock
|
||||
|
||||
init {
|
||||
require(scale.isFinite() && scale > 0f) { "SynthBedrock scale must be positive, got $scale" }
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model
|
||||
|
||||
data class ActorDeclaration(
|
||||
val id: String,
|
||||
val kind: ActorKind
|
||||
) {
|
||||
init {
|
||||
require(id.isNotBlank()) { "ActorDeclaration id must be non-blank" }
|
||||
}
|
||||
}
|
||||
|
||||
sealed class ActorKind {
|
||||
object PlayerTakeover : ActorKind()
|
||||
|
||||
object RealEntity : ActorKind()
|
||||
|
||||
object SynthesizedPokemon : ActorKind()
|
||||
|
||||
object SynthesizedBedrock : ActorKind()
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model
|
||||
|
||||
import com.cobblemon.mod.common.api.cinematic.model.tracks.ActorTrack
|
||||
|
||||
/** Null visibility carries over between beats; tracks never carry over. */
|
||||
data class ActorDirection(
|
||||
val visible: Boolean? = null,
|
||||
val startPose: StartPose? = null,
|
||||
val startPoseMode: StartPoseMode? = null,
|
||||
val tracks: List<ActorTrack> = emptyList()
|
||||
) {
|
||||
init {
|
||||
if (startPose != null) {
|
||||
require(visible != false) {
|
||||
"ActorDirection.startPose declared but visible = false; hidden actors cannot have a start pose"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model
|
||||
|
||||
import com.cobblemon.mod.common.api.camera.model.HudElement
|
||||
|
||||
/** Null duration leaves the beat unbounded; feeds without cuts are inactive. */
|
||||
data class Beat(
|
||||
val id: String,
|
||||
val duration: Float? = null,
|
||||
val isLooping: Boolean = false,
|
||||
val speed: Float = 1.0f,
|
||||
val actorDirections: Map<String, ActorDirection> = emptyMap(),
|
||||
val cuts: Map<String, CutTrack> = emptyMap(),
|
||||
val guiTrack: SceneGuiTrack? = null,
|
||||
val renderPlayerBody: Boolean = true,
|
||||
val hiddenHudElements: Set<HudElement> = emptySet(),
|
||||
val cues: List<SceneCue> = emptyList()
|
||||
) {
|
||||
init {
|
||||
require(id.isNotBlank()) { "Beat id must be non-blank" }
|
||||
require(speed.isFinite() && speed > 0f) { "Beat speed must be positive, got $speed" }
|
||||
duration?.let {
|
||||
require(it.isFinite() && it >= 0f) { "Beat duration must be non-negative, got $it" }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model
|
||||
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
|
||||
/** Clamping at a beat's duration does not end the scene; completion requires an explicit transition. */
|
||||
data class BeatTransition(
|
||||
val sourceBeatId: String,
|
||||
val targetBeatId: String,
|
||||
val condition: ExpressionLike,
|
||||
val transition: CutTransition = CutTransition.Blend(0.4f),
|
||||
val endsScene: Boolean = false
|
||||
) {
|
||||
init {
|
||||
require(sourceBeatId.isNotBlank()) { "BeatTransition sourceBeatId must be non-blank" }
|
||||
require(endsScene || targetBeatId.isNotBlank()) { "BeatTransition targetBeatId must be non-blank" }
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model
|
||||
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
class CinematicValidationException(val reason: Component) : IllegalArgumentException(reason.string)
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model
|
||||
|
||||
data class CutTrack(
|
||||
val entries: List<CutEntry>
|
||||
) {
|
||||
init {
|
||||
require(entries.isNotEmpty()) { "CutTrack must have at least one entry" }
|
||||
require(entries.zipWithNext().all { (a, b) -> a.time <= b.time }) {
|
||||
"CutTrack entries must be sorted ascending by time"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class CutEntry(
|
||||
val time: Float,
|
||||
val shotId: String,
|
||||
val transition: CutTransition = CutTransition.Instant
|
||||
) {
|
||||
init {
|
||||
require(time.isFinite() && time >= 0f) { "CutEntry time must be non-negative, got $time" }
|
||||
require(shotId.isNotBlank()) { "CutEntry shotId must be non-blank" }
|
||||
}
|
||||
}
|
||||
|
||||
sealed class CutTransition {
|
||||
object Instant : CutTransition()
|
||||
|
||||
data class Blend(val duration: Float) : CutTransition() {
|
||||
init {
|
||||
require(duration.isFinite() && duration > 0f) { "Blend duration must be positive, got $duration" }
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model
|
||||
|
||||
enum class DisconnectPolicy {
|
||||
END_SCENE,
|
||||
SUBSTITUTE,
|
||||
HIDE_ACTOR,
|
||||
FAIL
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model
|
||||
|
||||
data class FeedDeclaration(
|
||||
val id: String,
|
||||
val kind: FeedKind
|
||||
) {
|
||||
init {
|
||||
require(id.isNotBlank()) { "FeedDeclaration id must be non-blank" }
|
||||
}
|
||||
|
||||
companion object {
|
||||
/** Bound for feed counts read off the wire, so a crafted packet can't drive a huge allocation. */
|
||||
const val MAX_FEEDS = 64
|
||||
}
|
||||
}
|
||||
|
||||
sealed class FeedKind {
|
||||
/** Occupies the full viewport. */
|
||||
object Fullscreen : FeedKind()
|
||||
|
||||
/** Picture-in-picture overlay in a viewport corner. [size] is a fraction of viewport. */
|
||||
data class Pip(val corner: Corner, val size: Float) : FeedKind() {
|
||||
init {
|
||||
require(size > 0f && size <= 1f) { "Pip size must be in (0, 1], got $size" }
|
||||
}
|
||||
}
|
||||
|
||||
/** Relative share of a paired split. */
|
||||
data class Split(val side: Side, val size: Float) : FeedKind() {
|
||||
init {
|
||||
require(size > 0f && size <= 1f) { "Split size must be in (0, 1], got $size" }
|
||||
}
|
||||
}
|
||||
|
||||
data class Diagonal(val half: DiagonalHalf) : FeedKind()
|
||||
|
||||
enum class Corner { TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT }
|
||||
enum class Side { LEFT, RIGHT, TOP, BOTTOM }
|
||||
enum class DiagonalHalf { UPPER, LOWER }
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model
|
||||
|
||||
fun <T> orderedKeyframes(keyframes: List<T>, time: (T) -> Float): List<T> {
|
||||
require(keyframes.isNotEmpty()) { "At least one keyframe is required" }
|
||||
require(keyframes.all { time(it).isFinite() && time(it) >= 0f }) { "Keyframe times must be finite and nonnegative" }
|
||||
val ordered = ArrayList<T>(keyframes.size)
|
||||
for (keyframe in keyframes.sortedBy(time)) {
|
||||
if (ordered.isNotEmpty() && time(ordered.last()) == time(keyframe)) {
|
||||
ordered[ordered.lastIndex] = keyframe
|
||||
} else {
|
||||
ordered.add(keyframe)
|
||||
}
|
||||
}
|
||||
return ordered
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model
|
||||
|
||||
import net.minecraft.network.chat.Component
|
||||
import com.cobblemon.mod.common.api.cinematic.runtime.ActorFraming
|
||||
import com.cobblemon.mod.common.api.camera.model.ParameterDefinition
|
||||
import com.cobblemon.mod.common.api.camera.result.ValidationError
|
||||
import com.cobblemon.mod.common.api.cinematic.runtime.ActorDependencyOrder
|
||||
import com.cobblemon.mod.common.api.cinematic.model.sources.builtin.OrbitPosition
|
||||
import com.cobblemon.mod.common.api.cinematic.model.sources.builtin.LookAt
|
||||
import com.cobblemon.mod.common.api.cinematic.model.sources.builtin.LookAtTarget
|
||||
|
||||
data class Scene(
|
||||
val id: String,
|
||||
val parameters: Map<String, ParameterDefinition> = emptyMap(),
|
||||
val actors: Map<String, ActorDeclaration> = emptyMap(),
|
||||
val shots: Map<String, Shot> = emptyMap(),
|
||||
val feeds: List<FeedDeclaration> = emptyList(),
|
||||
val startBeatId: String,
|
||||
val beats: Map<String, Beat>,
|
||||
val transitions: List<BeatTransition> = emptyList(),
|
||||
val version: Int = 2,
|
||||
val damageImmunityDuringTakeover: Boolean = false,
|
||||
val disconnectPolicy: DisconnectPolicy = DisconnectPolicy.END_SCENE
|
||||
) {
|
||||
init {
|
||||
require(id.isNotBlank()) { "Scene id must be non-blank" }
|
||||
require(startBeatId.isNotBlank()) { "Scene startBeatId must be non-blank" }
|
||||
require(version == 2) { "Scene.version must be 2, got $version" }
|
||||
}
|
||||
|
||||
fun getBeat(beatId: String): Beat? = beats[beatId]
|
||||
|
||||
fun getShot(shotId: String): Shot? = shots[shotId]
|
||||
|
||||
fun getActor(actorId: String): ActorDeclaration? = actors[actorId]
|
||||
|
||||
fun getFeed(feedId: String): FeedDeclaration? = feeds.firstOrNull { it.id == feedId }
|
||||
|
||||
fun getTransitionsFrom(beatId: String): List<BeatTransition> =
|
||||
transitions.filter { it.sourceBeatId == beatId }
|
||||
|
||||
fun validate(): List<ValidationError> {
|
||||
val errors = mutableListOf<ValidationError>()
|
||||
|
||||
if (startBeatId !in beats) {
|
||||
errors.add(ValidationError(
|
||||
path = "startBeatId",
|
||||
message = Component.translatable("cobblemon.cinematic_editor.validation.start_missing", startBeatId)
|
||||
))
|
||||
}
|
||||
|
||||
actors.forEach { (key, actor) ->
|
||||
if (actor.id != key) {
|
||||
errors.add(ValidationError(
|
||||
path = "actors[$key].id",
|
||||
message = Component.translatable("cobblemon.cinematic_editor.validation.actor_id", key, actor.id)
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
shots.forEach { (key, shot) ->
|
||||
val framingActors = (shot.position as? OrbitPosition)?.actorIds.orEmpty() +
|
||||
listOfNotNull((shot.position as? OrbitPosition)?.bearingActorId) +
|
||||
((shot.rotation as? LookAt)?.target as? LookAtTarget.Actors)?.actorIds.orEmpty()
|
||||
framingActors.distinct().filter { it !in actors && it !in ActorFraming.groups }.forEach { actorId ->
|
||||
errors.add(ValidationError(path = "shots[$key]", message = Component.translatable("cobblemon.cinematic_editor.validation.framing_actor", actorId)))
|
||||
}
|
||||
if (shot.id != key) {
|
||||
errors.add(ValidationError(
|
||||
path = "shots[$key].id",
|
||||
message = Component.translatable("cobblemon.cinematic_editor.validation.shot_id", key, shot.id)
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
val feedIds = feeds.map { it.id }
|
||||
val duplicateFeedIds = feedIds.groupingBy { it }.eachCount().filter { it.value > 1 }.keys
|
||||
duplicateFeedIds.forEach { duplicateId ->
|
||||
errors.add(ValidationError(
|
||||
path = "feeds",
|
||||
message = Component.translatable("cobblemon.cinematic_editor.validation.duplicate_feed", duplicateId)
|
||||
))
|
||||
}
|
||||
|
||||
val cueIds = mutableSetOf<String>()
|
||||
beats.forEach { (beatKey, beat) ->
|
||||
beat.actorDirections.forEach { (actorId, direction) ->
|
||||
if (direction.tracks.any { it.trackType == "pathfinding" } &&
|
||||
direction.tracks.count { it.trackType in setOf("pathfinding", "spline_movement", "keyframe_movement", "follow_actor", "attach", "pose_lock") } > 1) {
|
||||
errors.add(ValidationError(
|
||||
path = "beats[$beatKey].actorDirections[$actorId].tracks",
|
||||
message = Component.translatable("cobblemon.cinematic_editor.validation.movement_conflict")
|
||||
))
|
||||
}
|
||||
}
|
||||
beat.cues.forEachIndexed { index, cue ->
|
||||
if (!cueIds.add(cue.id)) errors.add(ValidationError(
|
||||
path = "beats[$beatKey].cues[$index].id", message = Component.translatable("cobblemon.cinematic_editor.validation.duplicate_cue", cue.id)))
|
||||
if (beat.duration != null && cue.time > beat.duration) errors.add(ValidationError(
|
||||
path = "beats[$beatKey].cues[$index].time", message = Component.translatable("cobblemon.cinematic_editor.validation.late_cue", cue.id)))
|
||||
}
|
||||
try {
|
||||
ActorDependencyOrder.resolve(actors.keys, beat)
|
||||
} catch (error: CinematicValidationException) {
|
||||
errors.add(ValidationError(path = "beats[$beatKey].actorDirections", message = error.reason))
|
||||
}
|
||||
if (beat.id != beatKey) {
|
||||
errors.add(ValidationError(
|
||||
path = "beats[$beatKey].id",
|
||||
message = Component.translatable("cobblemon.cinematic_editor.validation.beat_id", beatKey, beat.id)
|
||||
))
|
||||
}
|
||||
beat.actorDirections.keys.forEach { actorRef ->
|
||||
if (actorRef !in actors) {
|
||||
errors.add(ValidationError(
|
||||
path = "beats[$beatKey].actorDirections[$actorRef]",
|
||||
message = Component.translatable("cobblemon.cinematic_editor.validation.actor_missing", actorRef)
|
||||
))
|
||||
}
|
||||
}
|
||||
beat.cuts.forEach { (feedRef, cutTrack) ->
|
||||
if (feedRef !in feedIds) {
|
||||
errors.add(ValidationError(
|
||||
path = "beats[$beatKey].cuts[$feedRef]",
|
||||
message = Component.translatable("cobblemon.cinematic_editor.validation.feed_missing", feedRef)
|
||||
))
|
||||
}
|
||||
cutTrack.entries.forEach { entry ->
|
||||
if (entry.shotId !in shots) {
|
||||
errors.add(ValidationError(
|
||||
path = "beats[$beatKey].cuts[$feedRef]",
|
||||
message = Component.translatable("cobblemon.cinematic_editor.validation.shot_missing", entry.shotId, entry.time)
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
transitions.forEachIndexed { index, transition ->
|
||||
if (transition.sourceBeatId !in beats) {
|
||||
errors.add(ValidationError(
|
||||
path = "transitions[$index].sourceBeatId",
|
||||
message = Component.translatable("cobblemon.cinematic_editor.validation.source_missing", transition.sourceBeatId)
|
||||
))
|
||||
}
|
||||
if (!transition.endsScene && transition.targetBeatId !in beats) {
|
||||
errors.add(ValidationError(
|
||||
path = "transitions[$index].targetBeatId",
|
||||
message = Component.translatable("cobblemon.cinematic_editor.validation.target_missing", transition.targetBeatId)
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
val graph = transitions.filter { !it.endsScene && it.sourceBeatId in beats && it.targetBeatId in beats }
|
||||
.groupBy({ it.sourceBeatId }, { it.targetBeatId })
|
||||
val reachable = findReachableBeats(graph)
|
||||
beats.keys.forEach { beatId ->
|
||||
if (beatId !in reachable) {
|
||||
errors.add(ValidationError(
|
||||
path = "beats[$beatId]",
|
||||
message = Component.translatable("cobblemon.cinematic_editor.validation.unreachable", startBeatId),
|
||||
severity = ValidationError.Severity.WARNING
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
val cycle = findCycle(graph)
|
||||
if (cycle != null) {
|
||||
errors.add(ValidationError(
|
||||
path = "transitions",
|
||||
message = Component.translatable("cobblemon.cinematic_editor.validation.cycle", cycle.joinToString(" -> ")),
|
||||
severity = ValidationError.Severity.WARNING
|
||||
))
|
||||
}
|
||||
|
||||
return errors
|
||||
}
|
||||
|
||||
private fun findReachableBeats(graph: Map<String, List<String>>): Set<String> {
|
||||
val reachable = mutableSetOf<String>()
|
||||
val queue = ArrayDeque<String>()
|
||||
if (startBeatId in beats) {
|
||||
queue.add(startBeatId)
|
||||
reachable.add(startBeatId)
|
||||
}
|
||||
while (queue.isNotEmpty()) {
|
||||
for (target in graph[queue.removeFirst()].orEmpty()) {
|
||||
if (reachable.add(target)) queue.addLast(target)
|
||||
}
|
||||
}
|
||||
return reachable
|
||||
}
|
||||
|
||||
private fun findCycle(graph: Map<String, List<String>>): List<String>? {
|
||||
val visited = mutableSetOf<String>()
|
||||
val active = mutableMapOf<String, Int>()
|
||||
val path = mutableListOf<String>()
|
||||
val stack = ArrayDeque<Iterator<String>>()
|
||||
fun enter(id: String) {
|
||||
visited.add(id)
|
||||
active[id] = path.size
|
||||
path.add(id)
|
||||
stack.addLast(graph[id].orEmpty().iterator())
|
||||
}
|
||||
for (id in beats.keys) {
|
||||
if (id in visited) continue
|
||||
enter(id)
|
||||
while (stack.isNotEmpty()) {
|
||||
val remaining = stack.last()
|
||||
if (remaining.hasNext()) {
|
||||
val target = remaining.next()
|
||||
val cycleStart = active[target]
|
||||
if (cycleStart != null) return path.subList(cycleStart, path.size) + target
|
||||
if (target !in visited) enter(target)
|
||||
} else {
|
||||
stack.removeLast()
|
||||
active.remove(path.removeAt(path.lastIndex))
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model
|
||||
|
||||
/** A scene-unique, one-shot signal; loops and beat re-entry never fire it again. */
|
||||
data class SceneCue(val id: String, val time: Float) {
|
||||
init {
|
||||
require(id.isNotBlank() && id.length <= 128) { "Cue id must contain 1 to 128 characters" }
|
||||
require(time.isFinite() && time >= 0f) { "Cue time must be finite and non-negative" }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model
|
||||
|
||||
data class SceneGuiTrack(
|
||||
val actions: List<SceneGuiAction>
|
||||
) {
|
||||
init {
|
||||
require(actions.zipWithNext().all { (a, b) -> a.time <= b.time }) {
|
||||
"SceneGuiTrack actions must be sorted by time"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class SceneGuiAction(
|
||||
val time: Float,
|
||||
val type: SceneGuiActionType,
|
||||
val guiId: String,
|
||||
val args: Map<String, SceneGuiArgValue> = emptyMap()
|
||||
) {
|
||||
init {
|
||||
require(time.isFinite() && time >= 0f) { "SceneGuiAction time must be non-negative, got $time" }
|
||||
}
|
||||
}
|
||||
|
||||
enum class SceneGuiActionType {
|
||||
OPEN,
|
||||
CLOSE,
|
||||
UPDATE_ARGS
|
||||
}
|
||||
|
||||
sealed class SceneGuiArgValue {
|
||||
data class Expression(val value: String) : SceneGuiArgValue()
|
||||
|
||||
data class StringLiteral(val value: String) : SceneGuiArgValue()
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model
|
||||
|
||||
import com.cobblemon.mod.common.api.cinematic.model.sources.FovSource
|
||||
import com.cobblemon.mod.common.api.cinematic.model.sources.Lens
|
||||
import com.cobblemon.mod.common.api.cinematic.model.sources.PositionSource
|
||||
import com.cobblemon.mod.common.api.cinematic.model.sources.RollSource
|
||||
import com.cobblemon.mod.common.api.cinematic.model.sources.RotationSource
|
||||
import com.cobblemon.mod.common.api.cinematic.model.sources.ShotModifier
|
||||
|
||||
data class Shot(
|
||||
val id: String,
|
||||
val position: PositionSource,
|
||||
val rotation: RotationSource,
|
||||
val fov: FovSource? = null,
|
||||
val roll: RollSource? = null,
|
||||
val lens: Lens? = null,
|
||||
val modifiers: List<ShotModifier> = emptyList()
|
||||
) {
|
||||
init {
|
||||
require(id.isNotBlank()) { "Shot id must be non-blank" }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model
|
||||
|
||||
import com.cobblemon.mod.common.api.camera.CameraRotation
|
||||
import com.cobblemon.mod.common.api.camera.model.PositionExpression
|
||||
|
||||
data class StartPose(
|
||||
val position: PositionExpression,
|
||||
val rotation: CameraRotation,
|
||||
val blendDurationSeconds: Float = 0.5f
|
||||
) {
|
||||
init {
|
||||
require(rotation.yaw.isFinite() && rotation.pitch.isFinite()) { "Start pose rotation must be finite" }
|
||||
require(blendDurationSeconds.isFinite() && blendDurationSeconds >= 0f) { "Start pose blend duration must be finite and nonnegative" }
|
||||
}
|
||||
}
|
||||
|
||||
/** Unset mode teleports newly visible actors and ignores the start pose for already visible actors. */
|
||||
enum class StartPoseMode {
|
||||
TELEPORT,
|
||||
|
||||
BLEND,
|
||||
|
||||
EXPECT,
|
||||
|
||||
IGNORE
|
||||
}
|
||||
+3
-5
@@ -6,10 +6,8 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.entity.projectile
|
||||
package com.cobblemon.mod.common.api.cinematic.model.sources
|
||||
|
||||
enum class FallingStarResultType {
|
||||
MINIOR,
|
||||
ITEM,
|
||||
POKEMON
|
||||
abstract class FovSource {
|
||||
abstract val type: String
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model.sources
|
||||
|
||||
data class Lens(
|
||||
val aspectCrop: Float? = null,
|
||||
val letterbox: Float = 0f
|
||||
) {
|
||||
init {
|
||||
aspectCrop?.let {
|
||||
require(it.isFinite() && it > 0f) { "Lens aspectCrop must be positive, got $it" }
|
||||
}
|
||||
require(letterbox >= 0f && letterbox <= 0.5f) {
|
||||
"Lens letterbox must be in [0, 0.5], got $letterbox"
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model.sources
|
||||
|
||||
abstract class PositionSource {
|
||||
abstract val type: String
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model.sources
|
||||
|
||||
abstract class RollSource {
|
||||
abstract val type: String
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model.sources
|
||||
|
||||
abstract class RotationSource {
|
||||
abstract val type: String
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model.sources
|
||||
|
||||
abstract class ShotModifier {
|
||||
abstract val type: String
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model.sources.builtin
|
||||
|
||||
import com.cobblemon.mod.common.api.cinematic.model.sources.ShotModifier
|
||||
import com.google.gson.JsonObject
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
data class ConstraintModifier(
|
||||
val minX: Double? = null, val maxX: Double? = null,
|
||||
val minY: Double? = null, val maxY: Double? = null,
|
||||
val minZ: Double? = null, val maxZ: Double? = null
|
||||
) : ShotModifier() {
|
||||
override val type: String = TYPE
|
||||
|
||||
init {
|
||||
require(listOfNotNull(minX, maxX, minY, maxY, minZ, maxZ).all { it.isFinite() }) { "Constraint bounds must be finite" }
|
||||
require(minX == null || maxX == null || minX <= maxX) { "Minimum X must not exceed maximum X" }
|
||||
require(minY == null || maxY == null || minY <= maxY) { "Minimum Y must not exceed maximum Y" }
|
||||
require(minZ == null || maxZ == null || minZ <= maxZ) { "Minimum Z must not exceed maximum Z" }
|
||||
}
|
||||
|
||||
fun apply(pos: Vec3): Vec3 = Vec3(
|
||||
pos.x.let { if (minX != null && it < minX) minX else if (maxX != null && it > maxX) maxX else it },
|
||||
pos.y.let { if (minY != null && it < minY) minY else if (maxY != null && it > maxY) maxY else it },
|
||||
pos.z.let { if (minZ != null && it < minZ) minZ else if (maxZ != null && it > maxZ) maxZ else it }
|
||||
)
|
||||
|
||||
companion object {
|
||||
const val TYPE = "constraint"
|
||||
fun fromJson(obj: JsonObject): ConstraintModifier = ConstraintModifier(
|
||||
minX = obj.get("minX")?.asDouble, maxX = obj.get("maxX")?.asDouble,
|
||||
minY = obj.get("minY")?.asDouble, maxY = obj.get("maxY")?.asDouble,
|
||||
minZ = obj.get("minZ")?.asDouble, maxZ = obj.get("maxZ")?.asDouble
|
||||
)
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model.sources.builtin
|
||||
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
import com.cobblemon.mod.common.api.cinematic.model.sources.PositionSource
|
||||
import com.google.gson.JsonObject
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
data class CranePosition(
|
||||
val pivot: Vec3,
|
||||
val armLength: Float,
|
||||
val startAngleDeg: Float,
|
||||
val angularVelocityDegPerSec: Float,
|
||||
val height: Float = 0f
|
||||
) : PositionSource() {
|
||||
override val type: String = TYPE
|
||||
|
||||
init {
|
||||
require(armLength.isFinite() && armLength > 0f) { "CranePosition armLength must be finite and positive" }
|
||||
require(startAngleDeg.isFinite() && angularVelocityDegPerSec.isFinite() && height.isFinite()) {
|
||||
"CranePosition angles, speed and height must be finite"
|
||||
}
|
||||
require(pivot.x.isFinite() && pivot.y.isFinite() && pivot.z.isFinite()) { "CranePosition pivot must be finite" }
|
||||
}
|
||||
|
||||
fun evaluate(time: Float): Vec3 {
|
||||
val angleRad = Math.toRadians(startAngleDeg + angularVelocityDegPerSec.toDouble() * time)
|
||||
return Vec3(
|
||||
pivot.x + armLength * cos(angleRad),
|
||||
pivot.y + height,
|
||||
pivot.z + armLength * sin(angleRad)
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TYPE = "crane"
|
||||
fun fromJson(obj: JsonObject): CranePosition {
|
||||
val p = obj.getAsJsonObject("pivot")
|
||||
return CranePosition(
|
||||
pivot = Vec3(p.get("x").asDouble, p.get("y").asDouble, p.get("z").asDouble),
|
||||
armLength = obj.get("armLength").asFloat,
|
||||
startAngleDeg = obj.get("startAngle")?.asFloat ?: 0f,
|
||||
angularVelocityDegPerSec = obj.get("angularVelocity").asFloat,
|
||||
height = obj.get("height")?.asFloat ?: 0f
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model.sources.builtin
|
||||
|
||||
import com.cobblemon.mod.common.api.cinematic.model.sources.PositionSource
|
||||
import com.google.gson.JsonObject
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
data class DollyPosition(
|
||||
val from: Vec3,
|
||||
val to: Vec3,
|
||||
val duration: Float
|
||||
) : PositionSource() {
|
||||
override val type: String = TYPE
|
||||
|
||||
init {
|
||||
require(duration.isFinite() && duration > 0f) { "DollyPosition duration must be finite and positive" }
|
||||
require(listOf(from.x, from.y, from.z, to.x, to.y, to.z).all { it.isFinite() }) {
|
||||
"DollyPosition endpoints must be finite"
|
||||
}
|
||||
}
|
||||
|
||||
fun evaluate(time: Float): Vec3 {
|
||||
val t = (time / duration).coerceIn(0f, 1f)
|
||||
return Vec3(
|
||||
from.x + (to.x - from.x) * t,
|
||||
from.y + (to.y - from.y) * t,
|
||||
from.z + (to.z - from.z) * t
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TYPE = "dolly"
|
||||
fun fromJson(obj: JsonObject): DollyPosition {
|
||||
val f = obj.getAsJsonObject("from")
|
||||
val t = obj.getAsJsonObject("to")
|
||||
return DollyPosition(
|
||||
from = Vec3(f.get("x").asDouble, f.get("y").asDouble, f.get("z").asDouble),
|
||||
to = Vec3(t.get("x").asDouble, t.get("y").asDouble, t.get("z").asDouble),
|
||||
duration = obj.get("duration").asFloat
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model.sources.builtin
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.cinematic.model.sources.FovSource
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveDouble
|
||||
import com.google.gson.JsonObject
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
data class ExpressionFov(
|
||||
val expression: ExpressionLike,
|
||||
val fallbackFov: Float = 70f
|
||||
) : FovSource() {
|
||||
override val type: String = "expression"
|
||||
@Transient private val warningReported = AtomicBoolean()
|
||||
|
||||
init {
|
||||
require(fallbackFov in 1f..179f) { "ExpressionFov fallbackFov must be in [1, 179]" }
|
||||
}
|
||||
|
||||
fun evaluate(runtime: MoLangRuntime): Float {
|
||||
return try {
|
||||
// coerceIn does not filter NaN — its comparisons are false either way — so check first.
|
||||
val raw = runtime.resolveDouble(expression).toFloat()
|
||||
if (!raw.isFinite()) {
|
||||
if (warningReported.compareAndSet(false, true)) {
|
||||
Cobblemon.LOGGER.warn("[ExpressionFov] Non-finite result $raw; using fallback $fallbackFov")
|
||||
}
|
||||
fallbackFov
|
||||
} else {
|
||||
raw.coerceIn(1f, 179f)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
if (warningReported.compareAndSet(false, true)) {
|
||||
Cobblemon.LOGGER.warn("[ExpressionFov] Evaluation failed: ${e.message}; using fallback $fallbackFov", e)
|
||||
}
|
||||
fallbackFov
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TYPE = "expression"
|
||||
fun fromJson(obj: JsonObject): ExpressionFov {
|
||||
val exprStr = obj.get("expression")?.asString
|
||||
?: throw IllegalArgumentException("ExpressionFov missing 'expression' field")
|
||||
val fallback = obj.get("fallback")?.asFloat ?: 70f
|
||||
return ExpressionFov(expression = exprStr.asExpressionLike(), fallbackFov = fallback)
|
||||
}
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model.sources.builtin
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.cinematic.model.sources.PositionSource
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveDouble
|
||||
import com.google.gson.JsonObject
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
data class ExpressionVec3Position(
|
||||
val xExpression: ExpressionLike,
|
||||
val yExpression: ExpressionLike,
|
||||
val zExpression: ExpressionLike,
|
||||
val fallback: Vec3 = Vec3.ZERO
|
||||
) : PositionSource() {
|
||||
override val type: String = "expression_vec3"
|
||||
@Transient private val warningReported = AtomicBoolean()
|
||||
|
||||
init {
|
||||
require(fallback.x.isFinite() && fallback.y.isFinite() && fallback.z.isFinite()) { "Expression position fallback must be finite" }
|
||||
}
|
||||
|
||||
fun evaluate(runtime: MoLangRuntime?): Vec3 {
|
||||
if (runtime == null) return fallback
|
||||
return try {
|
||||
val x = runtime.resolveDouble(xExpression)
|
||||
val y = runtime.resolveDouble(yExpression)
|
||||
val z = runtime.resolveDouble(zExpression)
|
||||
// MoLang can return NaN or infinity without throwing, so validate before sending transforms.
|
||||
if (!x.isFinite() || !y.isFinite() || !z.isFinite()) {
|
||||
if (warningReported.compareAndSet(false, true)) {
|
||||
Cobblemon.LOGGER.warn("[ExpressionVec3Position] Non-finite result ($x, $y, $z); using fallback $fallback")
|
||||
}
|
||||
fallback
|
||||
} else {
|
||||
Vec3(x, y, z)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
if (warningReported.compareAndSet(false, true)) {
|
||||
Cobblemon.LOGGER.warn("[ExpressionVec3Position] Evaluation failed: ${e.message}; using fallback $fallback", e)
|
||||
}
|
||||
fallback
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TYPE = "expression_vec3"
|
||||
|
||||
fun fromJson(obj: JsonObject): ExpressionVec3Position {
|
||||
val x = obj.get("x")?.asString
|
||||
?: throw IllegalArgumentException("ExpressionVec3Position missing 'x'")
|
||||
val y = obj.get("y")?.asString
|
||||
?: throw IllegalArgumentException("ExpressionVec3Position missing 'y'")
|
||||
val z = obj.get("z")?.asString
|
||||
?: throw IllegalArgumentException("ExpressionVec3Position missing 'z'")
|
||||
val fb = obj.get("fallback")?.asJsonObject
|
||||
val fallback = if (fb != null) {
|
||||
Vec3(fb.get("x").asDouble, fb.get("y").asDouble, fb.get("z").asDouble)
|
||||
} else Vec3.ZERO
|
||||
return ExpressionVec3Position(
|
||||
xExpression = x.asExpressionLike(),
|
||||
yExpression = y.asExpressionLike(),
|
||||
zExpression = z.asExpressionLike(),
|
||||
fallback = fallback
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model.sources.builtin
|
||||
|
||||
import com.cobblemon.mod.common.api.cinematic.model.sources.FovSource
|
||||
import com.google.gson.JsonObject
|
||||
|
||||
data class FixedFov(val fov: Float) : FovSource() {
|
||||
override val type: String = "fixed"
|
||||
|
||||
init {
|
||||
require(fov in 1f..179f) { "FixedFov must be in [1, 179], got $fov" }
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TYPE = "fixed"
|
||||
fun fromJson(obj: JsonObject): FixedFov = FixedFov(obj.get("value").asFloat)
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model.sources.builtin
|
||||
|
||||
import com.cobblemon.mod.common.api.cinematic.model.sources.PositionSource
|
||||
import com.google.gson.JsonObject
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
data class FixedPosition(val position: Vec3) : PositionSource() {
|
||||
override val type: String = "fixed"
|
||||
|
||||
init {
|
||||
require(position.x.isFinite() && position.y.isFinite() && position.z.isFinite()) { "Fixed position must be finite" }
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TYPE = "fixed"
|
||||
fun fromJson(obj: JsonObject): FixedPosition {
|
||||
val pos = obj.getAsJsonObject("position") ?: throw IllegalArgumentException("FixedPosition missing 'position'")
|
||||
return FixedPosition(Vec3(pos.get("x").asDouble, pos.get("y").asDouble, pos.get("z").asDouble))
|
||||
}
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model.sources.builtin
|
||||
|
||||
import com.cobblemon.mod.common.api.cinematic.model.sources.RollSource
|
||||
import com.google.gson.JsonObject
|
||||
|
||||
data class FixedRoll(val roll: Float) : RollSource() {
|
||||
override val type: String = "fixed"
|
||||
|
||||
init {
|
||||
require(roll.isFinite()) { "Fixed roll must be finite" }
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TYPE = "fixed"
|
||||
fun fromJson(obj: JsonObject): FixedRoll = FixedRoll(obj.get("value").asFloat)
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model.sources.builtin
|
||||
|
||||
import com.cobblemon.mod.common.api.camera.CameraRotation
|
||||
import com.cobblemon.mod.common.api.cinematic.model.sources.RotationSource
|
||||
import com.google.gson.JsonObject
|
||||
|
||||
data class FixedRotation(val rotation: CameraRotation) : RotationSource() {
|
||||
override val type: String = "fixed"
|
||||
|
||||
init {
|
||||
require(rotation.yaw.isFinite() && rotation.pitch.isFinite()) { "Fixed rotation must be finite" }
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TYPE = "fixed"
|
||||
fun fromJson(obj: JsonObject): FixedRotation {
|
||||
return FixedRotation(CameraRotation(
|
||||
yaw = obj.get("yaw").asFloat,
|
||||
pitch = obj.get("pitch").asFloat
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user