mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-11-03 23:08:53 -05:00
Compare commits
143
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
433a66124b | ||
|
|
4209ca3845 | ||
|
|
6edd81c0f5 | ||
|
|
7939b4ca71 | ||
|
|
0cc22b6675 | ||
|
|
0405eea167 | ||
|
|
17d07774d2 | ||
|
|
d71373c237 | ||
|
|
a0e732dc6e | ||
|
|
ea20c2aa4c | ||
|
|
da5272c473 | ||
|
|
a785e574e0 | ||
|
|
4b236b0268 | ||
|
|
1cd86ae5d6 | ||
|
|
b7489a0b14 | ||
|
|
f7554425dc | ||
|
|
858d2e908a | ||
|
|
b61e0b0c82 | ||
|
|
4d9a6e71c9 | ||
|
|
a0010de504 | ||
|
|
cb73a30e23 | ||
|
|
9a7536b068 | ||
|
|
bd973e702e | ||
|
|
ede1851d34 | ||
|
|
cdb8ee0d8e | ||
|
|
e7d86a382c | ||
|
|
eb911df830 | ||
|
|
1c30acc53c | ||
|
|
32b0699235 | ||
|
|
e9c6580230 | ||
|
|
f893eb48fd | ||
|
|
232e2f18bf | ||
|
|
c266c99710 | ||
|
|
2a0e8f6d47 | ||
|
|
e6bd8ec529 | ||
|
|
911a95e873 | ||
|
|
447cfc2ae5 | ||
|
|
8dfeb0d260 | ||
|
|
caa7b19833 | ||
|
|
64dd8ae193 | ||
|
|
156ee6f290 | ||
|
|
fe433d1417 | ||
|
|
0dc662d295 | ||
|
|
081e370bfd | ||
|
|
3ef0567287 | ||
|
|
3cad9e5481 | ||
|
|
dc8b7908be | ||
|
|
85085a1eca | ||
|
|
bff59dee6e | ||
|
|
bb5828531a | ||
|
|
cd08e98c28 | ||
|
|
331f7ca425 | ||
|
|
71c9ac0ff0 | ||
|
|
1404cc0ab5 | ||
|
|
6ca908a91d | ||
|
|
0948b8da9a | ||
|
|
22e04a53b3 | ||
|
|
df3217b41b | ||
|
|
9ff15a1913 | ||
|
|
ca58801794 | ||
|
|
38fa5e2628 | ||
|
|
fae1ae7124 | ||
|
|
3ec5f76c73 | ||
|
|
5bb8aaba55 | ||
|
|
23ba41e981 | ||
|
|
29b049452b | ||
|
|
0b0f665804 | ||
|
|
5d53fba2ce | ||
|
|
14cc851562 | ||
|
|
7223d1fd68 | ||
|
|
75f52e4cf4 | ||
|
|
55446dd4b1 | ||
|
|
8b825d558f | ||
|
|
9a7f97f11f | ||
|
|
95b8d62e4a | ||
|
|
4354c3fb03 | ||
|
|
f25a676bd5 | ||
|
|
a9906762a0 | ||
|
|
7b5b88eca2 | ||
|
|
291682ba52 | ||
|
|
546d403b45 | ||
|
|
c9f40e32a1 | ||
|
|
d642b8dd07 | ||
|
|
549a11116e | ||
|
|
b5468a4a4f | ||
|
|
c5d278ccb7 | ||
|
|
bf5e15de45 | ||
|
|
f4af417267 | ||
|
|
69c04acaeb | ||
|
|
83a6bb188f | ||
|
|
494a8b5e91 | ||
|
|
c8021f2f08 | ||
|
|
8cdf3af047 | ||
|
|
c90a24e1ab | ||
|
|
83e3cfc34e | ||
|
|
133dd4e5b7 | ||
|
|
a8cca14b86 | ||
|
|
9b0f356fa4 | ||
|
|
f2b0a102b6 | ||
|
|
a7d01b230a | ||
|
|
2a7db4b9b8 | ||
|
|
77e5f2501d | ||
|
|
fc2335f5d5 | ||
|
|
e6513717bd | ||
|
|
0e0c98f693 | ||
|
|
528bfa4e22 | ||
|
|
83c87779d7 | ||
|
|
dc33235144 | ||
|
|
7d8329b311 | ||
|
|
9b46757d14 | ||
|
|
935c658c5f | ||
|
|
0426f4fbf9 | ||
|
|
fe5970180d | ||
|
|
89b81d6882 | ||
|
|
46e771a062 | ||
|
|
4c0095844b | ||
|
|
10a2ef27d6 | ||
|
|
3c7637515c | ||
|
|
0a5abdb331 | ||
|
|
4ed7413dd2 | ||
|
|
40b66c24fc | ||
|
|
20a35de3d8 | ||
|
|
2eb6042d06 | ||
|
|
5ec2fc7937 | ||
|
|
f57093b835 | ||
|
|
03bb782dc4 | ||
|
|
d296fa81dc | ||
|
|
1621bada06 | ||
|
|
873ccc8109 | ||
|
|
eb4257cc26 | ||
|
|
dfcb988f1e | ||
|
|
2ca2a77333 | ||
|
|
b468e4eb6c | ||
|
|
c39397413f | ||
|
|
b3fe03194a | ||
|
|
d2eafe7b41 | ||
|
|
7f78c15f6b | ||
|
|
0cd1f8a2fd | ||
|
|
d6c2da3d90 | ||
|
|
ba84883eae | ||
|
|
fcfdfb270d | ||
|
|
96d1d9d552 | ||
|
|
0d1de548a0 |
No files matched your search
@@ -157,6 +157,9 @@ build:
|
||||
paths:
|
||||
- neoforge/build/libs
|
||||
- fabric/build/libs
|
||||
exclude:
|
||||
- neoforge/build/libs/*-dev-shadow.jar
|
||||
- fabric/build/libs/*-dev-shadow.jar
|
||||
|
||||
publish:
|
||||
stage: deploy
|
||||
|
||||
+59
-6
@@ -7,38 +7,91 @@
|
||||
- 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:
|
||||
- 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
|
||||
#### Generation 4
|
||||
- Snover
|
||||
- Abomasnow
|
||||
- Burmy
|
||||
- Wormadam
|
||||
- Mothim
|
||||
|
||||
#### Regional Forms
|
||||
#### Generation 5
|
||||
- Tympole
|
||||
- Palpitoad
|
||||
- Seismitoad
|
||||
|
||||
#### Generation 6
|
||||
- Helioptile
|
||||
- Heliolisk
|
||||
|
||||
#### Generation 7
|
||||
- Grubbin
|
||||
- Charjabug
|
||||
- Vikavolt
|
||||
|
||||
#### Generation 9
|
||||
- Greavard
|
||||
- Houndstone
|
||||
|
||||
### Model updates for the following Pokémon
|
||||
- Cacnea
|
||||
- Cacturne
|
||||
- Binacle
|
||||
- Barbaracle
|
||||
- Glimmet
|
||||
- Glimmora
|
||||
- Deerling
|
||||
- Sawsbuck (All forms)
|
||||
- Absol
|
||||
|
||||
### Animation updates for the following Pokémon
|
||||
|
||||
#### Added sounds to the following moves
|
||||
- Cacnea
|
||||
- Cacturne
|
||||
|
||||
### 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
|
||||
- Make ride rotations less jittery in multiplayer.
|
||||
- Changes tm shelf discs to use textures instead of tinting and overlays to line up with item display
|
||||
- Blank TM can now be inserted into the Disc Shelf
|
||||
|
||||
### Fixes
|
||||
- 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
|
||||
- Type Gem blocks now properly generate clusters off of the block.
|
||||
- Starter Screen Categories will no longer stop rendering if they are bigger than the viewport, and you are not viewing top or bottom edges
|
||||
- Random Starter option now properly handled in height calculation, so now it won't run off into other categories or be un-accessible due to scroll limits if it causes a new row
|
||||
- Mochi and Feathers no longer drop glass bottles on use
|
||||
- Fixed a rare set of concurrency bugs related to reloading packs on NeoForge; fixes a ModernFix issue
|
||||
- Removed unnecessary conditions for Mimikyu's standing pose. Hopefully fixes the rare instance of it using its shoulder animations during battle in multiplayer scenarios.
|
||||
- Fixed Rockruff line not blinking
|
||||
- Fixed Flygon sometimes using its running animation instead of walking
|
||||
- Fixed Bramblin always sleeping outside of battle
|
||||
- Fixed Dragonair using its battle idle as a normal idle
|
||||
- Fixed Lycanroc's head movement
|
||||
- Added head movement to Archaludon
|
||||
- Fixed Duraludon line not having any sleep animations
|
||||
- Fixed Diglett line not having their faint animations
|
||||
- Fixed Kingambit moving its legs while walking
|
||||
- Various Structure fixes
|
||||
- Fixed shiny pokemon under certain circumstances forgetting taught TMs
|
||||
|
||||
### Developer
|
||||
- Fixed wrong order of operations in the code flow prior to the `FOSSIL_REVIVED` event causing pokemon to appear without entity link
|
||||
- Fixed TestPartySlot command not correctly comparing the provided spec with the target Pokémon
|
||||
|
||||
### Molang & Datapacks
|
||||
- A new `negate` variant for evolution requirements has been added, which will negate (invert) the provided inner condition.
|
||||
- Added Molang functions for individual Pokédex ids, wherein a subdex is passed in as a string to `dex_caught_count` etc.
|
||||
|
||||
### Particles
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
- Some kind of particle effect for them? they're meant to have glowing eyes, so maybe some red particles on the eye locator
|
||||
--- global posers? stacked posers?
|
||||
--- red texture seems to be what some people wanted.
|
||||
|
||||
/- shoulder mounts part of it
|
||||
- omni boost
|
||||
- roar when player comes within reach, adjust levels
|
||||
|
||||
- Riding settings to control what the min scale is for a pokemon to be ridable.
|
||||
+5
-2
@@ -1,3 +1,6 @@
|
||||
import utilities.gitBranch
|
||||
import utilities.gitShortCommit
|
||||
|
||||
plugins {
|
||||
id("cobblemon.root-conventions")
|
||||
}
|
||||
@@ -6,6 +9,6 @@ version = "${project.property("mod_version")}+${project.property("mc_version")}"
|
||||
|
||||
val isSnapshot = project.property("snapshot")?.equals("true") == true
|
||||
if (isSnapshot) {
|
||||
val fixedBranchName = versioning.info.branch.substringAfter("/")
|
||||
version = "$version-${fixedBranchName}-${versioning.info.build}"
|
||||
val fixedBranchName = gitBranch().substringAfter("/")
|
||||
version = "$version-${fixedBranchName}-${gitShortCommit()}"
|
||||
}
|
||||
+15
-6
@@ -1,9 +1,8 @@
|
||||
|
||||
import utilities.isSnapshot
|
||||
import utilities.version
|
||||
import java.time.OffsetDateTime
|
||||
import java.time.ZoneOffset
|
||||
import java.time.format.DateTimeFormatter
|
||||
import utilities.gitBranch
|
||||
import utilities.gitCommit
|
||||
|
||||
/*
|
||||
*
|
||||
@@ -72,6 +71,14 @@ tasks.withType<Test> {
|
||||
}
|
||||
}
|
||||
|
||||
// Git info lives in its own output dir (not processResources) so a new commit only rewrites this one file.
|
||||
val writeGitInfo by tasks.registering(WriteProperties::class) {
|
||||
destinationFile = layout.buildDirectory.file("generated/gitInfo/cobblemon-git.properties")
|
||||
property("commit", gitCommit())
|
||||
property("branch", gitBranch())
|
||||
}
|
||||
sourceSets.main { output.dir(mapOf("builtBy" to writeGitInfo), layout.buildDirectory.dir("generated/gitInfo")) }
|
||||
|
||||
tasks.processResources {
|
||||
exclude("data/**/README.md")
|
||||
}
|
||||
@@ -98,11 +105,13 @@ sourceSets {
|
||||
property("modid", "cobblemon")
|
||||
property("version", project.version())
|
||||
property("isSnapshot", if(rootProject.isSnapshot()) "true" else "false")
|
||||
property("gitCommit", versioning.info.commit)
|
||||
property("branch", versioning.info.branch)
|
||||
System.getProperty("buildNumber")?.let { property("buildNumber", it) }
|
||||
property("timestamp", OffsetDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss")) + " UTC")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The platform jars are built from :common:jar, so the remapped common jars are only needed by `publish`
|
||||
tasks.assemble {
|
||||
setDependsOn(dependsOn.filterNot { (it as? TaskProvider<*>)?.name in setOf("remapJar", "remapSourcesJar") })
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 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.duck.biome;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface BiomeSourceDuck {
|
||||
void addPossibleBiomes(List<Holder<Biome>> biomes);
|
||||
}
|
||||
@@ -8,14 +8,21 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.duck.MinecraftServerDuck;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.minecraft.core.LayeredRegistryAccess;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.RegistryLayer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.Level;
|
||||
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 java.util.Map;
|
||||
import java.util.Optional;
|
||||
@@ -23,18 +30,41 @@ import java.util.Optional;
|
||||
@Mixin(MinecraftServer.class)
|
||||
public class MinecraftServerMixin implements MinecraftServerDuck {
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private Map<ResourceKey<Level>, ServerLevel> levels;
|
||||
@Shadow
|
||||
@Final
|
||||
private Map<ResourceKey<Level>, ServerLevel> levels;
|
||||
|
||||
@Override
|
||||
public Optional<ResourceKey<Level>> cobblemon$getLevelKey(final Level level) {
|
||||
return this.levels.entrySet()
|
||||
.stream()
|
||||
// Reference equality is intended here, the level we're handed is the same one as in the
|
||||
// map so we don't need to check value semantics.
|
||||
.filter(entry -> entry.getValue() == level)
|
||||
.map(Map.Entry::getKey)
|
||||
.findFirst();
|
||||
}
|
||||
@Override
|
||||
public Optional<ResourceKey<Level>> cobblemon$getLevelKey(final Level level) {
|
||||
return this.levels.entrySet()
|
||||
.stream()
|
||||
// Reference equality is intended here, the level we're handed is the same one as in the
|
||||
// map so we don't need to check value semantics.
|
||||
.filter(entry -> entry.getValue() == level)
|
||||
.map(Map.Entry::getKey)
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wraps the earliest {@code compositeAccess()} call in {@link MinecraftServer}'s constructor
|
||||
* so Cobblemon can capture the server registry access as soon as it exists.
|
||||
*
|
||||
* <p>This sets {@link Cobblemon#registryAccess} before downstream initialization
|
||||
* depends on biome lookups, while still delegating to the original call unchanged.</p>
|
||||
*
|
||||
* @author MeAlam
|
||||
* @since April 9th 2026
|
||||
*/
|
||||
@WrapOperation(method = "<init>", at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/core/LayeredRegistryAccess;compositeAccess()Lnet/minecraft/core/RegistryAccess$Frozen;",
|
||||
ordinal = 0
|
||||
))
|
||||
private RegistryAccess.Frozen cobblemon$captureRegistryAccess
|
||||
(LayeredRegistryAccess<RegistryLayer> instance, Operation<RegistryAccess.Frozen> original) {
|
||||
Cobblemon.registryAccess = instance.compositeAccess();
|
||||
|
||||
return original.call(instance);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.biome;
|
||||
|
||||
|
||||
import net.minecraft.data.worldgen.BootstrapContext;
|
||||
import net.minecraft.data.worldgen.biome.BiomeData;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
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;
|
||||
|
||||
/**
|
||||
* TODO (MeAlam):<br>
|
||||
* This mixin is currently disabled, as it does not appear to be required at this time.
|
||||
* It is retained for potential future use if biome registration issues arise.
|
||||
*
|
||||
* <p>
|
||||
* When enabled, this mixin registers biomes into the bootstrap context
|
||||
* of Minecraft's {@code BiomeData} class.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Example usage:
|
||||
* <pre>{@code
|
||||
* context.register(MY_BIOME_KEY, createMyBiome());
|
||||
*
|
||||
* // e.g.
|
||||
* context.register(
|
||||
* CobblemonBiomes.TEST_BIOME,
|
||||
* CobblemonBiomes.createTestBiome()
|
||||
* );
|
||||
* }</pre>
|
||||
*
|
||||
* @author MeAlam
|
||||
* @since April 9th 2026
|
||||
*/
|
||||
@Mixin(BiomeData.class)
|
||||
public class BiomeDataMixin {
|
||||
@Inject(method = "bootstrap", at = @At("TAIL"))
|
||||
private static void cobblemon$registerBiomes(BootstrapContext<Biome> context, CallbackInfo ci) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.biome;
|
||||
|
||||
import com.cobblemon.mod.common.duck.biome.BiomeSourceDuck;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeResolver;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* TODO (MeAlam):<br>
|
||||
* This mixin is currently disabled, as it does not appear to be required at this time.
|
||||
* It is retained for potential future use if biome injection becomes necessary.
|
||||
*
|
||||
* <p>
|
||||
* When enabled, this mixin extends the {@code BiomeSource} by modifying the
|
||||
* {@code possibleBiomes} supplier to include additional biomes at runtime.
|
||||
* It merges existing biomes with new ones while ensuring uniqueness.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Example usage:
|
||||
* <pre>{@code
|
||||
* ((BiomeSourceDuck) biomeSource).addPossibleBiomes(List.of(
|
||||
* biomeHolderA,
|
||||
* biomeHolderB
|
||||
* ));
|
||||
*
|
||||
* // Existing and new biomes are merged with duplicates removed.
|
||||
* }</pre>
|
||||
*
|
||||
* @author MeAlam
|
||||
* @since April 9th 2026
|
||||
*/
|
||||
@Mixin(BiomeSource.class)
|
||||
public abstract class BiomeSourceMixin implements BiomeResolver, BiomeSourceDuck {
|
||||
@Mutable
|
||||
@Final
|
||||
@Shadow
|
||||
private Supplier<Set<Holder<Biome>>> possibleBiomes;
|
||||
|
||||
@Override
|
||||
public void addPossibleBiomes(List<Holder<Biome>> biomes) {
|
||||
List<Holder<Biome>> combined = new ArrayList<>();
|
||||
combined.addAll(this.possibleBiomes.get());
|
||||
combined.addAll(biomes);
|
||||
|
||||
this.possibleBiomes = () -> new ObjectLinkedOpenHashSet<>(combined.stream().distinct().collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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.biome;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.util.biome.RegistryExtensions;
|
||||
import com.cobblemon.mod.common.world.biome.CobblemonBiome;
|
||||
import com.cobblemon.mod.common.world.biome.CobblemonBiomeLoader;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.HolderGetter;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.biome.*;
|
||||
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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Ensures compatibility with Biolith by applying this mixin before its biome modifications.
|
||||
*
|
||||
* <p>
|
||||
* Biolith uses mixins (see
|
||||
* <a href="https://github.com/TerraformersMC/Biolith/blob/1.21.1/common/src/main/java/com/terraformersmc/biolith/impl/mixin/MixinMultiNoiseBiomeSource.java">
|
||||
* MixinMultiNoiseBiomeSource
|
||||
* </a>)
|
||||
* with a priority of {@code 900}, allowing it to run before Terrablender.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Because Biolith includes functionality to disable vanilla biomes, this mixin must
|
||||
* execute before Biolith’s transformations to ensure compatibility and prevent
|
||||
* unintended biome removal or conflicts.
|
||||
* </p>
|
||||
*
|
||||
* @author MeAlam
|
||||
* @since April 9th 2026
|
||||
*/
|
||||
@Mixin(value = MultiNoiseBiomeSource.class, priority = 850)
|
||||
public abstract class MultiNoiseBiomeSourceMixin extends BiomeSource {
|
||||
|
||||
@Shadow
|
||||
protected abstract Climate.ParameterList<Holder<Biome>> parameters();
|
||||
|
||||
@Unique
|
||||
private Climate.ParameterList<Holder.Reference<Biome>> cobblemon$parameters;
|
||||
|
||||
@WrapOperation(
|
||||
method = "parameters",
|
||||
at = @At(value = "INVOKE", target = "Lcom/mojang/datafixers/util/Either;map(Ljava/util/function/Function;Ljava/util/function/Function;)Ljava/lang/Object;"),
|
||||
remap = false
|
||||
)
|
||||
private Object cobblemon$injectBiomes(
|
||||
Either<Climate.ParameterList<RegistryAccess.RegistryEntry<Biome>>,
|
||||
RegistryAccess.RegistryEntry<MultiNoiseBiomeSourceParameterList>> instance,
|
||||
Function<Climate.ParameterList<RegistryAccess.RegistryEntry<Biome>>,
|
||||
Climate.ParameterList<RegistryAccess.RegistryEntry<Biome>>> leftMap,
|
||||
Function<RegistryAccess.RegistryEntry<MultiNoiseBiomeSourceParameterList>,
|
||||
Climate.ParameterList<RegistryAccess.RegistryEntry<Biome>>> rightMap,
|
||||
Operation<Object> original) {
|
||||
synchronized (this) {
|
||||
if (cobblemon$parameters == null) {
|
||||
/* NOTE:
|
||||
* Minecraft also does this exact cast on the return of this operation, so we know it's safe.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
Climate.ParameterList<Holder.Reference<Biome>> originalEntries =
|
||||
(Climate.ParameterList<Holder.Reference<Biome>>) original.call(instance, leftMap, rightMap);
|
||||
|
||||
Map<ResourceLocation, CobblemonBiome> loadedBiomes = CobblemonBiomeLoader.getLoadedBiomes();
|
||||
List<Pair<Climate.ParameterPoint, Holder.Reference<Biome>>> parameterList =
|
||||
new ArrayList<>(originalEntries.values().size() + loadedBiomes.size());
|
||||
parameterList.addAll(originalEntries.values());
|
||||
|
||||
HolderGetter<Biome> biomeEntryGetter = RegistryExtensions.getRegistryLookup(Registries.BIOME).orElseThrow();
|
||||
int appended = 0;
|
||||
int skipped = 0;
|
||||
|
||||
for (Map.Entry<ResourceLocation, CobblemonBiome> loadedEntry : loadedBiomes.entrySet()) {
|
||||
ResourceKey<Biome> biomeKey = ResourceKey.create(Registries.BIOME, loadedEntry.getKey());
|
||||
Optional<Holder.Reference<Biome>> biomeHolder = biomeEntryGetter.get(biomeKey);
|
||||
|
||||
if (biomeHolder.isEmpty()) {
|
||||
skipped++;
|
||||
Cobblemon.LOGGER.warn("MEALAM Skipping cobblemon biome climate entry for missing biome {}", loadedEntry.getKey());
|
||||
continue;
|
||||
}
|
||||
|
||||
parameterList.add(new Pair<>(loadedEntry.getValue().getParameters(), biomeHolder.get()));
|
||||
appended++;
|
||||
}
|
||||
|
||||
Cobblemon.LOGGER.info(
|
||||
"MEALAM Biome source climate entries: base={}, appended={}, skipped={}.",
|
||||
originalEntries.values().size(),
|
||||
appended,
|
||||
skipped
|
||||
);
|
||||
|
||||
cobblemon$parameters = new Climate.ParameterList<>(parameterList);
|
||||
}
|
||||
return cobblemon$parameters;
|
||||
}
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.biome;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.CobblemonBiomes;
|
||||
import com.cobblemon.mod.common.world.biome.CobblemonBiomeLoader;
|
||||
import com.mojang.serialization.Decoder;
|
||||
import net.minecraft.core.WritableRegistry;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.RegistryDataLoader;
|
||||
import net.minecraft.resources.RegistryOps;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
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.Map;
|
||||
|
||||
/**
|
||||
* Registers Cobblemon biomes during datapack registry loading.
|
||||
*
|
||||
* <p>Injected into {@link RegistryDataLoader} at the tail of
|
||||
* {@code loadContentsFromManager}.</p>
|
||||
*
|
||||
* <p>At this point, vanilla biome JSON has already been decoded, but registries are not frozen
|
||||
* yet, making this the safest point to add biome entries.</p>
|
||||
*
|
||||
* <p>Only applies when the currently loaded registry is {@link Registries#BIOME}.</p>
|
||||
*
|
||||
* @author MeAlam
|
||||
* @since April 9th 2026
|
||||
*/
|
||||
@Mixin(RegistryDataLoader.class)
|
||||
public class RegistryDataLoaderMixin {
|
||||
@Inject(method = "loadContentsFromManager", at = @At("TAIL"))
|
||||
private static <E> void cobblemon$registerBiomes(
|
||||
ResourceManager resourceManager,
|
||||
RegistryOps.RegistryInfoLookup registryInfoLookup,
|
||||
WritableRegistry<E> registry,
|
||||
Decoder<E> codec,
|
||||
Map<ResourceKey<?>, Exception> loadingErrors,
|
||||
CallbackInfo ci
|
||||
) {
|
||||
if (!registry.key().equals(Registries.BIOME)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
WritableRegistry<Biome> biomeRegistry = (WritableRegistry<Biome>) registry;
|
||||
|
||||
CobblemonBiomes.register(
|
||||
CobblemonBiomeLoader.load(resourceManager, registryInfoLookup)
|
||||
);
|
||||
CobblemonBiomes.INSTANCE.setRegistry(biomeRegistry);
|
||||
Cobblemon.implementation.registerBiomes();
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,12 @@ object CobblemonBuildDetails {
|
||||
const val VERSION = "{{ version }}"
|
||||
const val SNAPSHOT = {{ isSnapshot }}
|
||||
|
||||
const val GIT_COMMIT = "{{ gitCommit | default("Not Specified") }}"
|
||||
const val BRANCH = "{{ branch | default("Not Specified") }}"
|
||||
// Read at runtime rather than templated in, so a new commit doesn't invalidate compiled code.
|
||||
private val git = java.util.Properties().apply {
|
||||
CobblemonBuildDetails::class.java.getResourceAsStream("/cobblemon-git.properties")?.use(::load)
|
||||
}
|
||||
@JvmField val GIT_COMMIT: String = git.getProperty("commit", "Not Specified")
|
||||
@JvmField val BRANCH: String = git.getProperty("branch", "Not Specified")
|
||||
|
||||
fun smallCommitHash(): String {
|
||||
return this.GIT_COMMIT.substring(0, 7)
|
||||
|
||||
@@ -137,6 +137,7 @@ import kotlin.reflect.jvm.isAccessible
|
||||
import kotlin.reflect.jvm.javaField
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.commands.synchronization.SingletonArgumentInfo
|
||||
import net.minecraft.core.RegistryAccess
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
@@ -182,7 +183,10 @@ object Cobblemon {
|
||||
var seasonResolver: SeasonResolver = TagSeasonResolver
|
||||
var wallpapers = mutableMapOf<UUID, Set<ResourceLocation>>()
|
||||
|
||||
val serverPlayerStructs = mutableMapOf<UUID, ObjectValue<Player>>()
|
||||
@JvmField
|
||||
var registryAccess: RegistryAccess.Frozen = RegistryAccess.EMPTY
|
||||
|
||||
val serverPlayerStructs = mutableMapOf<UUID, ObjectValue<Player>>()
|
||||
|
||||
val statistics: CobblemonStats = CobblemonStats
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import com.cobblemon.mod.common.world.biome.CobblemonBiome
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.level.biome.Biome
|
||||
|
||||
object CobblemonBiomes : PlatformRegistry<Registry<Biome>, ResourceKey<Registry<Biome>>, Biome>() {
|
||||
override var registry: Registry<Biome>? = null
|
||||
override val resourceKey: ResourceKey<Registry<Biome>> = Registries.BIOME
|
||||
|
||||
@JvmField
|
||||
val TEST_BIOME: ResourceKey<Biome> = registerKey("test_biome")
|
||||
|
||||
@JvmStatic
|
||||
fun register(data: Map<ResourceLocation, CobblemonBiome>) {
|
||||
data.forEach { (identifier, cobblemonBiome) ->
|
||||
create(identifier, cobblemonBiome.biome)
|
||||
}
|
||||
}
|
||||
|
||||
private fun registerKey(key: String): ResourceKey<Biome> {
|
||||
return ResourceKey.create(Registries.BIOME, cobblemonResource(key))
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
|
||||
object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, ResourceKey<Registry<BlockEntityType<*>>>, BlockEntityType<*>>() {
|
||||
|
||||
override val registry: Registry<BlockEntityType<*>> = BuiltInRegistries.BLOCK_ENTITY_TYPE
|
||||
override var registry: Registry<BlockEntityType<*>>? = BuiltInRegistries.BLOCK_ENTITY_TYPE
|
||||
override val resourceKey: ResourceKey<Registry<BlockEntityType<*>>> = Registries.BLOCK_ENTITY_TYPE
|
||||
|
||||
@JvmField
|
||||
|
||||
@@ -59,7 +59,7 @@ import net.minecraft.world.level.material.PushReaction
|
||||
@Suppress("SameParameterValue", "HasPlatformType", "MemberVisibilityCanBePrivate", "unused")
|
||||
object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<Block>>, Block>() {
|
||||
|
||||
override val registry: Registry<Block> = BuiltInRegistries.BLOCK
|
||||
override var registry: Registry<Block>? = BuiltInRegistries.BLOCK
|
||||
override val resourceKey: ResourceKey<Registry<Block>> = Registries.BLOCK
|
||||
|
||||
val APRICORN_BLOCK_SET_TYPE = BlockSetType("apricorn")
|
||||
|
||||
@@ -30,7 +30,7 @@ import net.minecraft.world.entity.ai.attributes.AttributeSupplier
|
||||
object CobblemonEntities : PlatformRegistry<Registry<EntityType<*>>, ResourceKey<Registry<EntityType<*>>>, EntityType<*>>() {
|
||||
|
||||
|
||||
override val registry: Registry<EntityType<*>> = BuiltInRegistries.ENTITY_TYPE
|
||||
override var registry: Registry<EntityType<*>>? = BuiltInRegistries.ENTITY_TYPE
|
||||
override val resourceKey: ResourceKey<Registry<EntityType<*>>> = Registries.ENTITY_TYPE
|
||||
|
||||
@JvmField
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.mojang.brigadier.arguments.ArgumentType
|
||||
import kotlin.reflect.KClass
|
||||
import net.minecraft.commands.synchronization.ArgumentTypeInfo
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.MinecraftServer
|
||||
@@ -122,6 +123,8 @@ interface CobblemonImplementation {
|
||||
* TODO
|
||||
*/
|
||||
fun registerMobEffects()
|
||||
|
||||
fun registerBiomes()
|
||||
|
||||
|
||||
/**
|
||||
@@ -168,12 +171,16 @@ interface CobblemonImplementation {
|
||||
* TODO
|
||||
*
|
||||
* @param identifier
|
||||
* @param reloader
|
||||
* @param reloaderFactory
|
||||
* @param type
|
||||
* @param dependencies
|
||||
*/
|
||||
fun registerResourceReloader(identifier: ResourceLocation, reloader: PreparableReloadListener, type: PackType, dependencies: Collection<ResourceLocation>)
|
||||
|
||||
fun registerResourceReloader(
|
||||
identifier: ResourceLocation,
|
||||
type: PackType,
|
||||
dependencies: Collection<ResourceLocation>,
|
||||
reloaderFactory: (HolderLookup.Provider) -> PreparableReloadListener
|
||||
)
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
|
||||
@@ -114,7 +114,7 @@ object CobblemonItemComponents : PlatformRegistry<Registry<DataComponentType<*>>
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:held_item_effect"), HELD_ITEM_EFFECT)
|
||||
}
|
||||
|
||||
override val registry = BuiltInRegistries.DATA_COMPONENT_TYPE
|
||||
override var registry = BuiltInRegistries.DATA_COMPONENT_TYPE
|
||||
override val resourceKey = Registries.DATA_COMPONENT_TYPE
|
||||
|
||||
}
|
||||
@@ -68,7 +68,7 @@ import net.minecraft.world.level.block.Block
|
||||
|
||||
@Suppress("unused", "SameParameterValue")
|
||||
object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<Item>>, Item>() {
|
||||
override val registry: Registry<Item> = BuiltInRegistries.ITEM
|
||||
override var registry: Registry<Item>? = BuiltInRegistries.ITEM
|
||||
override val resourceKey: ResourceKey<Registry<Item>> = Registries.ITEM
|
||||
|
||||
@JvmField
|
||||
|
||||
@@ -23,8 +23,7 @@ object CobblemonMenuType : PlatformRegistry<Registry<MenuType<*>>, ResourceKey<R
|
||||
val COOKING_POT = MenuType.register("cooking_pot_menu", ::CookingPotMenu)
|
||||
val TM_MACHINE = MenuType.register("tm_machine_menu", ::TMMachineMenu)
|
||||
|
||||
override val registry: Registry<MenuType<*>>
|
||||
get() = BuiltInRegistries.MENU
|
||||
override var registry: Registry<MenuType<*>>? = BuiltInRegistries.MENU
|
||||
override val resourceKey: ResourceKey<Registry<MenuType<*>>>
|
||||
get() = Registries.MENU
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
|
||||
object CobblemonMobEffects : PlatformRegistry<Registry<MobEffect>, ResourceKey<Registry<MobEffect>>, MobEffect>() {
|
||||
override val registry: Registry<MobEffect> = BuiltInRegistries.MOB_EFFECT
|
||||
override var registry: Registry<MobEffect>? = BuiltInRegistries.MOB_EFFECT
|
||||
override val resourceKey: ResourceKey<Registry<MobEffect>> = Registries.MOB_EFFECT
|
||||
|
||||
@JvmField
|
||||
|
||||
@@ -20,7 +20,7 @@ import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
|
||||
object CobblemonPoiTypes: PlatformRegistry<Registry<PoiType>, ResourceKey<Registry<PoiType>>, PoiType>() {
|
||||
override val registry: Registry<PoiType> = BuiltInRegistries.POINT_OF_INTEREST_TYPE
|
||||
override var registry: Registry<PoiType>? = BuiltInRegistries.POINT_OF_INTEREST_TYPE
|
||||
override val resourceKey: ResourceKey<Registry<PoiType>> = Registries.POINT_OF_INTEREST_TYPE
|
||||
|
||||
@JvmField
|
||||
|
||||
@@ -27,8 +27,7 @@ object CobblemonRecipeSerializers : PlatformRegistry<Registry<RecipeSerializer<*
|
||||
|
||||
val BREWING_STAND: RecipeSerializer<*> = register("cobblemon:brewing_stand", BrewingStandRecipe.Serializer())
|
||||
|
||||
override val registry: Registry<RecipeSerializer<*>>
|
||||
get() = BuiltInRegistries.RECIPE_SERIALIZER
|
||||
override var registry: Registry<RecipeSerializer<*>>? = BuiltInRegistries.RECIPE_SERIALIZER
|
||||
override val resourceKey: ResourceKey<Registry<RecipeSerializer<*>>>
|
||||
get() = Registries.RECIPE_SERIALIZER
|
||||
|
||||
|
||||
@@ -27,8 +27,7 @@ object CobblemonRecipeTypes : PlatformRegistry<Registry<RecipeType<*>>, Resource
|
||||
|
||||
val BREWING_STAND: RecipeType<BrewingStandRecipe> = register("cobblemon:brewing_stand")
|
||||
|
||||
override val registry: Registry<RecipeType<*>>
|
||||
get() = BuiltInRegistries.RECIPE_TYPE
|
||||
override var registry: Registry<RecipeType<*>>? = BuiltInRegistries.RECIPE_TYPE
|
||||
override val resourceKey: ResourceKey<Registry<RecipeType<*>>>
|
||||
get() = Registries.RECIPE_TYPE
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import net.minecraft.world.level.block.SoundType
|
||||
|
||||
object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Registry<SoundEvent>>, SoundEvent>() {
|
||||
|
||||
override val registry: Registry<SoundEvent> = BuiltInRegistries.SOUND_EVENT
|
||||
override var registry: Registry<SoundEvent>? = BuiltInRegistries.SOUND_EVENT
|
||||
override val resourceKey: ResourceKey<Registry<SoundEvent>> = Registries.SOUND_EVENT
|
||||
|
||||
@JvmField
|
||||
|
||||
@@ -20,7 +20,7 @@ import net.minecraft.world.entity.ai.village.poi.PoiType
|
||||
import net.minecraft.world.entity.npc.VillagerProfession
|
||||
|
||||
object CobblemonVillagerProfessions: PlatformRegistry<Registry<VillagerProfession>, ResourceKey<Registry<VillagerProfession>>, VillagerProfession>() {
|
||||
override val registry: Registry<VillagerProfession> = BuiltInRegistries.VILLAGER_PROFESSION
|
||||
override var registry: Registry<VillagerProfession>? = BuiltInRegistries.VILLAGER_PROFESSION
|
||||
override val resourceKey: ResourceKey<Registry<VillagerProfession>> = Registries.VILLAGER_PROFESSION
|
||||
|
||||
@JvmField
|
||||
|
||||
@@ -95,6 +95,6 @@ object CobblemonCriteria : PlatformRegistry<Registry<CriterionTrigger<*>>, Resou
|
||||
@JvmField
|
||||
val LEARN_TM_COUNT = this.create("tms_learned", SimpleCriterionTrigger(CountableCriterion.CODEC))
|
||||
|
||||
override val registry = BuiltInRegistries.TRIGGER_TYPES
|
||||
override var registry = BuiltInRegistries.TRIGGER_TYPES
|
||||
override val resourceKey = Registries.TRIGGER_TYPE
|
||||
}
|
||||
+1
-1
@@ -21,7 +21,7 @@ object CobblemonEntitySubPredicates : PlatformRegistry<Registry<MapCodec<out Ent
|
||||
@JvmStatic
|
||||
val POKE_POBBER = this.create("poke_bobber", FishingBobberPredicate.CODEC)
|
||||
|
||||
override val registry: Registry<MapCodec<out EntitySubPredicate>> = BuiltInRegistries.ENTITY_SUB_PREDICATE_TYPE
|
||||
override var registry: Registry<MapCodec<out EntitySubPredicate>>? = BuiltInRegistries.ENTITY_SUB_PREDICATE_TYPE
|
||||
|
||||
override val resourceKey: ResourceKey<Registry<MapCodec<out EntitySubPredicate>>> = Registries.ENTITY_SUB_PREDICATE_TYPE
|
||||
|
||||
|
||||
@@ -44,8 +44,15 @@ interface JsonDataRegistry<T> : DataRegistry {
|
||||
*/
|
||||
val resourcePath: String
|
||||
|
||||
override fun reload(manager: ResourceManager) {
|
||||
val data = hashMapOf<ResourceLocation, T>()
|
||||
/**
|
||||
* Traverses JSON resources for this registry and maps them to their resolved identifiers.
|
||||
* Returning null from [parse] skips the resource.
|
||||
*/
|
||||
fun <R> loadJsonData(
|
||||
manager: ResourceManager,
|
||||
parse: (reader: BufferedReader, sourceIdentifier: ResourceLocation, resolvedIdentifier: ResourceLocation) -> R?
|
||||
): Map<ResourceLocation, R> {
|
||||
val data = hashMapOf<ResourceLocation, R>()
|
||||
manager.listResources(resourcePath) { path -> path.endsWith(JSON_EXTENSION) }.forEach { (identifier, resource) ->
|
||||
if (identifier.namespace == "pixelmon") {
|
||||
return@forEach
|
||||
@@ -54,11 +61,21 @@ interface JsonDataRegistry<T> : DataRegistry {
|
||||
resource.open().use { stream ->
|
||||
stream.bufferedReader().use { reader ->
|
||||
val resolvedIdentifier = ResourceLocation.fromNamespaceAndPath(identifier.namespace, File(identifier.path).nameWithoutExtension)
|
||||
data[resolvedIdentifier] = parse(reader, resolvedIdentifier)
|
||||
parse(reader, identifier, resolvedIdentifier)?.let { parsed ->
|
||||
data[resolvedIdentifier] = parsed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
override fun reload(manager: ResourceManager) {
|
||||
val data = loadJsonData(manager) { reader, _, resolvedIdentifier ->
|
||||
parse(reader, resolvedIdentifier)
|
||||
}
|
||||
|
||||
reload(data)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.data
|
||||
|
||||
import com.cobblemon.mod.common.util.endsWith
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.core.HolderLookup
|
||||
import java.io.BufferedReader
|
||||
import java.io.File
|
||||
import java.util.concurrent.ExecutionException
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.server.packs.resources.ResourceManager
|
||||
|
||||
/**
|
||||
* A [DataRegistry] that consumes JSON files.
|
||||
* Every deserialized instance is attached to an [Identifier].
|
||||
* For example a file under data/mymod/[resourcePath]/entry.json would be backed by the identifier modid:entry.
|
||||
*
|
||||
* @param T The type of the data consumed by this registry.
|
||||
*
|
||||
* @author Licious
|
||||
* @since August 5th, 2022
|
||||
*/
|
||||
interface ServerJsonDataRegistry<T> : DataRegistry {
|
||||
|
||||
/**
|
||||
* The [TypeToken] of type [T].
|
||||
*/
|
||||
val typeToken: TypeToken<T>
|
||||
|
||||
/**
|
||||
* The folder location for the data this registry will consume.
|
||||
*/
|
||||
val resourcePath: String
|
||||
|
||||
override val type: PackType
|
||||
get() = PackType.SERVER_DATA
|
||||
|
||||
override fun reload(manager: ResourceManager) {
|
||||
//NO-OP, handled by reload(manager, registry)
|
||||
}
|
||||
|
||||
fun reload(manager: ResourceManager, registry: HolderLookup.Provider) {
|
||||
val gson = setupParser(registry)
|
||||
val data = hashMapOf<ResourceLocation, T>()
|
||||
manager.listResources(resourcePath) { path -> path.endsWith(JSON_EXTENSION) }.forEach { (identifier, resource) ->
|
||||
if (identifier.namespace == "pixelmon") {
|
||||
return@forEach
|
||||
}
|
||||
|
||||
resource.open().use { stream ->
|
||||
stream.bufferedReader().use { reader ->
|
||||
val resolvedIdentifier = ResourceLocation.fromNamespaceAndPath(identifier.namespace, File(identifier.path).nameWithoutExtension)
|
||||
data[resolvedIdentifier] = parse(reader, resolvedIdentifier, gson)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reload(data, registry)
|
||||
}
|
||||
|
||||
fun parse(reader: BufferedReader, identifier: ResourceLocation, gson: Gson): T {
|
||||
return try {
|
||||
gson.fromJson(reader, typeToken.type)
|
||||
} catch (exception: Exception) {
|
||||
throw ExecutionException("Error loading JSON for data: $identifier", exception)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the creation of [Gson] instances which have adapters that are registry-aware, e.g. [com.cobblemon.mod.common.pokemon.evolution.adapters.LegacyItemConditionWrapperAdapter]
|
||||
*/
|
||||
fun setupParser(registry: HolderLookup.Provider): Gson
|
||||
|
||||
/**
|
||||
* Reloads this registry from the deserialized data.
|
||||
*
|
||||
* @param data A map of the data associating an instance to the respective identifier from the [ResourceManager].
|
||||
*/
|
||||
fun reload(data: Map<ResourceLocation, T>, registry: HolderLookup.Provider)
|
||||
|
||||
companion object {
|
||||
const val JSON_EXTENSION = ".json"
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ object Fossils: JsonDataRegistry<Fossil> {
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
|
||||
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter)
|
||||
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter())
|
||||
.create()
|
||||
|
||||
override val typeToken: TypeToken<Fossil> = TypeToken.get(Fossil::class.java)
|
||||
|
||||
+24
-20
@@ -10,7 +10,7 @@ package com.cobblemon.mod.common.api.interaction
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.data.ServerJsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
|
||||
@@ -26,6 +26,7 @@ import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.advancements.critereon.ItemPredicate
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
@@ -36,28 +37,31 @@ import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.levelgen.structure.Structure
|
||||
import net.minecraft.world.level.material.Fluid
|
||||
|
||||
object PokemonInteractions : JsonDataRegistry<PokemonInteractionSet> {
|
||||
object PokemonInteractions : ServerJsonDataRegistry<PokemonInteractionSet> {
|
||||
override val id = cobblemonResource("pokemon_interactions")
|
||||
override val type = PackType.SERVER_DATA
|
||||
override fun setupParser(registry: HolderLookup.Provider): Gson {
|
||||
return GsonBuilder()
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter)
|
||||
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter(registry))
|
||||
.registerTypeAdapter(Requirement::class.java, CobblemonRequirementAdapter)
|
||||
.registerTypeAdapter(InteractionEffect::class.java, InteractionEffectAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, BiomeLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Block::class.java).type, BlockLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Structure::class.java).type, StructureLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Fluid::class.java).type, FluidLikeConditionAdapter)
|
||||
.registerTypeAdapter(IntRange::class.java, IntRangeAdapter)
|
||||
.registerTypeAdapterFactory(LowerCaseEnumTypeAdapterFactory())
|
||||
.setPrettyPrinting()
|
||||
.create()
|
||||
}
|
||||
|
||||
override val observable = SimpleObservable<PokemonInteractions>()
|
||||
override val typeToken: TypeToken<PokemonInteractionSet> = TypeToken.get(PokemonInteractionSet::class.java)
|
||||
override val resourcePath = "pokemon_interactions"
|
||||
override val gson: Gson = GsonBuilder()
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter)
|
||||
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter)
|
||||
.registerTypeAdapter(Requirement::class.java, CobblemonRequirementAdapter)
|
||||
.registerTypeAdapter(InteractionEffect::class.java, InteractionEffectAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, BiomeLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Block::class.java).type, BlockLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Structure::class.java).type, StructureLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Fluid::class.java).type, FluidLikeConditionAdapter)
|
||||
.registerTypeAdapter(IntRange::class.java, IntRangeAdapter)
|
||||
.registerTypeAdapterFactory(LowerCaseEnumTypeAdapterFactory())
|
||||
.setPrettyPrinting()
|
||||
.create()
|
||||
|
||||
val interactions = mutableListOf<PokemonInteractionSet>()
|
||||
|
||||
@@ -65,7 +69,7 @@ object PokemonInteractions : JsonDataRegistry<PokemonInteractionSet> {
|
||||
PokemonInteractionsSyncPacket(interactions).sendToPlayer(player)
|
||||
}
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, PokemonInteractionSet>) {
|
||||
override fun reload(data: Map<ResourceLocation, PokemonInteractionSet>, registry: HolderLookup.Provider) {
|
||||
interactions.clear()
|
||||
val split = data.entries
|
||||
.partition {
|
||||
@@ -87,4 +91,4 @@ object PokemonInteractions : JsonDataRegistry<PokemonInteractionSet> {
|
||||
.flatMap { it.interactions }
|
||||
.firstOrNull(interactionCheck)
|
||||
}
|
||||
}
|
||||
}
|
||||
+22
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.pokedex.AbstractPokedexManager
|
||||
import com.cobblemon.mod.common.api.pokedex.CaughtCount
|
||||
import com.cobblemon.mod.common.api.pokedex.CaughtPercent
|
||||
import com.cobblemon.mod.common.api.pokedex.Dexes
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexManager
|
||||
import com.cobblemon.mod.common.api.pokedex.SeenCount
|
||||
@@ -74,6 +75,27 @@ object PokedexMoLangFunctions : AbstractMoLangFunctionHolder<AbstractPokedexMana
|
||||
functions["caught_percent"] = { DoubleValue(pokedex.getGlobalCalculatedValue(CaughtPercent)) }
|
||||
functions["seen_percent"] = { DoubleValue(pokedex.getGlobalCalculatedValue(SeenPercent)) }
|
||||
|
||||
functions["dex_caught_count"] = { params ->
|
||||
val dexId = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
if (Dexes.dexEntryMap.containsKey(dexId)) DoubleValue(pokedex.getDexCalculatedValue(dexId, CaughtCount))
|
||||
else DoubleValue.ZERO
|
||||
}
|
||||
functions["dex_seen_count"] = { params ->
|
||||
val dexId = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
if (Dexes.dexEntryMap.containsKey(dexId)) DoubleValue(pokedex.getDexCalculatedValue(dexId, SeenCount))
|
||||
else DoubleValue.ZERO
|
||||
}
|
||||
functions["dex_caught_percent"] = { params ->
|
||||
val dexId = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
if (Dexes.dexEntryMap.containsKey(dexId)) DoubleValue(pokedex.getDexCalculatedValue(dexId, CaughtPercent).toDouble())
|
||||
else DoubleValue.ZERO
|
||||
}
|
||||
functions["dex_seen_percent"] = { params ->
|
||||
val dexId = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
if (Dexes.dexEntryMap.containsKey(dexId)) DoubleValue(pokedex.getDexCalculatedValue(dexId, SeenPercent).toDouble())
|
||||
else DoubleValue.ZERO
|
||||
}
|
||||
|
||||
when (pokedex) {
|
||||
is PokedexManager -> {
|
||||
functions["player_id"] = { StringValue(pokedex.uuid.toString()) }
|
||||
|
||||
+23
-7
@@ -8,8 +8,10 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.orientation
|
||||
|
||||
import com.cobblemon.mod.common.util.math.QuatSpring
|
||||
import com.cobblemon.mod.common.util.math.geometry.toDegrees
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import com.cobblemon.mod.common.util.math.simpleSpringDamperQuat
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@@ -26,6 +28,8 @@ open class OrientationController(val entity: LivingEntity) {
|
||||
val FORWARDS: Vector3f = Vector3f(0.0f, 0.0f, -1.0f)
|
||||
val UP: Vector3f = Vector3f(0.0f, 1.0f, 0.0f)
|
||||
val LEFT: Vector3f = Vector3f(-1.0f, 0.0f, 0.0f)
|
||||
private const val TICK_DT = 1f / 20f // Minecraft server tick rate
|
||||
private const val RENDER_SMOOTH_HALFLIFE = 0.1f // seconds to close ~half the gap
|
||||
}
|
||||
|
||||
open var active: Boolean = false
|
||||
@@ -33,6 +37,8 @@ open class OrientationController(val entity: LivingEntity) {
|
||||
var orientation: Matrix3f? = null
|
||||
private set
|
||||
|
||||
private val renderSpring = QuatSpring()
|
||||
|
||||
private var renderOrientationO: Matrix3f? = null
|
||||
private var renderOrientation: Matrix3f? = null
|
||||
|
||||
@@ -54,6 +60,8 @@ open class OrientationController(val entity: LivingEntity) {
|
||||
orientation = null
|
||||
renderOrientationO = null
|
||||
renderOrientation = null
|
||||
renderSpring.quat.identity()
|
||||
renderSpring.angVel.set(0f, 0f, 0f)
|
||||
active = false
|
||||
}
|
||||
|
||||
@@ -77,18 +85,26 @@ open class OrientationController(val entity: LivingEntity) {
|
||||
return oldQuat
|
||||
}
|
||||
|
||||
/** Every tick move the current render orientation towards the last known true orientation **/
|
||||
fun tick() {
|
||||
if (!active || orientation == null) return
|
||||
renderOrientationO = renderOrientation
|
||||
val current = orientation
|
||||
val renderMatrix = this.renderOrientation ?: current
|
||||
val renderQuat = Quaternionf().setFromUnnormalized(renderMatrix)
|
||||
val targetQuat = Quaternionf().setFromUnnormalized(current)
|
||||
val dampingFactor = 0.66f // Smooth interpolation to reduce jitter of orientations recieved from the server.
|
||||
renderQuat.slerp(targetQuat, dampingFactor)
|
||||
val current = orientation!!
|
||||
val targetQuat = Quaternionf().setFromUnnormalized(current)
|
||||
|
||||
if (renderOrientation == null) {
|
||||
// First tick: snap the spring to the target instead of easing in from identity
|
||||
renderSpring.quat.set(targetQuat)
|
||||
renderSpring.angVel.set(0f, 0f, 0f)
|
||||
}
|
||||
|
||||
// Use a "quat spring" to smoothly move the render orientation towards the goal orientation.
|
||||
// It takes into account the orientations angular velocities and should be much more resilient
|
||||
// to sharp changes in goal orientation or late/missed packets.
|
||||
simpleSpringDamperQuat(renderSpring, targetQuat, 0.15f, TICK_DT)
|
||||
|
||||
val newRenderOrientation = Matrix3f()
|
||||
renderQuat.get(newRenderOrientation)
|
||||
renderSpring.quat.get(newRenderOrientation)
|
||||
renderOrientation = newRenderOrientation
|
||||
}
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Fluid::class.java).type, FluidLikeConditionAdapter)
|
||||
.registerTypeAdapter(EggGroup::class.java, EggGroupAdapter)
|
||||
.registerTypeAdapter(MobEffect::class.java, RegistryElementAdapter<MobEffect>(BuiltInRegistries::MOB_EFFECT))
|
||||
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter)
|
||||
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter())
|
||||
.registerTypeAdapter(RidingBehaviourSettings::class.java, RidingBehaviourSettingsAdapter)
|
||||
.registerTypeAdapter(RideSoundSettingsList::class.java, RideSoundSettingsListAdapter)
|
||||
.registerTypeAdapter(ObtainableItemCondition::class.java, ObtainableItemConditionAdapter)
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.riding.util
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.phys.AABB
|
||||
import kotlin.math.floor
|
||||
|
||||
/**
|
||||
* Walks every block position inside [searchBox] and turns each solid block into one
|
||||
* full-cube [FieldPrimitive].
|
||||
*
|
||||
* @author Jackson
|
||||
* @since July 27th, 2026
|
||||
*/
|
||||
|
||||
fun collectPrimitivesFromBlocks(
|
||||
level: BlockGetter,
|
||||
searchBox: AABB,
|
||||
shape: PrimitiveShape,
|
||||
includeFluids: Boolean = false
|
||||
): List<FieldPrimitive> {
|
||||
val primitives = mutableListOf<FieldPrimitive>()
|
||||
|
||||
val minX = floor(searchBox.minX).toInt()
|
||||
val maxX = floor(searchBox.maxX).toInt()
|
||||
val minY = floor(searchBox.minY).toInt()
|
||||
val maxY = floor(searchBox.maxY).toInt()
|
||||
val minZ = floor(searchBox.minZ).toInt()
|
||||
val maxZ = floor(searchBox.maxZ).toInt()
|
||||
|
||||
val pos = BlockPos.MutableBlockPos()
|
||||
for (x in minX..maxX) {
|
||||
for (y in minY..maxY) {
|
||||
for (z in minZ..maxZ) {
|
||||
pos.set(x, y, z)
|
||||
val state = level.getBlockState(pos)
|
||||
|
||||
val isSolid = !state.getCollisionShape(level, pos).isEmpty
|
||||
val isFluid = includeFluids && !state.fluidState.isEmpty
|
||||
if (!isSolid && !isFluid) continue
|
||||
|
||||
primitives.add(
|
||||
FieldPrimitive(
|
||||
shape = shape,
|
||||
centerX = x + 0.5f, centerY = y + 0.5f, centerZ = z + 0.5f,
|
||||
halfWidth = 0.5f, halfHeight = 0.5f, halfDepth = 0.5f
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return primitives
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.util
|
||||
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.sqrt
|
||||
|
||||
/**
|
||||
* Helpful Functions when working with signed distance fields/functions.
|
||||
* https://iquilezles.org/articles/distfunctions/
|
||||
*
|
||||
* @author Jackson
|
||||
* @since July 27th, 2026
|
||||
*/
|
||||
|
||||
/** Which distance formula a primitive uses. */
|
||||
enum class PrimitiveShape {
|
||||
BOX,
|
||||
ROUNDED_BOX,
|
||||
ELLIPSOID
|
||||
}
|
||||
|
||||
/** Tunable constants for the field. */
|
||||
data class DistanceFieldTuning(
|
||||
val smoothingRange: Float = 0.5f,
|
||||
val roundingRadius: Float = 0.08f
|
||||
)
|
||||
|
||||
/** A single shape in the field - a center position, half-extents, and which formula to use. */
|
||||
data class FieldPrimitive(
|
||||
val shape: PrimitiveShape,
|
||||
val centerX: Float, val centerY: Float, val centerZ: Float,
|
||||
val halfWidth: Float, val halfHeight: Float, val halfDepth: Float
|
||||
)
|
||||
|
||||
/** Fast approximate 1/sqrt(x) - the Quake III trick, cheaper than a real sqrt + divide. */
|
||||
fun fastInverseSqrt(value: Float): Float {
|
||||
var x = value
|
||||
val halfX = 0.5f * x
|
||||
var bits = java.lang.Float.floatToIntBits(x)
|
||||
bits = 0x5f3759df - (bits shr 1)
|
||||
x = java.lang.Float.intBitsToFloat(bits)
|
||||
x *= (1.5f - halfX * x * x)
|
||||
return x
|
||||
}
|
||||
|
||||
/** Exact distance from a point to an axis-aligned box. Inputs are relative to the box's own center. */
|
||||
fun boxDistance(relX: Float, relY: Float, relZ: Float, halfWidth: Float, halfHeight: Float, halfDepth: Float): Float {
|
||||
val qx = abs(relX) - halfWidth
|
||||
val qy = abs(relY) - halfHeight
|
||||
val qz = abs(relZ) - halfDepth
|
||||
val ox = max(qx, 0f)
|
||||
val oy = max(qy, 0f)
|
||||
val oz = max(qz, 0f)
|
||||
val outside = sqrt(ox * ox + oy * oy + oz * oz)
|
||||
val inside = min(max(qx, max(qy, qz)), 0f)
|
||||
return outside + inside
|
||||
}
|
||||
|
||||
/** Same as boxDistance but with rounded corners/edges https://iquilezles.org/articles/distfunctions/ */
|
||||
fun roundedBoxDistance(relX: Float, relY: Float, relZ: Float, halfWidth: Float, halfHeight: Float, halfDepth: Float, roundingRadius: Float): Float =
|
||||
boxDistance(relX, relY, relZ, halfWidth - roundingRadius, halfHeight - roundingRadius, halfDepth - roundingRadius) - roundingRadius
|
||||
|
||||
/** Approximate (lower-bound) distance to an ellipsoid https://iquilezles.org/articles/ellipsoids/. */
|
||||
fun ellipsoidDistance(relX: Float, relY: Float, relZ: Float, halfWidth: Float, halfHeight: Float, halfDepth: Float): Float {
|
||||
val px = relX / halfWidth
|
||||
val py = relY / halfHeight
|
||||
val pz = relZ / halfDepth
|
||||
val inverseMagnitude = fastInverseSqrt(px * px + py * py + pz * pz)
|
||||
val trueDistance = sqrt(relX * relX + relY * relY + relZ * relZ)
|
||||
return trueDistance * (1.0f - inverseMagnitude)
|
||||
}
|
||||
|
||||
/** Distance from a point to one primitive, dispatched by its shape. */
|
||||
fun distanceToPrimitive(primitive: FieldPrimitive, sampleX: Float, sampleY: Float, sampleZ: Float, tuning: DistanceFieldTuning): Float {
|
||||
val relX = sampleX - primitive.centerX
|
||||
val relY = sampleY - primitive.centerY
|
||||
val relZ = sampleZ - primitive.centerZ
|
||||
return when (primitive.shape) {
|
||||
PrimitiveShape.BOX -> boxDistance(relX, relY, relZ, primitive.halfWidth, primitive.halfHeight, primitive.halfDepth)
|
||||
PrimitiveShape.ROUNDED_BOX -> roundedBoxDistance(relX, relY, relZ, primitive.halfWidth, primitive.halfHeight, primitive.halfDepth, tuning.roundingRadius)
|
||||
PrimitiveShape.ELLIPSOID -> ellipsoidDistance(relX, relY, relZ, primitive.halfWidth, primitive.halfHeight, primitive.halfDepth)
|
||||
}
|
||||
}
|
||||
|
||||
///** Normalized quadratic smooth-min https://iquilezles.org/articles/smin/ */
|
||||
//fun smoothMinimum(a: Float, b: Float, smoothingRange: Float): Float {
|
||||
// if (smoothingRange <= 0.001f) return min(a, b)
|
||||
// val k = smoothingRange * 4.0f
|
||||
// val h = (0.5f + 0.5f * (b - a) / k).coerceIn(0f, 1f)
|
||||
// return b + (a - b) * h - k * h * (1f - h)
|
||||
//}
|
||||
//
|
||||
///** Folds every primitive's distance together into one field value at a point. */
|
||||
//fun sampleField(primitives: List<FieldPrimitive>, sampleX: Float, sampleY: Float, sampleZ: Float, tuning: DistanceFieldTuning): Float {
|
||||
// var result = Float.POSITIVE_INFINITY
|
||||
// for (primitive in primitives) {
|
||||
// val distance = distanceToPrimitive(primitive, sampleX, sampleY, sampleZ, tuning)
|
||||
// result = if (result == Float.POSITIVE_INFINITY) distance else smoothMinimum(result, distance, tuning.smoothingRange)
|
||||
// }
|
||||
// return result
|
||||
//}
|
||||
|
||||
/** Normalized quadratic smooth-min https://iquilezles.org/articles/smin/ */
|
||||
fun smoothMinimum(a: Float, b: Float, smoothingRange: Float): Float {
|
||||
if (smoothingRange <= 0.001f) return min(a, b)
|
||||
val k = smoothingRange * 4.0f
|
||||
val h = (0.5f + 0.5f * (b - a) / k).coerceIn(0f, 1f)
|
||||
return b + (a - b) * h - k * h * (1f - h)
|
||||
}
|
||||
|
||||
/** Folds nearby primitive distances together into one field value at a point. */
|
||||
fun sampleField(primitives: List<FieldPrimitive>, sampleX: Float, sampleY: Float, sampleZ: Float, tuning: DistanceFieldTuning): Float {
|
||||
if (primitives.isEmpty()) return Float.POSITIVE_INFINITY
|
||||
|
||||
val distances = FloatArray(primitives.size) { distanceToPrimitive(primitives[it], sampleX, sampleY, sampleZ, tuning) }
|
||||
val minDistance = distances.min()
|
||||
|
||||
if (tuning.smoothingRange <= 0.001f) return minDistance
|
||||
|
||||
// Anything more than a few blend-widths past the closest primitive is cut - its
|
||||
// contribution would be negligible in a correct blend anyway, but left in, it still
|
||||
// drags the chained result down the more of them there are.
|
||||
val cutoff = tuning.smoothingRange * 3f
|
||||
|
||||
var result = Float.POSITIVE_INFINITY
|
||||
for (distance in distances) {
|
||||
if (distance - minDistance > cutoff) continue
|
||||
result = if (result == Float.POSITIVE_INFINITY) distance else smoothMinimum(result, distance, tuning.smoothingRange)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/** Finite-difference gradient of the field at a point - points away from the surface, magnitude ~1 for a clean field. */
|
||||
fun estimateGradient(primitives: List<FieldPrimitive>, point: Vec3, tuning: DistanceFieldTuning, epsilon: Float = 0.05f): Vec3 {
|
||||
val px = point.x.toFloat()
|
||||
val py = point.y.toFloat()
|
||||
val pz = point.z.toFloat()
|
||||
|
||||
val dx = sampleField(primitives, px + epsilon, py, pz, tuning) - sampleField(primitives, px - epsilon, py, pz, tuning)
|
||||
val dy = sampleField(primitives, px, py + epsilon, pz, tuning) - sampleField(primitives, px, py - epsilon, pz, tuning)
|
||||
val dz = sampleField(primitives, px, py, pz + epsilon, tuning) - sampleField(primitives, px, py, pz - epsilon, tuning)
|
||||
|
||||
val gradient = Vec3(dx.toDouble(), dy.toDouble(), dz.toDouble())
|
||||
return if (gradient.lengthSqr() > 1e-8) gradient.normalize() else Vec3(0.0, 1.0, 0.0)
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.riding.util
|
||||
|
||||
import net.minecraft.core.particles.DustParticleOptions
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.phys.AABB
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Vector3f
|
||||
|
||||
/** One shell to draw - a target field value, a color, a particle size. */
|
||||
data class DistanceFieldLayer(
|
||||
val isoValue: Float,
|
||||
val color: Vector3f,
|
||||
val particleSize: Float = 1.0f
|
||||
)
|
||||
|
||||
/**
|
||||
* Marches a grid of vertical columns through the field around [center] and spawns a
|
||||
* particle everywhere it crosses one of [layers]' target values. Server-side only.
|
||||
*/
|
||||
fun visualizeDistanceField(
|
||||
referenceEntity: Entity,
|
||||
center: Vec3,
|
||||
layers: List<DistanceFieldLayer>,
|
||||
shape: PrimitiveShape = PrimitiveShape.BOX,
|
||||
horizontalRadius: Double = 4.0,
|
||||
verticalRange: Double = 4.0,
|
||||
sampleSpacing: Double = 0.5,
|
||||
marchStep: Double = 0.1,
|
||||
tuning: DistanceFieldTuning = DistanceFieldTuning()
|
||||
) {
|
||||
val level = referenceEntity.level()
|
||||
if (level !is ServerLevel) return
|
||||
|
||||
val searchBox = AABB(
|
||||
center.x - horizontalRadius, center.y - verticalRange, center.z - horizontalRadius,
|
||||
center.x + horizontalRadius, center.y, center.z + horizontalRadius
|
||||
)
|
||||
|
||||
val primitives = collectPrimitivesFromBlocks(level, searchBox, shape, includeFluids = true)
|
||||
if (primitives.isEmpty()) return
|
||||
|
||||
var x = -horizontalRadius
|
||||
while (x <= horizontalRadius) {
|
||||
var z = -horizontalRadius
|
||||
while (z <= horizontalRadius) {
|
||||
marchColumn(level, primitives, center, x, z, verticalRange, marchStep, layers, tuning)
|
||||
z += sampleSpacing
|
||||
}
|
||||
x += sampleSpacing
|
||||
}
|
||||
}
|
||||
|
||||
private fun marchColumn(
|
||||
level: ServerLevel,
|
||||
primitives: List<FieldPrimitive>,
|
||||
center: Vec3,
|
||||
offsetX: Double,
|
||||
offsetZ: Double,
|
||||
verticalRange: Double,
|
||||
marchStep: Double,
|
||||
layers: List<DistanceFieldLayer>,
|
||||
tuning: DistanceFieldTuning
|
||||
) {
|
||||
val previousValue = FloatArray(layers.size) { Float.NaN }
|
||||
|
||||
var y = verticalRange
|
||||
while (y >= -verticalRange) {
|
||||
val worldX = (center.x + offsetX).toFloat()
|
||||
val worldY = (center.y + y).toFloat()
|
||||
val worldZ = (center.z + offsetZ).toFloat()
|
||||
val fieldValue = sampleField(primitives, worldX, worldY, worldZ, tuning)
|
||||
|
||||
for (layerIndex in layers.indices) {
|
||||
val layer = layers[layerIndex]
|
||||
val previous = previousValue[layerIndex]
|
||||
|
||||
if (!previous.isNaN() && crossedTarget(previous, fieldValue, layer.isoValue)) {
|
||||
val t = (layer.isoValue - previous) / (fieldValue - previous)
|
||||
val crossingY = (y + marchStep) - marchStep * t
|
||||
spawnLayerParticle(level, center.add(offsetX, crossingY, offsetZ), layer)
|
||||
}
|
||||
|
||||
previousValue[layerIndex] = fieldValue
|
||||
}
|
||||
|
||||
y -= marchStep
|
||||
}
|
||||
}
|
||||
|
||||
private fun crossedTarget(previous: Float, current: Float, target: Float): Boolean =
|
||||
(previous - target) * (current - target) < 0f
|
||||
|
||||
private fun spawnLayerParticle(level: ServerLevel, pos: Vec3, layer: DistanceFieldLayer) {
|
||||
val particle = DustParticleOptions(layer.color, layer.particleSize)
|
||||
level.sendParticles(particle, pos.x, pos.y, pos.z, 1, 0.0, 0.0, 0.0, 0.0)
|
||||
}
|
||||
@@ -128,6 +128,7 @@ class DiscShelfBlockEntity(pos: BlockPos, state: BlockState) : BlockEntity(Cobbl
|
||||
|
||||
fun isValidItem(stack: ItemStack): Boolean {
|
||||
return stack.item is TechnicalMachineItem
|
||||
|| stack.item == CobblemonItems.BLANK_TM
|
||||
|| stack.item == CobblemonItems.UPGRADE
|
||||
|| stack.item == CobblemonItems.DUBIOUS_DISC
|
||||
|| stack.has(DataComponents.JUKEBOX_PLAYABLE)
|
||||
|
||||
+2
@@ -31,6 +31,7 @@ import com.cobblemon.mod.common.client.sound.instances.CancellableSoundInstance
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.item.PokeBallItem
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.activestate.SentOutState
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.giveOrDropItemStack
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
@@ -235,6 +236,7 @@ class FossilMultiblockStructure (
|
||||
entity.setPos(fixedPosition.center.subtract(0.0, 0.5, 0.0))
|
||||
// TODO: Find a correct way to set the new entity's Yaw rotation. (Face away from the machine)
|
||||
if (world.addFreshEntity(entity)) {
|
||||
pokemon.state = SentOutState(entity)
|
||||
CobblemonEvents.FOSSIL_REVIVED.post(FossilRevivedEvent(pokemon, null))
|
||||
return true
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -71,7 +71,7 @@ open class VariableObjectSelectionList(x: Int, y: Int, width: Int, height: Int):
|
||||
var stackHeight = -scrollAmount.toInt()
|
||||
guiGraphics.enableScissor(x, y, x + width, y + height)
|
||||
children.forEachIndexed { index, entry ->
|
||||
if (stackHeight in 1..<height || stackHeight + entry.height in 1..<height) {
|
||||
if (stackHeight < height && stackHeight + entry.height > 0) {
|
||||
entry.render(guiGraphics, index, x, y + stackHeight, mouseX, mouseY, partialTick)
|
||||
}
|
||||
stackHeight += entry.height
|
||||
|
||||
+4
-6
@@ -8,12 +8,10 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.startselection.widgets
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.PokemonGUIAnimationStyle
|
||||
import com.cobblemon.mod.common.client.gui.VariableObjectSelectionList
|
||||
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
|
||||
import com.cobblemon.mod.common.client.gui.startselection.StarterSelectionScreen
|
||||
@@ -29,12 +27,11 @@ import org.joml.Quaternionf
|
||||
import org.joml.Vector3f
|
||||
|
||||
class CategoryList(
|
||||
private val paneWidth: Int,
|
||||
private val paneHeight: Int,
|
||||
paneWidth: Int,
|
||||
paneHeight: Int,
|
||||
private val categories: List<RenderableStarterCategory>,
|
||||
val listX: Int,
|
||||
val listY: Int,
|
||||
private val minecraft: Minecraft = Minecraft.getInstance(),
|
||||
private val starterSelectionScreen: StarterSelectionScreen
|
||||
) : VariableObjectSelectionList(
|
||||
listX,
|
||||
@@ -70,7 +67,8 @@ class CategoryList(
|
||||
}
|
||||
|
||||
private fun createEntries() = categories.map { category ->
|
||||
val rows = (category.pokemon.size - 1) / 3 + 1
|
||||
val pokemonCount = category.pokemon.size - if (category.randomStarter) 0 else 1
|
||||
val rows = pokemonCount / 3 + 1
|
||||
val height = CONTAINER_BUTTON_SIZE * rows + BUTTON_SEPERATION * (rows + 1) + HEADER_HEIGHT + 3
|
||||
Category(category, height)
|
||||
}
|
||||
|
||||
+14
-28
@@ -8,9 +8,9 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.block
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.block.entity.DiscShelfBlockEntity
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.client.render.color.TechnicalMachineItemColorProvider
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer
|
||||
@@ -37,15 +37,15 @@ class DiscShelfBlockEntityRenderer(ctx: BlockEntityRendererProvider.Context) :
|
||||
private val slotHeightPixels = 2
|
||||
private val textureSize = 16f
|
||||
|
||||
private val slotUMax = slotWidthPixels / textureSize
|
||||
private val slotVMax = slotHeightPixels / textureSize
|
||||
|
||||
private val leftMargin = 1f
|
||||
private val rightMargin = 1f
|
||||
private val topMargin = 1f
|
||||
private val interRowSpacing = 0f
|
||||
private val tmOverlayDepthOffset = -0.0002f
|
||||
private val slotBrightnessMultiplier = 0.65f
|
||||
|
||||
private val tmBaseTexture = cobblemonResource("textures/block/disc_shelf/technical_machine_base.png")
|
||||
private val tmOverlayTexture = cobblemonResource("textures/block/disc_shelf/technical_machine_overlay.png")
|
||||
private val musicDiscUnknownTexture = cobblemonResource("textures/block/disc_shelf/music_disc_unknown.png")
|
||||
|
||||
override fun render(
|
||||
@@ -98,35 +98,19 @@ class DiscShelfBlockEntityRenderer(ctx: BlockEntityRendererProvider.Context) :
|
||||
poseStack.translate(posX, posY, -0.001f)
|
||||
|
||||
if (item.item == CobblemonItems.TECHNICAL_MACHINE) {
|
||||
val baseColor = TechnicalMachineItemColorProvider.getColor(item, 0)
|
||||
val overlayColor = TechnicalMachineItemColorProvider.getColor(item, 1)
|
||||
|
||||
val elementId = item.components.get(CobblemonItemComponents.TM_MOVE)!!.move.elementalType.showdownId
|
||||
val texture = cobblemonResource("textures/block/disc_shelf/${elementId}_tm.png")
|
||||
renderSlotQuad(
|
||||
poseStack,
|
||||
buffer,
|
||||
tmBaseTexture,
|
||||
baseColor,
|
||||
texture,
|
||||
0xFFFFFF,
|
||||
packedLight,
|
||||
slotWidth,
|
||||
slotHeight,
|
||||
tint = true,
|
||||
useTextRenderType = true
|
||||
)
|
||||
|
||||
poseStack.pushPose()
|
||||
poseStack.translate(0.0, 0.0, tmOverlayDepthOffset.toDouble())
|
||||
renderSlotQuad(
|
||||
poseStack,
|
||||
buffer,
|
||||
tmOverlayTexture,
|
||||
overlayColor,
|
||||
packedLight,
|
||||
slotWidth,
|
||||
slotHeight,
|
||||
tint = true,
|
||||
useTextRenderType = true
|
||||
)
|
||||
poseStack.popPose()
|
||||
} else {
|
||||
val tex = getItemTexture(item)
|
||||
renderSlotQuad(
|
||||
@@ -176,13 +160,15 @@ class DiscShelfBlockEntityRenderer(ctx: BlockEntityRendererProvider.Context) :
|
||||
val g = (gBase * slotBrightnessMultiplier).coerceIn(0f, 1f)
|
||||
val b = (bBase * slotBrightnessMultiplier).coerceIn(0f, 1f)
|
||||
|
||||
consumer.addVertex(matrix, 0f, 0f, 0f).setColor(r, g, b, a).setUv(0f, 1f)
|
||||
// The quad faces -Z, so a viewer looking at it sees +X on their left.
|
||||
// U runs from slotUMax at x = 0 to 0 at x = width so the art is not mirrored.
|
||||
consumer.addVertex(matrix, 0f, 0f, 0f).setColor(r, g, b, a).setUv(slotUMax, slotVMax)
|
||||
.setUv1(0, 0).setUv2(light and 0xFFFF, light shr 16).setNormal(0f, 0f, -1f)
|
||||
consumer.addVertex(matrix, 0f, height, 0f).setColor(r, g, b, a).setUv(0f, 0f)
|
||||
consumer.addVertex(matrix, 0f, height, 0f).setColor(r, g, b, a).setUv(slotUMax, 0f)
|
||||
.setUv1(0, 0).setUv2(light and 0xFFFF, light shr 16).setNormal(0f, 0f, -1f)
|
||||
consumer.addVertex(matrix, width, height, 0f).setColor(r, g, b, a).setUv(1f, 0f)
|
||||
consumer.addVertex(matrix, width, height, 0f).setColor(r, g, b, a).setUv(0f, 0f)
|
||||
.setUv1(0, 0).setUv2(light and 0xFFFF, light shr 16).setNormal(0f, 0f, -1f)
|
||||
consumer.addVertex(matrix, width, 0f, 0f).setColor(r, g, b, a).setUv(1f, 1f)
|
||||
consumer.addVertex(matrix, width, 0f, 0f).setColor(r, g, b, a).setUv(0f, slotVMax)
|
||||
.setUv1(0, 0).setUv2(light and 0xFFFF, light shr 16).setNormal(0f, 0f, -1f)
|
||||
}
|
||||
|
||||
|
||||
-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.client.render.color
|
||||
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.item.components.TMMoveComponent.Companion.getTMMove
|
||||
import net.minecraft.client.color.item.ItemColor
|
||||
import net.minecraft.util.FastColor
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
object TechnicalMachineItemColorProvider : ItemColor {
|
||||
override fun getColor(itemStack: ItemStack, layer: Int): Int {
|
||||
val moveType = getTMMove(itemStack)?.elementalType ?: ElementalTypes.NORMAL
|
||||
val color = when (layer) {
|
||||
0 -> moveType.primaryColor
|
||||
1 -> moveType.secondaryColor
|
||||
else -> 0xFFFFFF
|
||||
}
|
||||
return FastColor.ARGB32.opaque(color)
|
||||
}
|
||||
}
|
||||
-63
@@ -1,63 +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.models.blockbench.pokemon.gen5
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.QuadrupedWalkAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.QuadrupedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class DeerlingModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame, QuadrupedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("deerling")
|
||||
override val head = getPart("head")
|
||||
|
||||
override var portraitScale = 3.5F
|
||||
override var portraitTranslation = Vec3(-0.55, -1.1, 0.0)
|
||||
|
||||
override var profileScale = 1.0F
|
||||
override var profileTranslation = Vec3(0.0, 0.25, 0.0)
|
||||
|
||||
override val foreLeftLeg= getPart("leg_front_left")
|
||||
override val foreRightLeg = getPart("leg_front_right")
|
||||
override val hindLeftLeg = getPart("leg_back_left")
|
||||
override val hindRightLeg = getPart("leg_back_right")
|
||||
|
||||
lateinit var standing: Pose
|
||||
lateinit var walk: Pose
|
||||
|
||||
override fun registerPoses() {
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
// bedrock("deerling", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
QuadrupedWalkAnimation(this, periodMultiplier = 0.8F, amplitudeMultiplier = 0.8F)
|
||||
// bedrock("deerling", "ground_walk")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PosableState<PokemonEntity>
|
||||
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("deerling", "faint") else null
|
||||
}
|
||||
-63
@@ -1,63 +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.models.blockbench.pokemon.gen5
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.QuadrupedWalkAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.QuadrupedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class SawsbuckModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame, QuadrupedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("sawsbuck")
|
||||
override val head = getPart("head")
|
||||
|
||||
override var portraitScale = 2.0F
|
||||
override var portraitTranslation = Vec3(-0.5, 1.1, 0.0)
|
||||
|
||||
override var profileScale = 0.65F
|
||||
override var profileTranslation = Vec3(0.0, 0.75, 0.0)
|
||||
|
||||
override val foreLeftLeg= getPart("leg_front_left")
|
||||
override val foreRightLeg = getPart("leg_front_right")
|
||||
override val hindLeftLeg = getPart("leg_back_left")
|
||||
override val hindRightLeg = getPart("leg_back_right")
|
||||
|
||||
lateinit var standing: Pose
|
||||
lateinit var walk: Pose
|
||||
|
||||
override fun registerPoses() {
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
// bedrock("sawsbuck", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
QuadrupedWalkAnimation(this, periodMultiplier = 0.9F, amplitudeMultiplier = 0.9F)
|
||||
// bedrock("sawsbuck", "ground_walk")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PosableState<PokemonEntity>
|
||||
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("sawsbuck", "faint") else null
|
||||
}
|
||||
-90
@@ -1,90 +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.models.blockbench.pokemon.gen9
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.createTransformation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.ModelPartTransformation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class GlimmetModel (root: ModelPart) : PokemonPosableModel(root) {
|
||||
override val rootPart = root.registerChildWithAllChildren("glimmet")
|
||||
|
||||
override var portraitScale = 2.0F
|
||||
override var portraitTranslation = Vec3(-0.5, 1.3, 0.0)
|
||||
|
||||
override var profileScale = 0.7F
|
||||
override var profileTranslation = Vec3(0.0, 0.8, 0.0)
|
||||
|
||||
lateinit var standing: Pose
|
||||
lateinit var walk: Pose
|
||||
lateinit var sleep: Pose
|
||||
lateinit var shoulderLeft: Pose
|
||||
lateinit var shoulderRight: Pose
|
||||
|
||||
val shoulderOffset = 8
|
||||
|
||||
override val cryAnimation = CryProvider { bedrockStateful("glimmet", "cry") }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk { bedrockStateful("glimmet", "blink") }
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
animations = arrayOf(bedrock("glimmet", "sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
bedrock("glimmet", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
bedrock("glimmet", "ground_walk")
|
||||
)
|
||||
)
|
||||
|
||||
shoulderLeft = registerPose(
|
||||
poseType = PoseType.SHOULDER_LEFT,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
bedrock("glimmet", "ground_idle")
|
||||
),
|
||||
transformedParts = arrayOf(
|
||||
rootPart.createTransformation().addPosition(ModelPartTransformation.X_AXIS, shoulderOffset)
|
||||
)
|
||||
)
|
||||
|
||||
shoulderRight = registerPose(
|
||||
poseType = PoseType.SHOULDER_RIGHT,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
bedrock("glimmet", "ground_idle")
|
||||
),
|
||||
transformedParts = arrayOf(
|
||||
rootPart.createTransformation().addPosition(ModelPartTransformation.X_AXIS, -shoulderOffset)
|
||||
)
|
||||
)
|
||||
}
|
||||
override fun getFaintAnimation(state: PosableState) = if (state.isPosedIn(standing, walk)) bedrockStateful("glimmet", "faint") else null
|
||||
}
|
||||
-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.client.render.models.blockbench.pokemon.gen9
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.util.isBattling
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class GlimmoraModel (root: ModelPart) : PokemonPosableModel(root) {
|
||||
override val rootPart = root.registerChildWithAllChildren("glimmora")
|
||||
|
||||
override var portraitScale = 2.0F
|
||||
override var portraitTranslation = Vec3(-0.6, -0.1, 0.0)
|
||||
|
||||
override var profileScale = 0.7F
|
||||
override var profileTranslation = Vec3(0.0, 0.8, 0.0)
|
||||
|
||||
lateinit var standing: Pose
|
||||
lateinit var walk: Pose
|
||||
lateinit var sleep: Pose
|
||||
lateinit var battleidle: Pose
|
||||
|
||||
override val cryAnimation = CryProvider { bedrockStateful("glimmora", "cry") }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk { bedrockStateful("glimmora", "blink") }
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
animations = arrayOf(bedrock("glimmora", "sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
transformTicks = 10,
|
||||
condition = { !it.isBattling },
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
bedrock("glimmora", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
bedrock("glimmora", "ground_walk")
|
||||
)
|
||||
)
|
||||
|
||||
battleidle = registerPose(
|
||||
poseName = "battle_idle",
|
||||
poseTypes = PoseType.STATIONARY_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
condition = { it.isBattling },
|
||||
animations = arrayOf(
|
||||
bedrock("glimmora", "battle_idle")
|
||||
)
|
||||
|
||||
)
|
||||
}
|
||||
override fun getFaintAnimation(state: PosableState) = if (state.isPosedIn(standing, walk, sleep)) bedrockStateful("glimmora", "faint") else
|
||||
if (state.isPosedIn(battleidle)) bedrockStateful("glimmora", "faint2")
|
||||
else null
|
||||
}
|
||||
-4
@@ -304,8 +304,6 @@ object VaryingModelRepository {
|
||||
inbuilt("sizzlipede", ::SizzlipedeModel)
|
||||
inbuilt("kleavor", ::KleavorModel)
|
||||
inbuilt("pyukumuku", ::PyukumukuModel)
|
||||
inbuilt("deerling", ::DeerlingModel)
|
||||
inbuilt("sawsbuck", ::SawsbuckModel)
|
||||
inbuilt("natu", ::NatuModel)
|
||||
inbuilt("xatu", ::XatuModel)
|
||||
inbuilt("milcery", :: MilceryModel)
|
||||
@@ -399,8 +397,6 @@ object VaryingModelRepository {
|
||||
inbuilt("sirfetchd", ::SirfetchdModel)
|
||||
inbuilt("duskull", ::DuskullModel)
|
||||
inbuilt("dusclops", ::DusclopsModel)
|
||||
inbuilt("glimmet", ::GlimmetModel)
|
||||
inbuilt("glimmora", ::GlimmoraModel)
|
||||
inbuilt("bonsly", ::BonslyModel)
|
||||
inbuilt("sudowoodo", ::SudowoodoModel)
|
||||
inbuilt("cetoddle", ::CetoddleModel)
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common.command
|
||||
|
||||
import com.cobblemon.mod.common.api.permission.CobblemonPermissions
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonPropertyExtractor
|
||||
import com.cobblemon.mod.common.command.argument.PokemonPropertiesArgumentType
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import com.cobblemon.mod.common.util.permission
|
||||
@@ -45,7 +44,7 @@ object TestPartySlotCommand {
|
||||
val player = context.player(PLAYER)
|
||||
val slot = IntegerArgumentType.getInteger(context, SLOT)
|
||||
val properties = PokemonPropertiesArgumentType.getPokemonProperties(context, PROPERTIES)
|
||||
return if (player.party().get(slot - 1)?.createPokemonProperties(PokemonPropertyExtractor.ALL)
|
||||
?.let { properties.isSubSetOf(it) } == true) Command.SINGLE_SUCCESS else NO_SUCCESS
|
||||
val target = player.party().get(slot - 1) ?: return NO_SUCCESS
|
||||
return if (properties.matches(target)) Command.SINGLE_SUCCESS else NO_SUCCESS
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import com.cobblemon.mod.common.api.berry.Berries
|
||||
import com.cobblemon.mod.common.api.cooking.Seasonings
|
||||
import com.cobblemon.mod.common.api.data.DataProvider
|
||||
import com.cobblemon.mod.common.api.data.DataRegistry
|
||||
import com.cobblemon.mod.common.api.data.ServerJsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.dialogue.Dialogues
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.fishing.PokeRods
|
||||
@@ -51,12 +52,16 @@ import com.cobblemon.mod.common.pokemon.properties.PropertiesCompletionProvider
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.ifClient
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import net.minecraft.core.HolderLookup
|
||||
import com.cobblemon.mod.common.world.biome.CobblemonBiomeLoader
|
||||
import java.util.UUID
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.server.packs.resources.PreparableReloadListener
|
||||
import net.minecraft.server.packs.resources.ResourceManager
|
||||
import net.minecraft.server.packs.resources.ResourceManagerReloadListener
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
object CobblemonDataProvider : DataProvider {
|
||||
|
||||
@@ -67,6 +72,10 @@ object CobblemonDataProvider : DataProvider {
|
||||
|
||||
private val scheduledActions = mutableMapOf<UUID, MutableList<() -> Unit>>()
|
||||
|
||||
// client is public only so we can use it cross-module. maybe a more elegant solution exists, but this works
|
||||
@ApiStatus.Internal
|
||||
val clientResourceReloader: PreparableReloadListener = ClientResourceReloader()
|
||||
|
||||
fun registerDefaults() {
|
||||
this.register(CobblemonScripts, reloadable = true)
|
||||
this.register(SpeciesFeatures, reloadable = false)
|
||||
@@ -83,6 +92,7 @@ object CobblemonDataProvider : DataProvider {
|
||||
this.register(PokeBalls, reloadable = false)
|
||||
this.register(PropertiesCompletionProvider, reloadable = false)
|
||||
this.register(CobblemonPartyPools, reloadable = false)
|
||||
this.register(CobblemonBiomeLoader, reloadable = true)
|
||||
this.register(CobblemonPartyCompositions, reloadable = false)
|
||||
this.register(SpawnDetailPresets, reloadable = true)
|
||||
this.register(CobblemonSpawnRules, reloadable = true)
|
||||
@@ -119,9 +129,9 @@ object CobblemonDataProvider : DataProvider {
|
||||
}
|
||||
|
||||
ifClient {
|
||||
Cobblemon.implementation.registerResourceReloader(cobblemonResource("client_resources"), SimpleResourceReloader(PackType.CLIENT_RESOURCES), PackType.CLIENT_RESOURCES, emptyList())
|
||||
Cobblemon.implementation.registerResourceReloader(cobblemonResource("client_resources"), PackType.CLIENT_RESOURCES, emptyList()) { clientResourceReloader }
|
||||
}
|
||||
Cobblemon.implementation.registerResourceReloader(cobblemonResource("data_resources"), SimpleResourceReloader(PackType.SERVER_DATA), PackType.SERVER_DATA, emptyList())
|
||||
Cobblemon.implementation.registerResourceReloader(cobblemonResource("data_resources"), PackType.SERVER_DATA, emptyList()) { ServerResourceReloader(it) }
|
||||
}
|
||||
|
||||
override fun <T : DataRegistry> register(registry: T, reloadable: Boolean): T {
|
||||
@@ -160,12 +170,25 @@ object CobblemonDataProvider : DataProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private class SimpleResourceReloader(private val type: PackType) : ResourceManagerReloadListener {
|
||||
private class ClientResourceReloader : ResourceManagerReloadListener {
|
||||
override fun onResourceManagerReload(manager: ResourceManager) {
|
||||
registries.filter { it.type == PackType.CLIENT_RESOURCES }.forEach { it.reload(manager) }
|
||||
}
|
||||
}
|
||||
|
||||
private class ServerResourceReloader(private val registryAccess: HolderLookup.Provider) : ResourceManagerReloadListener {
|
||||
override fun onResourceManagerReload(manager: ResourceManager) {
|
||||
// Check for a server running, this is due to the create a world screen triggering datapack reloads, these are fine to happen as many times as needed as players may be in the process of adding their datapacks.
|
||||
val reloadAllowed = server()?.isReady != true
|
||||
registries.filter { it.type == this.type && (reloadAllowed || it in reloadableRegistries) }
|
||||
.forEach { it.reload(manager) }
|
||||
registries
|
||||
.filter { it.type == PackType.SERVER_DATA && (reloadAllowed || it in reloadableRegistries) }
|
||||
.forEach {
|
||||
if (it is ServerJsonDataRegistry<*>) {
|
||||
it.reload(manager, registryAccess)
|
||||
} else {
|
||||
it.reload(manager)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,8 +31,6 @@ interface EVIncreaseItem: PokemonSelectingItem {
|
||||
override fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon) = pokemon.evs.getOrDefault(stat) < EVs.MAX_STAT_VALUE &&
|
||||
super.canUseOnPokemon(stack, pokemon)
|
||||
|
||||
val sound: SoundEvent
|
||||
|
||||
override fun applyToPokemon(
|
||||
player: ServerPlayer,
|
||||
stack: ItemStack,
|
||||
@@ -40,14 +38,12 @@ interface EVIncreaseItem: PokemonSelectingItem {
|
||||
): InteractionResultHolder<ItemStack> {
|
||||
val evsGained = pokemon.evs.add(stat, evIncreaseAmount, ItemEvSource(player, stack, pokemon))
|
||||
return if (evsGained > 0) {
|
||||
pokemon.entity?.playSound(sound, 1F, 1F)
|
||||
stack.consume(1, player)
|
||||
if (!player.hasInfiniteMaterials()) {
|
||||
player.giveOrDropItemStack(ItemStack(Items.GLASS_BOTTLE))
|
||||
}
|
||||
onSuccessfulApply(player, stack, pokemon)
|
||||
InteractionResultHolder.success(stack)
|
||||
} else {
|
||||
InteractionResultHolder.fail(stack)
|
||||
}
|
||||
}
|
||||
|
||||
fun onSuccessfulApply(player: ServerPlayer, stack: ItemStack, pokemon: Pokemon)
|
||||
}
|
||||
@@ -11,8 +11,8 @@ package com.cobblemon.mod.common.item.interactive
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.item.CobblemonItem
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.InteractionResultHolder
|
||||
import net.minecraft.world.entity.player.Player
|
||||
@@ -21,7 +21,6 @@ import net.minecraft.world.level.Level
|
||||
|
||||
class FeatherItem(override val stat: Stat): CobblemonItem(Properties()), EVIncreaseItem {
|
||||
override val evIncreaseAmount: Int = 1
|
||||
override val sound: SoundEvent = CobblemonSounds.MEDICINE_FEATHER_USE
|
||||
|
||||
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
|
||||
if (user is ServerPlayer) {
|
||||
@@ -29,4 +28,9 @@ class FeatherItem(override val stat: Stat): CobblemonItem(Properties()), EVIncre
|
||||
}
|
||||
return InteractionResultHolder.success(user.getItemInHand(hand))
|
||||
}
|
||||
|
||||
override fun onSuccessfulApply(player: ServerPlayer, stack: ItemStack, pokemon: Pokemon) {
|
||||
pokemon.entity?.playSound(CobblemonSounds.MEDICINE_FEATHER_USE)
|
||||
stack.consume(1, player)
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@ import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.item.CobblemonItem
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.InteractionResultHolder
|
||||
import net.minecraft.world.entity.player.Player
|
||||
@@ -22,7 +21,6 @@ import net.minecraft.world.level.Level
|
||||
|
||||
class MochiItem(override val stat: Stat): CobblemonItem(Properties()), EVIncreaseItem {
|
||||
override val evIncreaseAmount: Int = 4
|
||||
override val sound: SoundEvent = CobblemonSounds.MOCHI_USE
|
||||
|
||||
override fun applyToPokemon(player: ServerPlayer, stack: ItemStack, pokemon: Pokemon): InteractionResultHolder<ItemStack> {
|
||||
if (!canUseOnPokemon(stack, pokemon)) {
|
||||
@@ -40,4 +38,9 @@ class MochiItem(override val stat: Stat): CobblemonItem(Properties()), EVIncreas
|
||||
}
|
||||
return InteractionResultHolder.success(user.getItemInHand(hand))
|
||||
}
|
||||
|
||||
override fun onSuccessfulApply(player: ServerPlayer, stack: ItemStack, pokemon: Pokemon) {
|
||||
pokemon.entity?.playSound(CobblemonSounds.MOCHI_USE)
|
||||
stack.consume(1, player)
|
||||
}
|
||||
}
|
||||
@@ -10,19 +10,20 @@ package com.cobblemon.mod.common.item.interactive
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.giveOrDropItemStack
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.InteractionResultHolder
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemNameBlockItem
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
|
||||
class VitaminItem(override val stat: Stat, block: Block): ItemNameBlockItem(block, Properties()), EVIncreaseItem {
|
||||
override val evIncreaseAmount: Int = 10
|
||||
override val sound: SoundEvent = CobblemonSounds.MEDICINE_PILLS_USE
|
||||
|
||||
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
|
||||
if (user is ServerPlayer) {
|
||||
@@ -30,4 +31,12 @@ class VitaminItem(override val stat: Stat, block: Block): ItemNameBlockItem(bloc
|
||||
}
|
||||
return InteractionResultHolder.success(user.getItemInHand(hand))
|
||||
}
|
||||
|
||||
override fun onSuccessfulApply(player: ServerPlayer, stack: ItemStack, pokemon: Pokemon) {
|
||||
pokemon.entity?.playSound(CobblemonSounds.MEDICINE_PILLS_USE)
|
||||
stack.consume(1, player)
|
||||
if (!player.hasInfiniteMaterials()) {
|
||||
player.giveOrDropItemStack(Items.GLASS_BOTTLE.defaultInstance)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ import net.minecraft.resources.ResourceKey
|
||||
|
||||
object CobblemonParticles : PlatformRegistry<Registry<ParticleType<*>>, ResourceKey<Registry<ParticleType<*>>>, ParticleType<*>>() {
|
||||
|
||||
override val registry: Registry<ParticleType<*>> = BuiltInRegistries.PARTICLE_TYPE
|
||||
override var registry: Registry<ParticleType<*>>? = BuiltInRegistries.PARTICLE_TYPE
|
||||
override val resourceKey: ResourceKey<Registry<ParticleType<*>>> = Registries.PARTICLE_TYPE
|
||||
|
||||
val SNOWSTORM_PARTICLE_TYPE = this.create("snowstorm", SnowstormParticleType())
|
||||
|
||||
@@ -26,66 +26,58 @@ import net.minecraft.resources.ResourceLocation
|
||||
* @author Licious
|
||||
* @since February 11th, 2023
|
||||
*/
|
||||
abstract class PlatformRegistry<R : Registry<T>, K : ResourceKey<R>, T> {
|
||||
abstract class PlatformRegistry<R : Registry<T>, K : ResourceKey<R>, T>(
|
||||
open var registry: R? = null,
|
||||
open val resourceKey: K? = null
|
||||
) {
|
||||
protected val queue = hashMapOf<ResourceLocation, T>()
|
||||
|
||||
/**
|
||||
* The vanilla [Registry].
|
||||
*/
|
||||
abstract val registry: R
|
||||
/**
|
||||
* Creates a new entry in this registry.
|
||||
*
|
||||
* @param E The type of the entry.
|
||||
* @param name The name of the entry, this will be an [ResourceLocation.path].
|
||||
* @param entry The entry being added.
|
||||
* @return The entry created.
|
||||
*/
|
||||
open fun <E : T> create(name: String, entry: E): E {
|
||||
val resourceLocation = cobblemonResource(name)
|
||||
return this.create(resourceLocation, entry)
|
||||
}
|
||||
|
||||
/**
|
||||
* The vanilla [ResourceKey].
|
||||
*/
|
||||
abstract val resourceKey: K
|
||||
/**
|
||||
* Creates a new entry in this registry. Introduced for sidemod usage
|
||||
*
|
||||
* @param E The type of the entry.
|
||||
* @param resourceLocation The name of the entry, this will be an [ResourceLocation.path].
|
||||
* @param entry The entry being added.
|
||||
* @return The entry created.
|
||||
*/
|
||||
open fun <E : T> create(resourceLocation: ResourceLocation, entry: E): E {
|
||||
this.queue[resourceLocation] = entry
|
||||
if (entry is BagItemLike) {
|
||||
BagItems.bagItems.add(
|
||||
priority = Priority.NORMAL,
|
||||
value = entry
|
||||
)
|
||||
}
|
||||
return entry
|
||||
}
|
||||
|
||||
protected val queue = hashMapOf<ResourceLocation, T>()
|
||||
/**
|
||||
* Handles the registration of this registry into the platform specific one.
|
||||
*
|
||||
* @param consumer The consumer that will handle the logic for registering every entry in this registry into the platform specific one.
|
||||
*/
|
||||
open fun register(consumer: (ResourceLocation, T) -> Unit) {
|
||||
this.queue.forEach(consumer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new entry in this registry.
|
||||
*
|
||||
* @param E The type of the entry.
|
||||
* @param name The name of the entry, this will be an [ResourceLocation.path].
|
||||
* @param entry The entry being added.
|
||||
* @return The entry created.
|
||||
*/
|
||||
open fun <E : T> create(name: String, entry: E): E {
|
||||
val resourceLocation = cobblemonResource(name)
|
||||
return this.create(resourceLocation, entry)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new entry in this registry. Introduced for sidemod usage
|
||||
*
|
||||
* @param E The type of the entry.
|
||||
* @param name The name of the entry, this will be an [ResourceLocation.path].
|
||||
* @param entry The entry being added.
|
||||
* @return The entry created.
|
||||
*/
|
||||
open fun <E : T> create(resourceLocation: ResourceLocation, entry: E): E {
|
||||
this.queue[resourceLocation] = entry
|
||||
if (entry is BagItemLike) {
|
||||
BagItems.bagItems.add(
|
||||
priority = Priority.NORMAL,
|
||||
value = entry
|
||||
)
|
||||
}
|
||||
return entry
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the registration of this registry into the platform specific one.
|
||||
*
|
||||
* @param consumer The consumer that will handle the logic for registering every entry in this registry into the platform specific one.
|
||||
*/
|
||||
open fun register(consumer: (ResourceLocation, T) -> Unit) {
|
||||
this.queue.forEach(consumer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of every entry in this registry.
|
||||
*
|
||||
* @return The entries of this registry.
|
||||
*/
|
||||
open fun all(): Collection<T> = this.queue.values.toList()
|
||||
/**
|
||||
* Returns a collection of every entry in this registry.
|
||||
*
|
||||
* @return The entries of this registry.
|
||||
*/
|
||||
open fun all(): Collection<T> = this.queue.values.toList()
|
||||
|
||||
}
|
||||
+1
@@ -68,6 +68,7 @@ object CobblemonRequirementAdapter : RequirementAdapter {
|
||||
this.registerType(AdvancementRequirement.ADAPTER_VARIANT, AdvancementRequirement::class)
|
||||
this.registerType(OwnerHoldsItemRequirement.ADAPTER_VARIANT, OwnerHoldsItemRequirement::class)
|
||||
this.registerType(ChanceRequirement.ADAPTER_VARIANT, ChanceRequirement::class)
|
||||
this.registerType(NegateRequirement.ADAPTER_VARIANT, NegateRequirement::class)
|
||||
}
|
||||
|
||||
val gson: Gson by lazy {
|
||||
|
||||
+14
-7
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.pokemon.evolution.adapters
|
||||
|
||||
import com.cobblemon.mod.common.util.adapters.CodecBackedAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.RegistryAccessResolver
|
||||
import com.google.gson.JsonDeserializationContext
|
||||
import com.google.gson.JsonDeserializer
|
||||
import com.google.gson.JsonElement
|
||||
@@ -19,6 +20,7 @@ import net.minecraft.advancements.critereon.ItemCustomDataPredicate
|
||||
import net.minecraft.advancements.critereon.ItemPredicate
|
||||
import net.minecraft.advancements.critereon.ItemSubPredicates
|
||||
import net.minecraft.advancements.critereon.NbtPredicate
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
@@ -26,13 +28,16 @@ import net.minecraft.tags.TagKey
|
||||
import java.lang.reflect.Type
|
||||
|
||||
// This is an ugly adapter because breaking changes are scary and people would ;(
|
||||
object LegacyItemConditionWrapperAdapter : JsonDeserializer<ItemPredicate>, JsonSerializer<ItemPredicate> {
|
||||
class LegacyItemConditionWrapperAdapter(val registryAccess: HolderLookup.Provider = RegistryAccessResolver.getAccess())
|
||||
: JsonDeserializer<ItemPredicate>, JsonSerializer<ItemPredicate> {
|
||||
|
||||
private const val TAG_PREFIX = "#"
|
||||
private const val LEGACY_ITEM = "item"
|
||||
private const val LEGACY_NBT = "nbt"
|
||||
companion object {
|
||||
private const val TAG_PREFIX = "#"
|
||||
private const val LEGACY_ITEM = "item"
|
||||
private const val LEGACY_NBT = "nbt"
|
||||
}
|
||||
|
||||
private val codecAdapter = CodecBackedAdapter(ItemPredicate.CODEC)
|
||||
private val codecAdapter = CodecBackedAdapter(ItemPredicate.CODEC, registryAccess)
|
||||
|
||||
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): ItemPredicate {
|
||||
if (json.isJsonPrimitive) {
|
||||
@@ -64,7 +69,9 @@ object LegacyItemConditionWrapperAdapter : JsonDeserializer<ItemPredicate>, Json
|
||||
{ id ->
|
||||
if (isTag) {
|
||||
val tag = TagKey.create(Registries.ITEM, id)
|
||||
builder.of(tag)
|
||||
registryAccess.lookup(Registries.ITEM)
|
||||
.map { builder.of(tag) }
|
||||
.orElseGet { builder }
|
||||
} else {
|
||||
BuiltInRegistries.ITEM.getOptional(id)
|
||||
.map { builder.of(it) }
|
||||
@@ -75,4 +82,4 @@ object LegacyItemConditionWrapperAdapter : JsonDeserializer<ItemPredicate>, Json
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.requirements
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
class NegateRequirement(val inner: Requirement) : Requirement {
|
||||
|
||||
override fun check(pokemon: Pokemon) = !inner.check(pokemon)
|
||||
|
||||
companion object {
|
||||
const val ADAPTER_VARIANT = "negate"
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,10 @@ fun Collection<JsonElement>.toJsonArray(): JsonArray {
|
||||
return array
|
||||
}
|
||||
|
||||
|
||||
fun JsonElement.asJsonObjectOrNull(): JsonObject? =
|
||||
if (isJsonObject) asJsonObject else null
|
||||
|
||||
fun JsonObject.isEmpty() = size() <= 0
|
||||
|
||||
fun JsonObject.isNotEmpty() = size() > 0
|
||||
|
||||
@@ -10,16 +10,19 @@ package com.cobblemon.mod.common.util.adapters
|
||||
|
||||
import com.google.gson.*
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.JsonOps
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.resources.RegistryOps
|
||||
import java.lang.reflect.Type
|
||||
|
||||
class CodecBackedAdapter<T>(val codec: Codec<T>) : JsonDeserializer<T>, JsonSerializer<T> {
|
||||
class CodecBackedAdapter<T>(val codec: Codec<T>, val registryAccess: HolderLookup.Provider = RegistryAccessResolver.getAccess()) : JsonDeserializer<T>, JsonSerializer<T> {
|
||||
|
||||
override fun deserialize(
|
||||
jElement: JsonElement,
|
||||
typeOfT: Type,
|
||||
context: JsonDeserializationContext
|
||||
): T {
|
||||
val ops = RegistryOpsProvider.getOpsWithDefaultFallback()
|
||||
val ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess)
|
||||
val result = ops.withDecoder(codec).apply(jElement)
|
||||
return result.result().orElseThrow {
|
||||
IllegalStateException("Failed to deserialize $jElement: ${result.error().orElse(null)}")
|
||||
@@ -31,7 +34,7 @@ class CodecBackedAdapter<T>(val codec: Codec<T>) : JsonDeserializer<T>, JsonSeri
|
||||
typeOfSrc: Type?,
|
||||
context: JsonSerializationContext?
|
||||
): JsonElement {
|
||||
val ops = RegistryOpsProvider.getOpsWithDefaultFallback()
|
||||
val ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess)
|
||||
val result = ops.withEncoder(codec).apply(src)
|
||||
return result.result().orElseThrow {
|
||||
IllegalStateException("Failed to serialize $src: ${result.error().orElse(null)}")
|
||||
|
||||
+13
-7
@@ -15,27 +15,33 @@ import com.google.gson.JsonElement
|
||||
import com.mojang.serialization.DynamicOps
|
||||
import com.mojang.serialization.JsonOps
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.core.RegistryAccess
|
||||
import net.minecraft.resources.RegistryOps
|
||||
|
||||
/**
|
||||
* Utility for obtaining RegistryOps with the correct client/server registry access.
|
||||
* Used when manually encoding/decoding registry-backed values (e.g., items, predicates).
|
||||
* Utility for getting RegistryAccess with the correct client/server registry access.
|
||||
* Used when as a fallback when manually encoding/decoding registry-backed values (e.g., items, predicates).
|
||||
*/
|
||||
object RegistryOpsProvider {
|
||||
fun getOpsWithDefaultFallback(): DynamicOps<JsonElement> {
|
||||
object RegistryAccessResolver {
|
||||
fun getAccess(): RegistryAccess {
|
||||
try {
|
||||
Cobblemon.implementation
|
||||
} catch (e: UninitializedPropertyAccessException) {
|
||||
return RegistryAccess.EMPTY
|
||||
}
|
||||
if (Cobblemon.implementation.environment() == Environment.CLIENT) {
|
||||
val minecraft = Minecraft.getInstance()
|
||||
if (minecraft != null && minecraft.level != null)
|
||||
return RegistryOps.create(JsonOps.INSTANCE, minecraft.level!!.registryAccess())
|
||||
return minecraft.level!!.registryAccess()
|
||||
}
|
||||
|
||||
|
||||
if (Cobblemon.implementation.environment() == Environment.SERVER) {
|
||||
val server = server()
|
||||
if (server != null)
|
||||
return RegistryOps.create(JsonOps.INSTANCE, server.registryAccess())
|
||||
return server.registryAccess()
|
||||
}
|
||||
|
||||
return JsonOps.INSTANCE
|
||||
return RegistryAccess.EMPTY
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.util.biome
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.core.RegistryAccess
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import java.util.*
|
||||
|
||||
object RegistryExtensions {
|
||||
@JvmStatic
|
||||
fun <T> getRegistryLookup(
|
||||
registryKey: ResourceKey<out Registry<T>>
|
||||
): Optional<HolderLookup.RegistryLookup<T>> {
|
||||
return Cobblemon.registryAccess.getRegistryLookup(registryKey)
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> RegistryAccess?.getRegistryLookup(
|
||||
registryKey: ResourceKey<out Registry<T>>
|
||||
): Optional<HolderLookup.RegistryLookup<T>> {
|
||||
if (this == null || this == RegistryAccess.EMPTY) {
|
||||
return Optional.empty()
|
||||
}
|
||||
|
||||
return this.lookup(registryKey)
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.api.abilities.Abilities
|
||||
import com.cobblemon.mod.common.api.abilities.Ability
|
||||
import com.cobblemon.mod.common.api.moves.BenchedMoves
|
||||
import com.cobblemon.mod.common.api.moves.MoveSet
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.SpeciesFeatures
|
||||
import com.cobblemon.mod.common.pokemon.EVs
|
||||
import com.cobblemon.mod.common.pokemon.FormData
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
@@ -21,20 +22,22 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.Species
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.codec.CodecUtils
|
||||
import com.cobblemon.mod.common.util.codec.internal.ClientPokemonP1.Companion.FEATURES
|
||||
import com.cobblemon.mod.common.util.codec.internal.ClientPokemonP1.Companion.FEATURE_ID
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.MapCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import java.util.Optional
|
||||
import java.util.UUID
|
||||
import net.minecraft.core.UUIDUtil
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.ComponentSerialization
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.StringTag
|
||||
import net.minecraft.nbt.Tag
|
||||
|
||||
internal class PokemonP1(
|
||||
val uuid: UUID,
|
||||
val species: Species,
|
||||
val form: FormData,
|
||||
val nickname: Optional<Component>,
|
||||
val features: List<CompoundTag>,
|
||||
val level: Int,
|
||||
val experience: Int,
|
||||
val friendship: Int,
|
||||
@@ -55,7 +58,22 @@ internal class PokemonP1(
|
||||
other.ability = this.ability
|
||||
other.species = this.species
|
||||
other.form = this.form
|
||||
this.nickname.ifPresent { other.nickname = it.copy() }
|
||||
this.features.forEach { featureNbt ->
|
||||
val featureId = featureNbt.getString(FEATURE_ID)
|
||||
if (featureId.isEmpty()) {
|
||||
return@forEach
|
||||
}
|
||||
val speciesFeatureProviders = SpeciesFeatures.getFeaturesFor(other.species)
|
||||
val feature = speciesFeatureProviders.firstNotNullOfOrNull { provider -> provider(featureNbt) } ?: return@forEach
|
||||
if (
|
||||
featureNbt.contains("keys", Tag.TAG_STRING.toInt()) &&
|
||||
!featureNbt.getList("keys", Tag.TAG_STRING.toInt()).contains(StringTag.valueOf(featureId))
|
||||
) {
|
||||
return@forEach
|
||||
}
|
||||
other.features.removeIf { it.name == feature.name }
|
||||
other.features.add(feature)
|
||||
}
|
||||
other.level = this.level
|
||||
other.experience = this.experience
|
||||
other.setFriendship(this.friendship)
|
||||
@@ -91,7 +109,7 @@ internal class PokemonP1(
|
||||
UUIDUtil.LENIENT_CODEC.fieldOf(DataKeys.POKEMON_UUID).forGetter(PokemonP1::uuid),
|
||||
Species.BY_IDENTIFIER_CODEC.fieldOf(DataKeys.POKEMON_SPECIES_IDENTIFIER).forGetter(PokemonP1::species),
|
||||
Codec.STRING.fieldOf(DataKeys.POKEMON_FORM_ID).forGetter { pokemon -> pokemon.form.formOnlyShowdownId() },
|
||||
ComponentSerialization.CODEC.optionalFieldOf(DataKeys.POKEMON_NICKNAME).forGetter(PokemonP1::nickname),
|
||||
Codec.list(CompoundTag.CODEC).optionalFieldOf(FEATURES, emptyList()).forGetter(PokemonP1::features),
|
||||
CodecUtils.dynamicIntRange(1) { Cobblemon.config.maxPokemonLevel }.fieldOf(DataKeys.POKEMON_LEVEL).forGetter(PokemonP1::level),
|
||||
Codec.intRange(0, Int.MAX_VALUE).fieldOf(DataKeys.POKEMON_EXPERIENCE).forGetter(PokemonP1::experience),
|
||||
CodecUtils.dynamicIntRange(0) { Cobblemon.config.maxPokemonFriendship }.fieldOf(DataKeys.POKEMON_FRIENDSHIP).forGetter(PokemonP1::friendship),
|
||||
@@ -104,9 +122,9 @@ internal class PokemonP1(
|
||||
Codec.FLOAT.fieldOf(DataKeys.POKEMON_SCALE_MODIFIER).forGetter(PokemonP1::scaleModifier),
|
||||
Codec.BOOL.fieldOf(DataKeys.POKEMON_SHINY).forGetter(PokemonP1::shiny),
|
||||
Ability.CODEC.fieldOf(DataKeys.POKEMON_ABILITY).forGetter(PokemonP1::ability)
|
||||
).apply(instance) { uuid, species, formId, nickname, level, experience, friendship, currentHealth, gender, ivs, evs, moveSet, benchedMoves, scaleModifier, shiny, ability ->
|
||||
).apply(instance) { uuid, species, formId, features, level, experience, friendship, currentHealth, gender, ivs, evs, moveSet, benchedMoves, scaleModifier, shiny, ability ->
|
||||
val form = species.forms.firstOrNull { it.formOnlyShowdownId() == formId } ?: species.standardForm
|
||||
PokemonP1(uuid, species, form, nickname, level, experience, friendship, currentHealth, gender, ivs, evs, moveSet, benchedMoves, scaleModifier, shiny, ability)
|
||||
PokemonP1(uuid, species, form, features, level, experience, friendship, currentHealth, gender, ivs, evs, moveSet, benchedMoves, scaleModifier, shiny, ability)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +132,11 @@ internal class PokemonP1(
|
||||
pokemon.uuid,
|
||||
pokemon.species,
|
||||
pokemon.form,
|
||||
Optional.ofNullable(pokemon.nickname),
|
||||
pokemon.features.map { feature ->
|
||||
val nbt = CompoundTag()
|
||||
nbt.putString(FEATURE_ID, feature.name)
|
||||
feature.saveToNBT(nbt)
|
||||
},
|
||||
pokemon.level,
|
||||
pokemon.experience,
|
||||
pokemon.friendship,
|
||||
|
||||
@@ -14,15 +14,12 @@ import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.pokemon.OriginalTrainerType
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.codec.internal.ClientPokemonP1.Companion.FEATURES
|
||||
import com.cobblemon.mod.common.util.codec.internal.ClientPokemonP1.Companion.FEATURE_ID
|
||||
import com.cobblemon.mod.common.util.codec.optionalFieldOfWithDefault
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.MapCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.StringTag
|
||||
import net.minecraft.nbt.Tag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.ComponentSerialization
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import java.util.*
|
||||
@@ -31,7 +28,7 @@ internal data class PokemonP3(
|
||||
val originalTrainerType: OriginalTrainerType,
|
||||
val originalTrainer: Optional<String>,
|
||||
val forcedAspects: Set<String>,
|
||||
val features: List<CompoundTag>,
|
||||
val nickname: Optional<Component>,
|
||||
val heldItemVisible: Optional<Boolean>,
|
||||
val canDropHeldItem: Optional<Boolean>,
|
||||
val cosmeticItem: ItemStack,
|
||||
@@ -51,22 +48,7 @@ internal data class PokemonP3(
|
||||
this.originalTrainer.ifPresent { other.originalTrainer = it }
|
||||
other.refreshOriginalTrainer()
|
||||
other.forcedAspects = this.forcedAspects
|
||||
this.features.forEach { featureNbt ->
|
||||
val featureId = featureNbt.getString(FEATURE_ID)
|
||||
if (featureId.isEmpty()) {
|
||||
return@forEach
|
||||
}
|
||||
val speciesFeatureProviders = SpeciesFeatures.getFeaturesFor(other.species)
|
||||
val feature = speciesFeatureProviders.firstNotNullOfOrNull { provider -> provider(featureNbt) } ?: return@forEach
|
||||
if (
|
||||
featureNbt.contains("keys", Tag.TAG_STRING.toInt()) &&
|
||||
!featureNbt.getList("keys", Tag.TAG_STRING.toInt()).contains(StringTag.valueOf(featureId))
|
||||
) {
|
||||
return@forEach
|
||||
}
|
||||
other.features.removeIf { it.name == feature.name }
|
||||
other.features.add(feature)
|
||||
}
|
||||
this.nickname.ifPresent { other.nickname = it.copy() }
|
||||
this.heldItemVisible.ifPresent { other.heldItemVisible = it }
|
||||
this.canDropHeldItem.ifPresent { other.canDropHeldItem = it }
|
||||
this.cosmeticItem.let { other.cosmeticItem = it }
|
||||
@@ -92,7 +74,7 @@ internal data class PokemonP3(
|
||||
OriginalTrainerType.CODEC.optionalFieldOfWithDefault(DataKeys.POKEMON_ORIGINAL_TRAINER_TYPE, OriginalTrainerType.NONE).forGetter(PokemonP3::originalTrainerType),
|
||||
Codec.STRING.optionalFieldOf(DataKeys.POKEMON_ORIGINAL_TRAINER).forGetter(PokemonP3::originalTrainer),
|
||||
Codec.list(Codec.STRING).optionalFieldOf(DataKeys.POKEMON_FORCED_ASPECTS, emptyList()).forGetter { it.forcedAspects.toMutableList() },
|
||||
Codec.list(CompoundTag.CODEC).optionalFieldOf(FEATURES, emptyList()).forGetter(PokemonP3::features),
|
||||
ComponentSerialization.CODEC.optionalFieldOf(DataKeys.POKEMON_NICKNAME).forGetter(PokemonP3::nickname),
|
||||
Codec.BOOL.optionalFieldOf(DataKeys.HELD_ITEM_VISIBLE).forGetter(PokemonP3::heldItemVisible),
|
||||
Codec.BOOL.optionalFieldOf(DataKeys.HELD_ITEM_AI_DROPPABLE).forGetter(PokemonP3::canDropHeldItem),
|
||||
ItemStack.CODEC.optionalFieldOf(DataKeys.POKEMON_COSMETIC_ITEM).forGetter { Optional.ofNullable(it.cosmeticItem.takeIf { !it.isEmpty }) },
|
||||
@@ -109,7 +91,7 @@ internal data class PokemonP3(
|
||||
originalTrainerType,
|
||||
originalTrainer,
|
||||
forcedAspects,
|
||||
features,
|
||||
nickname,
|
||||
heldItemVisible,
|
||||
canDropHeldItem,
|
||||
cosmeticItem,
|
||||
@@ -125,7 +107,7 @@ internal data class PokemonP3(
|
||||
originalTrainerType,
|
||||
originalTrainer,
|
||||
forcedAspects.toSet(),
|
||||
features,
|
||||
nickname,
|
||||
heldItemVisible,
|
||||
canDropHeldItem,
|
||||
cosmeticItem.orElse(ItemStack.EMPTY),
|
||||
@@ -146,11 +128,7 @@ internal data class PokemonP3(
|
||||
pokemon.originalTrainerType,
|
||||
Optional.ofNullable(pokemon.originalTrainer),
|
||||
pokemon.forcedAspects,
|
||||
pokemon.features.map { feature ->
|
||||
val nbt = CompoundTag()
|
||||
nbt.putString(FEATURE_ID, feature.name)
|
||||
feature.saveToNBT(nbt)
|
||||
},
|
||||
Optional.ofNullable(pokemon.nickname),
|
||||
Optional.ofNullable(pokemon.heldItemVisible),
|
||||
Optional.ofNullable(pokemon.canDropHeldItem),
|
||||
pokemon.cosmeticItem,
|
||||
|
||||
@@ -53,4 +53,60 @@ fun Quaternionf.toEulerXYZDegrees(): Vector3f {
|
||||
vector.z = vector.z.toDegrees()
|
||||
|
||||
return vector
|
||||
}
|
||||
|
||||
|
||||
/* // is not allocation free so just inline ".get(AxisAngle4f)" like in the function below this
|
||||
fun Quaternionf.toScaledAngleAxis(angAxisScaled: Vector3f) {
|
||||
val axisAng4 = AxisAngle4f()
|
||||
this.get(axisAng4)
|
||||
|
||||
angAxisScaled.x = axisAng4.x
|
||||
angAxisScaled.y = axisAng4.y
|
||||
angAxisScaled.z = axisAng4.z
|
||||
angAxisScaled.mul(axisAng4.angle)
|
||||
} */
|
||||
|
||||
fun Quaternionf.toScaledAngleAxis(dest: Vector3f) {
|
||||
var x = this.x
|
||||
var y = this.y
|
||||
var z = this.z
|
||||
var w = this.w
|
||||
|
||||
if (w > 1.0f) {
|
||||
val invNorm = 1.0f / kotlin.math.sqrt(x * x + y * y + z * z + w * w)
|
||||
x *= invNorm
|
||||
y *= invNorm
|
||||
z *= invNorm
|
||||
w *= invNorm
|
||||
}
|
||||
|
||||
val angle = 2.0f * kotlin.math.acos(w)
|
||||
val s = kotlin.math.sqrt(1.0f - w * w)
|
||||
|
||||
if (s < 0.001f) {
|
||||
dest.x = x * angle
|
||||
dest.y = y * angle
|
||||
dest.z = z * angle
|
||||
} else {
|
||||
val invS = angle / s
|
||||
dest.x = x * invS
|
||||
dest.y = y * invS
|
||||
dest.z = z * invS
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun Quaternionf.setFromScaledAngleAxis(angAxisScaled: Vector3f) {
|
||||
val len = angAxisScaled.length()
|
||||
if (len > 1e-5f) {
|
||||
this.rotationAxis(
|
||||
len,
|
||||
angAxisScaled.x / len,
|
||||
angAxisScaled.y / len,
|
||||
angAxisScaled.z / len
|
||||
)
|
||||
} else {
|
||||
this.identity()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* 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.util.math
|
||||
|
||||
import net.minecraft.util.Mth
|
||||
import kotlin.math.max
|
||||
import kotlin.math.sqrt
|
||||
import kotlin.math.abs
|
||||
import org.joml.Quaternionf
|
||||
import org.joml.Vector3f
|
||||
|
||||
/**
|
||||
* Much of the code here is directly taken or inspired off this great article:
|
||||
* https://theorangeduck.com/page/spring-roll-call#critical
|
||||
*
|
||||
* Very much worth the read.
|
||||
*
|
||||
* Util funcitons for using springs to smoothly/naturally approach one value towards a target
|
||||
*/
|
||||
|
||||
/**
|
||||
* Need to pass in and mutate both a value and a velocity to a spring
|
||||
*/
|
||||
class FloatSpring(
|
||||
var value: Float = 0f,
|
||||
var velocity: Float = 0f
|
||||
)
|
||||
|
||||
class QuatSpring(
|
||||
var quat: Quaternionf = Quaternionf(),
|
||||
var angVel: Vector3f = Vector3f()
|
||||
)
|
||||
|
||||
|
||||
/**
|
||||
* Provides a fast negative exponent approximation for e^-x
|
||||
*/
|
||||
fun negExp(x: Float): Float {
|
||||
return 1.0f / (1.0f + x + 0.48f*x*x + 0.235f*x*x*x)
|
||||
}
|
||||
|
||||
fun halflifeToDamping(halflife: Float, eps: Float = 1e-5f): Float {
|
||||
return (4.0f * 0.69314718056f) / (halflife + eps)
|
||||
}
|
||||
|
||||
fun simpleSpringDamper(
|
||||
spring: FloatSpring,
|
||||
goalValue: Float,
|
||||
halflife: Float,
|
||||
dt: Float,
|
||||
isAngle: Boolean = false
|
||||
) {
|
||||
val y = halflifeToDamping(halflife) / 2.0f
|
||||
val j0 = if (isAngle) Mth.wrapDegrees(spring.value - goalValue) else spring.value - goalValue
|
||||
val j1 = spring.velocity + j0*y;
|
||||
val eydt = negExp(y*dt);
|
||||
|
||||
spring.value = eydt*(j0 + j1*dt) + goalValue;
|
||||
spring.velocity = eydt*(spring.velocity - j1*y*dt);
|
||||
}
|
||||
|
||||
fun simpleSpringDamperQuat(
|
||||
spring: QuatSpring,
|
||||
goalQuat: Quaternionf,
|
||||
halflife: Float,
|
||||
dt: Float
|
||||
) {
|
||||
val y = halflifeToDamping(halflife) / 2.0f
|
||||
|
||||
// Quaternions have double cover q and -q represent the same rotation.
|
||||
// so an accidentally rotation the long way could be calculated.
|
||||
// account for that specifically
|
||||
val goal = if (spring.quat.dot(goalQuat) < 0f) {
|
||||
Quaternionf(-goalQuat.x, -goalQuat.y, -goalQuat.z, -goalQuat.w)
|
||||
} else {
|
||||
goalQuat
|
||||
}
|
||||
|
||||
// Gather the rotation from the goal to the current
|
||||
val goalToCurrQuat = Quaternionf(spring.quat).mul(Quaternionf(goal).conjugate())
|
||||
|
||||
val j0 = Vector3f()
|
||||
goalToCurrQuat.toScaledAngleAxis(j0)
|
||||
|
||||
val j1: Vector3f = Vector3f(spring.angVel).add(Vector3f(j0).mul(y))
|
||||
|
||||
val eydt: Float = negExp(y * dt)
|
||||
|
||||
val scaledAxis = Vector3f(j0).add(Vector3f(j1).mul(dt)).mul(eydt)
|
||||
|
||||
spring.quat.setFromScaledAngleAxis(scaledAxis)
|
||||
spring.quat.mul(goal)
|
||||
|
||||
spring.angVel.sub(j1.mul(y * dt))
|
||||
spring.angVel.mul(eydt)
|
||||
}
|
||||
|
||||
/**
|
||||
* Below is essentially the same code as found here: https://github.com/orangeduck/Spring-It-On/blob/main/inertialeasing.c
|
||||
* https://theorangeduck.com/page/inertial-easing <- the blogpost
|
||||
*/
|
||||
|
||||
// Class to hold the "time" along the curve/function and scale of the function currently
|
||||
// Held in this class so both can be mutated and returned in one function call
|
||||
class InertialVals(
|
||||
var t: Float = 0f,
|
||||
var s: Float = 0f,
|
||||
var offset: Float = 0f,
|
||||
)
|
||||
|
||||
// Includes the negative portion
|
||||
fun smoothstep(t: Float, s: Float): Float {
|
||||
return s * (if(t > 1.0f) 1.0f else 3*t*t - 2*t*t*t)
|
||||
}
|
||||
|
||||
// Derivative of the above smoothstep
|
||||
fun smoothstepDt(t: Float, s: Float): Float {
|
||||
return s * (if(t > 1.0f) 0.0f else 6*t - 6*t*t)
|
||||
}
|
||||
|
||||
// Solve for smoothstep parameters `t` and `s` given new target `x` and velocity `v`
|
||||
fun smoothstepSolve( //TODO change these names to make more sense
|
||||
vals: InertialVals,
|
||||
x: Float, // Target Value x
|
||||
v: Float, // Goal velocity
|
||||
overshoot: Float = 0.05f,
|
||||
eps: Float = 1e-8f
|
||||
) {
|
||||
// If velocity is low enough then start from time zero
|
||||
if (abs(v) < 1e-8f) {
|
||||
vals.t = 0f
|
||||
vals.s = x
|
||||
return
|
||||
}
|
||||
|
||||
// If x is negative then invert signs and re-Solve
|
||||
if (x < 0f) {
|
||||
smoothstepSolve(vals, -x, -v, overshoot, eps)
|
||||
vals.s *= -1f
|
||||
return
|
||||
}
|
||||
|
||||
// Find the possible times that solve for the given `x` and `v`
|
||||
// Quadratic formula!
|
||||
val q: Float = sqrt(max((6*x - v)*(6*x - v) + 8*v*v, eps))
|
||||
val t0: Float = (v - 6*x + q) / (4*v)
|
||||
val t1: Float = (v - 6*x - q) / (4*v)
|
||||
|
||||
// Overshoot if the alternative time is between -0.5f and -(0.5f + overshoot)
|
||||
vals.t = if(-0.5f > t1 && t1 > -(0.5f + overshoot)) t1 else t0;
|
||||
|
||||
// Find the un-scaled velocity at the fitted time
|
||||
val vt: Float = smoothstepDt(vals.t, 1f);
|
||||
|
||||
// Find the scaling factor so that the velocity at the fitted time matches
|
||||
vals.s = if(abs(vt) < eps) 0f else v / vt;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.world.biome
|
||||
|
||||
import com.google.gson.JsonElement
|
||||
import net.minecraft.world.level.biome.Biome
|
||||
import net.minecraft.world.level.biome.Climate
|
||||
|
||||
data class CobblemonBiome(
|
||||
val biome: Biome,
|
||||
val parameters: Climate.ParameterPoint,
|
||||
val customData: Map<String, JsonElement> = emptyMap()
|
||||
)
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.world.biome
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.world.biome.parse.CobblemonBiomeJsonParser
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.mojang.serialization.JsonOps
|
||||
import net.minecraft.resources.RegistryOps
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.server.packs.resources.ResourceManager
|
||||
import java.io.Reader
|
||||
|
||||
object CobblemonBiomeLoader : JsonDataRegistry<CobblemonBiome> {
|
||||
|
||||
override val gson: Gson = GsonBuilder().setPrettyPrinting().create()
|
||||
override val typeToken: TypeToken<CobblemonBiome> = TypeToken.get(CobblemonBiome::class.java)
|
||||
override val resourcePath = "biomes"
|
||||
override val id = cobblemonResource(resourcePath)
|
||||
override val type = PackType.SERVER_DATA
|
||||
override val observable = SimpleObservable<CobblemonBiomeLoader>()
|
||||
|
||||
private var loadedBiomes: Map<ResourceLocation, CobblemonBiome> = emptyMap()
|
||||
|
||||
@JvmStatic
|
||||
fun load(
|
||||
manager: ResourceManager,
|
||||
registryInfoLookup: RegistryOps.RegistryInfoLookup
|
||||
): Map<ResourceLocation, CobblemonBiome> {
|
||||
|
||||
val ops = RegistryOps.create(JsonOps.INSTANCE, registryInfoLookup)
|
||||
|
||||
val result = loadJsonData(manager) { reader, _, _ ->
|
||||
parseBiome(reader, ops)
|
||||
}
|
||||
|
||||
loadedBiomes = result.toMap()
|
||||
|
||||
observable.emit(this)
|
||||
Cobblemon.LOGGER.info("MEALAM Loaded {} cobblemon biomes.", result.size)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun parseBiome(
|
||||
reader: Reader,
|
||||
ops: RegistryOps<JsonElement>
|
||||
): CobblemonBiome? = CobblemonBiomeJsonParser.parse(reader, ops)
|
||||
|
||||
override fun reload(manager: ResourceManager) = observable.emit(this)
|
||||
override fun reload(data: Map<ResourceLocation, CobblemonBiome>) = Unit
|
||||
override fun sync(player: ServerPlayer) = Unit
|
||||
|
||||
@JvmStatic
|
||||
fun getLoadedBiomes(): Map<ResourceLocation, CobblemonBiome> = loadedBiomes
|
||||
|
||||
@JvmStatic
|
||||
fun getLoadedBiome(location: ResourceLocation): CobblemonBiome =
|
||||
loadedBiomes[location]
|
||||
?: error("MEALAM Unknown location: $location")
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.world.biome.parse
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import com.mojang.serialization.JsonOps
|
||||
import net.minecraft.resources.RegistryOps
|
||||
import net.minecraft.world.level.biome.Climate
|
||||
|
||||
object ClimateParametersSectionParser : CobblemonBiomeSectionParser {
|
||||
override val id = "parameters"
|
||||
|
||||
override fun parse(
|
||||
root: JsonObject,
|
||||
ops: RegistryOps<JsonElement>,
|
||||
builder: CobblemonBiomeParseBuilder
|
||||
): Boolean {
|
||||
val params = root.getAsJsonObject("parameters")
|
||||
if (params == null) {
|
||||
Cobblemon.LOGGER.error("MEALAM Missing 'parameters' section in biome JSON")
|
||||
return false
|
||||
}
|
||||
|
||||
val result = Climate.ParameterPoint.CODEC.parse(JsonOps.INSTANCE, params)
|
||||
val parameterPoint = result.result().orElse(null)
|
||||
if (parameterPoint == null) {
|
||||
val errorMessage = result.error().map { it.message() }.orElse("unknown error")
|
||||
Cobblemon.LOGGER.error("MEALAM Failed to parse climate parameters: {}", errorMessage)
|
||||
return false
|
||||
}
|
||||
|
||||
builder.parameters = parameterPoint
|
||||
return true
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.world.biome.parse
|
||||
|
||||
import com.cobblemon.mod.common.util.asJsonObjectOrNull
|
||||
import com.cobblemon.mod.common.world.biome.CobblemonBiome
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonParser
|
||||
import net.minecraft.resources.RegistryOps
|
||||
import java.io.Reader
|
||||
|
||||
object CobblemonBiomeJsonParser {
|
||||
private val sectionParsers = mutableListOf(
|
||||
VanillaBiomeSectionParser,
|
||||
ClimateParametersSectionParser,
|
||||
CustomDataSectionParser(setOf("parameters"))
|
||||
)
|
||||
|
||||
fun parse(reader: Reader, ops: RegistryOps<JsonElement>): CobblemonBiome? {
|
||||
val root = JsonParser.parseReader(reader).asJsonObjectOrNull() ?: return null
|
||||
val builder = CobblemonBiomeParseBuilder()
|
||||
|
||||
for (parser in getParsers()) {
|
||||
if (!parser.parse(root, ops, builder) && parser.required) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
return builder.buildOrNull()
|
||||
}
|
||||
|
||||
fun register(parser: CobblemonBiomeSectionParser) {
|
||||
sectionParsers.add(parser)
|
||||
}
|
||||
|
||||
private fun getParsers(): List<CobblemonBiomeSectionParser> = sectionParsers.toList()
|
||||
}
|
||||
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.world.biome.parse
|
||||
|
||||
import com.cobblemon.mod.common.world.biome.CobblemonBiome
|
||||
import com.google.gson.JsonElement
|
||||
import net.minecraft.world.level.biome.Biome
|
||||
import net.minecraft.world.level.biome.Climate
|
||||
|
||||
class CobblemonBiomeParseBuilder {
|
||||
var biome: Biome? = null
|
||||
var parameters: Climate.ParameterPoint? = null
|
||||
val customData: MutableMap<String, JsonElement> = linkedMapOf()
|
||||
|
||||
fun buildOrNull(): CobblemonBiome? {
|
||||
val parsedBiome = biome ?: return null
|
||||
val parsedParameters = parameters ?: return null
|
||||
return CobblemonBiome(parsedBiome, parsedParameters, customData.toMap())
|
||||
}
|
||||
}
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.world.biome.parse
|
||||
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import net.minecraft.resources.RegistryOps
|
||||
|
||||
interface CobblemonBiomeSectionParser {
|
||||
val id: String
|
||||
val required: Boolean
|
||||
get() = true
|
||||
|
||||
fun parse(
|
||||
root: JsonObject,
|
||||
ops: RegistryOps<JsonElement>,
|
||||
builder: CobblemonBiomeParseBuilder
|
||||
): Boolean
|
||||
}
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.world.biome.parse
|
||||
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import net.minecraft.resources.RegistryOps
|
||||
|
||||
class CustomDataSectionParser(
|
||||
private val reservedKeys: Set<String>
|
||||
) : CobblemonBiomeSectionParser {
|
||||
override val id = "custom_data"
|
||||
override val required = false
|
||||
|
||||
override fun parse(
|
||||
root: JsonObject,
|
||||
ops: RegistryOps<JsonElement>,
|
||||
builder: CobblemonBiomeParseBuilder
|
||||
): Boolean {
|
||||
for ((key, value) in root.entrySet()) {
|
||||
if (key !in reservedKeys) {
|
||||
builder.customData[key] = value.deepCopy()
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.world.biome.parse
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import net.minecraft.resources.RegistryOps
|
||||
import net.minecraft.world.level.biome.Biome
|
||||
|
||||
object VanillaBiomeSectionParser : CobblemonBiomeSectionParser {
|
||||
override val id = "vanilla_biome"
|
||||
|
||||
override fun parse(
|
||||
root: JsonObject,
|
||||
ops: RegistryOps<JsonElement>,
|
||||
builder: CobblemonBiomeParseBuilder
|
||||
): Boolean {
|
||||
val result = Biome.DIRECT_CODEC.parse(ops, root)
|
||||
val biome = result.result().orElse(null)
|
||||
if (biome == null) {
|
||||
val errorMessage = result.error().map { it.message() }.orElse("unknown error")
|
||||
Cobblemon.LOGGER.error("MEALAM Failed to parse vanilla biome: {}", errorMessage)
|
||||
return false
|
||||
}
|
||||
|
||||
builder.biome = biome
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ import net.minecraft.world.level.levelgen.feature.Feature
|
||||
|
||||
object CobblemonFeatures : PlatformRegistry<Registry<Feature<*>>, ResourceKey<Registry<Feature<*>>>, Feature<*>>() {
|
||||
|
||||
override val registry: Registry<Feature<*>> = BuiltInRegistries.FEATURE
|
||||
override var registry: Registry<Feature<*>>? = BuiltInRegistries.FEATURE
|
||||
override val resourceKey: ResourceKey<Registry<Feature<*>>> = Registries.FEATURE
|
||||
|
||||
@JvmField
|
||||
|
||||
@@ -43,7 +43,7 @@ class TypeGemFeature : Feature<BlockStateConfiguration>(BlockStateConfiguration.
|
||||
val coreState = TYPE_GEM_CORE.defaultBlockState()
|
||||
|
||||
// Place the gem first then make sure it placed before placing the core.
|
||||
worldGenLevel.setBlock(origin, coreState, UPDATE_ALL)
|
||||
worldGenLevel.setBlock(chosenPos, gemState, UPDATE_ALL)
|
||||
if (!worldGenLevel.getBlockState(chosenPos).`is`(gemBlock)) {
|
||||
return false
|
||||
}
|
||||
|
||||
+7173
-195
File diff suppressed because it is too large.
Load diff
+1805
-337
File diff suppressed because it is too large.
Load diff
+245
-151
@@ -1,192 +1,286 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.absol.render": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"hips": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
},
|
||||
"chest": {
|
||||
"rotation": [12.5, 0, 0]
|
||||
},
|
||||
"tail": {
|
||||
"rotation": [-8.01788, 32.61138, -0.66603]
|
||||
},
|
||||
"neck": {
|
||||
"rotation": [15.34479, -13.10699, 9.18372]
|
||||
},
|
||||
"head": {
|
||||
"rotation": [-25.32307, -13.66763, -4.61603]
|
||||
},
|
||||
"hair": {
|
||||
"rotation": [0, 0, 45]
|
||||
},
|
||||
"hair2": {
|
||||
"rotation": [1.95155, 7.24305, 27.62353]
|
||||
},
|
||||
"hair3": {
|
||||
"rotation": [8.61775, 34.05444, 17.64371]
|
||||
},
|
||||
"neck_fur_right2": {
|
||||
"rotation": [0, 0, -30]
|
||||
},
|
||||
"neck_fur_left2": {
|
||||
"rotation": [0, 0, 40]
|
||||
},
|
||||
"neck_fur_back2": {
|
||||
"rotation": [-45, 0, 0]
|
||||
},
|
||||
"chest_fur": {
|
||||
"rotation": [-42.5, 0, 0]
|
||||
},
|
||||
"chest_fur_right": {
|
||||
"rotation": [0, 35, 0]
|
||||
},
|
||||
"chest_fur_left": {
|
||||
"rotation": [0, -25, 0]
|
||||
},
|
||||
"chest_fur_1": {
|
||||
"rotation": [27.5, 0, 0]
|
||||
},
|
||||
"chest_fur_2": {
|
||||
"rotation": [7.5, 0, 0]
|
||||
},
|
||||
"leg_back_left": {
|
||||
"rotation": [21.9659, -13.44762, -0.11731]
|
||||
},
|
||||
"leg_back_left2": {
|
||||
"rotation": [-10, 0, 0]
|
||||
},
|
||||
"leg_back_left3": {
|
||||
"rotation": [5, 0, 0]
|
||||
},
|
||||
"foot__back_left": {
|
||||
"rotation": [-14.82005, -12.39135, -1.6575]
|
||||
},
|
||||
"leg_front_left": {
|
||||
"rotation": [-25.47479, -17.22575, 3.13388],
|
||||
"position": [0, -0.25, 0]
|
||||
},
|
||||
"leg_front_left2": {
|
||||
"rotation": [14.61364, 12.22219, 2.52829]
|
||||
},
|
||||
"foot_front_left": {
|
||||
"rotation": [12.15846, -18.26883, -13.36473]
|
||||
},
|
||||
"eyes_open": {
|
||||
"position": [0, 0, 0]
|
||||
},
|
||||
"eyes_happy": {
|
||||
"position": [0, 0, 0]
|
||||
},
|
||||
"eyes_closed": {
|
||||
"position": [0, 0, 0]
|
||||
},
|
||||
"eyes_halfclosed": {
|
||||
"position": [0, 0, 0]
|
||||
},
|
||||
"leg_back_right": {
|
||||
"rotation": [0, -22.5, 0],
|
||||
"position": [-0.11888, 0, -1.67283]
|
||||
},
|
||||
"foot_back_right": {
|
||||
"rotation": [0, 15, 0]
|
||||
},
|
||||
"waist": {
|
||||
"rotation": [0, -20, 0]
|
||||
},
|
||||
"leg_front_right": {
|
||||
"rotation": [12.5, 0, 0]
|
||||
},
|
||||
"leg_front_right2": {
|
||||
"rotation": [0, 0, -10]
|
||||
},
|
||||
"foot_front_right": {
|
||||
"rotation": [-12.07362, 14.63639, 13.31914]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.absol.ground_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"neck": {
|
||||
"rotation": [20, 0, 0]
|
||||
"rotation": [30, 0, 0]
|
||||
},
|
||||
"head": {
|
||||
"rotation": [-17.5, 0, 0]
|
||||
},
|
||||
"hair": {
|
||||
"rotation": [0, 0, 47]
|
||||
"rotation": [0, 0, -2.5]
|
||||
},
|
||||
"hair2": {
|
||||
"rotation": [0, 8.5, 38]
|
||||
"rotation": [2.5, 10, 0]
|
||||
},
|
||||
"hair3": {
|
||||
"rotation": [9.69368, 25.60466, 13.24197]
|
||||
"rotation": [1.9544, 7.5589, 12.4168]
|
||||
},
|
||||
"neck_fur_right2": {
|
||||
"rotation": [0, 0, -30]
|
||||
"neck_fluff_left": {
|
||||
"rotation": [0, 0, 67.5]
|
||||
},
|
||||
"neck_fur_left2": {
|
||||
"rotation": [0, 0, 40]
|
||||
},
|
||||
"neck_fur_back2": {
|
||||
"neck_fluff_back": {
|
||||
"rotation": [-45, 0, 0]
|
||||
},
|
||||
"chest_fur": {
|
||||
"rotation": [-30, 0, 0]
|
||||
"chest_fluff": {
|
||||
"rotation": [-12.5, 0, 0]
|
||||
},
|
||||
"chest_fur_right": {
|
||||
"rotation": [0, 35, 0]
|
||||
"chest_fluff_right": {
|
||||
"rotation": [0, 37.5, 0]
|
||||
},
|
||||
"chest_fur_left": {
|
||||
"rotation": [0, -25, 0]
|
||||
"chest_fluff_left": {
|
||||
"rotation": [0, -37.5, 0]
|
||||
},
|
||||
"chest_fur_1": {
|
||||
"rotation": [27.5, 0, 0]
|
||||
"chest_fluff2": {
|
||||
"rotation": [-7.5, 0, 0]
|
||||
},
|
||||
"chest_fur_2": {
|
||||
"chest_fluff3": {
|
||||
"rotation": [7.5, 0, 0]
|
||||
},
|
||||
"tail": {
|
||||
"rotation": [-22.5, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.absol.cry": {
|
||||
"animation_length": 2,
|
||||
"bones": {
|
||||
"mouth": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.17],
|
||||
"0.25": {"pre": [0, 0, 0.17], "post": [0, 0, -1]},
|
||||
"1.7917": {"pre": [0, 0, -1], "post": [0, 0, 0.17]}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sound_effects": {
|
||||
"0.04": {
|
||||
"effect": "pokemon.absol.cry"
|
||||
"rotation": [10, 0, 0]
|
||||
},
|
||||
"neck_fluff_right": {
|
||||
"rotation": [0, 0, -67.5]
|
||||
},
|
||||
"torso": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
},
|
||||
"torso2": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"head_angle": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"leg_front_left": {
|
||||
"rotation": [-4.9083, 1.8509, 2.416]
|
||||
},
|
||||
"leg_back_left": {
|
||||
"rotation": [0, -10, 0]
|
||||
},
|
||||
"leg_back_left2": {
|
||||
"rotation": [5, 0, 0]
|
||||
},
|
||||
"leg_back_left3": {
|
||||
"rotation": [10, 0, 0]
|
||||
},
|
||||
"foot_back_left": {
|
||||
"rotation": [-13.9904, -4.9952, -0.2186]
|
||||
},
|
||||
"foot_front_left": {
|
||||
"rotation": [4.991, -1.4949, -3.2033]
|
||||
},
|
||||
"neck_fluff_back2": {
|
||||
"rotation": [-50, 0, 0]
|
||||
},
|
||||
"leg_front_right": {
|
||||
"rotation": [2.585, -1.6431, -2.3501]
|
||||
},
|
||||
"leg_front_right2": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
},
|
||||
"foot_front_right": {
|
||||
"rotation": [-4.9201, 6.845, 3.7466]
|
||||
},
|
||||
"leg_back_right": {
|
||||
"rotation": [0, 10, 0]
|
||||
},
|
||||
"leg_back_right2": {
|
||||
"rotation": [5, 0, 0]
|
||||
},
|
||||
"leg_back_right3": {
|
||||
"rotation": [10, 0, 0]
|
||||
},
|
||||
"foot_back_right": {
|
||||
"rotation": [-13.9904, 4.9952, 0.2186]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.absol.blink": {
|
||||
"animation_length": 0.1667,
|
||||
"bones": {
|
||||
"eyes_open": {
|
||||
"eye_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 1],
|
||||
"0.125": {"pre": [0, 0, 1], "post": [0, 0, 1]},
|
||||
"0.1667": {"pre": [0, 0, 1], "post": [0, 0, 0]}
|
||||
"0.0": [-0.1, 0, 0.1],
|
||||
"0.1667": {"pre": [-0.1, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_closed": {
|
||||
"eye_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -1],
|
||||
"0.125": {"pre": [0, 0, -1], "post": [0, 0, -1]},
|
||||
"0.1667": {"pre": [0, 0, -1], "post": [0, 0, 0]}
|
||||
"0.0": [0.1, 0, 0.1],
|
||||
"0.1667": {"pre": [0.1, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [-0.1, 0, -0.1],
|
||||
"0.1667": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0.1, 0, -0.1],
|
||||
"0.1667": {"pre": [0.1, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_blink_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.absol.ditto_face": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"face": {
|
||||
"position": [0, 0, 0.1],
|
||||
"scale": 0
|
||||
},
|
||||
"face_ditto": {
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.absol.pose": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"neck": {
|
||||
"rotation": [30.3812, -8.6492, -5.0384]
|
||||
},
|
||||
"head": {
|
||||
"rotation": [-17.5, 0, 0]
|
||||
},
|
||||
"hair": {
|
||||
"rotation": [0, 0, -2.5]
|
||||
},
|
||||
"hair2": {
|
||||
"rotation": [2.5, 10, 0]
|
||||
},
|
||||
"hair3": {
|
||||
"rotation": [1.9544, 7.5589, 12.4168]
|
||||
},
|
||||
"neck_fluff_left": {
|
||||
"rotation": [0, 0, 67.5]
|
||||
},
|
||||
"neck_fluff_back": {
|
||||
"rotation": [-45, 0, 0]
|
||||
},
|
||||
"chest_fluff": {
|
||||
"rotation": [-17.5, 0, 0]
|
||||
},
|
||||
"chest_fluff_right": {
|
||||
"rotation": [0, 37.5, 0]
|
||||
},
|
||||
"chest_fluff_left": {
|
||||
"rotation": [0, -37.5, 0]
|
||||
},
|
||||
"chest_fluff2": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"chest_fluff3": {
|
||||
"rotation": [7.5, 0, 0]
|
||||
},
|
||||
"tail": {
|
||||
"rotation": [-2.2793, -9.656, -2.6129]
|
||||
},
|
||||
"horn": {
|
||||
"rotation": [0, -10, 0]
|
||||
},
|
||||
"neck_fluff_right": {
|
||||
"rotation": [0, 0, -52.5]
|
||||
},
|
||||
"body": {
|
||||
"rotation": [0, 65, 0],
|
||||
"position": [2, -0.55, 0]
|
||||
},
|
||||
"torso": {
|
||||
"rotation": [9.9864, 0.6469, -2.4149]
|
||||
},
|
||||
"torso2": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"head_angle": {
|
||||
"rotation": [-5.7686, -29.8743, 2.8806]
|
||||
},
|
||||
"leg_front_left": {
|
||||
"rotation": [16.5711, -9.4592, -13.6836],
|
||||
"position": [0.75, -2, 0]
|
||||
},
|
||||
"leg_front_left2": {
|
||||
"rotation": [-45, 0, 0]
|
||||
},
|
||||
"leg_back_left": {
|
||||
"rotation": [14.2119, -9.413, -10.1281]
|
||||
},
|
||||
"leg_back_left2": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
},
|
||||
"leg_back_left3": {
|
||||
"rotation": [17.5, 0, 0]
|
||||
},
|
||||
"foot_back_left": {
|
||||
"rotation": [-27.3943, 4.3233, 8.0916]
|
||||
},
|
||||
"iris_left": {
|
||||
"position": [1, 0, 0]
|
||||
},
|
||||
"foot_front_left": {
|
||||
"rotation": [41.9868, -4.2611, 0.0665],
|
||||
"position": [0, 0, -0.75]
|
||||
},
|
||||
"claw_middle_front_left": {
|
||||
"rotation": [7.5, 0, 0]
|
||||
},
|
||||
"claw_outer_front_left": {
|
||||
"rotation": [7.5, 0, 0]
|
||||
},
|
||||
"claw_inner_front_left": {
|
||||
"rotation": [7.5, 0, 0]
|
||||
},
|
||||
"neck_fluff_back2": {
|
||||
"rotation": [-50, 0, 0]
|
||||
},
|
||||
"leg_front_right": {
|
||||
"rotation": [-37.5352, -0.064, 9.7291],
|
||||
"position": [-0.25, -1.75, 0]
|
||||
},
|
||||
"leg_front_right2": {
|
||||
"rotation": [3.5, 0, 0]
|
||||
},
|
||||
"foot_front_right": {
|
||||
"rotation": [34.0275, 7.3656, -7.2548],
|
||||
"position": [0, 0.3, 0]
|
||||
},
|
||||
"leg_back_right": {
|
||||
"rotation": [-18.2881, 9.413, 10.1281],
|
||||
"position": [-0.25, 0, 0]
|
||||
},
|
||||
"leg_back_right2": {
|
||||
"rotation": [16.5248, 0.124, 0.1823]
|
||||
},
|
||||
"leg_back_right3": {
|
||||
"rotation": [6, 0, 0]
|
||||
},
|
||||
"foot_back_right": {
|
||||
"rotation": [-2.4124, 5.5284, -9.8095]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.absol.cry": {
|
||||
"sound_effects": {
|
||||
"0.04": {
|
||||
"effect": "pokemon.absol.cry"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1028
-26
File diff suppressed because it is too large.
Load diff
+208
@@ -0,0 +1,208 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.burmy_plant.ground_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"rotation": [2.5201, 0.3141, 0.0322],
|
||||
"position": [0, 6, 0]
|
||||
},
|
||||
"body_rotation": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
},
|
||||
"spring2": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
},
|
||||
"segment1": {
|
||||
"position": [0, 0.5, 0]
|
||||
},
|
||||
"leg_left1": {
|
||||
"rotation": [0, 15, 0]
|
||||
},
|
||||
"leg_right1": {
|
||||
"rotation": [0, -15, 0]
|
||||
},
|
||||
"segment2": {
|
||||
"position": [0, 0.5, 0]
|
||||
},
|
||||
"segment3": {
|
||||
"position": [0, 0.5, 0]
|
||||
},
|
||||
"leg_left2": {
|
||||
"rotation": [0, 17.5, 0]
|
||||
},
|
||||
"leg_left3": {
|
||||
"rotation": [0, 25, 0]
|
||||
},
|
||||
"leg_right2": {
|
||||
"rotation": [0, -17.5, 0]
|
||||
},
|
||||
"leg_right3": {
|
||||
"rotation": [0, -25, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.burmy_plant.ground_idle_naked": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body_rotation": {
|
||||
"rotation": [7.5, 0, 0],
|
||||
"position": [0, 0, -3]
|
||||
},
|
||||
"segment1": {
|
||||
"rotation": [75, 0, 0]
|
||||
},
|
||||
"leg_left1": {
|
||||
"rotation": [0.00002, 0.00005, 0.00002]
|
||||
},
|
||||
"cloak_plant": {
|
||||
"scale": 0
|
||||
},
|
||||
"body": {
|
||||
"rotation": [2.5, 0, 0],
|
||||
"position": [0, -7.25, 0]
|
||||
},
|
||||
"leg_right1": {
|
||||
"rotation": [0.00002, -0.00005, -0.00002]
|
||||
},
|
||||
"segment2": {
|
||||
"rotation": [5, 0, 0]
|
||||
},
|
||||
"segment3": {
|
||||
"rotation": [2.5781, -0.5734, 0.2485]
|
||||
},
|
||||
"leg_left2": {
|
||||
"rotation": [2.53742, -4.92385, -0.87038]
|
||||
},
|
||||
"leg_left3": {
|
||||
"rotation": [7.53742, -4.92385, -0.87038]
|
||||
},
|
||||
"leg_right2": {
|
||||
"rotation": [2.53742, 4.92385, 0.87038]
|
||||
},
|
||||
"leg_right3": {
|
||||
"rotation": [7.53742, 4.92385, 0.87038]
|
||||
},
|
||||
"face": {
|
||||
"position": [0, 0, 1]
|
||||
},
|
||||
"cloaked_face": {
|
||||
"scale": 0
|
||||
},
|
||||
"face_ditto": {
|
||||
"position": [0, 0, 1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.burmy_plant.spring": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"rotation": [2.5201, 0.3141, 0.0322],
|
||||
"position": [0, 6, 0]
|
||||
},
|
||||
"body_rotation": {
|
||||
"rotation": [2.5, 0, 0],
|
||||
"position": [0, -3, 0]
|
||||
},
|
||||
"spring2": {
|
||||
"rotation": [35.9366, -29.087, 32.6804]
|
||||
},
|
||||
"segment1": {
|
||||
"position": [0, 0.5, 0]
|
||||
},
|
||||
"leg_left1": {
|
||||
"rotation": [0, 15, 0]
|
||||
},
|
||||
"spring": {
|
||||
"rotation": [-26.941, -5.7358, -11.1249]
|
||||
},
|
||||
"spring3": {
|
||||
"rotation": [-24.3803, 6.6782, -46.9093]
|
||||
},
|
||||
"spring4": {
|
||||
"rotation": [0, 0, -35]
|
||||
},
|
||||
"leg_right1": {
|
||||
"rotation": [0, -15, 0]
|
||||
},
|
||||
"segment2": {
|
||||
"position": [0, 0.5, 0]
|
||||
},
|
||||
"segment3": {
|
||||
"position": [0, 0.5, 0]
|
||||
},
|
||||
"leg_left2": {
|
||||
"rotation": [0, 17.5, 0]
|
||||
},
|
||||
"leg_left3": {
|
||||
"rotation": [0, 25, 0]
|
||||
},
|
||||
"leg_right2": {
|
||||
"rotation": [0, -17.5, 0]
|
||||
},
|
||||
"leg_right3": {
|
||||
"rotation": [0, -25, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.burmy_plant.ditto_face": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"face": {
|
||||
"position": [0, 0, 0.1],
|
||||
"scale": 0
|
||||
},
|
||||
"face_ditto": {
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.burmy_plant.blink": {
|
||||
"animation_length": 0.1667,
|
||||
"bones": {
|
||||
"pupil_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.125": {"pre": [0, 0, 0.1], "post": [0, 0, 0.1]},
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_closed_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.125": {"pre": [0, 0, -0.1], "post": [0, 0, -0.1]},
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.125": {"pre": [0, 0, 0.1], "post": [0, 0, 0.1]},
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_closed_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.125": {"pre": [0, 0, -0.1], "post": [0, 0, -0.1]},
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_blink_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+208
@@ -0,0 +1,208 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.burmy_sandy.ground_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"rotation": [2.5201, 0.3141, 0.0322],
|
||||
"position": [0, 6, 0]
|
||||
},
|
||||
"body_rotation": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
},
|
||||
"spring2": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
},
|
||||
"segment1": {
|
||||
"position": [0, 0.5, 0]
|
||||
},
|
||||
"leg_left1": {
|
||||
"rotation": [0, 15, 0]
|
||||
},
|
||||
"leg_right1": {
|
||||
"rotation": [0, -15, 0]
|
||||
},
|
||||
"segment2": {
|
||||
"position": [0, 0.5, 0]
|
||||
},
|
||||
"segment3": {
|
||||
"position": [0, 0.5, 0]
|
||||
},
|
||||
"leg_left2": {
|
||||
"rotation": [0, 17.5, 0]
|
||||
},
|
||||
"leg_left3": {
|
||||
"rotation": [0, 25, 0]
|
||||
},
|
||||
"leg_right2": {
|
||||
"rotation": [0, -17.5, 0]
|
||||
},
|
||||
"leg_right3": {
|
||||
"rotation": [0, -25, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.burmy_sandy.ground_idle_naked": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body_rotation": {
|
||||
"rotation": [7.5, 0, 0],
|
||||
"position": [0, 0, -3]
|
||||
},
|
||||
"segment1": {
|
||||
"rotation": [75, 0, 0]
|
||||
},
|
||||
"leg_left1": {
|
||||
"rotation": [0.00002, 0.00005, 0.00002]
|
||||
},
|
||||
"cloak_plant": {
|
||||
"scale": 0
|
||||
},
|
||||
"body": {
|
||||
"rotation": [2.5, 0, 0],
|
||||
"position": [0, -7.25, 0]
|
||||
},
|
||||
"leg_right1": {
|
||||
"rotation": [0.00002, -0.00005, -0.00002]
|
||||
},
|
||||
"segment2": {
|
||||
"rotation": [5, 0, 0]
|
||||
},
|
||||
"segment3": {
|
||||
"rotation": [2.5781, -0.5734, 0.2485]
|
||||
},
|
||||
"leg_left2": {
|
||||
"rotation": [2.53742, -4.92385, -0.87038]
|
||||
},
|
||||
"leg_left3": {
|
||||
"rotation": [7.53742, -4.92385, -0.87038]
|
||||
},
|
||||
"leg_right2": {
|
||||
"rotation": [2.53742, 4.92385, 0.87038]
|
||||
},
|
||||
"leg_right3": {
|
||||
"rotation": [7.53742, 4.92385, 0.87038]
|
||||
},
|
||||
"face": {
|
||||
"position": [0, 0, 1]
|
||||
},
|
||||
"cloaked_face": {
|
||||
"scale": 0
|
||||
},
|
||||
"face_ditto": {
|
||||
"position": [0, 0, 1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.burmy_sandy.spring": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"rotation": [2.5201, 0.3141, 0.0322],
|
||||
"position": [0, 6, 0]
|
||||
},
|
||||
"body_rotation": {
|
||||
"rotation": [2.5, 0, 0],
|
||||
"position": [0, -3, 0]
|
||||
},
|
||||
"spring2": {
|
||||
"rotation": [35.9366, -29.087, 32.6804]
|
||||
},
|
||||
"segment1": {
|
||||
"position": [0, 0.5, 0]
|
||||
},
|
||||
"leg_left1": {
|
||||
"rotation": [0, 15, 0]
|
||||
},
|
||||
"spring": {
|
||||
"rotation": [-26.941, -5.7358, -11.1249]
|
||||
},
|
||||
"spring3": {
|
||||
"rotation": [-24.3803, 6.6782, -46.9093]
|
||||
},
|
||||
"spring4": {
|
||||
"rotation": [0, 0, -35]
|
||||
},
|
||||
"leg_right1": {
|
||||
"rotation": [0, -15, 0]
|
||||
},
|
||||
"segment2": {
|
||||
"position": [0, 0.5, 0]
|
||||
},
|
||||
"segment3": {
|
||||
"position": [0, 0.5, 0]
|
||||
},
|
||||
"leg_left2": {
|
||||
"rotation": [0, 17.5, 0]
|
||||
},
|
||||
"leg_left3": {
|
||||
"rotation": [0, 25, 0]
|
||||
},
|
||||
"leg_right2": {
|
||||
"rotation": [0, -17.5, 0]
|
||||
},
|
||||
"leg_right3": {
|
||||
"rotation": [0, -25, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.burmy_sandy.ditto_face": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"face": {
|
||||
"position": [0, 0, 0.1],
|
||||
"scale": 0
|
||||
},
|
||||
"face_ditto": {
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.burmy_sandy.blink": {
|
||||
"animation_length": 0.1667,
|
||||
"bones": {
|
||||
"pupil_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.125": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_closed_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.125": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.125": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_closed_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.125": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_blink_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+208
@@ -0,0 +1,208 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.burmy_trash.ground_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"rotation": [2.5201, 0.3141, 0.0322],
|
||||
"position": [0, 6, 0]
|
||||
},
|
||||
"body_rotation": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
},
|
||||
"spring2": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
},
|
||||
"segment1": {
|
||||
"position": [0, 0.5, 0]
|
||||
},
|
||||
"leg_left1": {
|
||||
"rotation": [0, 15, 0]
|
||||
},
|
||||
"leg_right1": {
|
||||
"rotation": [0, -15, 0]
|
||||
},
|
||||
"segment2": {
|
||||
"position": [0, 0.5, 0]
|
||||
},
|
||||
"segment3": {
|
||||
"position": [0, 0.5, 0]
|
||||
},
|
||||
"leg_left2": {
|
||||
"rotation": [0, 17.5, 0]
|
||||
},
|
||||
"leg_left3": {
|
||||
"rotation": [0, 25, 0]
|
||||
},
|
||||
"leg_right2": {
|
||||
"rotation": [0, -17.5, 0]
|
||||
},
|
||||
"leg_right3": {
|
||||
"rotation": [0, -25, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.burmy_trash.ground_idle_naked": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body_rotation": {
|
||||
"rotation": [7.5, 0, 0],
|
||||
"position": [0, 0, -3]
|
||||
},
|
||||
"segment1": {
|
||||
"rotation": [75, 0, 0]
|
||||
},
|
||||
"leg_left1": {
|
||||
"rotation": [0.00002, 0.00005, 0.00002]
|
||||
},
|
||||
"cloak_plant": {
|
||||
"scale": 0
|
||||
},
|
||||
"body": {
|
||||
"rotation": [2.5, 0, 0],
|
||||
"position": [0, -7.25, 0]
|
||||
},
|
||||
"leg_right1": {
|
||||
"rotation": [0.00002, -0.00005, -0.00002]
|
||||
},
|
||||
"segment2": {
|
||||
"rotation": [5, 0, 0]
|
||||
},
|
||||
"segment3": {
|
||||
"rotation": [2.5781, -0.5734, 0.2485]
|
||||
},
|
||||
"leg_left2": {
|
||||
"rotation": [2.53742, -4.92385, -0.87038]
|
||||
},
|
||||
"leg_left3": {
|
||||
"rotation": [7.53742, -4.92385, -0.87038]
|
||||
},
|
||||
"leg_right2": {
|
||||
"rotation": [2.53742, 4.92385, 0.87038]
|
||||
},
|
||||
"leg_right3": {
|
||||
"rotation": [7.53742, 4.92385, 0.87038]
|
||||
},
|
||||
"face": {
|
||||
"position": [0, 0, 1]
|
||||
},
|
||||
"cloaked_face": {
|
||||
"scale": 0
|
||||
},
|
||||
"face_ditto": {
|
||||
"position": [0, 0, 1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.burmy_trash.spring": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"rotation": [2.5201, 0.3141, 0.0322],
|
||||
"position": [0, 6, 0]
|
||||
},
|
||||
"body_rotation": {
|
||||
"rotation": [2.5, 0, 0],
|
||||
"position": [0, -3, 0]
|
||||
},
|
||||
"spring2": {
|
||||
"rotation": [35.9366, -29.087, 32.6804]
|
||||
},
|
||||
"segment1": {
|
||||
"position": [0, 0.5, 0]
|
||||
},
|
||||
"leg_left1": {
|
||||
"rotation": [0, 15, 0]
|
||||
},
|
||||
"spring": {
|
||||
"rotation": [-26.941, -5.7358, -11.1249]
|
||||
},
|
||||
"spring3": {
|
||||
"rotation": [-24.3803, 6.6782, -46.9093]
|
||||
},
|
||||
"spring4": {
|
||||
"rotation": [0, 0, -35]
|
||||
},
|
||||
"leg_right1": {
|
||||
"rotation": [0, -15, 0]
|
||||
},
|
||||
"segment2": {
|
||||
"position": [0, 0.5, 0]
|
||||
},
|
||||
"segment3": {
|
||||
"position": [0, 0.5, 0]
|
||||
},
|
||||
"leg_left2": {
|
||||
"rotation": [0, 17.5, 0]
|
||||
},
|
||||
"leg_left3": {
|
||||
"rotation": [0, 25, 0]
|
||||
},
|
||||
"leg_right2": {
|
||||
"rotation": [0, -17.5, 0]
|
||||
},
|
||||
"leg_right3": {
|
||||
"rotation": [0, -25, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.burmy_trash.ditto_face": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"face": {
|
||||
"position": [0, 0, 0.1],
|
||||
"scale": 0
|
||||
},
|
||||
"face_ditto": {
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.burmy_trash.blink": {
|
||||
"animation_length": 0.1667,
|
||||
"bones": {
|
||||
"pupil_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.125": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_closed_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.125": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.125": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_closed_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.125": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_blink_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.wormadam_plant.ground_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"rotation": [5, 0, 0],
|
||||
"position": [0, 6, 0]
|
||||
},
|
||||
"body_rotation": {
|
||||
"rotation": [0, 0, 0]
|
||||
},
|
||||
"antenna": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
},
|
||||
"ear_left": {
|
||||
"rotation": [0, -12.5, 0]
|
||||
},
|
||||
"ear_left2": {
|
||||
"rotation": [0, 0, 20]
|
||||
},
|
||||
"ear_left3": {
|
||||
"rotation": [0, 0, 22.5]
|
||||
},
|
||||
"ear_back_left": {
|
||||
"rotation": [-7.5, 0, 25]
|
||||
},
|
||||
"ear_left4": {
|
||||
"rotation": [0, 0, 17.5]
|
||||
},
|
||||
"ear_right": {
|
||||
"rotation": [0, 12.5, 0]
|
||||
},
|
||||
"ear_right2": {
|
||||
"rotation": [0, 0, -20]
|
||||
},
|
||||
"ear_right3": {
|
||||
"rotation": [0, 0, -22.5]
|
||||
},
|
||||
"ear_right4": {
|
||||
"rotation": [0, 0, -17.5]
|
||||
},
|
||||
"ear_back_right": {
|
||||
"rotation": [-7.5, 0, -25]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.wormadam_plant.blink": {
|
||||
"animation_length": 0.1667,
|
||||
"bones": {
|
||||
"pupil_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.125": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_closed_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.125": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.125": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_closed_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.125": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_blink_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.wormadam_plant.ditto_face": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"face": {
|
||||
"position": [0, 0, 0.1],
|
||||
"scale": 0
|
||||
},
|
||||
"face_ditto": {
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.wormadam_sandy.ground_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"rotation": [5, 0, 0],
|
||||
"position": [0, 6, 0]
|
||||
},
|
||||
"body_rotation": {
|
||||
"rotation": [0, 0, 0]
|
||||
},
|
||||
"antenna": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
},
|
||||
"ear_left": {
|
||||
"rotation": [0, -12.5, 0]
|
||||
},
|
||||
"ear_left2": {
|
||||
"rotation": [0, 0, 20]
|
||||
},
|
||||
"ear_left3": {
|
||||
"rotation": [0, 0, 22.5]
|
||||
},
|
||||
"ear_back_left": {
|
||||
"rotation": [-7.5, 0, 25]
|
||||
},
|
||||
"ear_left4": {
|
||||
"rotation": [0, 0, 17.5]
|
||||
},
|
||||
"ear_right": {
|
||||
"rotation": [0, 12.5, 0]
|
||||
},
|
||||
"ear_right2": {
|
||||
"rotation": [0, 0, -20]
|
||||
},
|
||||
"ear_right3": {
|
||||
"rotation": [0, 0, -22.5]
|
||||
},
|
||||
"ear_right4": {
|
||||
"rotation": [0, 0, -17.5]
|
||||
},
|
||||
"ear_back_right": {
|
||||
"rotation": [-7.5, 0, -25]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.wormadam_sandy.blink": {
|
||||
"animation_length": 0.1667,
|
||||
"bones": {
|
||||
"pupil_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.125": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_closed_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.125": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.125": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_closed_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.125": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_blink_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.wormadam_sandy.ditto_face": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"face": {
|
||||
"position": [0, 0, 0.1],
|
||||
"scale": 0
|
||||
},
|
||||
"face_ditto": {
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.wormadam_trash.ground_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"rotation": [5, 0, 0],
|
||||
"position": [0, 6, 0]
|
||||
},
|
||||
"body_rotation": {
|
||||
"rotation": [0, 0, 0]
|
||||
},
|
||||
"antenna": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
},
|
||||
"ear_left": {
|
||||
"rotation": [0, -12.5, 0]
|
||||
},
|
||||
"ear_left2": {
|
||||
"rotation": [0, 0, 20]
|
||||
},
|
||||
"ear_left3": {
|
||||
"rotation": [0, 0, 22.5]
|
||||
},
|
||||
"ear_back_left": {
|
||||
"rotation": [-7.5, 0, 25]
|
||||
},
|
||||
"ear_left4": {
|
||||
"rotation": [0, 0, 17.5]
|
||||
},
|
||||
"ear_right": {
|
||||
"rotation": [0, 12.5, 0]
|
||||
},
|
||||
"ear_right2": {
|
||||
"rotation": [0, 0, -20]
|
||||
},
|
||||
"ear_right3": {
|
||||
"rotation": [0, 0, -22.5]
|
||||
},
|
||||
"ear_right4": {
|
||||
"rotation": [0, 0, -17.5]
|
||||
},
|
||||
"ear_back_right": {
|
||||
"rotation": [-7.5, 0, -25]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.wormadam_trash.blink": {
|
||||
"animation_length": 0.1667,
|
||||
"bones": {
|
||||
"pupil_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.125": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_closed_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.125": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.125": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_closed_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.125": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_blink_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.wormadam_trash.ditto_face": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"face": {
|
||||
"position": [0, 0, 0.1],
|
||||
"scale": 0
|
||||
},
|
||||
"face_ditto": {
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.mothim.ground_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"torso": {
|
||||
"rotation": [5, 0, 0]
|
||||
},
|
||||
"wing_upper_left": {
|
||||
"rotation": [1.3185, -9.9136, -7.6143]
|
||||
},
|
||||
"wing_lower_left": {
|
||||
"rotation": [-2.5, -12.5, 0]
|
||||
},
|
||||
"head": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"antenna_left": {
|
||||
"rotation": [-22.4229, 1.9113, 4.6211]
|
||||
},
|
||||
"antenna_left2": {
|
||||
"rotation": [-7.5, 0, 0]
|
||||
},
|
||||
"tail": {
|
||||
"rotation": [-12.5, 0, 0]
|
||||
},
|
||||
"antenna_right": {
|
||||
"rotation": [-22.4229, -1.9113, -4.6211]
|
||||
},
|
||||
"antenna_right2": {
|
||||
"rotation": [-7.5, 0, 0]
|
||||
},
|
||||
"arm_left": {
|
||||
"rotation": [-0.9096, 19.9802, 44.8398]
|
||||
},
|
||||
"arm_right": {
|
||||
"rotation": [-0.9096, -19.9802, -44.8398]
|
||||
},
|
||||
"leg_left": {
|
||||
"rotation": [-9.041, -41.7073, 13.4501]
|
||||
},
|
||||
"leg_right": {
|
||||
"rotation": [-9.041, 41.7073, -13.4501]
|
||||
},
|
||||
"wing_upper_right": {
|
||||
"rotation": [1.3185, 9.9136, 7.6143]
|
||||
},
|
||||
"wing_lower_right": {
|
||||
"rotation": [-2.5, 12.5, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.mothim.blink": {
|
||||
"animation_length": 0.1667,
|
||||
"bones": {
|
||||
"eye_open_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.125": {"pre": [0, 0, 0.1], "post": [0, 0, 0.1]},
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eye_open_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.125": {"pre": [0, 0, 0.1], "post": [0, 0, 0.1]},
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eye_closed_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.125": {"pre": [0, 0, -0.1], "post": [0, 0, -0.1]},
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, -0.1]}
|
||||
}
|
||||
},
|
||||
"eye_closed_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.125": {"pre": [0, 0, -0.1], "post": [0, 0, -0.1]},
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, -0.1]}
|
||||
}
|
||||
},
|
||||
"eyes_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_blink_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.snover.ground_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"tail": {
|
||||
"rotation": [-7.44134, 0.07948, 0.53084]
|
||||
},
|
||||
"arm_right": {
|
||||
"rotation": [0, 0, "-32.5-5*Math.sin((query.anim_time-0.5) * 90 * 1)"]
|
||||
},
|
||||
"arm_right2": {
|
||||
"rotation": [0, "-12.5+5*Math.sin((query.anim_time-0.75) * 90 * 1)", 0]
|
||||
},
|
||||
"torso": {
|
||||
"rotation": ["-2.5+2*Math.sin((query.anim_time-0) * 90 * 1)", 0, "-2*Math.sin((query.anim_time-0.8) * 90 * 0.5)"],
|
||||
"position": [0, "0.1*Math.sin((query.anim_time-0.75) * 90 * 1)", 0]
|
||||
},
|
||||
"torso2": {
|
||||
"rotation": ["5+1*Math.sin((query.anim_time-0.25) * 90 * 1)", 0, 0]
|
||||
},
|
||||
"arm_left": {
|
||||
"rotation": [0, 0, "32.5+5*Math.sin((query.anim_time-0.5) * 90 * 1)"]
|
||||
},
|
||||
"arm_left2": {
|
||||
"rotation": [0, "12.5-5*Math.sin((query.anim_time-0.75) * 90 * 1)", 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.snover.blink": {
|
||||
"animation_length": 0.1667,
|
||||
"bones": {
|
||||
"pupil_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_closed_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"pupil_closed_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_blink_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.snover.ditto_face": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"eyes": {
|
||||
"scale": 0
|
||||
},
|
||||
"face_ditto": {
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.snover.berries_female": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"berry_front": {
|
||||
"position": [0, 0, -4]
|
||||
},
|
||||
"berry_front_right": {
|
||||
"position": [-4, 0, -4]
|
||||
},
|
||||
"berry_back_right": {
|
||||
"position": [-4, 0, 4]
|
||||
},
|
||||
"berry_front_left": {
|
||||
"position": [4, 0, -4]
|
||||
},
|
||||
"berry_back_left": {
|
||||
"position": [4, 0, 4]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.abomasnow.ground_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"torso2": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
},
|
||||
"head": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
},
|
||||
"arm_left": {
|
||||
"rotation": [0, 0, 35]
|
||||
},
|
||||
"arm_left2": {
|
||||
"rotation": [4.75346, 32.18826, 8.87221]
|
||||
},
|
||||
"finger_front_left": {
|
||||
"rotation": [-3.96713, -14.47751, 15.50409]
|
||||
},
|
||||
"finger_middle_left": {
|
||||
"rotation": [0, 0, 15]
|
||||
},
|
||||
"finger_back_left": {
|
||||
"rotation": [3.96713, 14.47751, 15.50409]
|
||||
},
|
||||
"foot_left": {
|
||||
"rotation": [0, -15, 0]
|
||||
},
|
||||
"tail": {
|
||||
"rotation": [-15, 0, 0]
|
||||
},
|
||||
"tail2": {
|
||||
"rotation": [5, 0, 0]
|
||||
},
|
||||
"tail3": {
|
||||
"rotation": [5, 0, 0]
|
||||
},
|
||||
"arm_right": {
|
||||
"rotation": [0, 0, -35]
|
||||
},
|
||||
"arm_right2": {
|
||||
"rotation": [4.75346, -32.18826, -8.87221]
|
||||
},
|
||||
"finger_front_right": {
|
||||
"rotation": [-3.96713, 14.47751, -15.50409]
|
||||
},
|
||||
"finger_middle_right": {
|
||||
"rotation": [0, 0, -15]
|
||||
},
|
||||
"finger_back_right": {
|
||||
"rotation": [3.96713, -14.47751, -15.50409]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.abomasnow.blink": {
|
||||
"animation_length": 0.1667,
|
||||
"bones": {
|
||||
"eye_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eye_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_blink_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.abomasnow.ditto_face": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"eyes": {
|
||||
"scale": 0
|
||||
},
|
||||
"face_ditto": {
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+279
@@ -0,0 +1,279 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.tympole.ground_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"torso": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
},
|
||||
"tail": {
|
||||
"rotation": [-37.5, 0, 0]
|
||||
},
|
||||
"tail2": {
|
||||
"rotation": [35, 0, 0]
|
||||
},
|
||||
"tail3": {
|
||||
"rotation": [10, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.tympole.sleep": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"rotation": [-95, 0, 0],
|
||||
"position": [0, 0, 2]
|
||||
},
|
||||
"tail": {
|
||||
"rotation": [-85, 0, 0]
|
||||
},
|
||||
"tail2": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"tail3": {
|
||||
"rotation": [-12.5, 0, 0]
|
||||
},
|
||||
"eye_left": {
|
||||
"position": [0, 0, 0.1]
|
||||
},
|
||||
"eye_right": {
|
||||
"position": [0, 0, 0.1]
|
||||
},
|
||||
"eyelid_right": {
|
||||
"position": [0, 0, -0.1]
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.tympole.blink": {
|
||||
"animation_length": 0.1667,
|
||||
"bones": {
|
||||
"eye_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eye_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_blink_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.tympole.ditto_face": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"face": {
|
||||
"scale": 0
|
||||
},
|
||||
"face_ditto": {
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.tympole.pose": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"rotation": [-8.5958, -5.68422, 21.80633],
|
||||
"position": [0, 8, 0]
|
||||
},
|
||||
"tail": {
|
||||
"rotation": [-67.5, -22.5, 0],
|
||||
"position": [0, -2, 0]
|
||||
},
|
||||
"tail2": {
|
||||
"rotation": [22.5, 0, 0]
|
||||
},
|
||||
"tail3": {
|
||||
"rotation": [22.5, 0, 0]
|
||||
},
|
||||
"mouth": {
|
||||
"position": [0, 0, 0.1]
|
||||
},
|
||||
"mouth_open": {
|
||||
"position": [0, 0, 0]
|
||||
},
|
||||
"mouth_open_small": {
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.tympole.happy": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"eye_left": {
|
||||
"position": [0, 0, 0.1]
|
||||
},
|
||||
"eye_right": {
|
||||
"position": [0, 0, 0.1]
|
||||
},
|
||||
"mouth": {
|
||||
"position": [0, 0, 0.1]
|
||||
},
|
||||
"mouth_open": {
|
||||
"position": [0, 0, -0.1]
|
||||
},
|
||||
"eye_left_happy": {
|
||||
"position": [0, 0, -0.1]
|
||||
},
|
||||
"eye_right_happy": {
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.tympole.shock": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"mouth": {
|
||||
"position": [0, 0, 0.1]
|
||||
},
|
||||
"mouth_open_tall": {
|
||||
"position": [0, 0, -0.1]
|
||||
},
|
||||
"eyebrow_left": {
|
||||
"position": [0, 0.5, 0]
|
||||
},
|
||||
"eyebrow_right": {
|
||||
"position": [0, 0.5, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.tympole.angry": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"eyebrow_left": {
|
||||
"rotation": [0, 0, -22.5],
|
||||
"position": [-0.25, -0.25, -0.04]
|
||||
},
|
||||
"eyebrow_right": {
|
||||
"rotation": [0, 0, 22.5],
|
||||
"position": [0.25, -0.25, -0.04]
|
||||
},
|
||||
"mouth": {
|
||||
"position": [0, 0, 0.1]
|
||||
},
|
||||
"eyelid_left_emote": {
|
||||
"position": [0, 0, -0.1]
|
||||
},
|
||||
"eyelid_right_emote": {
|
||||
"position": [0, 0, -0.1]
|
||||
},
|
||||
"mouth_angry": {
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.tympole.sad": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"eyebrow_left": {
|
||||
"rotation": [0, 0, 10],
|
||||
"position": [0.15, 0, -0.04]
|
||||
},
|
||||
"eyebrow_right": {
|
||||
"rotation": [0, 0, -10],
|
||||
"position": [-0.15, 0, -0.04]
|
||||
},
|
||||
"mouth": {
|
||||
"position": [0, 0, 0.1]
|
||||
},
|
||||
"eyelid_left_emote": {
|
||||
"position": [0.9, 0, -0.1]
|
||||
},
|
||||
"eyelid_right_emote": {
|
||||
"position": [-0.9, 0, -0.1]
|
||||
},
|
||||
"mouth_sad": {
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.tympole.hurt": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"eyebrow_left": {
|
||||
"position": [0, -0.25, 0]
|
||||
},
|
||||
"eyebrow_right": {
|
||||
"position": [0, -0.25, 0]
|
||||
},
|
||||
"eye_left": {
|
||||
"position": [0, 0, 0.1]
|
||||
},
|
||||
"eye_right": {
|
||||
"position": [0, 0, 0.1]
|
||||
},
|
||||
"mouth": {
|
||||
"position": [0, 0, 0.1]
|
||||
},
|
||||
"mouth_open_frown": {
|
||||
"position": [0, 0, -0.1]
|
||||
},
|
||||
"eye_left_hurt": {
|
||||
"position": [0, 0, -0.1]
|
||||
},
|
||||
"eye_right_hurt": {
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.tympole.unamused": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"mouth": {
|
||||
"position": [0, 0, 0.1]
|
||||
},
|
||||
"mouth_angry": {
|
||||
"position": [0, 0, -0.1]
|
||||
},
|
||||
"eyelid_left_unamused": {
|
||||
"position": [0, 0, -0.1]
|
||||
},
|
||||
"eyelid_right_unamused": {
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.tympole.scale": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"tympole": {
|
||||
"scale": 0.65
|
||||
},
|
||||
"ear_left_inside": {
|
||||
"position": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+223
@@ -0,0 +1,223 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.palpitoad.ground_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"palpitoad": {
|
||||
"scale": 1
|
||||
},
|
||||
"torso": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
},
|
||||
"tail": {
|
||||
"rotation": [-32.5, 0, 0]
|
||||
},
|
||||
"nose": {
|
||||
"rotation": [-10, 0, 0]
|
||||
},
|
||||
"leg_left": {
|
||||
"rotation": [0, 15, 0]
|
||||
},
|
||||
"leg_right": {
|
||||
"rotation": [0, -15, 0]
|
||||
},
|
||||
"tail2": {
|
||||
"rotation": [20, 0, 0]
|
||||
},
|
||||
"tail3": {
|
||||
"rotation": [12.5, 0, 0]
|
||||
},
|
||||
"tongue": {
|
||||
"rotation": [260, 0, 0]
|
||||
},
|
||||
"tongue_2": {
|
||||
"rotation": [180, 0, 0]
|
||||
},
|
||||
"tongue_3": {
|
||||
"rotation": [180, 0, 0]
|
||||
},
|
||||
"tongue_4": {
|
||||
"rotation": [180, 0, 0]
|
||||
},
|
||||
"tongue_5": {
|
||||
"rotation": [180, 0, 0]
|
||||
},
|
||||
"tongue_6": {
|
||||
"rotation": [180, 0, 0]
|
||||
},
|
||||
"tongue_7": {
|
||||
"rotation": [180, 0, 0]
|
||||
},
|
||||
"tongue_8": {
|
||||
"rotation": [180, 0, 0]
|
||||
},
|
||||
"tongue_9": {
|
||||
"rotation": [180, 0, 0]
|
||||
},
|
||||
"tongue_10": {
|
||||
"rotation": [180, 0, 0]
|
||||
},
|
||||
"tongue_11": {
|
||||
"rotation": [180, 0, 0]
|
||||
},
|
||||
"tongue_12": {
|
||||
"rotation": [180, 0, 0]
|
||||
},
|
||||
"head": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.palpitoad.blink": {
|
||||
"animation_length": 0.1667,
|
||||
"bones": {
|
||||
"eye_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.125": [0, 0, 0.1],
|
||||
"0.1667": [0, 0, 0]
|
||||
}
|
||||
},
|
||||
"shine_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.125": [0, 0, 0.1],
|
||||
"0.1667": [0, 0, 0]
|
||||
}
|
||||
},
|
||||
"eye_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.125": [0, 0, 0.1],
|
||||
"0.1667": [0, 0, 0]
|
||||
}
|
||||
},
|
||||
"shine_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.125": [0, 0, 0.1],
|
||||
"0.1667": [0, 0, 0]
|
||||
}
|
||||
},
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.125": [0, 0, -0.1],
|
||||
"0.1667": [0, 0, 0]
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.125": [0, 0, -0.1],
|
||||
"0.1667": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.palpitoad.ditto_face": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"mouth_open_big_bottom": {
|
||||
"scale": 0
|
||||
},
|
||||
"face": {
|
||||
"scale": 0
|
||||
},
|
||||
"face_ditto": {
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.palpitoad.pose": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"position": [0, 1, 0]
|
||||
},
|
||||
"leg_left": {
|
||||
"rotation": [20, 25, 0]
|
||||
},
|
||||
"toes_left": {
|
||||
"rotation": [-20, 0, 0]
|
||||
},
|
||||
"leg_right": {
|
||||
"rotation": [20, -25, 0]
|
||||
},
|
||||
"toes_right": {
|
||||
"rotation": [-20, 0, 0]
|
||||
},
|
||||
"torso": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"head_angle": {
|
||||
"rotation": [5, 10, 0]
|
||||
},
|
||||
"mouth": {
|
||||
"position": [0, 0, 0.1]
|
||||
},
|
||||
"nose": {
|
||||
"rotation": [-10, 0, 0]
|
||||
},
|
||||
"tail": {
|
||||
"rotation": [27.5, -30, 0]
|
||||
},
|
||||
"tail2": {
|
||||
"rotation": [27.5, 0, 0]
|
||||
},
|
||||
"tongue": {
|
||||
"rotation": [-10, -32.5, 0]
|
||||
},
|
||||
"tongue_2": {
|
||||
"rotation": [-42.79487, -18.88952, 16.68541]
|
||||
},
|
||||
"tongue_3": {
|
||||
"rotation": [-38.85707, -12.27659, 12.56853]
|
||||
},
|
||||
"tongue_4": {
|
||||
"rotation": [-25, 0, 0]
|
||||
},
|
||||
"tongue_5": {
|
||||
"rotation": [-10.82756, 27.88369, 21.32202]
|
||||
},
|
||||
"tongue_6": {
|
||||
"rotation": [-10, 42.5, 0]
|
||||
},
|
||||
"tongue_7": {
|
||||
"rotation": [-30.86748, 12.95254, -7.63074]
|
||||
},
|
||||
"mouth_open": {
|
||||
"position": [0, 0, -0.1]
|
||||
},
|
||||
"tongue_8": {
|
||||
"rotation": [-15, 0, 0]
|
||||
},
|
||||
"tongue_9": {
|
||||
"rotation": [-22.5, 0, 0]
|
||||
},
|
||||
"tongue_12": {
|
||||
"rotation": [40, 0, 0]
|
||||
},
|
||||
"tongue_11": {
|
||||
"rotation": [37.5, 0, 0]
|
||||
},
|
||||
"tongue_10": {
|
||||
"rotation": [-15, 0, 0]
|
||||
},
|
||||
"shine_left": {
|
||||
"position": [-0.25, 0, 0]
|
||||
},
|
||||
"shine_right": {
|
||||
"position": [-0.25, 0, 0]
|
||||
},
|
||||
"pupil_left": {
|
||||
"position": [-0.25, 0, 0]
|
||||
},
|
||||
"pupil_right": {
|
||||
"position": [-0.25, 0, 0]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+341
@@ -0,0 +1,341 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.seismitoad.ground_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"position": [0, -3.2, 0]
|
||||
},
|
||||
"torso": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
},
|
||||
"shoulder_left": {
|
||||
"rotation": [34.3569, -7.1313, 32.7929]
|
||||
},
|
||||
"arm_left": {
|
||||
"rotation": [0, 27.5, 5]
|
||||
},
|
||||
"elbow_left": {
|
||||
"rotation": [-15, 22.5, 0]
|
||||
},
|
||||
"hand_left": {
|
||||
"rotation": [0, 0, 22.5]
|
||||
},
|
||||
"leg_left": {
|
||||
"rotation": [-45, -20, -10],
|
||||
"position": [-1, 0, 0]
|
||||
},
|
||||
"knee_left": {
|
||||
"rotation": [60, -10, 10]
|
||||
},
|
||||
"foot_left": {
|
||||
"rotation": [-12, 0, -5]
|
||||
},
|
||||
"wart_knee_left": {
|
||||
"rotation": [22.5, 0, 7.5]
|
||||
},
|
||||
"neck_rotation": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
},
|
||||
"head": {
|
||||
"rotation": [-90, 0, 0]
|
||||
},
|
||||
"finger_middle_left2": {
|
||||
"rotation": [0, 0, 15]
|
||||
},
|
||||
"finger_front_left": {
|
||||
"rotation": [0, 0, 7.5]
|
||||
},
|
||||
"finger_front_left2": {
|
||||
"rotation": [0, 0, 15]
|
||||
},
|
||||
"finger_back_left": {
|
||||
"rotation": [0, 0, 7.5]
|
||||
},
|
||||
"finger_back_left2": {
|
||||
"rotation": [0, 0, 15]
|
||||
},
|
||||
"shoulder_right": {
|
||||
"rotation": [34.3569, 7.1313, -32.7929]
|
||||
},
|
||||
"arm_right": {
|
||||
"rotation": [0, -27.5, -5]
|
||||
},
|
||||
"elbow_right": {
|
||||
"rotation": [-15, -22.5, 0]
|
||||
},
|
||||
"hand_right": {
|
||||
"rotation": [0, 0, -22.5]
|
||||
},
|
||||
"finger_middle_right2": {
|
||||
"rotation": [0, 0, -15]
|
||||
},
|
||||
"finger_front_right": {
|
||||
"rotation": [0, 0, -7.5]
|
||||
},
|
||||
"finger_front_right2": {
|
||||
"rotation": [0, 0, -15]
|
||||
},
|
||||
"finger_back_right": {
|
||||
"rotation": [0, 0, -7.5]
|
||||
},
|
||||
"finger_back_right2": {
|
||||
"rotation": [0, 0, -15]
|
||||
},
|
||||
"toe_back_left2": {
|
||||
"rotation": [-10, 0, 0]
|
||||
},
|
||||
"toe_out_left2": {
|
||||
"rotation": [7.5, 0, 0]
|
||||
},
|
||||
"toe_in_left2": {
|
||||
"rotation": [7.5, 0, 0]
|
||||
},
|
||||
"leg_right": {
|
||||
"rotation": [-45, 20, 10],
|
||||
"position": [1, 0, 0]
|
||||
},
|
||||
"knee_right": {
|
||||
"rotation": [60, 10, -10]
|
||||
},
|
||||
"foot_right": {
|
||||
"rotation": [-12, 0, 5]
|
||||
},
|
||||
"toe_out_right2": {
|
||||
"rotation": [7.5, 0, 0]
|
||||
},
|
||||
"toe_in_right2": {
|
||||
"rotation": [7.5, 0, 0]
|
||||
},
|
||||
"toe_back_right2": {
|
||||
"rotation": [-10, 0, 0]
|
||||
},
|
||||
"wart_knee_right": {
|
||||
"rotation": [22.5, 0, -7.5]
|
||||
},
|
||||
"neck": {
|
||||
"rotation": [-45, 0, 0]
|
||||
},
|
||||
"tongue": {
|
||||
"position": [0, -0.25, 3]
|
||||
},
|
||||
"tongue2": {
|
||||
"position": [0, 0, 5]
|
||||
},
|
||||
"tongue3": {
|
||||
"position": [0, 0, 5]
|
||||
},
|
||||
"tongue4": {
|
||||
"position": [0, 0, 5]
|
||||
},
|
||||
"tongue5": {
|
||||
"position": [0, 0, 5]
|
||||
},
|
||||
"tongue_tip": {
|
||||
"position": [0, -1, 3]
|
||||
},
|
||||
"head_angle": {
|
||||
"rotation": [90, 0, 0]
|
||||
},
|
||||
"neck_angle": {
|
||||
"rotation": [45, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.seismitoad.blink": {
|
||||
"animation_length": 0.2917,
|
||||
"bones": {
|
||||
"eye_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.0833": {"pre": [0, 0, 0], "post": [0, 0, 0.1]},
|
||||
"0.2917": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eye_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.2083": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.0833": {"pre": [0, 0, 0], "post": [0, 0, -0.1]},
|
||||
"0.2917": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.2083": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.2083": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_blink_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.2083": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.seismitoad.ditto_face": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"face": {
|
||||
"scale": 0
|
||||
},
|
||||
"face_ditto": {
|
||||
"position": [0, 0, -0.1]
|
||||
},
|
||||
"tongue": {
|
||||
"scale": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.seismitoad.pose": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"rotation": [0, -30, 0],
|
||||
"position": [0, -2.25, 0]
|
||||
},
|
||||
"torso": {
|
||||
"rotation": [17.5, 0, 0]
|
||||
},
|
||||
"jaw": {
|
||||
"rotation": [42.5, 0, 0]
|
||||
},
|
||||
"shoulder_left": {
|
||||
"rotation": [-5, -7.5, 25]
|
||||
},
|
||||
"arm_left": {
|
||||
"rotation": [0, 5, 0]
|
||||
},
|
||||
"elbow_left": {
|
||||
"rotation": [-12.5, 50, 0]
|
||||
},
|
||||
"finger_middle_left": {
|
||||
"rotation": [0, 0, 7.5]
|
||||
},
|
||||
"leg_left": {
|
||||
"rotation": [-40.6299, -29.1905, -7.6552]
|
||||
},
|
||||
"knee_left": {
|
||||
"rotation": [37.5, 0, 0]
|
||||
},
|
||||
"foot_left": {
|
||||
"rotation": [6.4717, -0.6518, 4.9574]
|
||||
},
|
||||
"head": {
|
||||
"rotation": [-22.0182, -4.7511, -24.0751]
|
||||
},
|
||||
"finger_middle_left2": {
|
||||
"rotation": [0, 0, 20]
|
||||
},
|
||||
"finger_front_left2": {
|
||||
"rotation": [0, 0, 15]
|
||||
},
|
||||
"finger_back_left": {
|
||||
"rotation": [0, 0, 27.5]
|
||||
},
|
||||
"finger_back_left2": {
|
||||
"rotation": [0, 0, 40]
|
||||
},
|
||||
"shoulder_right": {
|
||||
"rotation": [0, 0, -22.5]
|
||||
},
|
||||
"arm_right": {
|
||||
"rotation": [0, -12.5, 0]
|
||||
},
|
||||
"elbow_right": {
|
||||
"rotation": [173.5473, -44.2356, -288.0659]
|
||||
},
|
||||
"hand_right": {
|
||||
"rotation": [0, 0, -15]
|
||||
},
|
||||
"finger_middle_right": {
|
||||
"rotation": [0, 0, -15]
|
||||
},
|
||||
"finger_middle_right2": {
|
||||
"rotation": [0, 0, -5]
|
||||
},
|
||||
"finger_front_right": {
|
||||
"rotation": [20.5765, 31.8072, -73.3068],
|
||||
"position": [0, 0, -0.5]
|
||||
},
|
||||
"finger_front_right2": {
|
||||
"rotation": [0, 0, -50]
|
||||
},
|
||||
"finger_back_right": {
|
||||
"rotation": [-19.2568, -34.3655, -80.4799],
|
||||
"position": [0, 0, 0.5]
|
||||
},
|
||||
"finger_back_right2": {
|
||||
"rotation": [0, 0, -50]
|
||||
},
|
||||
"toe_back_left2": {
|
||||
"rotation": [-10, 0, 0]
|
||||
},
|
||||
"toe_out_left2": {
|
||||
"rotation": [7.5, 0, 0]
|
||||
},
|
||||
"toe_in_left2": {
|
||||
"rotation": [7.5, 0, 0]
|
||||
},
|
||||
"leg_right": {
|
||||
"rotation": [-38.922, 39.0907, 8.6174]
|
||||
},
|
||||
"knee_right": {
|
||||
"rotation": [37.5, 0, 0]
|
||||
},
|
||||
"foot_right": {
|
||||
"rotation": [7.4593, 0.7817, -5.949]
|
||||
},
|
||||
"toe_out_right2": {
|
||||
"rotation": [7.5, 0, 0]
|
||||
},
|
||||
"toe_in_right2": {
|
||||
"rotation": [7.5, 0, 0]
|
||||
},
|
||||
"toe_back_right2": {
|
||||
"rotation": [-10, 0, 0]
|
||||
},
|
||||
"pupil_right": {
|
||||
"position": [-0.25, 0, 0]
|
||||
},
|
||||
"pupil_left": {
|
||||
"position": [-0.25, 0, 0]
|
||||
},
|
||||
"neck": {
|
||||
"rotation": [0, -4, 0]
|
||||
},
|
||||
"tongue": {
|
||||
"rotation": [-25, 0, 0]
|
||||
},
|
||||
"tongue2": {
|
||||
"rotation": [-10, 25, 0]
|
||||
},
|
||||
"tongue3": {
|
||||
"rotation": [-5, 32.5, 0]
|
||||
},
|
||||
"tongue4": {
|
||||
"rotation": [-5, 45, 0]
|
||||
},
|
||||
"tongue5": {
|
||||
"rotation": [-22.99, 11.5348, -4.8492]
|
||||
},
|
||||
"tongue_tip": {
|
||||
"rotation": [-25.3376, 9.0548, -4.2618]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.deerling.ground_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"position": [0, -0.1, 0]
|
||||
},
|
||||
"torso": {
|
||||
"rotation": [5, 0, 0]
|
||||
},
|
||||
"torso2": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"neck": {
|
||||
"rotation": [7.5, 0, 0]
|
||||
},
|
||||
"ear_left2": {
|
||||
"rotation": [0, 0, 7.5]
|
||||
},
|
||||
"ear_right2": {
|
||||
"rotation": [0, 0, -7.5]
|
||||
},
|
||||
"tail": {
|
||||
"rotation": [5, 0, 0]
|
||||
},
|
||||
"leg_front_left": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
},
|
||||
"foot_front_left": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
},
|
||||
"leg_back_left": {
|
||||
"rotation": [2.5, 0, -2.5]
|
||||
},
|
||||
"leg_back_left2": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
},
|
||||
"foot_back_left": {
|
||||
"rotation": [0, 0, 2.5]
|
||||
},
|
||||
"leg_front_right": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
},
|
||||
"foot_front_right": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
},
|
||||
"leg_back_right": {
|
||||
"rotation": [2.5, 0, 2.5]
|
||||
},
|
||||
"leg_back_right2": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
},
|
||||
"foot_back_right": {
|
||||
"rotation": [0, 0, -2.5]
|
||||
},
|
||||
"head": {
|
||||
"rotation": [-7.5, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.deerling.blink": {
|
||||
"animation_length": 0.1667,
|
||||
"bones": {
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0.1, 0, -0.1],
|
||||
"0.1667": {"pre": [0.1, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eye_left": {
|
||||
"position": {
|
||||
"0.0": [-0.1, 0, 0.1],
|
||||
"0.1667": {"pre": [-0.1, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eye_right": {
|
||||
"position": {
|
||||
"0.0": [0.1, 0, 0.1],
|
||||
"0.1667": {"pre": [0.1, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [-0.1, 0, -0.1],
|
||||
"0.1667": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0.1],
|
||||
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyes_blink_ditto": {
|
||||
"position": {
|
||||
"0.0": [0, 0, -0.1],
|
||||
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.sawsbuck_autumn.ground_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"position": [0, -0.4, 0]
|
||||
},
|
||||
"head": {
|
||||
"rotation": [-3, 0, 0]
|
||||
},
|
||||
"leg_front_left": {
|
||||
"rotation": [0, -3, -2]
|
||||
},
|
||||
"leg_front_left2": {
|
||||
"rotation": [0, 0, 0]
|
||||
},
|
||||
"leg_front_left3": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
},
|
||||
"foot_front_left": {
|
||||
"rotation": [-0.5, 0, 2]
|
||||
},
|
||||
"leg_back_left": {
|
||||
"rotation": [-5, -3, -2]
|
||||
},
|
||||
"leg_back_left2": {
|
||||
"rotation": [3, 0, 0]
|
||||
},
|
||||
"leg_back_left3": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"foot_back_left": {
|
||||
"rotation": [7, -1, 2]
|
||||
},
|
||||
"leg_front_right": {
|
||||
"rotation": [0, 3, 2]
|
||||
},
|
||||
"leg_front_right2": {
|
||||
"rotation": [0, 0, 0]
|
||||
},
|
||||
"leg_front_right3": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
},
|
||||
"foot_front_right": {
|
||||
"rotation": [-0.5, 0, -2]
|
||||
},
|
||||
"leg_back_right": {
|
||||
"rotation": [-5, 3, 2]
|
||||
},
|
||||
"leg_back_right2": {
|
||||
"rotation": [3, 0, 0]
|
||||
},
|
||||
"leg_back_right3": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"foot_back_right": {
|
||||
"rotation": [7, 1, -2]
|
||||
},
|
||||
"ear_left": {
|
||||
"rotation": [0, 0, -10]
|
||||
},
|
||||
"ear_right": {
|
||||
"rotation": [0, 0, 10]
|
||||
},
|
||||
"tail1": {
|
||||
"rotation": [-3, 0, 0]
|
||||
},
|
||||
"tail2": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"torso": {
|
||||
"rotation": [5, 0, 0]
|
||||
},
|
||||
"torso2": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"neck": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"ftorso2": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.sawsbuck_autumn.blink": {
|
||||
"animation_length": 0.1667,
|
||||
"bones": {
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0.1, -0.1, 0],
|
||||
"0.1667": {"pre": [0.1, -0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [-0.1, -0.1, 0],
|
||||
"0.1667": {"pre": [-0.1, -0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eye_left": {
|
||||
"position": {
|
||||
"0.0": [-0.1, 0.1, 0],
|
||||
"0.1667": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyebrow_left": {
|
||||
"position": {
|
||||
"0.0": [-0.1, 0.1, 0],
|
||||
"0.1667": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eye_right": {
|
||||
"position": {
|
||||
"0.0": [0.1, 0.1, 0],
|
||||
"0.1667": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyebrow_right": {
|
||||
"position": {
|
||||
"0.0": [0.1, 0.1, 0],
|
||||
"0.1667": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.sawsbuck_spring.ground_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"position": [0, -0.4, 0]
|
||||
},
|
||||
"head": {
|
||||
"rotation": [-3, 0, 0]
|
||||
},
|
||||
"leg_front_left": {
|
||||
"rotation": [0, -3, -2]
|
||||
},
|
||||
"leg_front_left2": {
|
||||
"rotation": [0, 0, 0]
|
||||
},
|
||||
"leg_front_left3": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
},
|
||||
"foot_front_left": {
|
||||
"rotation": [-0.5, 0, 2]
|
||||
},
|
||||
"leg_back_left": {
|
||||
"rotation": [-5, -3, -2]
|
||||
},
|
||||
"leg_back_left2": {
|
||||
"rotation": [3, 0, 0]
|
||||
},
|
||||
"leg_back_left3": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"foot_back_left": {
|
||||
"rotation": [7, -1, 2]
|
||||
},
|
||||
"leg_front_right": {
|
||||
"rotation": [0, 3, 2]
|
||||
},
|
||||
"leg_front_right2": {
|
||||
"rotation": [0, 0, 0]
|
||||
},
|
||||
"leg_front_right3": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
},
|
||||
"foot_front_right": {
|
||||
"rotation": [-0.5, 0, -2]
|
||||
},
|
||||
"leg_back_right": {
|
||||
"rotation": [-5, 3, 2]
|
||||
},
|
||||
"leg_back_right2": {
|
||||
"rotation": [3, 0, 0]
|
||||
},
|
||||
"leg_back_right3": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"foot_back_right": {
|
||||
"rotation": [7, 1, -2]
|
||||
},
|
||||
"ear_left": {
|
||||
"rotation": [0, 0, -10]
|
||||
},
|
||||
"ear_right": {
|
||||
"rotation": [0, 0, 10]
|
||||
},
|
||||
"tail1": {
|
||||
"rotation": [-3, 0, 0]
|
||||
},
|
||||
"tail2": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"torso": {
|
||||
"rotation": [5, 0, 0]
|
||||
},
|
||||
"torso2": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"neck": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"ftorso2": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.sawsbuck_spring.blink": {
|
||||
"animation_length": 0.1667,
|
||||
"bones": {
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0.1, -0.1, 0],
|
||||
"0.1667": {"pre": [0.1, -0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [-0.1, -0.1, 0],
|
||||
"0.1667": {"pre": [-0.1, -0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eye_left": {
|
||||
"position": {
|
||||
"0.0": [-0.1, 0.1, 0],
|
||||
"0.1667": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyebrow_left": {
|
||||
"position": {
|
||||
"0.0": [-0.1, 0.1, 0],
|
||||
"0.1667": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eye_right": {
|
||||
"position": {
|
||||
"0.0": [0.1, 0.1, 0],
|
||||
"0.1667": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyebrow_right": {
|
||||
"position": {
|
||||
"0.0": [0.1, 0.1, 0],
|
||||
"0.1667": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.sawsbuck_summer.ground_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"position": [0, -0.4, 0]
|
||||
},
|
||||
"head": {
|
||||
"rotation": [-3, 0, 0]
|
||||
},
|
||||
"leg_front_left": {
|
||||
"rotation": [0, -3, -2]
|
||||
},
|
||||
"leg_front_left2": {
|
||||
"rotation": [0, 0, 0]
|
||||
},
|
||||
"leg_front_left3": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
},
|
||||
"foot_front_left": {
|
||||
"rotation": [-0.5, 0, 2]
|
||||
},
|
||||
"leg_back_left": {
|
||||
"rotation": [-5, -3, -2]
|
||||
},
|
||||
"leg_back_left2": {
|
||||
"rotation": [3, 0, 0]
|
||||
},
|
||||
"leg_back_left3": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"foot_back_left": {
|
||||
"rotation": [7, -1, 2]
|
||||
},
|
||||
"leg_front_right": {
|
||||
"rotation": [0, 3, 2]
|
||||
},
|
||||
"leg_front_right2": {
|
||||
"rotation": [0, 0, 0]
|
||||
},
|
||||
"leg_front_right3": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
},
|
||||
"foot_front_right": {
|
||||
"rotation": [-0.5, 0, -2]
|
||||
},
|
||||
"leg_back_right": {
|
||||
"rotation": [-5, 3, 2]
|
||||
},
|
||||
"leg_back_right2": {
|
||||
"rotation": [3, 0, 0]
|
||||
},
|
||||
"leg_back_right3": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"foot_back_right": {
|
||||
"rotation": [7, 1, -2]
|
||||
},
|
||||
"ear_left": {
|
||||
"rotation": [0, 0, -10]
|
||||
},
|
||||
"ear_right": {
|
||||
"rotation": [0, 0, 10]
|
||||
},
|
||||
"tail1": {
|
||||
"rotation": [-3, 0, 0]
|
||||
},
|
||||
"tail2": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"torso": {
|
||||
"rotation": [5, 0, 0]
|
||||
},
|
||||
"torso2": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"neck": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"ftorso2": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
},
|
||||
"bush_left3_summer": {
|
||||
"rotation": [0, 0, -5]
|
||||
},
|
||||
"bush_left4_summer": {
|
||||
"rotation": [0, 0, -7.5]
|
||||
},
|
||||
"bush_right3_summer": {
|
||||
"rotation": [0, 0, 5]
|
||||
},
|
||||
"bush_right4_summer": {
|
||||
"rotation": [0, 0, 7.5]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.sawsbuck_summer.blink": {
|
||||
"animation_length": 0.1667,
|
||||
"bones": {
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0.1, -0.1, 0],
|
||||
"0.1667": {"pre": [0.1, -0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [-0.1, -0.1, 0],
|
||||
"0.1667": {"pre": [-0.1, -0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eye_left": {
|
||||
"position": {
|
||||
"0.0": [-0.1, 0.1, 0],
|
||||
"0.1667": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyebrow_left": {
|
||||
"position": {
|
||||
"0.0": [-0.1, 0.1, 0],
|
||||
"0.1667": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eye_right": {
|
||||
"position": {
|
||||
"0.0": [0.1, 0.1, 0],
|
||||
"0.1667": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyebrow_right": {
|
||||
"position": {
|
||||
"0.0": [0.1, 0.1, 0],
|
||||
"0.1667": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.sawsbuck_winter.ground_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"position": [0, -0.4, 0]
|
||||
},
|
||||
"head": {
|
||||
"rotation": [-3, 0, 0]
|
||||
},
|
||||
"leg_front_left": {
|
||||
"rotation": [0, -3, -2]
|
||||
},
|
||||
"leg_front_left2": {
|
||||
"rotation": [0, 0, 0]
|
||||
},
|
||||
"leg_front_left3": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
},
|
||||
"foot_front_left": {
|
||||
"rotation": [-0.5, 0, 2]
|
||||
},
|
||||
"leg_back_left": {
|
||||
"rotation": [-5, -3, -2]
|
||||
},
|
||||
"leg_back_left2": {
|
||||
"rotation": [3, 0, 0]
|
||||
},
|
||||
"leg_back_left3": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"foot_back_left": {
|
||||
"rotation": [7, -1, 2]
|
||||
},
|
||||
"leg_front_right": {
|
||||
"rotation": [0, 3, 2]
|
||||
},
|
||||
"leg_front_right2": {
|
||||
"rotation": [0, 0, 0]
|
||||
},
|
||||
"leg_front_right3": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
},
|
||||
"foot_front_right": {
|
||||
"rotation": [-0.5, 0, -2]
|
||||
},
|
||||
"leg_back_right": {
|
||||
"rotation": [-5, 3, 2]
|
||||
},
|
||||
"leg_back_right2": {
|
||||
"rotation": [3, 0, 0]
|
||||
},
|
||||
"leg_back_right3": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"foot_back_right": {
|
||||
"rotation": [7, 1, -2]
|
||||
},
|
||||
"ear_left": {
|
||||
"rotation": [0, 0, -10]
|
||||
},
|
||||
"ear_right": {
|
||||
"rotation": [0, 0, 10]
|
||||
},
|
||||
"tail1": {
|
||||
"rotation": [-3, 0, 0]
|
||||
},
|
||||
"tail2": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"torso": {
|
||||
"rotation": [5, 0, 0]
|
||||
},
|
||||
"torso2": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"neck": {
|
||||
"rotation": [-5, 0, 0]
|
||||
},
|
||||
"ftorso2": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
},
|
||||
"bush_left3_summer": {
|
||||
"rotation": [0, 0, -5]
|
||||
},
|
||||
"bush_left4_summer": {
|
||||
"rotation": [0, 0, -7.5]
|
||||
},
|
||||
"bush_right3_summer": {
|
||||
"rotation": [0, 0, 5]
|
||||
},
|
||||
"bush_right4_summer": {
|
||||
"rotation": [0, 0, 7.5]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.sawsbuck_winter.blink": {
|
||||
"animation_length": 0.1667,
|
||||
"bones": {
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0.1, -0.1, 0],
|
||||
"0.1667": {"pre": [0.1, -0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [-0.1, -0.1, 0],
|
||||
"0.1667": {"pre": [-0.1, -0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eye_left": {
|
||||
"position": {
|
||||
"0.0": [-0.1, 0.1, 0],
|
||||
"0.1667": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyebrow_left": {
|
||||
"position": {
|
||||
"0.0": [-0.1, 0.1, 0],
|
||||
"0.1667": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eye_right": {
|
||||
"position": {
|
||||
"0.0": [0.1, 0.1, 0],
|
||||
"0.1667": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyebrow_right": {
|
||||
"position": {
|
||||
"0.0": [0.1, 0.1, 0],
|
||||
"0.1667": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loaded 100 of 425 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user