mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-21 06:36:25 -04:00
Compare commits
116
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45a9ad866e | ||
|
|
9c3066e787 | ||
|
|
eb8598278f | ||
|
|
6777c8d57d | ||
|
|
bf7d40c9b5 | ||
|
|
5abb3d7f97 | ||
|
|
975ad8186a | ||
|
|
26b6419f04 | ||
|
|
89e43945a3 | ||
|
|
bd8dcddf35 | ||
|
|
dd372f3160 | ||
|
|
c56aab28d4 | ||
|
|
3cdf28ffdd | ||
|
|
c6fb18ea51 | ||
|
|
2d851cb134 | ||
|
|
f685be0aab | ||
|
|
6ab5ad52ec | ||
|
|
079b2ae766 | ||
|
|
34eea827e7 | ||
|
|
06c6ee5a9c | ||
|
|
54748c20ea | ||
|
|
02e63b6fc8 | ||
|
|
3aebcf66ec | ||
|
|
49a5f716b7 | ||
|
|
0bd7b4dab3 | ||
|
|
8cbada0cf5 | ||
|
|
f0784fec2d | ||
|
|
cfe0c5e0a5 | ||
|
|
0bc5bb5caa | ||
|
|
3330941a2c | ||
|
|
79ea082d7e | ||
|
|
3d78929ff0 | ||
|
|
5d94b03f7a | ||
|
|
587305eb52 | ||
|
|
e363ce5e0e | ||
|
|
e49b704200 | ||
|
|
ec8b35860c | ||
|
|
74c49bf2da | ||
|
|
c03e7d9ed3 | ||
|
|
2652e53e0c | ||
|
|
b423fb1c46 | ||
|
|
8ae26a268a | ||
|
|
39b522abcc | ||
|
|
9bcfcef4fd | ||
|
|
60ac2d8058 | ||
|
|
9366d28141 | ||
|
|
75b48196b7 | ||
|
|
f6dbb1387c | ||
|
|
1a27e14bec | ||
|
|
75bc03fdcb | ||
|
|
7915f3f94e | ||
|
|
f65cb9538c | ||
|
|
396ab13164 | ||
|
|
309ff3da13 | ||
|
|
3af91e2a74 | ||
|
|
2e027e3db7 | ||
|
|
fc40fb02c0 | ||
|
|
2c1c0299f9 | ||
|
|
08cbbaf68c | ||
|
|
6e911acf01 | ||
|
|
f6d82a1b28 | ||
|
|
702126aeab | ||
|
|
df566e8fcb | ||
|
|
c83e0f33b5 | ||
|
|
f279f936b6 | ||
|
|
f8e20bafd9 | ||
|
|
a5211ca7ff | ||
|
|
2f7bedf001 | ||
|
|
44c31a9ddb | ||
|
|
cfc8a15db1 | ||
|
|
d5ba22a86c | ||
|
|
a38505f1c5 | ||
|
|
3cf1ba1fb3 | ||
|
|
9f5d595827 | ||
|
|
75673f0204 | ||
|
|
b43a7571ff | ||
|
|
b071dc04d3 | ||
|
|
12f9ff1647 | ||
|
|
3256a302df | ||
|
|
edbe447477 | ||
|
|
2f43910368 | ||
|
|
c2e87e4cfa | ||
|
|
e40d2ee806 | ||
|
|
ba74e7603b | ||
|
|
19c3fe6dc4 | ||
|
|
d0778dd124 | ||
|
|
e29087c805 | ||
|
|
e850253d88 | ||
|
|
bbb692f521 | ||
|
|
da1d67bbe6 | ||
|
|
792834f219 | ||
|
|
94b31cd658 | ||
|
|
19364f39c6 | ||
|
|
2fc8f6b9df | ||
|
|
9089ff3bbb | ||
|
|
90f581051c | ||
|
|
061bdcc478 | ||
|
|
6811394f71 | ||
|
|
1235a70323 | ||
|
|
d94952347f | ||
|
|
7fe6141640 | ||
|
|
4b1653ca6c | ||
|
|
7265ab57b9 | ||
|
|
27e3a95b06 | ||
|
|
38de3c6267 | ||
|
|
376e5ac906 | ||
|
|
b225283dcc | ||
|
|
b90f852a71 | ||
|
|
fdf7a9703a | ||
|
|
bb41f28342 | ||
|
|
c5ee7ebe7a | ||
|
|
f6ae10e1d9 | ||
|
|
b2070b53fb | ||
|
|
7fb873dc2c | ||
|
|
641f529de3 | ||
|
|
db9fb4fefa |
+24
-36
@@ -1,54 +1,40 @@
|
||||
# Changelog
|
||||
## [1.8.1 (MONTH Xth, 2026)](#1-8-1)
|
||||
## [1.8.2 (MONTH xth, 2026)](#1-8-2)
|
||||
|
||||
### Additions
|
||||
- The following items can now be placed on the ground as blocks:
|
||||
- King's Rock, Galarica Cuff, Unremarkable Teacup, Masterpiece Teacup, Chipped Pot, Cracked Pot, Sachet, Metal Powder, Quick Powder, Bright Powder, Icy Rock, Heat Rock, Smooth Rock, Damp Rock, Destiny Knot, Luminous Moss, Never-Melt Ice, Wide Lens, Scope Lens, and Zoom Lens.
|
||||
- Iron Ball, Metal Coat, Throat Spray, HP Up, Protein, Iron, Carbos, Calcium, Zinc, PP Up, PP Max, Upgrade, Dubious Disc, and Loaded Dice.
|
||||
- The following items can now be placed on various surfaces:
|
||||
- Galarica Wreath, Magnet, Flame Orb, Life Orb, Toxic Orb, Light Ball, and Smoke Ball.
|
||||
- The following items can now be placed as blocks, and have additional functionality:
|
||||
- Ring Target, Metronome, and Eject Button.
|
||||
- The following items can now be worn by Players and Pokémon:
|
||||
- Galarica Wreath, Cleanse Tag, Spell Tag, Sharp Beak, Covert Cloak, Shell Helmet, and Never-Melt Ice.
|
||||
- Wearable items can now be equipped by a player by holding it and right-clicking (or rebound use/interact)
|
||||
- Wearable items that can be placed down are exempt from this behaviour.
|
||||
|
||||
### New rideable Pokémon
|
||||
|
||||
### Pokémon Added
|
||||
|
||||
#### Regional Forms
|
||||
|
||||
### Model updates for the following Pokémon
|
||||
|
||||
### Animation updates for the following Pokémon
|
||||
|
||||
#### Added sounds to the following moves
|
||||
|
||||
### Changes
|
||||
- Updated various recipes to display in Recipe Groups within the Recipe Book
|
||||
- Updated most recipes to display more logically/consistently within the Recipe Book's categories
|
||||
|
||||
### Fixes
|
||||
- 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 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 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 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
|
||||
|
||||
- Correctly grants "They're Minerals!" advancement when planting a type gem
|
||||
- Type Gem Blocks now have advancements to give you the recipe in the recipe book (the data for the advancements were inside the recipes somehow??)
|
||||
- Some other recipes without advancements have also been corrected
|
||||
- Corrected the TM Recipes for Charge Beam and Payday
|
||||
|
||||
### Developer
|
||||
|
||||
@@ -56,5 +42,7 @@
|
||||
|
||||
### Particles
|
||||
|
||||
#### New Move Animations
|
||||
|
||||
### Localization
|
||||
- Updated translations for:
|
||||
@@ -0,0 +1,41 @@
|
||||
# Changelog
|
||||
## [1.8.1 (September 13th, 2026)](#1-8-1)
|
||||
|
||||
### Animation updates for the following Pokémon
|
||||
- Flapple, Appletun, Dipplin, Hydrapple (placeholder animations only).
|
||||
|
||||
### 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 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 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 unintentional watermelon cosmetic for Hisuian Electrode.
|
||||
- Fixed Blastoise having an unintentional passenger seat.
|
||||
- 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 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 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.
|
||||
|
||||
### Localization
|
||||
- Updated translations for:
|
||||
- Brazilian Portuguese
|
||||
- Simplified Chinese
|
||||
- Japanese
|
||||
@@ -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,7 +32,6 @@ repositories {
|
||||
maven(url = "https://api.modrinth.com/maven")
|
||||
maven(url = "https://maven.neoforged.net/releases")
|
||||
maven(url = "https://maven.gegy.dev")
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
}
|
||||
|
||||
@@ -41,7 +40,6 @@ dependencies {
|
||||
modImplementation(libs.fabric.loader)
|
||||
modApi(libs.molang)
|
||||
|
||||
|
||||
// Integrations
|
||||
compileOnlyApi(libs.jei.api)
|
||||
modCompileOnly(libs.bundles.common.integrations.compileOnly) {
|
||||
@@ -64,19 +62,14 @@ 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
@@ -1,153 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.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
@@ -1,155 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.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
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.camera.accessor;
|
||||
|
||||
public interface CameraFeedRenderState {
|
||||
boolean cobblemonRenderHand();
|
||||
boolean cobblemonRenderBlockOutline();
|
||||
}
|
||||
@@ -8,8 +8,6 @@
|
||||
|
||||
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;
|
||||
@@ -134,16 +132,6 @@ 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,12 +11,9 @@ 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);
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.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
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.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,9 +10,7 @@ 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
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.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();
|
||||
}
|
||||
+1
-7
@@ -9,13 +9,10 @@
|
||||
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")
|
||||
@@ -25,7 +22,4 @@ public interface TrackedEntityAccessor {
|
||||
|
||||
@Accessor("serverEntity")
|
||||
ServerEntity getServerEntity();
|
||||
|
||||
@Invoker("updatePlayers")
|
||||
void cobblemon$updatePlayers(List<ServerPlayer> players);
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -15,11 +15,9 @@ 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;
|
||||
@@ -34,6 +32,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Mixin(BrewingStandBlockEntity.class)
|
||||
public class BrewingStandBlockEntityMixin {
|
||||
|
||||
|
||||
@@ -9,17 +9,11 @@
|
||||
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,7 +13,6 @@ 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;
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.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
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.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
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.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,12 +8,8 @@
|
||||
|
||||
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;
|
||||
@@ -23,15 +19,11 @@ 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 {
|
||||
@@ -39,7 +31,6 @@ 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;
|
||||
@@ -51,7 +42,6 @@ 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;
|
||||
@@ -95,29 +85,4 @@ 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
@@ -1,178 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.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,9 +10,7 @@ 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;
|
||||
|
||||
+12
-119
@@ -9,142 +9,43 @@
|
||||
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 abstract class GameRendererMixin implements CameraFeedRenderState {
|
||||
|
||||
@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;
|
||||
|
||||
public class GameRendererMixin {
|
||||
@Unique
|
||||
private Camera cobblemon$playerCamera;
|
||||
long lastTime = -1;
|
||||
|
||||
@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) {
|
||||
@Inject(
|
||||
method = "render",
|
||||
at = @At(value = "TAIL")
|
||||
)
|
||||
public void render(DeltaTracker counter, boolean tick, CallbackInfo ci) {
|
||||
Minecraft client = Minecraft.getInstance();
|
||||
if (client.level == null) {
|
||||
cobblemon$restoreCamera();
|
||||
return;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
// Don't play scheduled animations when the game is paused
|
||||
if (client.isPaused()) {
|
||||
cobblemon$lastTime = newTime;
|
||||
lastTime = newTime;
|
||||
return;
|
||||
}
|
||||
|
||||
if (cobblemon$lastTime != -1) {
|
||||
float delta = (newTime - cobblemon$lastTime) / 1000F;
|
||||
ClientTaskTracker.INSTANCE.update(delta);
|
||||
if (lastTime != -1) {
|
||||
ClientTaskTracker.INSTANCE.update((newTime - lastTime) / 1000F);
|
||||
}
|
||||
cobblemon$lastTime = newTime;
|
||||
lastTime = newTime;
|
||||
}
|
||||
|
||||
@ModifyArg(
|
||||
@@ -159,12 +60,4 @@ public abstract class GameRendererMixin implements CameraFeedRenderState {
|
||||
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,7 +9,6 @@
|
||||
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;
|
||||
@@ -29,11 +28,6 @@ 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,14 +8,11 @@
|
||||
|
||||
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;
|
||||
@@ -34,34 +31,11 @@ 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) {
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.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();
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.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,8 +9,6 @@
|
||||
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;
|
||||
@@ -27,8 +25,6 @@ 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;
|
||||
@@ -39,35 +35,11 @@ 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 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;
|
||||
}
|
||||
public abstract class EntityMixin {
|
||||
|
||||
@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,11 +8,6 @@
|
||||
|
||||
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
|
||||
@@ -81,8 +76,6 @@ 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.*
|
||||
@@ -104,10 +97,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
|
||||
@@ -122,6 +115,7 @@ 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
|
||||
@@ -266,9 +260,6 @@ 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)
|
||||
@@ -283,13 +274,8 @@ object Cobblemon {
|
||||
PlatformEvents.RIGHT_CLICK_BLOCK.subscribe { event ->
|
||||
val player = event.player
|
||||
val block = player.level().getBlockState(event.pos).block
|
||||
player.party().forEach { pokemon ->
|
||||
pokemon.lockedEvolutions
|
||||
.filterIsInstance<BlockClickEvolution>()
|
||||
.forEach { evolution ->
|
||||
evolution.attemptEvolution(pokemon, BlockClickEvolution.BlockInteractionContext(block, player.level()))
|
||||
}
|
||||
}
|
||||
val context = BlockClickTrigger.Context(block, player.level())
|
||||
player.party().forEach { pokemon -> pokemon.triggerTransformations<BlockClickTrigger>(context) }
|
||||
}
|
||||
|
||||
PlatformEvents.CHANGE_DIMENSION.subscribe {
|
||||
@@ -311,7 +297,6 @@ object Cobblemon {
|
||||
HeldItemProvider.register(CobblemonHeldItemManager, Priority.LOWEST)
|
||||
}
|
||||
|
||||
|
||||
fun sendServerSettingsPacketToPlayer(player: ServerPlayer) {
|
||||
ServerSettingsPacket(
|
||||
this.config.preventCompletePartyDeposit,
|
||||
@@ -334,6 +319,7 @@ object Cobblemon {
|
||||
|
||||
SHINY_ASPECT.register()
|
||||
GENDER_ASPECT.register()
|
||||
FORM_ASPECTS.register()
|
||||
COSMETIC_SLOT_ASPECT.register()
|
||||
CHARACTERISTIC_RAINBOW_ASPECT.register()
|
||||
ALPHA_ASPECT.register()
|
||||
@@ -364,8 +350,6 @@ object Cobblemon {
|
||||
CustomPokemonProperty.register(NoAIProperty)
|
||||
CustomPokemonProperty.register(HeldItemVisibleProperty)
|
||||
|
||||
SceneBuiltinSources.register()
|
||||
|
||||
CobblemonEvents.POKEMON_PROPERTY_INITIALISED.emit(Unit)
|
||||
|
||||
CallbackHandler.setup()
|
||||
@@ -462,14 +446,7 @@ 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,6 +9,7 @@
|
||||
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
|
||||
@@ -19,16 +20,7 @@ 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.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.adapters.*
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.endsWith
|
||||
import com.google.gson.Gson
|
||||
|
||||
@@ -109,10 +109,4 @@ 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)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ import com.cobblemon.mod.common.block.MintBlock.MintType
|
||||
import com.cobblemon.mod.common.block.campfirepot.CampfireBlock
|
||||
import com.cobblemon.mod.common.block.campfirepot.CampfirePotBlock
|
||||
import com.cobblemon.mod.common.block.chest.GildedChestBlock
|
||||
import com.cobblemon.mod.common.block.decor.ActivatableDecorationBlock
|
||||
import com.cobblemon.mod.common.block.decor.RingTargetBlock
|
||||
import com.cobblemon.mod.common.block.general.BaleBlock
|
||||
import com.cobblemon.mod.common.block.general.HorizontalRotationCarpetBlock
|
||||
import com.cobblemon.mod.common.block.general.HorizontalRotationalBlock
|
||||
@@ -620,6 +622,88 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val WEAKNESS_POLICY = create("weakness_policy", WallAttachedDirectionalShapeBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.ITEM_BLOCK_PAPER_LARGE_SOUNDS).mapColor(MapColor.NONE).noOcclusion().noCollission(), 14, 12, 1))
|
||||
|
||||
@JvmField
|
||||
val RING_TARGET = create("ring_target", RingTargetBlock(BlockBehaviour.Properties.of().sound(SoundType.WOOD).mapColor(MapColor.NONE).noOcclusion().strength(0.125f)))
|
||||
@JvmField
|
||||
val MAGNET = create("magnet", MagnetBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.NONE).noOcclusion().strength(0.075f)))
|
||||
@JvmField
|
||||
val GALARICA_WREATH = create("galarica_wreath", GalaricaWreathBlock(BlockBehaviour.Properties.of().sound(SoundType.AZALEA_LEAVES).mapColor(MapColor.NONE).noOcclusion().noCollission()))
|
||||
|
||||
@JvmField
|
||||
val FLAME_ORB = create("flame_orb", OrbBlock(BlockBehaviour.Properties.of().sound(SoundType.GLASS).mapColor(MapColor.NONE).noOcclusion().lightLevel{15}))
|
||||
@JvmField
|
||||
val TOXIC_ORB = create("toxic_orb", OrbBlock(BlockBehaviour.Properties.of().sound(SoundType.GLASS).mapColor(MapColor.NONE).noOcclusion()))
|
||||
@JvmField
|
||||
val LIFE_ORB = create("life_orb", OrbBlock(BlockBehaviour.Properties.of().sound(SoundType.GLASS).mapColor(MapColor.NONE).noOcclusion().lightLevel{7}))
|
||||
@JvmField
|
||||
val LIGHT_BALL = create("light_ball", OrbBlock(BlockBehaviour.Properties.of().sound(SoundType.GLASS).mapColor(MapColor.NONE).noOcclusion().lightLevel{13}))
|
||||
@JvmField
|
||||
val SMOKE_BALL = create("smoke_ball", OrbBlock(BlockBehaviour.Properties.of().sound(SoundType.GLASS).mapColor(MapColor.NONE).noOcclusion()))
|
||||
|
||||
@JvmField
|
||||
val KINGS_ROCK = create("kings_rock", DecorativeItemBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).mapColor(MapColor.NONE).noOcclusion(), DecorativeItemBlock.DecorativeItemBlockType.CENTERED_6x))
|
||||
|
||||
@JvmField
|
||||
val GALARICA_CUFF = create("galarica_cuff", DecorativeItemBlock(BlockBehaviour.Properties.of().sound(SoundType.AZALEA_LEAVES).mapColor(MapColor.NONE).noCollission().noOcclusion(), DecorativeItemBlock.DecorativeItemBlockType.FLATTENED_10x4))
|
||||
@JvmField
|
||||
val UNREMARKABLE_TEACUP = create("unremarkable_teacup", DecorativeItemBlock(BlockBehaviour.Properties.of().sound(SoundType.DECORATED_POT).mapColor(MapColor.NONE).noOcclusion(), DecorativeItemBlock.DecorativeItemBlockType.TEACUP))
|
||||
@JvmField
|
||||
val MASTERPIECE_TEACUP = create("masterpiece_teacup", DecorativeItemBlock(BlockBehaviour.Properties.of().sound(SoundType.DECORATED_POT).mapColor(MapColor.NONE).noOcclusion(), DecorativeItemBlock.DecorativeItemBlockType.TEACUP))
|
||||
@JvmField
|
||||
val CHIPPED_POT = create("chipped_pot", DecorativeItemBlock(BlockBehaviour.Properties.of().sound(SoundType.DECORATED_POT).mapColor(MapColor.NONE).noOcclusion(), DecorativeItemBlock.DecorativeItemBlockType.TEAPOT))
|
||||
@JvmField
|
||||
val CRACKED_POT = create("cracked_pot", DecorativeItemBlock(BlockBehaviour.Properties.of().sound(SoundType.DECORATED_POT).mapColor(MapColor.NONE).noOcclusion(), DecorativeItemBlock.DecorativeItemBlockType.TEAPOT))
|
||||
|
||||
@JvmField
|
||||
val SACHET = create("sachet", DecorativeItemBlock(BlockBehaviour.Properties.of().sound(SoundType.WOOL).mapColor(MapColor.NONE).noOcclusion(), DecorativeItemBlock.DecorativeItemBlockType.POUCH))
|
||||
@JvmField
|
||||
val METAL_POWDER = create("metal_powder", DecorativeItemBlock(BlockBehaviour.Properties.of().sound(SoundType.WOOL).mapColor(MapColor.NONE).noOcclusion(), DecorativeItemBlock.DecorativeItemBlockType.POUCH))
|
||||
@JvmField
|
||||
val QUICK_POWDER = create("quick_powder", DecorativeItemBlock(BlockBehaviour.Properties.of().sound(SoundType.WOOL).mapColor(MapColor.NONE).noOcclusion(), DecorativeItemBlock.DecorativeItemBlockType.POUCH))
|
||||
@JvmField
|
||||
val BRIGHT_POWDER = create("bright_powder", DecorativeItemBlock(BlockBehaviour.Properties.of().sound(SoundType.WOOL).mapColor(MapColor.NONE).noOcclusion().lightLevel{3}, DecorativeItemBlock.DecorativeItemBlockType.POUCH))
|
||||
|
||||
@JvmField
|
||||
val NEVER_MELT_ICE = create("never_melt_ice", DecorativeItemBlock(BlockBehaviour.Properties.of().sound(SoundType.GLASS).mapColor(MapColor.NONE).noOcclusion().friction(0.989F), DecorativeItemBlock.DecorativeItemBlockType.NEVERMELT))
|
||||
@JvmField
|
||||
val SCOPE_LENS = create("scope_lens", DecorativeItemBlock(BlockBehaviour.Properties.of().sound(SoundType.COPPER).mapColor(MapColor.NONE).noOcclusion(), DecorativeItemBlock.DecorativeItemBlockType.SCOPE))
|
||||
@JvmField
|
||||
val WIDE_LENS = create("wide_lens", DecorativeItemBlock(BlockBehaviour.Properties.of().sound(SoundType.COPPER).mapColor(MapColor.NONE).noOcclusion(), DecorativeItemBlock.DecorativeItemBlockType.WIDE))
|
||||
@JvmField
|
||||
val ZOOM_LENS = create("zoom_lens", DecorativeItemBlock(BlockBehaviour.Properties.of().sound(SoundType.COPPER).mapColor(MapColor.NONE).noOcclusion(), DecorativeItemBlock.DecorativeItemBlockType.ZOOM))
|
||||
|
||||
@JvmField
|
||||
val ICY_ROCK = create("icy_rock", DecorativeItemBlock(BlockBehaviour.Properties.of().sound(SoundType.DEEPSLATE).mapColor(MapColor.NONE).noOcclusion(), DecorativeItemBlock.DecorativeItemBlockType.FLATTENED_8x4))
|
||||
@JvmField
|
||||
val HEAT_ROCK = create("heat_rock", DecorativeItemBlock(BlockBehaviour.Properties.of().sound(SoundType.DEEPSLATE).mapColor(MapColor.NONE).noOcclusion(), DecorativeItemBlock.DecorativeItemBlockType.FLATTENED_8x4))
|
||||
@JvmField
|
||||
val SMOOTH_ROCK = create("smooth_rock", DecorativeItemBlock(BlockBehaviour.Properties.of().sound(SoundType.DEEPSLATE).mapColor(MapColor.NONE).noOcclusion(), DecorativeItemBlock.DecorativeItemBlockType.FLATTENED_8x4))
|
||||
@JvmField
|
||||
val DAMP_ROCK = create("damp_rock", DecorativeItemBlock(BlockBehaviour.Properties.of().sound(SoundType.DEEPSLATE).mapColor(MapColor.NONE).noOcclusion(), DecorativeItemBlock.DecorativeItemBlockType.FLATTENED_8x6))
|
||||
@JvmField
|
||||
val DESTINY_KNOT = create("destiny_knot", DecorativeItemBlock(BlockBehaviour.Properties.of().sound(SoundType.WOOL).mapColor(MapColor.NONE).noOcclusion(), DecorativeItemBlock.DecorativeItemBlockType.KNOT))
|
||||
@JvmField
|
||||
val LUMINOUS_MOSS = create("luminous_moss", DecorativeItemBlock(BlockBehaviour.Properties.of().sound(SoundType.MOSS).mapColor(MapColor.NONE).noOcclusion().lightLevel{5}, DecorativeItemBlock.DecorativeItemBlockType.CENTERED_8x))
|
||||
|
||||
@JvmField
|
||||
val METRONOME = create("metronome", ActivatableDecorationBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.NONE).pushReaction(PushReaction.DESTROY).noOcclusion(), ActivatableDecorationBlock.ActivatableDecorationBlockType.METRONOME))
|
||||
@JvmField
|
||||
val EJECT_BUTTON = create("eject_button", EjectButtonBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.NONE).pushReaction(PushReaction.DESTROY).noOcclusion().strength(0.125f), 40))
|
||||
|
||||
@JvmField
|
||||
val LOADED_DICE = create("loaded_dice", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.DICE))
|
||||
@JvmField
|
||||
val IRON_BALL = create("iron_ball", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.IRON_BALL))
|
||||
@JvmField
|
||||
val METAL_COAT = create("metal_coat", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.METAL_COAT))
|
||||
@JvmField
|
||||
val UPGRADE = create("upgrade", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.UPGRADE))
|
||||
@JvmField
|
||||
val DUBIOUS_DISC = create("dubious_disc", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.UPGRADE))
|
||||
|
||||
@JvmField
|
||||
val THROAT_SPRAY = create("throat_spray", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.THROAT_SPRAY))
|
||||
|
||||
@JvmField
|
||||
val FULL_HEAL = create("full_heal", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.STATUS_RESTORE))
|
||||
@JvmField
|
||||
@@ -670,6 +754,23 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val X_SPEED = create("x_${Stats.SPEED.identifier.path}", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
|
||||
|
||||
@JvmField
|
||||
val HP_UP = create("hp_up", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.VITAMIN))
|
||||
@JvmField
|
||||
val PROTEIN = create("protein", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.VITAMIN))
|
||||
@JvmField
|
||||
val IRON = create("iron", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.VITAMIN))
|
||||
@JvmField
|
||||
val CARBOS = create("carbos", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.VITAMIN))
|
||||
@JvmField
|
||||
val CALCIUM = create("calcium", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.VITAMIN))
|
||||
@JvmField
|
||||
val ZINC = create("zinc", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.VITAMIN))
|
||||
@JvmField
|
||||
val PP_UP = create("pp_up", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.VITAMIN))
|
||||
@JvmField
|
||||
val PP_MAX = create("pp_max", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.VITAMIN))
|
||||
|
||||
@JvmField
|
||||
val MONITOR = create("monitor", MonitorBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).lightLevel { if (it.getValue(MonitorBlock.SCREEN) != MonitorBlock.MonitorScreen.OFF) 13 else 0 }))
|
||||
@JvmField
|
||||
@@ -682,12 +783,10 @@ 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 }))
|
||||
|
||||
@JvmField
|
||||
val TM_MACHINE = create(
|
||||
"tm_machine",
|
||||
TMMachineBlock(
|
||||
@@ -716,7 +815,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
|
||||
@JvmField
|
||||
val PASTURE = create("pasture", PastureBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BROWN).sound(SoundType.WOOD).strength(2F).noOcclusion().pushReaction(PushReaction.BLOCK).lightLevel { if ((it.getValue(PastureBlock.ON) as Boolean) && (it.getValue(PastureBlock.PART) == PastureBlock.PasturePart.TOP)) 13 else 0 }))
|
||||
|
||||
@JvmField
|
||||
val RED_MINT = create("red_mint", MintBlock(MintType.RED, BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_RED).noCollission().randomTicks().instabreak().sound(CobblemonSounds.MINT_SOUNDS).pushReaction(PushReaction.DESTROY)))
|
||||
@JvmField
|
||||
val BLUE_MINT = create("blue_mint", MintBlock(MintType.BLUE, BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BLUE).noCollission().randomTicks().instabreak().sound(CobblemonSounds.MINT_SOUNDS).pushReaction(PushReaction.DESTROY)))
|
||||
|
||||
@@ -15,11 +15,7 @@ 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)
|
||||
@@ -65,6 +61,7 @@ object CobblemonCommands {
|
||||
ChangeBoxWallpaperCommand.register(dispatcher)
|
||||
RunMolangCommand.register(dispatcher)
|
||||
RunMolangScriptCommand.register(dispatcher)
|
||||
SpectateBattleCommand.register(dispatcher)
|
||||
CobblemonConfigCommand.register(dispatcher)
|
||||
UnlockPCBoxWallpaperCommand.register(dispatcher)
|
||||
BehaviourEditCommand.register(dispatcher)
|
||||
@@ -80,8 +77,5 @@ 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,7 +13,6 @@ 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
|
||||
@@ -82,12 +81,6 @@ 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)
|
||||
@@ -106,4 +99,4 @@ object CobblemonEntities : PlatformRegistry<Registry<EntityType<*>>, ResourceKey
|
||||
consumer(POKEMON, PokemonEntity.createAttributes())
|
||||
consumer(NPC, NPCEntity.createAttributes())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ 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
|
||||
|
||||
@@ -38,7 +38,6 @@ 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
|
||||
@@ -75,9 +74,6 @@ 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
|
||||
@@ -469,8 +465,6 @@ 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
|
||||
|
||||
@@ -478,9 +472,9 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
// Evolution items
|
||||
@JvmField val LINK_CABLE = create("link_cable", LinkCableItem())
|
||||
@JvmField val DRAGON_SCALE = noSettingsItem("dragon_scale")
|
||||
@JvmField val METAL_COAT = noSettingsItem("metal_coat")
|
||||
@JvmField val UPGRADE = noSettingsItem("upgrade")
|
||||
@JvmField val DUBIOUS_DISC = noSettingsItem("dubious_disc")
|
||||
@JvmField val METAL_COAT = itemNameBlockItem("metal_coat", CobblemonBlocks.METAL_COAT)
|
||||
@JvmField val UPGRADE = itemNameBlockItem("upgrade", CobblemonBlocks.UPGRADE)
|
||||
@JvmField val DUBIOUS_DISC = itemNameBlockItem("dubious_disc", CobblemonBlocks.DUBIOUS_DISC)
|
||||
@JvmField val DEEP_SEA_SCALE = noSettingsItem("deep_sea_scale")
|
||||
@JvmField val DEEP_SEA_TOOTH = noSettingsItem("deep_sea_tooth")
|
||||
@JvmField val ELECTIRIZER = noSettingsItem("electirizer")
|
||||
@@ -489,7 +483,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField val PROTECTOR = noSettingsItem("protector")
|
||||
@JvmField val REAPER_CLOTH = noSettingsItem("reaper_cloth")
|
||||
@JvmField val PRISM_SCALE = noSettingsItem("prism_scale")
|
||||
@JvmField val SACHET = noSettingsItem("sachet")
|
||||
@JvmField val SACHET = itemNameBlockItem("sachet", CobblemonBlocks.SACHET)
|
||||
@JvmField val WHIPPED_DREAM = create("whipped_dream", foodItem(8, 0.3f))
|
||||
@JvmField val STRAWBERRY_SWEET = create("strawberry_sweet", foodItem(6, 0.125f))
|
||||
@JvmField val LOVE_SWEET = create("love_sweet", foodItem(6, 0.125f))
|
||||
@@ -498,22 +492,20 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField val FLOWER_SWEET = create("flower_sweet", foodItem(6, 0.125f))
|
||||
@JvmField val STAR_SWEET = create("star_sweet", foodItem(6, 0.125f))
|
||||
@JvmField val RIBBON_SWEET = create("ribbon_sweet", foodItem(6, 0.125f))
|
||||
@JvmField val CHIPPED_POT = noSettingsItem("chipped_pot")
|
||||
@JvmField val CRACKED_POT = noSettingsItem("cracked_pot")
|
||||
@JvmField val MASTERPIECE_TEACUP = noSettingsItem("masterpiece_teacup")
|
||||
@JvmField val UNREMARKABLE_TEACUP = noSettingsItem("unremarkable_teacup")
|
||||
@JvmField val CHIPPED_POT = itemNameBlockItem("chipped_pot", CobblemonBlocks.CHIPPED_POT)
|
||||
@JvmField val CRACKED_POT = itemNameBlockItem("cracked_pot", CobblemonBlocks.CRACKED_POT)
|
||||
@JvmField val MASTERPIECE_TEACUP = itemNameBlockItem("masterpiece_teacup", CobblemonBlocks.MASTERPIECE_TEACUP)
|
||||
@JvmField val UNREMARKABLE_TEACUP = itemNameBlockItem("unremarkable_teacup", CobblemonBlocks.UNREMARKABLE_TEACUP)
|
||||
@JvmField val SWEET_APPLE = compostableItem("sweet_apple", foodItem(4, 0.3f), 0.65f)
|
||||
@JvmField val TART_APPLE = compostableItem("tart_apple", foodItem(4, 0.3f), 0.65f)
|
||||
@JvmField val SYRUPY_APPLE = compostableItem("syrupy_apple", foodItem(4, 0.3f), 0.65f)
|
||||
@JvmField val GALARICA_CUFF = noSettingsItem("galarica_cuff")
|
||||
@JvmField val GALARICA_WREATH = noSettingsItem("galarica_wreath")
|
||||
@JvmField val GALARICA_CUFF = itemNameBlockItem("galarica_cuff", CobblemonBlocks.GALARICA_CUFF)
|
||||
@JvmField val BLACK_AUGURITE = noSettingsItem("black_augurite")
|
||||
@JvmField val PEAT_BLOCK = noSettingsItem("peat_block")
|
||||
@JvmField val RAZOR_CLAW = noSettingsItem("razor_claw")
|
||||
@JvmField val RAZOR_FANG = noSettingsItem("razor_fang")
|
||||
@JvmField val AUSPICIOUS_ARMOR = heldItem("auspicious_armor")
|
||||
@JvmField val MALICIOUS_ARMOR = heldItem("malicious_armor")
|
||||
@JvmField val SHELL_HELMET = heldItem("shell_helmet")
|
||||
@JvmField val METAL_ALLOY = noSettingsItem("metal_alloy")
|
||||
@JvmField val SCROLL_OF_DARKNESS = noSettingsItem("scroll_of_darkness")
|
||||
@JvmField val SCROLL_OF_WATERS = noSettingsItem("scroll_of_waters")
|
||||
@@ -657,17 +649,17 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val EXPERIENCE_CANDY_XL = candyItem("exp_candy_xl") { _, _ -> CandyItem.DEFAULT_XL_CANDY_YIELD }
|
||||
@JvmField
|
||||
val CALCIUM = create("calcium", VitaminItem(Stats.SPECIAL_ATTACK))
|
||||
val CALCIUM = create("calcium", VitaminItem(Stats.SPECIAL_ATTACK, CobblemonBlocks.CALCIUM))
|
||||
@JvmField
|
||||
val CARBOS = create("carbos", VitaminItem(Stats.SPEED))
|
||||
val CARBOS = create("carbos", VitaminItem(Stats.SPEED, CobblemonBlocks.CARBOS))
|
||||
@JvmField
|
||||
val HP_UP = create("hp_up", VitaminItem(Stats.HP))
|
||||
val HP_UP = create("hp_up", VitaminItem(Stats.HP, CobblemonBlocks.HP_UP))
|
||||
@JvmField
|
||||
val IRON = create("iron", VitaminItem(Stats.DEFENCE))
|
||||
val IRON = create("iron", VitaminItem(Stats.DEFENCE, CobblemonBlocks.IRON))
|
||||
@JvmField
|
||||
val PROTEIN = create("protein", VitaminItem(Stats.ATTACK))
|
||||
val PROTEIN = create("protein", VitaminItem(Stats.ATTACK, CobblemonBlocks.PROTEIN))
|
||||
@JvmField
|
||||
val ZINC = create("zinc", VitaminItem(Stats.SPECIAL_DEFENCE))
|
||||
val ZINC = create("zinc", VitaminItem(Stats.SPECIAL_DEFENCE, CobblemonBlocks.ZINC))
|
||||
@JvmField
|
||||
val HEALTH_MOCHI = create("health_mochi", MochiItem(Stats.HP))
|
||||
@JvmField
|
||||
@@ -749,9 +741,9 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val MAX_REVIVE = create("max_revive", ReviveItem(max = true))
|
||||
@JvmField
|
||||
val PP_UP = create("pp_up", PPUpItem(1))
|
||||
val PP_UP = create("pp_up", PPUpItem(1, CobblemonBlocks.PP_UP))
|
||||
@JvmField
|
||||
val PP_MAX = create("pp_max", PPUpItem(3))
|
||||
val PP_MAX = create("pp_max", PPUpItem(3, CobblemonBlocks.PP_MAX))
|
||||
|
||||
@JvmField
|
||||
val RED_MINT_SEEDS = mintSeed("red", MintType.RED.getCropBlock())
|
||||
@@ -928,11 +920,18 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField val CHOICE_SPECS = wearableItem("choice_specs")
|
||||
@JvmField val EXP_SHARE = wearableItem("exp_share")
|
||||
@JvmField val FOCUS_BAND = wearableItem("focus_band")
|
||||
@JvmField val KINGS_ROCK = wearableItem("kings_rock")
|
||||
@JvmField val KINGS_ROCK = wearableBlockItem("kings_rock", CobblemonBlocks.KINGS_ROCK)
|
||||
@JvmField val NEVER_MELT_ICE = wearableBlockItem("never_melt_ice", CobblemonBlocks.NEVER_MELT_ICE)
|
||||
@JvmField val MUSCLE_BAND = wearableItem("muscle_band")
|
||||
@JvmField val ROCKY_HELMET = wearableItem("rocky_helmet")
|
||||
@JvmField val SAFETY_GOGGLES = wearableItem("safety_goggles")
|
||||
@JvmField val WISE_GLASSES = wearableItem("wise_glasses")
|
||||
@JvmField val SHARP_BEAK = wearableItem("sharp_beak")
|
||||
@JvmField val COVERT_CLOAK = wearableItem("covert_cloak")
|
||||
@JvmField val SHELL_HELMET = wearableItem("shell_helmet")
|
||||
@JvmField val GALARICA_WREATH = wearableBlockItem("galarica_wreath", CobblemonBlocks.GALARICA_WREATH)
|
||||
@JvmField val CLEANSE_TAG = wearableBlockItem("cleanse_tag", CobblemonBlocks.CLEANSE_TAG)
|
||||
@JvmField val SPELL_TAG = wearableBlockItem("spell_tag", CobblemonBlocks.SPELL_TAG)
|
||||
|
||||
// Held Items
|
||||
@JvmField
|
||||
@@ -960,17 +959,13 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val CHOICE_SCARF = heldItem("choice_scarf")
|
||||
@JvmField
|
||||
val CLEANSE_TAG = itemNameBlockItem("cleanse_tag", CobblemonBlocks.CLEANSE_TAG)
|
||||
@JvmField
|
||||
val CLEAR_AMULET = heldItem("clear_amulet")
|
||||
@JvmField
|
||||
val COVERT_CLOAK = heldItem("covert_cloak")
|
||||
@JvmField
|
||||
val DESTINY_KNOT = heldItem("destiny_knot")
|
||||
val DESTINY_KNOT = itemNameBlockItem("destiny_knot", CobblemonBlocks.DESTINY_KNOT)
|
||||
@JvmField
|
||||
val DRAGON_FANG = heldItem("dragon_fang")
|
||||
@JvmField
|
||||
val EJECT_BUTTON = heldItem("eject_button")
|
||||
val EJECT_BUTTON = itemNameBlockItem("eject_button", CobblemonBlocks.EJECT_BUTTON)
|
||||
@JvmField
|
||||
val EJECT_PACK = heldItem("eject_pack")
|
||||
@JvmField
|
||||
@@ -984,7 +979,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val FAIRY_FEATHER = heldItem("fairy_feather")
|
||||
@JvmField
|
||||
val FLAME_ORB = heldItem("flame_orb")
|
||||
val FLAME_ORB = itemNameBlockItem("flame_orb", CobblemonBlocks.FLAME_ORB)
|
||||
@JvmField
|
||||
val FLOAT_STONE = heldItem("float_stone")
|
||||
@JvmField
|
||||
@@ -998,34 +993,32 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val HEAVY_DUTY_BOOTS = heldItem("heavy_duty_boots")
|
||||
@JvmField
|
||||
val IRON_BALL = heldItem("iron_ball")
|
||||
val IRON_BALL = itemNameBlockItem("iron_ball", CobblemonBlocks.IRON_BALL)
|
||||
@JvmField
|
||||
val LAGGING_TAIL = heldItem("lagging_tail")
|
||||
@JvmField
|
||||
val LEFTOVERS = compostableHeldItem("leftovers", null, 0.50f)
|
||||
@JvmField
|
||||
val LIFE_ORB = heldItem("life_orb")
|
||||
val LIFE_ORB = itemNameBlockItem("life_orb", CobblemonBlocks.LIFE_ORB)
|
||||
@JvmField
|
||||
val LIGHT_BALL = heldItem("light_ball")
|
||||
val LIGHT_BALL = itemNameBlockItem("light_ball", CobblemonBlocks.LIGHT_BALL)
|
||||
@JvmField
|
||||
val LIGHT_CLAY = heldItem("light_clay")
|
||||
@JvmField
|
||||
val LOADED_DICE = heldItem("loaded_dice")
|
||||
val LOADED_DICE = itemNameBlockItem("loaded_dice", CobblemonBlocks.LOADED_DICE)
|
||||
@JvmField
|
||||
val LUCKY_EGG = heldItem("lucky_egg")
|
||||
@JvmField
|
||||
val LUMINOUS_MOSS = heldItem("luminous_moss")
|
||||
val LUMINOUS_MOSS = itemNameBlockItem("luminous_moss", CobblemonBlocks.LUMINOUS_MOSS)
|
||||
@JvmField
|
||||
val MAGNET = heldItem("magnet")
|
||||
val MAGNET = itemNameBlockItem("magnet", CobblemonBlocks.MAGNET)
|
||||
@JvmField
|
||||
val METRONOME = heldItem("metronome")
|
||||
val METRONOME = itemNameBlockItem("metronome", CobblemonBlocks.METRONOME)
|
||||
@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 POISON_BARB = heldItem("poison_barb")
|
||||
@JvmField
|
||||
val POWER_ANKLET = heldItem("power_anklet")
|
||||
@@ -1050,13 +1043,11 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val RED_CARD = heldItem("red_card")
|
||||
@JvmField
|
||||
val RING_TARGET = heldItem("ring_target")
|
||||
val RING_TARGET = itemNameBlockItem("ring_target", CobblemonBlocks.RING_TARGET)
|
||||
@JvmField
|
||||
val ROOM_SERVICE = heldItem("room_service")
|
||||
@JvmField
|
||||
val SCOPE_LENS = heldItem("scope_lens")
|
||||
@JvmField
|
||||
val SHARP_BEAK = heldItem("sharp_beak")
|
||||
val SCOPE_LENS = itemNameBlockItem("scope_lens", CobblemonBlocks.SCOPE_LENS)
|
||||
@JvmField
|
||||
val SHED_SHELL = heldItem("shed_shell")
|
||||
@JvmField
|
||||
@@ -1068,9 +1059,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val SOFT_SAND = heldItem("soft_sand")
|
||||
@JvmField
|
||||
val SPELL_TAG = itemNameBlockItem("spell_tag", CobblemonBlocks.SPELL_TAG)
|
||||
@JvmField
|
||||
val SMOKE_BALL = heldItem("smoke_ball")
|
||||
val SMOKE_BALL = itemNameBlockItem("smoke_ball", CobblemonBlocks.SMOKE_BALL)
|
||||
@JvmField
|
||||
val SOOTHE_BELL = heldItem("soothe_bell")
|
||||
@JvmField
|
||||
@@ -1078,9 +1067,9 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val TERRAIN_EXTENDER = heldItem("terrain_extender")
|
||||
@JvmField
|
||||
val THROAT_SPRAY = heldItem("throat_spray")
|
||||
val THROAT_SPRAY = itemNameBlockItem("throat_spray", CobblemonBlocks.THROAT_SPRAY)
|
||||
@JvmField
|
||||
val TOXIC_ORB = heldItem("toxic_orb")
|
||||
val TOXIC_ORB = itemNameBlockItem("toxic_orb", CobblemonBlocks.TOXIC_ORB)
|
||||
@JvmField
|
||||
val TWISTED_SPOON = heldItem("twisted_spoon")
|
||||
@JvmField
|
||||
@@ -1088,9 +1077,9 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val WEAKNESS_POLICY = itemNameBlockItem("weakness_policy", CobblemonBlocks.WEAKNESS_POLICY)
|
||||
@JvmField
|
||||
val WIDE_LENS = heldItem("wide_lens")
|
||||
val WIDE_LENS = itemNameBlockItem("wide_lens", CobblemonBlocks.WIDE_LENS)
|
||||
@JvmField
|
||||
val ZOOM_LENS = heldItem("zoom_lens")
|
||||
val ZOOM_LENS = itemNameBlockItem("zoom_lens", CobblemonBlocks.ZOOM_LENS)
|
||||
@JvmField
|
||||
val MENTAL_HERB = compostableHeldItem("mental_herb", null, 0.85F)
|
||||
@JvmField
|
||||
@@ -1102,19 +1091,19 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val WHITE_HERB = compostableHeldItem("white_herb", null, 0.85F)
|
||||
@JvmField
|
||||
val BRIGHT_POWDER = heldItem("bright_powder")
|
||||
val BRIGHT_POWDER = itemNameBlockItem("bright_powder", CobblemonBlocks.BRIGHT_POWDER)
|
||||
@JvmField
|
||||
val METAL_POWDER = heldItem("metal_powder")
|
||||
val METAL_POWDER = itemNameBlockItem("metal_powder", CobblemonBlocks.METAL_POWDER)
|
||||
@JvmField
|
||||
val QUICK_POWDER = heldItem("quick_powder")
|
||||
val QUICK_POWDER = itemNameBlockItem("quick_powder", CobblemonBlocks.QUICK_POWDER)
|
||||
@JvmField
|
||||
val DAMP_ROCK = heldItem("damp_rock")
|
||||
val DAMP_ROCK = itemNameBlockItem("damp_rock", CobblemonBlocks.DAMP_ROCK)
|
||||
@JvmField
|
||||
val HEAT_ROCK = heldItem("heat_rock")
|
||||
val HEAT_ROCK = itemNameBlockItem("heat_rock", CobblemonBlocks.HEAT_ROCK)
|
||||
@JvmField
|
||||
val SMOOTH_ROCK = heldItem("smooth_rock")
|
||||
val SMOOTH_ROCK = itemNameBlockItem("smooth_rock", CobblemonBlocks.SMOOTH_ROCK)
|
||||
@JvmField
|
||||
val ICY_ROCK = heldItem("icy_rock")
|
||||
val ICY_ROCK = itemNameBlockItem("icy_rock", CobblemonBlocks.ICY_ROCK)
|
||||
|
||||
// Mulch
|
||||
@JvmField
|
||||
@@ -1605,7 +1594,16 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
|
||||
private fun wearableItem(name: String, heldItemRemappedName: String? = null): CobblemonItem = create(
|
||||
name,
|
||||
WearableItem(name).also {
|
||||
WearableHatItem(name).also {
|
||||
wearables.add(it)
|
||||
if (heldItemRemappedName != null) {
|
||||
CobblemonHeldItemManager.registerRemap(it, heldItemRemappedName)
|
||||
}
|
||||
}
|
||||
)
|
||||
private fun wearableBlockItem(name: String, block: Block, heldItemRemappedName: String? = null): WearableBlockItem = create(
|
||||
name,
|
||||
WearableBlockItem(name, block).also {
|
||||
wearables.add(it)
|
||||
if (heldItemRemappedName != null) {
|
||||
CobblemonHeldItemManager.registerRemap(it, heldItemRemappedName)
|
||||
|
||||
@@ -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,7 +9,6 @@
|
||||
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
|
||||
@@ -17,17 +16,15 @@ 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,20 +17,6 @@ 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
|
||||
@@ -46,10 +32,6 @@ 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
|
||||
@@ -71,16 +53,6 @@ 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
|
||||
@@ -100,30 +72,17 @@ 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
|
||||
@@ -148,11 +107,10 @@ 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
|
||||
@@ -202,8 +160,6 @@ 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
|
||||
@@ -223,15 +179,10 @@ 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
|
||||
@@ -246,6 +197,8 @@ 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
|
||||
@@ -263,9 +216,11 @@ 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
|
||||
@@ -286,16 +241,11 @@ 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
|
||||
@@ -444,7 +394,6 @@ 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))
|
||||
@@ -461,37 +410,9 @@ 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(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))
|
||||
list.add(PacketRegisterInfo(BattleChallengeExpiredPacket.ID, BattleChallengeExpiredPacket::decode, BattleChallengeExpiredHandler))
|
||||
list.add(PacketRegisterInfo(BattleReplacePokemonPacket.ID, BattleReplacePokemonPacket::decode, BattleReplacePokemonHandler))
|
||||
list.add(PacketRegisterInfo(BattleTransformPokemonPacket.ID, BattleTransformPokemonPacket::decode, BattleTransformPokemonHandler))
|
||||
|
||||
// MultiBattleTeam Packets
|
||||
list.add(PacketRegisterInfo(TeamRequestNotificationPacket.ID, TeamRequestNotificationPacket::decode, TeamRequestNotificationHandler))
|
||||
@@ -531,11 +452,6 @@ 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))
|
||||
@@ -565,25 +481,8 @@ 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(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))
|
||||
list.add(PacketRegisterInfo(PokemonUnpasturedPacket.ID, PokemonUnpasturedPacket::decode, PokemonUnpasturedHandler))
|
||||
list.add(PacketRegisterInfo(UpdatePastureConflictFlagPacket.ID, UpdatePastureConflictFlagPacket::decode, UpdatePastureConflictFlagHandler))
|
||||
|
||||
// Orientation
|
||||
list.add(PacketRegisterInfo(ClientboundUpdateOrientationPacket.ID, ClientboundUpdateOrientationPacket::decode, ClientboundUpdateOrientationHandler))
|
||||
@@ -614,6 +513,11 @@ 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))
|
||||
@@ -681,7 +585,6 @@ 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))
|
||||
|
||||
@@ -730,6 +633,10 @@ 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))
|
||||
@@ -749,29 +656,8 @@ 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(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))
|
||||
list.add(PacketRegisterInfo(SetEntityBehaviourPacket.ID, SetEntityBehaviourPacket::decode, SetEntityBehaviourHandler))
|
||||
list.add(PacketRegisterInfo(DamageOnCollisionPacket.ID, DamageOnCollisionPacket::decode, DamageOnCollisionPacketHandler))
|
||||
|
||||
// Habitat blocks
|
||||
list.add(PacketRegisterInfo(SaveHabitatBlockSettingsPacket.ID, SaveHabitatBlockSettingsPacket::decode, SaveHabitatBlockSettingsHandler))
|
||||
@@ -779,10 +665,6 @@ 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
|
||||
}
|
||||
@@ -790,4 +672,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,6 +8,7 @@
|
||||
|
||||
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
|
||||
@@ -18,7 +19,6 @@ 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.server.level.ServerPlayer
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
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.server.level.ServerPlayer
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
class ReelInPokemonContext(val species : ResourceLocation, val baitId: ResourceLocation)
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
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
|
||||
@@ -25,7 +26,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
|
||||
*/
|
||||
@@ -45,6 +46,8 @@ class AbilityTemplate(
|
||||
*/
|
||||
fun create(json: JsonObject) = create().loadFromJSON(json)
|
||||
|
||||
override fun showdownId(): String = ShowdownIdentifiable.REGEX.replace(this.name.lowercase(), "")
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
|
||||
-1
@@ -18,7 +18,6 @@ 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,7 +13,6 @@ 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,7 +13,6 @@ 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,16 +8,12 @@
|
||||
|
||||
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,13 +11,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.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,12 +8,10 @@
|
||||
|
||||
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,8 +10,6 @@ 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,9 +9,7 @@
|
||||
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,7 +15,6 @@ 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,8 +10,6 @@ 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,8 +10,6 @@ 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,7 +25,6 @@ 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,6 +22,7 @@ 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
|
||||
@@ -34,7 +35,6 @@ 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()
|
||||
|
||||
+17
-32
@@ -35,7 +35,6 @@ 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
|
||||
@@ -55,9 +54,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.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.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.util.battleLang
|
||||
import com.cobblemon.mod.common.util.getPlayer
|
||||
import com.cobblemon.mod.common.util.giveOrDropItemStack
|
||||
@@ -81,18 +80,14 @@ import net.minecraft.world.item.ItemStack
|
||||
open class PokemonBattle(
|
||||
val format: BattleFormat,
|
||||
val side1: BattleSide,
|
||||
val side2: BattleSide,
|
||||
initializeProgress: Boolean = true
|
||||
val side2: BattleSide
|
||||
) {
|
||||
/** 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>()
|
||||
|
||||
@@ -101,15 +96,9 @@ 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.evolutionProxy.current().progress()
|
||||
.filterIsInstance<LastBattleCriticalHitsEvolutionProgress>()
|
||||
battlePokemon.effectedPokemon.requirementProgress
|
||||
.filterIsInstance<LastBattleCriticalHitsTransformationProgress>()
|
||||
.forEach { it.reset() }
|
||||
}
|
||||
}
|
||||
@@ -248,9 +237,7 @@ open class PokemonBattle(
|
||||
}
|
||||
|
||||
fun turn(newTurnNumber: Int) {
|
||||
// Prepare all actors before notifying synchronous AI, or its first response can clear other actors' requests.
|
||||
actors.forEach { it.prepareTurn() }
|
||||
actors.forEach { it.fireChoiceRequest() }
|
||||
actors.forEach { it.turn() }
|
||||
// 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()
|
||||
@@ -263,7 +250,6 @@ open class PokemonBattle(
|
||||
}
|
||||
|
||||
fun end() {
|
||||
if (ended) return
|
||||
ended = true
|
||||
val awardToFainted = Cobblemon.config.awardExperienceToFaintedPokemon
|
||||
val awardOnLoss = Cobblemon.config.awardExperienceOnBattleLoss
|
||||
@@ -285,12 +271,13 @@ open class PokemonBattle(
|
||||
val facedFainted = opponentPokemon.facedOpponents.contains(faintedPokemon)
|
||||
val pokemon = opponentPokemon.effectedPokemon
|
||||
if (facedFainted) {
|
||||
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))
|
||||
}
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -478,7 +465,7 @@ open class PokemonBattle(
|
||||
val message = battleLang("crash").red()
|
||||
this.actors.filterIsInstance<PlayerBattleActor>().forEach { it.entity?.sendSystemMessage(message) }
|
||||
this.saveBattleLog()
|
||||
if (stadiumSession != null) BattleRegistry.abortStadiumBattle(battleId) else this.stop()
|
||||
this.stop()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -486,7 +473,6 @@ open class PokemonBattle(
|
||||
ticks++
|
||||
if (isPvW && !ended && dispatches.isEmpty()) checkFlee()
|
||||
}
|
||||
stadiumSession?.tick()
|
||||
}
|
||||
|
||||
open fun checkFlee() {
|
||||
@@ -522,7 +508,6 @@ open class PokemonBattle(
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
if (ended) return
|
||||
writeShowdownAction(">forcetie") // This will terminate the Showdown connection
|
||||
end()
|
||||
}
|
||||
@@ -599,4 +584,4 @@ open class PokemonBattle(
|
||||
queryStruct.addFunction("has_rule") { params -> DoubleValue(params.getString(0) in format.ruleSet) }
|
||||
return queryStruct
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
-33
@@ -11,9 +11,8 @@ 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
|
||||
@@ -50,40 +49,36 @@ 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 {
|
||||
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
|
||||
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.")
|
||||
}
|
||||
} catch (exception: IllegalActionChoiceException) {
|
||||
LOGGER.error("AI was unable to choose an action, we're going to need to pass!")
|
||||
exception.printStackTrace()
|
||||
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 }
|
||||
request?.let {
|
||||
setActionResponses(it.iterate(this.activePokemon) { _, _ , _->
|
||||
PassActionResponse
|
||||
})
|
||||
} ?: {
|
||||
val response = mutableListOf<ShowdownActionResponse>()
|
||||
repeat(activePokemon.size) {
|
||||
response.add(PassActionResponse)
|
||||
}
|
||||
setActionResponses(response)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
-23
@@ -22,11 +22,10 @@ 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,
|
||||
@@ -53,8 +52,6 @@ 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
|
||||
|
||||
@@ -74,33 +71,23 @@ abstract class BattleActor(
|
||||
open fun isForPlayer(serverPlayerEntity: ServerPlayer) = serverPlayerEntity.uuid in getPlayerUUIDs()
|
||||
open fun isForPokemon(pokemonEntity: PokemonEntity) = activePokemon.any { it.battlePokemon?.effectedPokemon?.entity == pokemonEntity }
|
||||
|
||||
/** 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
|
||||
}
|
||||
fun turn() {
|
||||
val request = request ?: return
|
||||
responses.clear()
|
||||
if (activePokemon.any { it.isAlive() }) {
|
||||
mustChoose = true
|
||||
sendUpdate(BattleMakeChoicePacket())
|
||||
}
|
||||
val requestActive = req.active
|
||||
if (req.wait || (requestActive.isNullOrEmpty() && req.forceSwitch.none { it })) {
|
||||
|
||||
|
||||
val requestActive = request.active
|
||||
if (requestActive == null || requestActive.isEmpty() || request.wait) {
|
||||
this.request = null
|
||||
expectingPassActions.clear()
|
||||
mustChoose = false
|
||||
} else if (req.forceSwitch.any { it }) {
|
||||
mustChoose = true
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/** Call only after every actor has been prepared for this turn. */
|
||||
fun fireChoiceRequest() {
|
||||
if (mustChoose) sendUpdate(BattleMakeChoicePacket())
|
||||
}
|
||||
|
||||
fun postUpdate() {
|
||||
val request = request ?: return
|
||||
val forceSwitchPokemon = request.forceSwitch.mapIndexedNotNull { index, b -> if (b) activePokemon[index] else null }
|
||||
@@ -175,4 +162,4 @@ abstract class BattleActor(
|
||||
|
||||
open fun win(otherWinners: List<BattleActor>, losers: List<BattleActor>) {}
|
||||
open fun lose(winners: List<BattleActor>, otherLosers: List<BattleActor>) {}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ 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
|
||||
@@ -30,7 +31,6 @@ 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 net.minecraft.core.BlockPos
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import java.awt.Color
|
||||
import java.util.EnumSet
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.tags.TagKey
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.camera
|
||||
|
||||
/** Minecraft yaw and pitch, in degrees. */
|
||||
data class CameraRotation(
|
||||
val yaw: Float,
|
||||
val pitch: Float
|
||||
)
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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}"
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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()
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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" }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model
|
||||
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
class CinematicValidationException(val reason: Component) : IllegalArgumentException(reason.string)
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model
|
||||
|
||||
enum class DisconnectPolicy {
|
||||
END_SCENE,
|
||||
SUBSTITUTE,
|
||||
HIDE_ACTOR,
|
||||
FAIL
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
|
||||
}
|
||||
@@ -1,231 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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" }
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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()
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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" }
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model.sources
|
||||
|
||||
abstract class PositionSource {
|
||||
abstract val type: String
|
||||
}
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model.sources
|
||||
|
||||
abstract class RollSource {
|
||||
abstract val type: String
|
||||
}
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model.sources
|
||||
|
||||
abstract class RotationSource {
|
||||
abstract val type: String
|
||||
}
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model.sources
|
||||
|
||||
abstract class ShotModifier {
|
||||
abstract val type: String
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
|
||||
|
||||
/** Offset is world-space and ignores actor orientation. */
|
||||
data class FollowActorPosition(
|
||||
val actorId: String,
|
||||
val offset: Vec3,
|
||||
val fallback: Vec3 = Vec3.ZERO
|
||||
) : PositionSource() {
|
||||
override val type: String = TYPE
|
||||
|
||||
init {
|
||||
require(listOf(offset.x, offset.y, offset.z, fallback.x, fallback.y, fallback.z).all { it.isFinite() }) {
|
||||
"FollowActorPosition offset and fallback must be finite"
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TYPE = "follow_actor"
|
||||
fun fromJson(obj: JsonObject): FollowActorPosition {
|
||||
val o = obj.getAsJsonObject("offset")
|
||||
val fObj = obj.getAsJsonObject("fallback")
|
||||
return FollowActorPosition(
|
||||
actorId = obj.get("actorId").asString,
|
||||
offset = Vec3(o.get("x").asDouble, o.get("y").asDouble, o.get("z").asDouble),
|
||||
fallback = if (fObj != null) Vec3(fObj.get("x").asDouble, fObj.get("y").asDouble, fObj.get("z").asDouble) else Vec3.ZERO
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cinematic.model.sources.builtin
|
||||
|
||||
import com.cobblemon.mod.common.api.cinematic.model.sources.FovSource
|
||||
import com.cobblemon.mod.common.api.cinematic.model.orderedKeyframes
|
||||
import com.google.gson.JsonObject
|
||||
|
||||
data class KeyframeFov(val keyframes: List<Kf>) : FovSource() {
|
||||
override val type: String = TYPE
|
||||
|
||||
data class Kf(val time: Float, val fov: Float)
|
||||
|
||||
init {
|
||||
keyframes.forEach { require(it.fov in 1f..179f) { "Fov must be in [1, 179], got ${it.fov}" } }
|
||||
}
|
||||
|
||||
@Transient private val playbackKeyframes = orderedKeyframes(keyframes) { it.time }
|
||||
|
||||
fun evaluate(time: Float): Float {
|
||||
val keyframes = playbackKeyframes
|
||||
if (keyframes.size == 1) return keyframes[0].fov
|
||||
if (time <= keyframes.first().time) return keyframes.first().fov
|
||||
if (time >= keyframes.last().time) return keyframes.last().fov
|
||||
for (i in 0 until keyframes.size - 1) {
|
||||
val a = keyframes[i]
|
||||
val b = keyframes[i + 1]
|
||||
if (time >= a.time && time <= b.time) {
|
||||
val d = b.time - a.time
|
||||
val t = if (d > 0f) (time - a.time) / d else 0f
|
||||
return a.fov + (b.fov - a.fov) * t
|
||||
}
|
||||
}
|
||||
return keyframes.last().fov
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TYPE = "keyframe"
|
||||
fun fromJson(obj: JsonObject): KeyframeFov {
|
||||
val kfs = obj.getAsJsonArray("keyframes").map { el ->
|
||||
val k = el.asJsonObject
|
||||
Kf(time = k.get("time").asFloat, fov = k.get("fov").asFloat)
|
||||
}
|
||||
return KeyframeFov(kfs)
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user