Compare commits

..
13203 changed files with 73723 additions and 901027 deletions
-1
View File
@@ -3,4 +3,3 @@
# are changed when only line endings change.
src/generated/**/.cache/cache text eol=lf
src/generated/**/*.json text eol=lf
CHANGELOG.md merge=union
-7
View File
@@ -21,8 +21,6 @@ build
# other
eclipse
run
runClient
runServer
# Files from Forge MDK
forge*changelog.txt
@@ -35,8 +33,3 @@ common/src/main/resources/assets/cobblemon/showdown
# Generated files
*/generated/resources/*
/fabric/src/generated/resources/cobblemon-common.accesswidener
/.ignored/
common/.fabric
# MacOS
.DS_Store
-2
View File
@@ -1,5 +1,3 @@
image: amazoncorretto:21
before_script:
- export GRADLE_USER_HOME=`pwd`/.gradle
-30
View File
@@ -1,30 +0,0 @@
<!-- 1. START HERE: (Before filling all this out, please quickly go to the list of all issues: (https://gitlab.com/cable-mc/cobblemon/-/issues/?sort=created_date&state=all) and do a quick search to see if your issue has already been reported. If it has, please add a comment to the existing issue instead of creating a new one.)-->
<!-- 2. If the issue was not already reported, please fill out the following template. -->
<!-- 3. If you do not know something, don't worry! Just fill out as much as you can to make sure the issue can get fixed asap. -->
## Summary
(Please summarize the bug encountered concisely)
## Steps to reproduce
(How one can reproduce the issue - this is very important)
## What is the current bug behavior?
(What actually happens)
## What is the expected correct behavior?
(What you should see instead)
## Cobblemon Version and Mod Loader
(Are you using Forge or Fabric? And what version of Cobblemon are you using?)
## Mods used besides Cobblemon
(Did you have any other mods installed besides Cobblemon? If so, please list them here)
## Relevant logs, screenshots and/or videos
(Paste any relevant logs - use code blocks (```) at the start and end to format console output, logs, and code, as
it's very hard to read otherwise. Or just put a link here)
## Additional Information
(If you can, link to the line of code that might be responsible for the problem, or any other info that might be useful)
/label ~bug
@@ -1,31 +0,0 @@
<!-- 1. START HERE: (Before filling all this out, please quickly go to the list of all issues: (https://gitlab.com/cable-mc/cobblemon/-/issues/?sort=created_date&state=all) and do a quick search to see if your feature was already requested. If it is, please add a comment to the existing issue instead of creating a new one.)-->
<!-- 2. If the feature request was not already reported, please fill out the following template. -->
<!-- 3. If you do not know something, don't worry! Just fill out as much as you can. -->
<!-- 4. The more info you provide here, the greater the chance of it being considered by the Design team. -->
## Summary
(Please summarize your feature request concisely)
## What are the projected benefits of this feature?
- (List)
- (benefits)
- (here)
## What could speak against this feature?
- (List)
- (possible)
- (cons)
## Why do you think the benefits outweigh the cons?
(Explain why you think the benefits outweigh the cons)
## Mods involved besides Cobblemon
(Does your suggestion require any other mods besides Cobblemon? If so, please list them here)
## Sketches, screenshots and/or videos
(Feel free to add any sketches, screenshots or videos that might help the Design team understand your suggestion)
## Additional Information
(Is there anything else you would like to add?)
/label ~feature ~suggestion ~needs-design
-1
View File
@@ -1 +0,0 @@
LambDynamicLights compat needs to be restored
-24
View File
@@ -1,24 +0,0 @@
### Additions
- Pokémon are now animated when seen in any GUI that isn't the party GUI.
- Quirk animations can now occur for Pokémon that are shoulder mounted.
### Changes
- Improved the performance of display cases that contain Pokémon photos.
### Fixes
- Fixed some Pokémon photos in display cases flashing if the Pokémon has gender differences.
- Fixed Bidoof and Jigglypuff sleep animations stopping after some time, causing them to be 'asleep' while T-posing menacingly.
- Fixed entities not changing poses unless you're looking at them.
- Fixed cries not playing on send-out if the Pokémon is off-screen.
### Developer
- Rebuilt large swaths of the model animation code to simplify it.
- Renamed a bunch of things from %Poseable% to %Posable% because spelling.
- Renamed StatelessAnimation to PoseAnimation.
- Renamed StatefulAnimation to ActiveAnimation.
- Documented the animation system.
### Data Pack & Resource Pack Creators
- Added MoLang compatibility in the isVisible property for transformed parts.
- Added q.has_aspect('some_aspect') function to animations, posers, and entity particle effects.
- Added support for conditional pose animations.
+88 -939
View File
File diff suppressed because it is too large Load Diff
@@ -11,12 +11,8 @@ repositories {
dependencies {
implementation(libs.kotlin)
implementation(libs.licenser)
implementation(libs.shadow)
implementation(libs.loom)
implementation(libs.architectury)
implementation(libs.blossom)
implementation(libs.ideaExt)
implementation(libs.architecturyPlugin)
}
+10
View File
@@ -0,0 +1,10 @@
import ca.stellardrift.build.configurate.ConfigFormats
import ca.stellardrift.build.configurate.catalog.PolyglotVersionCatalogExtension
plugins {
id("ca.stellardrift.polyglot-version-catalogs") version "5.0.1"
}
extensions.configure<PolyglotVersionCatalogExtension> {
from(ConfigFormats.YAML, file("../gradle/libs.versions.yml"))
}
@@ -0,0 +1,58 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
val accessWidenerFile = "src/main/resources/cobblemon-common.accesswidener"
plugins {
java
`java-library`
id("org.cadixdev.licenser")
id("dev.architectury.loom")
id("architectury-plugin")
kotlin("jvm")
}
repositories {
mavenCentral()
}
license {
header(rootProject.file("HEADER"))
}
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
architectury {
minecraft = project.property("mc_version").toString()
}
loom {
silentMojangMappingsLicense()
accessWidenerPath.set(project(":common").file(ACCESS_WIDENER))
mixin {
defaultRefmapName.set("cobblemon-${project.name}-refmap.json")
}
}
dependencies {
minecraft("net.minecraft:minecraft:${rootProject.property("mc_version")}")
mappings("net.fabricmc:yarn:${rootProject.property("yarn_version")}:v2")
}
tasks {
withType<JavaCompile> {
options.encoding = "UTF-8"
options.release.set(17)
}
withType<KotlinCompile> {
kotlinOptions.jvmTarget = "17"
}
withType<Jar> {
from(rootProject.file("LICENSE"))
}
}
@@ -0,0 +1,32 @@
plugins {
id("cobblemon.base-conventions")
id("com.github.johnrengelman.shadow")
}
val bundle: Configuration by configurations.creating {
isCanBeConsumed = false
isCanBeResolved = true
}
tasks {
jar {
archiveBaseName.set("Cobblemon-${project.name}")
archiveClassifier.set("dev-slim")
}
shadowJar {
archiveClassifier.set("dev-shadow")
archiveBaseName.set("Cobblemon-${project.name}")
configurations = listOf(bundle)
mergeServiceFiles()
}
remapJar {
dependsOn(shadowJar)
inputFile.set(shadowJar.flatMap { it.archiveFile })
archiveBaseName.set("Cobblemon-${project.name}")
archiveVersion.set("${rootProject.version}")
}
}
@@ -1,9 +1,6 @@
import utilities.VersionType
import utilities.writeVersion
plugins {
id("java")
id("java-library")
java
`java-library`
id("maven-publish")
id("dev.architectury.loom")
}
@@ -34,7 +31,7 @@ publishing {
groupId = "com.cobblemon"
artifactId = project.findProperty("maven.artifactId")?.toString() ?: project.name
version = project.writeVersion(VersionType.PUBLISHING)
version = rootProject.version.toString()
}
}
}
@@ -0,0 +1,21 @@
plugins {
`java-library`
}
tasks {
val collectJars by registering(Copy::class) {
val tasks = subprojects.filter { it.path != ":common" }.map { it.tasks.named("remapJar") }
dependsOn(tasks)
from(tasks)
into(buildDir.resolve("libs"))
}
assemble {
dependsOn(collectJars)
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
@@ -1,3 +1,2 @@
package utilities
const val ACCESS_WIDENER = "src/main/resources/cobblemon-common.accesswidener"
+4 -4
View File
@@ -1,12 +1,12 @@
plugins {
base
id("cobblemon.root-conventions")
id ("net.nemerosa.versioning") version "3.1.0"
}
group = "com.cobblemon.mod"
version = "${project.property("mod_version")}+${project.property("mc_version")}"
val isSnapshot = project.property("snapshot")?.equals("true") ?: false
if (isSnapshot) {
val fixedBranchName = versioning.info.branch.substringAfter("/")
version = "$version-${fixedBranchName}-${versioning.info.build}"
}
version = "$version-SNAPSHOT"
}
+14 -69
View File
@@ -1,60 +1,36 @@
import java.time.OffsetDateTime
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import utilities.isSnapshot
import utilities.version
/*
*
* * 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/.
*
*/
plugins {
id("cobblemon.base-conventions")
id("cobblemon.publish-conventions")
id("net.kyori.blossom")
id("org.jetbrains.gradle.plugin.idea-ext")
id("net.nemerosa.versioning")
}
architectury {
common("neoforge", "fabric")
common("forge", "fabric")
}
repositories {
maven(url = "${rootProject.projectDir}/deps")
maven(url = "https://api.modrinth.com/maven")
maven(url = "https://maven.neoforged.net/releases")
mavenLocal()
}
dependencies {
implementation(libs.bundles.kotlin)
modImplementation(libs.fabric.loader)
implementation(libs.stdlib)
implementation(libs.reflect)
modImplementation(libs.fabricLoader)
modApi(libs.molang)
// Integrations
// compileOnlyApi(libs.jei.api)
modCompileOnly(libs.bundles.fabric.integrations.compileOnly) {
isTransitive = false
}
// Flywheel has no common dep so just pick one and don't use any platform specific code in common
// modCompileOnly(libs.flywheelFabric)
// Showdown
// For Showdown
modCompileOnly(libs.graal)
// Data Storage
modCompileOnly(libs.bundles.mongo)
//shadowCommon group: 'commons-io', name: 'commons-io', version: '2.6'
// Unit Testing
testImplementation(libs.bundles.unitTesting)
testRuntimeOnly(libs.junitEngine)
testImplementation(libs.junitApi)
testImplementation(libs.junitParams)
testImplementation(libs.mockito)
testImplementation(libs.mockk)
testImplementation(libs.classgraph)
}
tasks.withType<Test> {
@@ -64,34 +40,3 @@ tasks.withType<Test> {
setExceptionFormat("full")
}
}
sourceSets {
main {
blossom {
kotlinSources {
fun generateLicenseHeader() : String {
val builder = StringBuilder()
builder.append("/*\n")
rootProject.file("HEADER").forEachLine {
if(it.isEmpty()) {
builder.append(" *").append("\n")
} else {
builder.append(" * ").append(it).append("\n")
}
}
return builder.append(" */").append("\n").toString()
}
property("license", generateLicenseHeader())
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")
}
}
}
}
@@ -1,24 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common;
import com.cobblemon.mod.common.entity.npc.NPCEntity;
import net.minecraft.entity.ai.brain.Brain;
import net.minecraft.entity.ai.brain.MemoryModuleType;
import net.minecraft.entity.ai.brain.sensor.Sensor;
import net.minecraft.entity.ai.brain.sensor.SensorType;
import java.util.Collection;
public class GenericsCheatClass {
// For some reason, doing this in the NPCEntity class in Kotlin gives confusing generic errors I could not resolve.
public static Brain.Profile<NPCEntity> createNPCBrain(Collection<MemoryModuleType<?>> memories, Collection<SensorType<? extends Sensor<? super NPCEntity>>> sensors) {
return Brain.createProfile(memories, sensors);
}
}
@@ -6,8 +6,10 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.gui.dialogue
package com.cobblemon.mod.common.access;
import net.minecraft.text.MutableText
import net.minecraft.sound.SoundCategory;
class DialogueRenderableSpeaker(val name: MutableText?, val face: RenderableFace?)
public interface SoundManagerDuck {
void toggleCategories(SoundCategory... categories);
}
@@ -1,16 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.bridges;
import net.minecraft.structure.processor.StructureProcessor;
public interface StructureProcessorListBridge {
void append(StructureProcessor processor);
void clear();
}
@@ -8,9 +8,10 @@
package com.cobblemon.mod.common.client.render.models.blockbench.pose;
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.Entity;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
@@ -37,22 +38,28 @@ public interface Bone {
/**
* Renders a particular bone in relation to a particular entity.
*
* @param context The render context this bone is being drawn for.
* @param entity The entity this bone is being drawn for. This parameter need not be available and can be null
* @param stack The current [MatrixStack] for the renderer
* @param buffer The vertex consumer deployed by the renderer
* @param packedLight The light level to be applied to the bone
* @param packedOverlay The overlay value to be applied to the bone
* @param color RGBA packed integer color value
* @param r A value representing the amount of red coloring that should be applied on the RGB scale
* @param g A value representing the amount of green coloring that should be applied on the RGB scale
* @param b A value representing the amount of blue coloring that should be applied on the RGB scale
* @param a The alpha value to apply to the model based on the RGB scale
*
* @since 1.4.0
*/
void render(
RenderContext context,
<T extends Entity> void render(
@Nullable T entity,
MatrixStack stack,
VertexConsumer buffer,
int packedLight,
int packedOverlay,
int color
float r,
float g,
float b,
float a
);
/**
@@ -1,96 +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.compat;
import com.cobblemon.mod.common.CobblemonEntities;
import com.cobblemon.mod.common.client.render.layer.PokemonOnShoulderRenderer;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.cobblemon.mod.common.pokemon.FormData;
import com.cobblemon.mod.common.pokemon.lighthing.LightingData;
//import dev.lambdaurora.lambdynlights.api.DynamicLightHandler;
//import dev.lambdaurora.lambdynlights.api.DynamicLightHandlers;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
// Java class due to relying on entrypoint on Fabric side
public class LambDynamicLightsCompat {
// This is all called on client side
// These things are checked every tick so try to keep it as free as possible
// That being said it's unlikely school Toshiba person is running dynamic lighting and shaders to enjoy this
// Make sure not to call anything Fabric specific :)
public static void hookCompat() {
// Pokémon entities
// DynamicLightHandlers.registerDynamicLightHandler(
// CobblemonEntities.POKEMON,
// DynamicLightHandler.makeHandler(
// pokemon -> resolvedPokemonLightLevel(pokemon, false),
// pokemon -> true
// )
// );
// DynamicLightHandlers.registerDynamicLightHandler(
// CobblemonEntities.POKEMON,
// DynamicLightHandler.makeHandler(
// pokemon -> resolvedPokemonLightLevel(pokemon, true),
// pokemon -> false
// )
// );
// Shouldered Pokémon
// DynamicLightHandlers.registerDynamicLightHandler(
// EntityType.PLAYER,
// DynamicLightHandler.makeHandler(
// player -> resolvedShoulderLightLevel(player, false),
// player -> true
// )
// );
// DynamicLightHandlers.registerDynamicLightHandler(
// EntityType.PLAYER,
// DynamicLightHandler.makeHandler(
// player -> resolvedShoulderLightLevel(player, true),
// player -> false
// )
// );
}
private static int resolvedPokemonLightLevel(PokemonEntity pokemon, boolean underwater) {
return extractFormLightLevel(pokemon.getForm(), underwater).orElse(0);
}
private static int resolvedShoulderLightLevel(PlayerEntity player, boolean underwater) {
final Pair<PokemonOnShoulderRenderer.ShoulderData, PokemonOnShoulderRenderer.ShoulderData> shoulderDataPair = PokemonOnShoulderRenderer.shoulderDataOf(player);
final Optional<Integer> leftLightLevel = extractShoulderLightLevel(shoulderDataPair.getLeft(), underwater);
final Optional<Integer> rightLightLevel = extractShoulderLightLevel(shoulderDataPair.getRight(), underwater);
return Math.max(leftLightLevel.orElse(0), rightLightLevel.orElse(0));
}
private static Optional<Integer> extractFormLightLevel(@NotNull FormData form, boolean underwater) {
if (form.getLightingData() == null || !liquidGlowModeSupport(form.getLightingData().getLiquidGlowMode(), underwater)) {
return Optional.empty();
}
return Optional.of(form.getLightingData().getLightLevel());
}
private static Optional<Integer> extractShoulderLightLevel(@Nullable PokemonOnShoulderRenderer.ShoulderData shoulderData, boolean underwater) {
if (shoulderData == null) {
return Optional.empty();
}
return extractFormLightLevel(shoulderData.getForm(), underwater);
}
private static boolean liquidGlowModeSupport(@NotNull LightingData.LiquidGlowMode liquidGlowMode, boolean underwater) {
return underwater ? liquidGlowMode.getGlowsUnderwater() : liquidGlowMode.getGlowsInLand();
}
}
@@ -1,22 +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.duck;
import net.minecraft.sound.SoundCategory;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
public interface SoundManagerDuck {
void pauseSounds(@Nullable Identifier id, @Nullable SoundCategory category);
void resumeSounds(@Nullable Identifier id, @Nullable SoundCategory category);
void stopSounds(@Nullable Identifier id, @Nullable SoundCategory category);
}
@@ -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.duck;
import net.minecraft.client.sound.SoundInstance;
import net.minecraft.sound.SoundCategory;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
public interface SoundSystemDuck {
void pauseSounds(@Nullable Identifier id, @Nullable SoundCategory category);
void resumeSounds(@Nullable Identifier id, @Nullable SoundCategory category);
void stopSounds(@Nullable Identifier id, @Nullable SoundCategory category);
Collection<SoundInstance> getSounds(@Nullable SoundCategory category);
}
@@ -1,34 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.CobblemonBuildDetails;
import net.minecraft.util.crash.CrashReport;
import net.minecraft.util.crash.CrashReportSection;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(CrashReport.class)
public final class CrashReportMixin {
@Inject(method = "addDetails", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/SystemDetails;writeTo(Ljava/lang/StringBuilder;)V"))
public void cobblemon$printCobblemonDetails(StringBuilder builder, CallbackInfo callback) {
CrashReportSection cobblemon = new CrashReportSection("Cobblemon");
cobblemon.add("Version", CobblemonBuildDetails.VERSION);
cobblemon.add("Is Snapshot", CobblemonBuildDetails.SNAPSHOT);
cobblemon.add("Git Commit", CobblemonBuildDetails.INSTANCE.smallCommitHash() + " (" + "https://gitlab.com/cable-mc/cobblemon/-/commit/" + CobblemonBuildDetails.GIT_COMMIT + ")");
cobblemon.add("Branch", CobblemonBuildDetails.BRANCH);
cobblemon.addStackTrace(builder);
builder.append("\n\n");
}
}
@@ -1,31 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.sherds.CobblemonSherds;
import net.minecraft.block.DecoratedPotPattern;
import net.minecraft.block.DecoratedPotPatterns;
import net.minecraft.item.Item;
import net.minecraft.registry.RegistryKey;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(DecoratedPotPatterns.class)
public abstract class DecoratedPotPatternsMixin {
@Inject(method = "fromSherd", at=@At("HEAD"), cancellable = true)
private static void cobblemon$getCobblemonSherdTexture(Item sherd,
CallbackInfoReturnable<RegistryKey<DecoratedPotPattern>> cir) {
if (CobblemonSherds.INSTANCE.getSherdToPattern().containsKey(sherd)) {
cir.setReturnValue(CobblemonSherds.INSTANCE.getSherdToPattern().get(sherd));
return;
}
}
}
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.client.CobblemonClient;
import net.minecraft.client.render.entity.EntityRenderDispatcher;
import net.minecraft.client.render.entity.EntityRenderer;
import net.minecraft.client.util.SkinTextures;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.resource.ResourceManager;
import org.spongepowered.asm.mixin.Mixin;
@@ -25,7 +24,7 @@ import java.util.Map;
@Mixin(EntityRenderDispatcher.class)
public class EntityRenderDispatcherMixin {
@Shadow private Map<SkinTextures.Model, EntityRenderer<? extends PlayerEntity>> modelRenderers;
@Shadow private Map<String, EntityRenderer<? extends PlayerEntity>> modelRenderers;
@Inject(
method = "reload",
@@ -34,4 +33,4 @@ public class EntityRenderDispatcherMixin {
public void resourceManagerReloadHook(ResourceManager resourceManager, CallbackInfo ci) {
CobblemonClient.INSTANCE.onAddLayer(this.modelRenderers);
}
}
}
@@ -1,33 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import net.minecraft.entity.passive.VillagerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.village.VillagerProfession;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.cobblemon.mod.common.villager.VillagerGatherableItems;
import java.util.Objects;
@Mixin(VillagerEntity.class)
public abstract class EntityVillagerMixin {
@Inject(method = "canGather", at = @At(value = "RETURN"), cancellable = true)
private void cobblemon$canGather(ItemStack stack, CallbackInfoReturnable<Boolean> ci) {
final VillagerEntity villager = (VillagerEntity) (Object) this;
if(ci.getReturnValue() == false && Objects.equals(villager.getVillagerData().getProfession(), VillagerProfession.FARMER) && villager.getInventory().canInsert(stack)) {
if(VillagerGatherableItems.INSTANCE.getVillagerGatherableItems().contains(stack.getItem()))
ci.setReturnValue(true);
}
}
}
@@ -1,38 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.block.PreEmptsExplosion;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.explosion.Explosion;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(value = Explosion.class)
public class ExplosionMixin {
@Redirect(
method = "affectWorld",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/World;getBlockState(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/BlockState;",
ordinal = 0
)
)
public BlockState cobblemon$whenExploded(World world, BlockPos pos) {
BlockState blockState = world.getBlockState(pos);
if(blockState.getBlock() instanceof PreEmptsExplosion preExplosionBlock) {
preExplosionBlock.whenExploded(world, blockState, pos);
}
return blockState;
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.CobblemonBlocks;
import com.cobblemon.mod.common.block.PastureBlock;
import net.minecraft.block.BlockState;
import net.minecraft.block.FenceBlock;
import net.minecraft.block.HorizontalFacingBlock;
import net.minecraft.util.math.Direction;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(value = FenceBlock.class)
public abstract class FenceBlockMixin {
// This could be done with a modify variable but it just doesn't seem to want to work, very crude unfinished explanation I had on Fabric discord was
// "boolean is a primitive, it isnt passed by reference but by value and you have your own object references anyway so assigning a new object to non-primitive references (variables) wont modify it after your mixin returns
//(you cant modify a random argument that mixin passes you that way, target the boolean not the FenceBlock)"
// However the issue is the only way to get all the params which we need is by passing in the entire method reference which enforces the return type.
@Redirect(method = "getStateForNeighborUpdate", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/FenceBlock;canConnect(Lnet/minecraft/block/BlockState;ZLnet/minecraft/util/math/Direction;)Z"))
private boolean cobblemon$getStateForNeighborUpdate(FenceBlock instance, BlockState state, boolean neighborIsFullSquare, Direction dir) {
return instance.canConnect(state, neighborIsFullSquare, dir) || this.cobblemon$canConnect(state, dir);
}
@Redirect(method = "getPlacementState", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/FenceBlock;canConnect(Lnet/minecraft/block/BlockState;ZLnet/minecraft/util/math/Direction;)Z"))
private boolean cobblemon$getPlacementState(FenceBlock instance, BlockState state, boolean neighborIsFullSquare, Direction dir) {
return instance.canConnect(state, neighborIsFullSquare, dir) || this.cobblemon$canConnect(state, dir);
}
private boolean cobblemon$canConnect(BlockState state, Direction dir) {
if (state.isOf(CobblemonBlocks.PASTURE) && state.get(PastureBlock.Companion.getPART()) == PastureBlock.PasturePart.BOTTOM) {
final Direction pastureFacing = state.get(HorizontalFacingBlock.FACING);
return dir == pastureFacing.rotateYClockwise() || dir == pastureFacing.rotateYCounterclockwise();
}
return false;
}
}
@@ -8,38 +8,20 @@
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.api.scheduling.ClientTaskTracker;
import net.minecraft.client.MinecraftClient;
import com.cobblemon.mod.common.api.scheduling.ScheduledTaskTracker;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.render.RenderTickCounter;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(GameRenderer.class)
public class GameRendererMixin {
@Unique
long lastTime = -1;
@Inject(
method = "render",
at = @At(value = "TAIL")
)
public void render(RenderTickCounter counter, boolean tick, CallbackInfo ci) {
MinecraftClient client = MinecraftClient.getInstance();
long newTime = System.currentTimeMillis();
// Don't play scheduled animations when the game is paused
if (client.isPaused()) {
lastTime = newTime;
return;
}
if (lastTime != -1) {
ClientTaskTracker.INSTANCE.update((newTime - lastTime) / 1000F);
}
lastTime = newTime;
public void render(float tickDelta, long startTime, boolean tick, CallbackInfo ci) {
ScheduledTaskTracker.INSTANCE.update();
}
}
@@ -1,70 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.client.CobblemonBakingOverrides;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import net.minecraft.client.color.block.BlockColors;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.render.model.json.JsonUnbakedModel;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.util.Identifier;
import net.minecraft.util.profiler.Profiler;
import org.slf4j.Logger;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.InjectionPoint;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.points.BeforeStringInvoke;
@Mixin(ModelLoader.class)
public abstract class ModelLoaderMixin {
@Shadow protected abstract void addModelToBake(ModelIdentifier modelId, UnbakedModel unbakedModel);
@Final
@Shadow
private Map<Identifier, UnbakedModel> unbakedModels;
@Final
@Shadow
private static Logger LOGGER;
@Inject(
method = "<init>",
at = @At("TAIL")
)
public void init(BlockColors blockColors,
Profiler profiler,
Map jsonUnbakedModels,
Map blockStates,
CallbackInfo ci) {
CobblemonBakingOverrides.INSTANCE.getModels().forEach(bakingOverride -> {
try {
JsonUnbakedModel unbakedModel = this.loadModelFromJson(bakingOverride.getModelLocation());
this.unbakedModels.put(bakingOverride.getModelIdentifier().id(), unbakedModel);
this.addModelToBake(bakingOverride.getModelIdentifier(), unbakedModel);
} catch (IOException e) {
LOGGER.error("Error loading a Cobblemon BakedModel:", e);
throw new RuntimeException(e);
}
});
}
@Shadow
private JsonUnbakedModel loadModelFromJson(Identifier id) throws IOException {
return null;
}
}
@@ -9,10 +9,10 @@
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Bone;
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext;
import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.Entity;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
@@ -22,7 +22,7 @@ import java.util.Map;
@Mixin(ModelPart.class)
public abstract class ModelPartMixin implements Bone {
@Shadow public abstract void render(MatrixStack matrices, VertexConsumer vertices, int light, int overlay, int color);
@Shadow public abstract void render(MatrixStack matrices, VertexConsumer vertices, int light, int overlay, float red, float green, float blue, float alpha);
@Shadow public abstract void rotate(MatrixStack matrixStack);
@@ -36,8 +36,8 @@ public abstract class ModelPartMixin implements Bone {
}
@Override
public void render(RenderContext context, MatrixStack stack, VertexConsumer buffer, int packedLight, int packedOverlay, int color) {
this.render(stack, buffer, packedLight, packedOverlay, color);
public <T extends Entity> void render(T entity, MatrixStack stack, VertexConsumer buffer, int packedLight, int packedOverlay, float r, float g, float b, float a) {
this.render(stack, buffer, packedLight, packedOverlay, r, g, b, a);
}
@Override
@@ -1,37 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.client.sound.battle.BattleMusicController;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.sound.MusicTracker;
import net.minecraft.client.sound.SoundInstance;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(MusicTracker.class)
public class MusicTrackerMixin {
@Shadow @Final
private MinecraftClient client;
@Shadow @Nullable
private SoundInstance current;
/** Freezes the tracker while a BattleMusicInstance is in progress. Current SoundInstance being tracked will be paused by BattleMusicHandler. */
@Inject(method = "tick()V", at = @At("HEAD"), cancellable = true)
public void tick(CallbackInfo cb) {
if (this.client.getSoundManager().isPlaying(BattleMusicController.INSTANCE.getMusic())) cb.cancel();
}
}
@@ -1,37 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.api.snowstorm.ParticleMaterials;
import com.google.common.collect.ImmutableList;
import net.minecraft.client.particle.ParticleManager;
import net.minecraft.client.particle.ParticleTextureSheet;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.List;
@Mixin(ParticleManager.class)
final class ParticleManagerMixin {
@Mutable
@Final
@Shadow
private static List<ParticleTextureSheet> PARTICLE_TEXTURE_SHEETS;
@Inject(at = @At("RETURN"), method = "<clinit>")
private static void lodestone$addTypes(CallbackInfo ci) {
PARTICLE_TEXTURE_SHEETS = ImmutableList.<ParticleTextureSheet>builder().addAll(PARTICLE_TEXTURE_SHEETS)
.add(ParticleMaterials.INSTANCE.getADD(), ParticleMaterials.INSTANCE.getALPHA(), ParticleMaterials.INSTANCE.getBLEND(), ParticleMaterials.INSTANCE.getOPAQUE()).build();
}
}
@@ -21,13 +21,13 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(Mouse.class)
public class PartyScrollMixin {
@Shadow
private double eventDeltaVerticalWheel;
private double eventDeltaWheel;
@Inject(
method = "onMouseScroll",
at = @At(
value = "FIELD",
target="Lnet/minecraft/client/Mouse;eventDeltaVerticalWheel:D",
target="Lnet/minecraft/client/Mouse;eventDeltaWheel:D",
opcode = Opcodes.PUTFIELD,
ordinal = 2,
shift = At.Shift.BEFORE
@@ -36,18 +36,18 @@ public class PartyScrollMixin {
)
public void onMouseScroll(long window, double horizontal, double vertical, CallbackInfo ci) {
if (PartySendBinding.INSTANCE.getWasDown()) {
int i = (int)eventDeltaVerticalWheel;
int i = (int)eventDeltaWheel;
if (i > 0) {
while (i-- > 0) CobblemonClient.INSTANCE.getStorage().shiftSelected(false);
ci.cancel();
eventDeltaVerticalWheel = 0;
eventDeltaWheel = 0;
PartySendBinding.INSTANCE.actioned();
} else if (i < 0) {
while (i++ < 0) CobblemonClient.INSTANCE.getStorage().shiftSelected(true);
ci.cancel();
eventDeltaVerticalWheel = 0;
eventDeltaWheel = 0;
PartySendBinding.INSTANCE.actioned();
}
}
}
}
}
@@ -1,33 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.CobblemonItems;
import net.minecraft.entity.mob.PiglinBrain;
import net.minecraft.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(PiglinBrain.class)
public class PiglinBarterMixin {
@Inject(method = "acceptsForBarter", at = @At(value = "RETURN"), cancellable = true)
private static void cobblemon$acceptsForBarter(ItemStack stack, CallbackInfoReturnable<Boolean> ci) {
if(!ci.getReturnValue()) {
//TODO: Make a tag?
if(stack.isOf(CobblemonItems.RELIC_COIN_POUCH))
ci.setReturnValue(true);
}
}
}
@@ -1,31 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.CobblemonItems;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.mob.PiglinEntity;
import net.minecraft.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(PiglinEntity.class)
public abstract class PiglinEntityMixin {
@Inject(method = "equipToOffHand", at = @At(value = "HEAD"), cancellable = true)
public void cobblemon$isValidBarteringItem(ItemStack stack, CallbackInfo ci) {
PiglinEntity entity = (PiglinEntity)(Object) this;
if (stack.isOf(CobblemonItems.RELIC_COIN_POUCH)) {
entity.equipStack(EquipmentSlot.OFFHAND, stack);
entity.updateDropChances(EquipmentSlot.OFFHAND);
ci.cancel();
}
}
}
@@ -14,18 +14,19 @@ import com.cobblemon.mod.common.api.events.CobblemonEvents;
import com.cobblemon.mod.common.api.events.item.LeftoversCreatedEvent;
import com.cobblemon.mod.common.api.storage.NoPokemonStoreException;
import com.cobblemon.mod.common.api.storage.party.PartyStore;
import com.cobblemon.mod.common.api.tags.CobblemonItemTags;
import com.cobblemon.mod.common.pokemon.Pokemon;
import com.cobblemon.mod.common.util.CompoundTagExtensionsKt;
import com.cobblemon.mod.common.util.DataKeys;
import net.minecraft.component.type.FoodComponent;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.sound.SoundEvent;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text;
import net.minecraft.world.World;
import org.objectweb.asm.Opcodes;
@@ -39,6 +40,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Objects;
import java.util.UUID;
import static com.cobblemon.mod.common.util.LocalizationUtilsKt.lang;
@Mixin(PlayerEntity.class)
public abstract class PlayerMixin extends LivingEntity {
@@ -139,9 +142,9 @@ public abstract class PlayerMixin extends LivingEntity {
shift = At.Shift.AFTER
)
)
public void onEatFood(World world, ItemStack stack, FoodComponent foodComponent, CallbackInfoReturnable<ItemStack> cir) {
public void onEatFood(World world, ItemStack stack, CallbackInfoReturnable<ItemStack> cir) {
if (!getWorld().isClient) {
if (stack.isIn(CobblemonItemTags.LEAVES_LEFTOVERS) && getWorld().random.nextDouble() < Cobblemon.config.getAppleLeftoversChance()) {
if (stack.getItem() == Items.APPLE && getWorld().random.nextDouble() < Cobblemon.config.getAppleLeftoversChance()) {
ItemStack leftovers = new ItemStack(CobblemonItems.LEFTOVERS);
ServerPlayerEntity player = Objects.requireNonNull(getServer()).getPlayerManager().getPlayer(uuid);
assert player != null;
@@ -6,9 +6,9 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.fabric.mixin;
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.fabric.brewing.CobblemonFabricBreweryRegistry;
import com.cobblemon.mod.common.brewing.BrewingRecipes;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.BrewingStandScreenHandler;
import org.spongepowered.asm.mixin.Mixin;
@@ -18,14 +18,14 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(BrewingStandScreenHandler.PotionSlot.class)
public class PotionSlotMixin {
@Inject(method = "matches", at = @At("RETURN"), cancellable = true)
private static void cobblemon$matches(ItemStack stack, CallbackInfoReturnable<Boolean> cir) {
if (cir.getReturnValue()) {
return;
@Inject(
method = "matches",
at = @At(value = "HEAD"),
cancellable = true
)
private static void matchesBrewable(ItemStack stack, CallbackInfoReturnable<Boolean> cir) {
if (BrewingRecipes.brewableItems.contains(stack.getItem())) {
cir.setReturnValue(true);
}
cir.setReturnValue(CobblemonFabricBreweryRegistry.INSTANCE.isValidPotionSlot(stack));
}
}
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.api.spawning.mixins.CachedOnlyChunkAccessor;
import com.mojang.datafixers.util.Either;
import net.minecraft.server.world.ChunkHolder;
import net.minecraft.server.world.ServerChunkManager;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.ChunkManager;
import net.minecraft.world.chunk.ChunkStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.concurrent.CompletableFuture;
@Mixin(ServerChunkManager.class)
public abstract class ServerChunkManagerMixin extends ChunkManager implements CachedOnlyChunkAccessor {
@Shadow @Nullable protected abstract ChunkHolder getChunkHolder(long pos);
@Override
public Chunk cobblemon$request(int x, int z, @NotNull ChunkStatus status) {
long l = ChunkPos.toLong(x, z);
ChunkHolder holder = getChunkHolder(l);
if (holder != null) {
CompletableFuture<Either<Chunk, ChunkHolder.Unloaded>> future = holder.getFutureFor(status);
if (future.isDone()) {
return future.join().left().orElse(null);
}
}
return null;
}
}
@@ -8,83 +8,36 @@
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.client.sound.battle.BattleMusicController;
import com.cobblemon.mod.common.duck.SoundManagerDuck;
import com.cobblemon.mod.common.duck.SoundSystemDuck;
import net.minecraft.client.sound.*;
import com.cobblemon.mod.common.access.SoundManagerDuck;
import net.minecraft.client.sound.SoundInstance;
import net.minecraft.client.sound.SoundManager;
import net.minecraft.sound.SoundCategory;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(SoundManager.class)
public abstract class SoundManagerMixin implements SoundManagerDuck {
public class SoundManagerMixin implements SoundManagerDuck {
@Shadow
public abstract boolean isPlaying(SoundInstance sound);
private boolean[] blockedCategories = new boolean[SoundCategory.values().length];
@Shadow @Final
private SoundSystem soundSystem;
// Never-ending ambient loops are a special exception (they are only initiated once) and should always be paused if filtered.
private boolean isAmbientLoop(SoundInstance sound) {
return sound instanceof BiomeEffectSoundPlayer.MusicLoop || sound instanceof AmbientSoundLoops.Underwater;
}
private boolean filterCondition(SoundInstance sound) {
return !isAmbientLoop(sound) &&
this.isPlaying(BattleMusicController.INSTANCE.getMusic()) &&
BattleMusicController.INSTANCE.getFilteredCategories().contains(sound.getCategory());
}
private boolean ambientLoopCondition(SoundInstance sound) {
return isAmbientLoop(sound) &&
this.isPlaying(BattleMusicController.INSTANCE.getMusic()) &&
BattleMusicController.INSTANCE.getFilteredCategories().contains(sound.getCategory());
}
/** Pauses the queried SoundInstance(s). If id is null, will pause all sounds belonging to the SoundCategory. */
@Override
public void pauseSounds(@Nullable Identifier id, @Nullable SoundCategory category) {
((SoundSystemDuck)soundSystem).pauseSounds(id, category);
public void toggleCategories(SoundCategory... categories) {
for (SoundCategory category : categories) {
int index = category.ordinal();
boolean blocked = blockedCategories[index];
blockedCategories[index] = !blocked;
}
}
/** Resumes the queried SoundInstance(s). If id is null, will resume all sounds belonging to the SoundCategory. */
@Override
public void resumeSounds(@Nullable Identifier id, @Nullable SoundCategory category) {
((SoundSystemDuck)soundSystem).resumeSounds(id, category);
}
/** Stops the queried SoundInstance(s). If id is null, will stop all sounds belonging to the SoundCategory. */
@Override
public void stopSounds(@Nullable Identifier id, @Nullable SoundCategory category) {
((SoundSystemDuck)soundSystem).stopSounds(id, category);
}
/** Blocks filtered sounds from being played while a BattleMusicInstance is in progress. */
@Inject(method = "play(Lnet/minecraft/client/sound/SoundInstance;)V", at = @At("HEAD"), cancellable = true)
public void playStart(SoundInstance sound, CallbackInfo cb) {
if (filterCondition(sound)) cb.cancel();
public void play(SoundInstance sound, CallbackInfo cb) {
if (blockedCategories[sound.getCategory().ordinal()]) cb.cancel();
}
@Inject(method = "play(Lnet/minecraft/client/sound/SoundInstance;I)V", at = @At("HEAD"), cancellable = true)
public void playStart(SoundInstance sound, int delay, CallbackInfo cb) {
if (filterCondition(sound)) cb.cancel();
}
/** Pauses ambient loops while a BattleMusicInstance is in progress. */
@Inject(method = "play(Lnet/minecraft/client/sound/SoundInstance;)V", at = @At("TAIL"))
public void playEnd(SoundInstance sound, CallbackInfo cb) {
if (ambientLoopCondition(sound)) this.pauseSounds(sound.getId(), SoundCategory.AMBIENT);
}
@Inject(method = "play(Lnet/minecraft/client/sound/SoundInstance;I)V", at = @At("TAIL"))
public void playEnd(SoundInstance sound, int delay, CallbackInfo cb) {
if (ambientLoopCondition(sound)) this.pauseSounds(sound.getId(), SoundCategory.AMBIENT);
public void play(SoundInstance sound, int delay, CallbackInfo cb) {
if (blockedCategories[sound.getCategory().ordinal()]) cb.cancel();
}
}
@@ -8,102 +8,31 @@
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.client.sound.battle.BattleMusicController;
import com.cobblemon.mod.common.duck.SoundSystemDuck;
import com.google.common.collect.Multimap;
import net.minecraft.client.sound.*;
import net.minecraft.client.sound.SoundInstance;
import net.minecraft.client.sound.SoundSystem;
import net.minecraft.sound.SoundCategory;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Map;
@Mixin(SoundSystem.class)
public abstract class SoundSystemMixin implements SoundSystemDuck {
@Shadow
private boolean started;
public abstract class SoundSystemMixin {
@Shadow
private Multimap<SoundCategory, SoundInstance> sounds;
@Shadow @Final
private Map<SoundInstance, Channel.SourceManager> sources;
@Shadow
protected abstract void stop(SoundInstance sound);
@Shadow
public abstract boolean isPlaying(SoundInstance sound);
/** Resumes the Source belonging to the queried SoundInstance. */
private void resume(SoundInstance sound) {
Channel.SourceManager sourceManager = this.sources.get(sound);
if (this.started && sourceManager != null) sourceManager.run(Source::resume);
}
/** Pauses the Source belonging to the queried SoundInstance. */
private void pause(SoundInstance sound) {
Channel.SourceManager sourceManager = this.sources.get(sound);
if (this.started && sourceManager != null) sourceManager.run(Source::pause);
}
/** Resumes the SoundInstance(s) queried by id and/or category. */
@Override
public void resumeSounds(@Nullable Identifier id, @Nullable SoundCategory category) {
if (category != null) {
this.sounds.get(category).forEach((sound) -> {
if (id == null || sound.getId().equals(id)) resume(sound);
});
} else if (id == null) {
this.sources.keySet().forEach(this::resume);
} else {
this.sources.keySet().forEach(sound -> {
if (sound.getId().equals(id)) resume(sound);
});
}
}
/** Pauses the SoundInstances queried by id and/or category. */
@Override
public void pauseSounds(@Nullable Identifier id, @Nullable SoundCategory category) {
if (category != null) {
this.sounds.get(category).forEach((sound) -> {
if (id == null || sound.getId().equals(id)) pause(sound);
});
} else if (id == null) {
this.sources.keySet().forEach(this::pause);
} else {
this.sources.keySet().forEach(sound -> {
if (sound.getId().equals(id)) pause(sound);
});
}
}
/** Allows stopping all SoundInstances that belong to a queried category. */
@Inject(method = "stopSounds(Lnet/minecraft/util/Identifier;Lnet/minecraft/sound/SoundCategory;)V", at = @At("HEAD"), cancellable = true)
public void stopSounds(@Nullable Identifier id, @Nullable SoundCategory category, CallbackInfo cb) {
if (id == null && category != null) {
this.sounds.get(category).forEach(this::stop);
cb.cancel();
}
}
/** Different behavior for resuming SoundInstances while a BattleMusicInstance is being played. We do not want to resume filtered sounds. */
@Inject(method = "resumeAll()V", at = @At("HEAD"), cancellable = true)
public void resumeAll(CallbackInfo cb) {
if (this.isPlaying(BattleMusicController.INSTANCE.getMusic())) {
this.sounds.values().forEach(sound -> {
if (sound == BattleMusicController.INSTANCE.getMusic() || !BattleMusicController.INSTANCE.getFilteredCategories().contains(sound.getCategory())) {
resume(sound);
}
});
sounds.get(category).forEach(this::stop);
cb.cancel();
}
}
@@ -1,32 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.mojang.datafixers.util.Pair;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.structure.pool.StructurePool;
import net.minecraft.structure.pool.StructurePoolElement;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.List;
@Mixin(StructurePool.class)
public interface StructurePoolAccessor {
@Accessor("elementCounts")
List<Pair<StructurePoolElement, Integer>> getElementCounts();
@Mutable
@Accessor("elementCounts")
void setElementCounts(List<Pair<StructurePoolElement, Integer>> elementCounts);
@Accessor("elements")
ObjectArrayList<StructurePoolElement> getElements();
}
@@ -1,207 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.world.CobblemonStructureIDs;
import net.minecraft.registry.Registry;
import net.minecraft.structure.PoolStructurePiece;
import net.minecraft.structure.StructureTemplateManager;
import net.minecraft.structure.pool.*;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.gen.chunk.ChunkGenerator;
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.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.*;
@Mixin(StructurePoolBasedGenerator.StructurePoolGenerator.class)
public abstract class StructurePoolGeneratorMixin {
Map<String, Integer> generatedStructureGroupCounts;
private static final Map<String, Integer> structureMaxes;
private static final Map<Identifier, Set<String>> structureGroups = new HashMap<>();
static {
String pokecenter = "pokecenter";
String berry = "berry_farm";
structureGroups.put(CobblemonStructureIDs.PLAINS_POKECENTER, Set.of(pokecenter));
structureGroups.put(CobblemonStructureIDs.DESERT_POKECENTER, Set.of(pokecenter));
structureGroups.put(CobblemonStructureIDs.SAVANNA_POKECENTER, Set.of(pokecenter));
structureGroups.put(CobblemonStructureIDs.SNOWY_POKECENTER, Set.of(pokecenter));
structureGroups.put(CobblemonStructureIDs.TAIGA_POKECENTER, Set.of(pokecenter));
structureGroups.put(CobblemonStructureIDs.SAVANNA_BERRY_SMALL, Set.of(berry));
structureGroups.put(CobblemonStructureIDs.SAVANNA_BERRY_LARGE, Set.of(berry));
structureGroups.put(CobblemonStructureIDs.PLAINS_BERRY_SMALL, Set.of(berry));
structureGroups.put(CobblemonStructureIDs.PLAINS_BERRY_LARGE, Set.of(berry));
structureGroups.put(CobblemonStructureIDs.SNOWY_BERRY_SMALL, Set.of(berry));
structureGroups.put(CobblemonStructureIDs.SNOWY_BERRY_LARGE, Set.of(berry));
structureGroups.put(CobblemonStructureIDs.DESERT_BERRY_SMALL, Set.of(berry));
structureGroups.put(CobblemonStructureIDs.DESERT_BERRY_LARGE, Set.of(berry));
structureGroups.put(CobblemonStructureIDs.TAIGA_BERRY_SMALL, Set.of(berry));
structureGroups.put(CobblemonStructureIDs.TAIGA_BERRY_LARGE, Set.of(berry));
//Mapped using location string as key
Map<String, Integer> aMap = new HashMap<>();
aMap.put(pokecenter, 1);
aMap.put(berry, 2);
// aMap.put(CobblemonStructureIDs.PLAINS_LONG_PATH, 3);
// aMap.put(CobblemonStructureIDs.DESERT_LONG_PATH, 3);
// aMap.put(CobblemonStructureIDs.SAVANNA_LONG_PATH, 3);
// aMap.put(CobblemonStructureIDs.SNOWY_LONG_PATH, 3);
// aMap.put(CobblemonStructureIDs.TAIGA_LONG_PATH, 3);
structureMaxes = Collections.unmodifiableMap(aMap);
}
public Set<String> getGroups(Identifier structureIdentifier) {
return structureGroups.getOrDefault(structureIdentifier, Set.of());
}
public boolean hasReachedMaximum(Identifier structureIdentifier) {
Set<String> groups = getGroups(structureIdentifier);
for (String group : groups) {
int count = generatedStructureGroupCounts.getOrDefault(group, 0);
if (count >= structureMaxes.getOrDefault(group, Integer.MAX_VALUE)) {
return true;
}
}
return false;
}
public void incrementStructureCount(Identifier structureIdentifier) {
Set<String> groups = getGroups(structureIdentifier);
for (String group : groups) {
generatedStructureGroupCounts.put(group, generatedStructureGroupCounts.getOrDefault(group, 0) + 1);
}
}
@Inject(method = "<init>", at = @At("RETURN"))
private void onStructurePoolGeneratorCreation(Registry<StructurePool> registry, int maxSize, ChunkGenerator chunkGenerator, StructureTemplateManager structureTemplateManager, List<? super PoolStructurePiece> children, Random random, CallbackInfo ci) {
generatedStructureGroupCounts = new HashMap<>();
}
@ModifyVariable(method = "generatePiece", at = @At("STORE"), ordinal = 1)
private Iterator<StructurePoolElement> reduceStructurePoolElementIterator(Iterator<StructurePoolElement> iterator) {
List<StructurePoolElement> reducedList = new ArrayList<>();
while (iterator.hasNext()) {
StructurePoolElement structure = iterator.next();
Identifier structurePieceLocationKey = getCobblemonOnlyLocation(structure);
if (structurePieceLocationKey == null) {
reducedList.add(structure);
continue;
}
if (!hasReachedMaximum(structurePieceLocationKey)) {
reducedList.add(structure);
}
}
return reducedList.iterator();
}
@ModifyVariable(method = "generatePiece", at = @At("HEAD"), ordinal = 0, argsOnly = true)
private PoolStructurePiece injected(PoolStructurePiece poolStructurePiece) {
Identifier structureLocationKey = getCobblemonOnlyLocation(poolStructurePiece.getPoolElement());
if (structureLocationKey != null) {
incrementStructureCount(structureLocationKey);
}
return poolStructurePiece;
}
// This doesn't SEEM necessary? It appears to work without.
// @Inject(method = "generatePiece", at = @At("HEAD"))
// private void beforeGeneratePiece(PoolStructurePiece piece, MutableObject<VoxelShape> pieceShape, int minY, boolean modifyBoundingBox, HeightLimitView world, NoiseConfig noiseConfig, CallbackInfo ci) {
//// Identifier structureLocationKey = getCobblemonOnlyLocation(piece.getPoolElement());
////
//// if (structureLocationKey != null) {
//// Integer currentlyGenerated = generatedStructureCounts.get(structureLocationKey);
//// if (currentlyGenerated == null) currentlyGenerated = 0;
//// generatedStructureCounts.put(structureLocationKey, currentlyGenerated + 1);
//// }
////
//// List<StructurePoolBasedGenerator.ShapedPoolStructurePiece> reducedStructurePiecesList = structurePieces.stream().toList();
////
//// for (Identifier maxStructureLocationKey : structureMaxes.keySet()) {
//// Integer maxAllowed = structureMaxes.get(maxStructureLocationKey);
////
//// Integer currentlyGenerated = generatedStructureCounts.get(maxStructureLocationKey);
//// if (currentlyGenerated == null) currentlyGenerated = 0;
//// if (currentlyGenerated < maxAllowed) {
//// continue;
//// }
////
//// //Already have max so need to remove
//// reducedStructurePiecesList = reducedStructurePiecesList.stream()
//// .filter(shapedStructurePiece -> {
//// Identifier locationKey = getCobblemonOnlyLocation(shapedStructurePiece.piece.getPoolElement());
//// if (locationKey == null) {
//// return true;
//// }
////
//// return !locationKey.equals(maxStructureLocationKey);
//// })
//// .collect(Collectors.toList());
//// }
////
//// structurePieces = new ArrayDeque<>(reducedStructurePiecesList);
// }
private static Identifier getCobblemonOnlyLocation(StructurePoolElement structurePoolElement) {
Identifier location = getLocationIfAvailable(structurePoolElement);
if (location == null) return null;
if (!location.getNamespace().equals("cobblemon")) return null;
return location;
}
private static Identifier getLocationIfAvailable(StructurePoolElement structurePoolElement) {
if (structurePoolElement instanceof LegacySinglePoolElement legacySinglePoolElement) {
if (legacySinglePoolElement.location.left().isEmpty()) return null;
return legacySinglePoolElement.location.left().get();
} else if (structurePoolElement instanceof SinglePoolElement singlePoolElement) {
if (singlePoolElement.location.left().isEmpty()) return null;
return singlePoolElement.location.left().get();
} else {
return null;
}
}
// private List<StructurePoolElement> removeInstanceOfLocationKeyFrom(List<StructurePoolElement> structureList, Integer allowedNumberOfInstances, Identifier locationKey) {
// List<StructurePoolElement> reducedList = new ArrayList<>();
// int instancesFound = 0;
//
// for (StructurePoolElement structurePoolElement: structureList) {
// Identifier structureKey = getCobblemonOnlyLocation(structurePoolElement);
// if (structureKey == null || !structureKey.equals(locationKey)) {
// reducedList.add(structurePoolElement);
// continue;
// }
//
// if (instancesFound >= allowedNumberOfInstances) {
// continue;
// }
//
// reducedList.add(structurePoolElement);
// instancesFound++;
// }
//
// return reducedList;
// }
}
@@ -1,43 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.bridges.StructureProcessorListBridge;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.structure.processor.StructureProcessor;
import net.minecraft.structure.processor.StructureProcessorList;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(StructureProcessorList.class)
public class StructureProcessorListMixin implements StructureProcessorListBridge {
@Final
@Mutable
@Shadow
private List<StructureProcessor> list;
@Override
public void append(StructureProcessor processor) {
List<StructureProcessor> mutable = new ArrayList<>(this.list);
mutable.add(processor);
this.list = ImmutableList.copyOf(mutable);
}
@Override
public void clear() {
this.list = ImmutableList.of();
}
}
@@ -8,16 +8,15 @@
package com.cobblemon.mod.common.mixin.accessor;
import net.minecraft.entity.vehicle.BoatEntity;
import net.minecraft.client.sound.MusicTracker;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(BoatEntity.class)
public interface BoatEntityAccessor {
@Mixin(MusicTracker.class)
public interface MusicTrackerAccessor {
@Accessor("timeUntilNextSong")
int timeUntilNextSong();
@Accessor
void setFallVelocity(double fallVelocity);
@Accessor
BoatEntity.Location getLocation();
@Accessor("timeUntilNextSong")
void setTimeUntilNextSong(int timeUntilNextSong);
}
@@ -1,32 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.invoker;
import java.util.List;
import juuxel.adorn.block.variant.BlockVariantSet;
import juuxel.adorn.block.variant.BlockVariantSets;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
//This is a yucky hack but better than what we were doing before
@Mixin(BlockVariantSets.class)
public abstract class AdornRegisterInvoker {
@Final
@Shadow(remap = false)
private static List<BlockVariantSet> variantSets;
@Inject(method = "register()V", at = @At("HEAD"), remap = false)
void register(CallbackInfo ci) {
// variantSets.add(AdornCompatibility.INSTANCE);
}
}
@@ -9,6 +9,7 @@
package com.cobblemon.mod.common.mixin.invoker;
import net.minecraft.block.*;
import net.minecraft.resource.featuretoggle.FeatureFlag;
import net.minecraft.sound.BlockSoundGroup;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@@ -18,23 +19,23 @@ import org.spongepowered.asm.mixin.gen.Invoker;
public interface BlocksInvoker {
@Invoker("createLogBlock")
static Block createLogBlock(MapColor topMapColor, MapColor sideMapColor) {
static PillarBlock createLogBlock(MapColor topMapColor, MapColor sideMapColor) {
throw new UnsupportedOperationException();
}
@Invoker("createLeavesBlock")
static Block createLeavesBlock(BlockSoundGroup soundGroup) {
static LeavesBlock createLeavesBlock(BlockSoundGroup soundGroup) {
throw new UnsupportedOperationException();
}
@Invoker("createWoodenButtonBlock")
static Block createWoodenButtonBlock(BlockSetType blockSetType) {
static ButtonBlock createWoodenButtonBlock(BlockSetType blockSetType, FeatureFlag... requiredFeatures) {
throw new UnsupportedOperationException();
}
@Invoker("createFlowerPotBlock")
static Block createFlowerPotBlock(Block flower) {
static FlowerPotBlock createFlowerPotBlock(Block flower, FeatureFlag... requiredFeatures) {
throw new UnsupportedOperationException();
}
}
}
@@ -11,13 +11,14 @@ package com.cobblemon.mod.common.mixin.invoker;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.BlockSetType;
import net.minecraft.block.DoorBlock;
import net.minecraft.sound.SoundEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(DoorBlock.class)
public interface DoorBlockInvoker {
@Invoker("<init>")
static DoorBlock cobblemon$create(BlockSetType blockSetType, AbstractBlock.Settings settings) {
static DoorBlock cobblemon$create(AbstractBlock.Settings settings, BlockSetType blockSetType) {
throw new UnsupportedOperationException();
}
}
}
@@ -1,20 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.invoker;
import net.minecraft.block.Block;
import org.spongepowered.asm.mixin.Mixin;
import net.minecraft.block.FireBlock;
import net.minecraft.block.Blocks;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(FireBlock.class)
public interface FireBlockInvoker {
@Invoker("registerFlammableBlock") void registerNewFlammableBlock(Block block, int burnChance, int spreadChance);
}
@@ -11,13 +11,14 @@ package com.cobblemon.mod.common.mixin.invoker;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.BlockSetType;
import net.minecraft.block.PressurePlateBlock;
import net.minecraft.sound.SoundEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(PressurePlateBlock.class)
public interface PressurePlateBlockInvoker {
@Invoker("<init>")
static PressurePlateBlock cobblemon$create(BlockSetType type, AbstractBlock.Settings settings) {
static PressurePlateBlock cobblemon$create(PressurePlateBlock.ActivationRule type, AbstractBlock.Settings settings, BlockSetType blockSetType) {
throw new UnsupportedOperationException();
}
}
}
@@ -1,20 +0,0 @@
package com.cobblemon.mod.common.mixin.invoker;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.BlockSetType;
import net.minecraft.block.PressurePlateBlock;
import net.minecraft.resource.featuretoggle.FeatureSet;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.screen.ScreenHandlerType.Factory;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(ScreenHandlerType.class)
public interface ScreenHandlerTypeInvoker {
@Invoker("<init>")
static <T extends ScreenHandler> ScreenHandlerType<T> cobblemon$create(Factory<T> factory, FeatureSet requiredFeatures) {
throw new UnsupportedOperationException();
}
}
@@ -11,13 +11,14 @@ package com.cobblemon.mod.common.mixin.invoker;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.BlockSetType;
import net.minecraft.block.TrapdoorBlock;
import net.minecraft.sound.SoundEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(TrapdoorBlock.class)
public interface TrapdoorBlockInvoker {
@Invoker("<init>")
static TrapdoorBlock cobblemon$create(BlockSetType blockSetType, AbstractBlock.Settings settings) {
static TrapdoorBlock cobblemon$create(AbstractBlock.Settings settings, BlockSetType blockSetType) {
throw new UnsupportedOperationException();
}
}
}
@@ -1,17 +0,0 @@
{{ license }}
package com.cobblemon.mod.common
object CobblemonBuildDetails {
const val MOD_ID = "{{ modid }}"
const val VERSION = "{{ version }}"
const val SNAPSHOT = {{ isSnapshot }}
const val GIT_COMMIT = "{{ gitCommit | default("Not Specified") }}"
const val BRANCH = "{{ branch | default("Not Specified") }}"
fun smallCommitHash(): String {
return this.GIT_COMMIT.substring(0, 7)
}
}
@@ -1,29 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common
import net.minecraft.client.MinecraftClient
import net.minecraft.client.render.model.BakedModel
import net.minecraft.client.util.ModelIdentifier
import net.minecraft.util.Identifier
/**
* Contains information for forcing a model to be baked
*
* @param modelLocation The location of the model
* @param modelIdentifier The identifier that the BakedModel will be registered to
*/
data class BakingOverride(
val modelLocation: Identifier,
val modelIdentifier: ModelIdentifier
) {
fun getModel(): BakedModel {
return MinecraftClient.getInstance().bakedModelManager.getModel(modelIdentifier)
}
}
@@ -8,26 +8,19 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.CobblemonBuildDetails.smallCommitHash
import com.cobblemon.mod.common.advancement.CobblemonCriteria
import com.cobblemon.mod.common.advancement.criterion.EvolvePokemonContext
import com.cobblemon.mod.common.api.Priority
import com.cobblemon.mod.common.api.SeasonResolver
import com.cobblemon.mod.common.api.data.DataProvider
import com.cobblemon.mod.common.api.drop.CommandDropEntry
import com.cobblemon.mod.common.api.drop.DropEntry
import com.cobblemon.mod.common.api.drop.ItemDropEntry
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.CobblemonEvents.BATTLE_VICTORY
import com.cobblemon.mod.common.api.events.CobblemonEvents.DATA_SYNCHRONIZED
import com.cobblemon.mod.common.api.events.CobblemonEvents.EVOLUTION_COMPLETE
import com.cobblemon.mod.common.api.events.CobblemonEvents.LEVEL_UP_EVENT
import com.cobblemon.mod.common.api.events.CobblemonEvents.POKEMON_CAPTURED
import com.cobblemon.mod.common.api.events.CobblemonEvents.TRADE_COMPLETED
import com.cobblemon.mod.common.api.net.serializers.IdentifierDataSerializer
import com.cobblemon.mod.common.api.net.serializers.PoseTypeDataSerializer
import com.cobblemon.mod.common.api.net.serializers.StringSetDataSerializer
import com.cobblemon.mod.common.api.net.serializers.UUIDSetDataSerializer
import com.cobblemon.mod.common.api.net.serializers.Vec3DataSerializer
import com.cobblemon.mod.common.api.permission.PermissionValidator
import com.cobblemon.mod.common.api.pokeball.catching.calculators.CaptureCalculator
@@ -39,40 +32,28 @@ import com.cobblemon.mod.common.api.pokemon.experience.ExperienceGroups
import com.cobblemon.mod.common.api.pokemon.experience.StandardExperienceCalculator
import com.cobblemon.mod.common.api.pokemon.feature.ChoiceSpeciesFeatureProvider
import com.cobblemon.mod.common.api.pokemon.feature.FlagSpeciesFeatureProvider
import com.cobblemon.mod.common.api.pokemon.feature.IntSpeciesFeatureProvider
import com.cobblemon.mod.common.api.pokemon.feature.SpeciesFeatures
import com.cobblemon.mod.common.api.pokemon.helditem.HeldItemProvider
import com.cobblemon.mod.common.api.pokemon.stats.EvCalculator
import com.cobblemon.mod.common.api.pokemon.stats.Generation8EvCalculator
import com.cobblemon.mod.common.api.pokemon.stats.StatProvider
import com.cobblemon.mod.common.api.properties.CustomPokemonProperty
import com.cobblemon.mod.common.api.scheduling.ServerRealTimeTaskTracker
import com.cobblemon.mod.common.api.scheduling.ServerTaskTracker
import com.cobblemon.mod.common.api.scheduling.ScheduledTaskTracker
import com.cobblemon.mod.common.api.spawning.BestSpawner
import com.cobblemon.mod.common.api.spawning.CobblemonSpawningProspector
import com.cobblemon.mod.common.api.spawning.WorldSlice
import com.cobblemon.mod.common.api.spawning.context.AreaContextResolver
import com.cobblemon.mod.common.api.spawning.context.AreaSpawningContext
import com.cobblemon.mod.common.api.spawning.context.calculators.AreaSpawningContextCalculator
import com.cobblemon.mod.common.api.spawning.context.calculators.AreaSpawningInput
import com.cobblemon.mod.common.api.spawning.prospecting.SpawningProspector
import com.cobblemon.mod.common.api.spawning.spawner.Spawner
import com.cobblemon.mod.common.api.starter.StarterHandler
import com.cobblemon.mod.common.api.storage.PokemonStoreManager
import com.cobblemon.mod.common.api.storage.adapter.conversions.ReforgedConversion
import com.cobblemon.mod.common.api.storage.adapter.database.MongoDBStoreAdapter
import com.cobblemon.mod.common.api.storage.adapter.flatfile.FileStoreAdapter
import com.cobblemon.mod.common.api.storage.adapter.flatfile.JSONStoreAdapter
import com.cobblemon.mod.common.api.storage.adapter.flatfile.NBTStoreAdapter
import com.cobblemon.mod.common.api.storage.adapter.flatifle.FileStoreAdapter
import com.cobblemon.mod.common.api.storage.adapter.flatifle.JSONStoreAdapter
import com.cobblemon.mod.common.api.storage.adapter.flatifle.NBTStoreAdapter
import com.cobblemon.mod.common.api.storage.factory.FileBackedPokemonStoreFactory
import com.cobblemon.mod.common.api.storage.molang.NbtMoLangDataStoreFactory
import com.cobblemon.mod.common.api.storage.pc.PCStore
import com.cobblemon.mod.common.api.storage.pc.link.PCLinkManager
import com.cobblemon.mod.common.api.storage.player.PlayerDataStoreManager
import com.cobblemon.mod.common.api.storage.player.factory.JsonPlayerDataStoreFactory
import com.cobblemon.mod.common.api.storage.player.factory.MongoPlayerDataStoreFactory
import com.cobblemon.mod.common.api.tags.CobblemonEntityTypeTags
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.battles.BagItems
import com.cobblemon.mod.common.battles.BattleFormat
import com.cobblemon.mod.common.battles.BattleRegistry
@@ -80,7 +61,6 @@ import com.cobblemon.mod.common.battles.BattleSide
import com.cobblemon.mod.common.battles.ShowdownThread
import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.command.argument.DialogueArgumentType
import com.cobblemon.mod.common.command.argument.MoveArgumentType
import com.cobblemon.mod.common.command.argument.PartySlotArgumentType
import com.cobblemon.mod.common.command.argument.PokemonArgumentType
@@ -104,22 +84,32 @@ import com.cobblemon.mod.common.pokemon.aspects.SHINY_ASPECT
import com.cobblemon.mod.common.pokemon.evolution.variants.BlockClickEvolution
import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
import com.cobblemon.mod.common.pokemon.properties.AspectPropertyType
import com.cobblemon.mod.common.pokemon.properties.HiddenAbilityPropertyType
import com.cobblemon.mod.common.pokemon.properties.UnaspectPropertyType
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
import com.cobblemon.mod.common.pokemon.properties.UntradeableProperty
import com.cobblemon.mod.common.pokemon.properties.tags.PokemonFlagProperty
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
import com.cobblemon.mod.common.trade.TradeManager
import com.cobblemon.mod.common.util.*
import com.cobblemon.mod.common.util.DataKeys
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.ifDedicatedServer
import com.cobblemon.mod.common.util.isLaterVersion
import com.cobblemon.mod.common.util.party
import com.cobblemon.mod.common.util.removeAmountIf
import com.cobblemon.mod.common.util.server
import com.cobblemon.mod.common.world.feature.CobblemonPlacedFeatures
import com.cobblemon.mod.common.world.feature.ore.CobblemonOrePlacedFeatures
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
import com.mongodb.ConnectionString
import com.mongodb.MongoClientSettings
import com.mongodb.client.MongoClient
import com.mongodb.client.MongoClients
import java.io.File
import java.io.FileReader
import java.io.FileWriter
import java.io.PrintWriter
import java.util.UUID
import kotlin.properties.Delegates
import kotlin.reflect.full.memberProperties
import kotlin.reflect.jvm.isAccessible
import kotlin.reflect.jvm.javaField
import net.minecraft.client.MinecraftClient
import net.minecraft.command.argument.serialize.ConstantArgumentSerializer
import net.minecraft.entity.data.TrackedDataHandlerRegistry
@@ -127,26 +117,14 @@ import net.minecraft.item.Items
import net.minecraft.item.NameTagItem
import net.minecraft.registry.RegistryKey
import net.minecraft.util.WorldSavePath
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
import java.io.File
import java.io.FileReader
import java.io.FileWriter
import java.io.PrintWriter
import java.util.*
import kotlin.properties.Delegates
import kotlin.reflect.full.memberProperties
import kotlin.reflect.jvm.isAccessible
import kotlin.reflect.jvm.javaField
import kotlin.math.roundToInt
object Cobblemon {
const val MODID = CobblemonBuildDetails.MOD_ID
const val VERSION = CobblemonBuildDetails.VERSION
const val MODID = "cobblemon"
const val VERSION = "1.4.0"
const val CONFIG_PATH = "config/$MODID/main.json"
val LOGGER: Logger = LogManager.getLogger()
val LOGGER = LogManager.getLogger()
lateinit var implementation: CobblemonImplementation
@Deprecated("This field is now a config value", ReplaceWith("Cobblemon.config.captureCalculator"))
@@ -166,7 +144,6 @@ object Cobblemon {
val bestSpawner = BestSpawner
val battleRegistry = BattleRegistry
var storage = PokemonStoreManager()
var molangData = NbtMoLangDataStoreFactory
lateinit var playerData: PlayerDataStoreManager
lateinit var starterConfig: StarterConfig
val dataProvider: DataProvider = CobblemonDataProvider
@@ -176,16 +153,8 @@ object Cobblemon {
fun preInitialize(implementation: CobblemonImplementation) {
this.implementation = implementation
this.LOGGER.info("Launching Cobblemon ${CobblemonBuildDetails.VERSION}${if(CobblemonBuildDetails.SNAPSHOT) "-SNAPSHOT" else ""} ")
if(CobblemonBuildDetails.SNAPSHOT) {
this.LOGGER.info(" - Git Commit: ${smallCommitHash()} (https://gitlab.com/cable-mc/cobblemon/-/commit/${CobblemonBuildDetails.GIT_COMMIT})")
this.LOGGER.info(" - Branch: ${CobblemonBuildDetails.BRANCH}")
}
implementation.registerPermissionValidator()
implementation.registerSoundEvents()
implementation.registerDataComponents()
implementation.registerBlocks()
implementation.registerItems()
implementation.registerEntityTypes()
@@ -193,8 +162,6 @@ object Cobblemon {
implementation.registerBlockEntityTypes()
implementation.registerWorldGenFeatures()
implementation.registerParticles()
implementation.registerEntityDataSerializers()
implementation.registerCriteria()
DropEntry.register("command", CommandDropEntry::class.java)
DropEntry.register("item", ItemDropEntry::class.java, isDefault = true)
@@ -208,6 +175,7 @@ object Cobblemon {
CobblemonPlacedFeatures.register()
this.registerArgumentTypes()
CobblemonCriteria // Init the fields and register the criteria
CobblemonGameRules // Init fields and register
ShoulderEffectRegistry.register()
@@ -239,7 +207,7 @@ object Cobblemon {
val player = event.player
val block = player.world.getBlockState(event.pos).block
player.party().forEach { pokemon ->
pokemon.lockedEvolutions
pokemon.evolutions
.filterIsInstance<BlockClickEvolution>()
.forEach { evolution ->
evolution.attemptEvolution(pokemon, BlockClickEvolution.BlockInteractionContext(block, player.world))
@@ -247,22 +215,13 @@ object Cobblemon {
}
}
// Register the grow_tumblestone advancement
PlatformEvents.RIGHT_CLICK_BLOCK.subscribe { AdvancementHandler.onTumbleStonePlaced(it) }
PlatformEvents.CHANGE_DIMENSION.subscribe {
it.player.party().forEach { pokemon -> pokemon.entity?.recallWithAnimation() }
}
// Lowest priority because this applies after luxury ball bonus as of gen 4
CobblemonEvents.FRIENDSHIP_UPDATED.subscribe(Priority.LOWEST) { event ->
var increment = (event.newFriendship - event.pokemon.friendship).toFloat()
// Our Luxury ball spec is diff from official, but we will still assume these stack
if (event.pokemon.heldItemNoCopy().isIn(CobblemonItemTags.IS_FRIENDSHIP_BOOSTER)) {
increment += increment * 0.5F
}
event.newFriendship = event.pokemon.friendship + increment.roundToInt()
}
TrackedDataHandlerRegistry.register(Vec3DataSerializer)
TrackedDataHandlerRegistry.register(StringSetDataSerializer)
TrackedDataHandlerRegistry.register(PoseTypeDataSerializer)
HeldItemProvider.register(CobblemonHeldItemManager, Priority.LOWEST)
}
@@ -278,7 +237,6 @@ object Cobblemon {
SpeciesFeatures.types["choice"] = ChoiceSpeciesFeatureProvider::class.java
SpeciesFeatures.types["flag"] = FlagSpeciesFeatureProvider::class.java
SpeciesFeatures.types["integer"] = IntSpeciesFeatureProvider::class.java
SpeciesFeatures.register(
DataKeys.CAN_BE_MILKED,
@@ -287,72 +245,28 @@ object Cobblemon {
DataKeys.HAS_BEEN_SHEARED,
FlagSpeciesFeatureProvider(keys = listOf(DataKeys.HAS_BEEN_SHEARED), default = false))
CustomPokemonProperty.register(UntradeableProperty)
CustomPokemonProperty.register(UncatchableProperty)
CustomPokemonProperty.register(PokemonFlagProperty)
CustomPokemonProperty.register(HiddenAbilityPropertyType)
CustomPokemonProperty.register(AspectPropertyType)
CustomPokemonProperty.register(UnaspectPropertyType)
ifDedicatedServer {
isDedicatedServer = true
PlatformEvents.SERVER_TICK_POST.subscribe { ScheduledTaskTracker.update() }
}
PlatformEvents.SERVER_TICK_POST.subscribe {
ServerTaskTracker.update(1/20F)
ServerRealTimeTaskTracker.update()
}
PlatformEvents.SERVER_TICK_PRE.subscribe {
ServerRealTimeTaskTracker.update()
}
PlatformEvents.SERVER_STARTING.subscribe { event ->
val server = event.server
playerData = PlayerDataStoreManager().also { it.setup(server) }
val mongoClient: MongoClient?
val pokemonStoreRoot = server.getSavePath(WorldSavePath.ROOT).resolve("pokemon").toFile()
val storeAdapter = when (config.storageFormat) {
"nbt", "json" -> {
val jsonFactory = JsonPlayerDataStoreFactory()
jsonFactory.setup(server)
playerData.setFactory(jsonFactory)
if (config.storageFormat == "nbt") {
NBTStoreAdapter(pokemonStoreRoot.absolutePath, useNestedFolders = true, folderPerClass = true)
} else {
JSONStoreAdapter(
pokemonStoreRoot.absolutePath,
useNestedFolders = true,
folderPerClass = true
)
}
}
"mongodb" -> {
try {
Class.forName("com.mongodb.client.MongoClient")
val mongoClientSettings = MongoClientSettings.builder()
.applyConnectionString(ConnectionString(config.mongoDBConnectionString))
.build()
mongoClient = MongoClients.create(mongoClientSettings)
val mongoFactory = MongoPlayerDataStoreFactory(mongoClient, config.mongoDBDatabaseName)
playerData.setFactory(mongoFactory)
MongoDBStoreAdapter(mongoClient, config.mongoDBDatabaseName)
} catch (e: ClassNotFoundException) {
LOGGER.error("MongoDB driver not found.")
throw e
}
}
else -> throw IllegalArgumentException("Unsupported storageFormat: ${config.storageFormat}")
}
.with(ReforgedConversion(server.getSavePath(WorldSavePath.ROOT))) as FileStoreAdapter<*>
storage.registerFactory(
priority = Priority.LOWEST,
factory = FileBackedPokemonStoreFactory(
adapter = storeAdapter,
adapter = if (config.storageFormat == "nbt") {
NBTStoreAdapter(pokemonStoreRoot.absolutePath, useNestedFolders = true, folderPerClass = true)
} else {
JSONStoreAdapter(pokemonStoreRoot.absolutePath, useNestedFolders = true, folderPerClass = true)
}.with(ReforgedConversion(server.getSavePath(WorldSavePath.ROOT))) as FileStoreAdapter<*>,
createIfMissing = true,
pcConstructor = { uuid -> PCStore(uuid).also { it.resize(config.defaultBoxCount) } }
)
@@ -373,22 +287,40 @@ object Cobblemon {
BATTLE_VICTORY.subscribe { AdvancementHandler.onWinBattle(it) }
EVOLUTION_COMPLETE.subscribe(Priority.LOWEST) { event ->
AdvancementHandler.onEvolve(event)
val pokemon = event.pokemon
val ninjaskIdentifier = cobblemonResource("ninjask")
// Ensure the config option is enabled and that the result was a ninjask and that shedinja exists
if (this.config.ninjaskCreatesShedinja && pokemon.species.resourceIdentifier == ninjaskIdentifier && PokemonSpecies.getByIdentifier(Pokemon.SHEDINJA) != null) {
val player = pokemon.getOwnerPlayer() ?: return@subscribe
if (player.inventory.containsAny { it.item is PokeBallItem }) {
var pokeball = Items.AIR
player.inventory.combinedInventory.forEach {
it.forEach {
itemStack -> if (itemStack.item is PokeBallItem && pokeball == Items.AIR) {
pokeball = itemStack.item as PokeBallItem
}
}
}
player.inventory.removeAmountIf(1) { it.item is PokeBallItem }
val properties = event.evolution.result.copy()
properties.species = Pokemon.SHEDINJA.toString()
val product = pokemon.clone()
product.removeHeldItem()
properties.apply(product)
product.caughtBall = (pokeball as PokeBallItem).pokeBall
pokemon.storeCoordinates.get()?.store?.add(product)
}
}
}
LEVEL_UP_EVENT.subscribe { AdvancementHandler.onLevelUp(it) }
TRADE_COMPLETED.subscribe { AdvancementHandler.onTradeCompleted(it) }
BagItems.observable.subscribe {
LOGGER.info("Starting dummy Showdown battle to force it to pre-load data.")
battleRegistry.startBattle(
BattleFormat.GEN_9_SINGLES,
BattleSide(PokemonBattleActor(UUID.randomUUID(), BattlePokemon(Pokemon().initialize()), -1F)),
BattleSide(PokemonBattleActor(UUID.randomUUID(), BattlePokemon(Pokemon().initialize()), -1F)),
true
).ifSuccessful { it.mute = true }
BattleSide(PokemonBattleActor(UUID.randomUUID(), BattlePokemon(Pokemon().initialize()), -1F))
).apply { mute = true }
}
//To whomever is merging, this is moved out of Cobblemon and into the CobblemonImplementations
//CobblemonSherds.registerSherds()
}
fun getLevel(dimension: RegistryKey<World>): World? {
@@ -492,7 +424,6 @@ object Cobblemon {
this.implementation.registerCommandArgument(cobblemonResource("move"), MoveArgumentType::class, ConstantArgumentSerializer.of(MoveArgumentType::move))
this.implementation.registerCommandArgument(cobblemonResource("party_slot"), PartySlotArgumentType::class, ConstantArgumentSerializer.of(PartySlotArgumentType::partySlot))
this.implementation.registerCommandArgument(cobblemonResource("pokemon_store"), PokemonStoreArgumentType::class, ConstantArgumentSerializer.of(PokemonStoreArgumentType::pokemonStore))
this.implementation.registerCommandArgument(cobblemonResource("dialogue"), DialogueArgumentType::class, ConstantArgumentSerializer.of(DialogueArgumentType::dialogue))
}
}
}
@@ -1,22 +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
import net.minecraft.entity.ai.brain.Activity
object CobblemonActivities {
val activities = mutableListOf<Activity>()
val BATTLING_ACTIVITY = Activity("pokemon_battling")
val NPC_BATTLING = Activity("npc_battling")
fun register(activity: Activity): Activity {
activities.add(activity)
return activity
}
}
@@ -8,16 +8,9 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.block.entity.BerryBlockEntity
import com.cobblemon.mod.common.block.entity.HealingMachineBlockEntity
import com.cobblemon.mod.common.block.entity.PCBlockEntity
import com.cobblemon.mod.common.block.entity.PokemonPastureBlockEntity
import com.cobblemon.mod.common.block.entity.FossilAnalyzerBlockEntity
import com.cobblemon.mod.common.block.entity.FossilMultiblockEntity
import com.cobblemon.mod.common.block.entity.RestorationTankBlockEntity
import com.cobblemon.mod.common.block.multiblock.FossilMultiblockBuilder
import com.cobblemon.mod.common.block.entity.*
import com.cobblemon.mod.common.block.entity.DisplayCaseBlockEntity
import com.cobblemon.mod.common.platform.PlatformRegistry
import net.minecraft.block.entity.BlockEntityType
import net.minecraft.registry.Registries
@@ -32,57 +25,9 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
@JvmField
val HEALING_MACHINE: BlockEntityType<HealingMachineBlockEntity> = this.create("healing_machine", BlockEntityType.Builder.create(::HealingMachineBlockEntity, CobblemonBlocks.HEALING_MACHINE).build(null))
@JvmField
val PC: BlockEntityType<PCBlockEntity> = this.create("pc", BlockEntityType.Builder.create(::PCBlockEntity, CobblemonBlocks.PC).build(null))
@JvmField
val BERRY = this.create("berry", BlockEntityType.Builder.create(::BerryBlockEntity, *CobblemonBlocks.berries().values.toTypedArray()).build(null))
@JvmField
val PASTURE: BlockEntityType<PokemonPastureBlockEntity> = this.create("pasture", BlockEntityType.Builder.create(::PokemonPastureBlockEntity, CobblemonBlocks.PASTURE).build(null))
@JvmField
val SIGN: BlockEntityType<CobblemonSignBlockEntity> = this.create("sign", BlockEntityType.Builder.create(::CobblemonSignBlockEntity, CobblemonBlocks.APRICORN_SIGN, CobblemonBlocks.APRICORN_WALL_SIGN).build(null))
@JvmField
val HANGING_SIGN: BlockEntityType<CobblemonHangingSignBlockEntity> = this.create("hanging_sign", BlockEntityType.Builder.create(::CobblemonHangingSignBlockEntity, CobblemonBlocks.APRICORN_HANGING_SIGN, CobblemonBlocks.APRICORN_WALL_HANGING_SIGN).build(null))
@JvmField
val TM_BLOCK: BlockEntityType<TMBlockEntity> = this.create("tm_block", BlockEntityType.Builder.create(::TMBlockEntity, CobblemonBlocks.TM_MACHINE).build(null))
@JvmField
val GILDED_CHEST: BlockEntityType<GildedChestBlockEntity> = this.create("chest", BlockEntityType.Builder.create(::GildedChestBlockEntity,
CobblemonBlocks.GILDED_CHEST,
CobblemonBlocks.BLUE_GILDED_CHEST,
CobblemonBlocks.YELLOW_GILDED_CHEST,
CobblemonBlocks.PINK_GILDED_CHEST,
CobblemonBlocks.BLACK_GILDED_CHEST,
CobblemonBlocks.WHITE_GILDED_CHEST,
CobblemonBlocks.GREEN_GILDED_CHEST,
CobblemonBlocks.GIMMIGHOUL_CHEST
).build(null))
@JvmField
val FOSSIL_MULTIBLOCK: BlockEntityType<FossilMultiblockEntity> = this.create("fossil_multiblock",
BlockEntityType.Builder.create({ pos, state -> FossilMultiblockEntity(pos, state, FossilMultiblockBuilder(pos)) },
CobblemonBlocks.MONITOR
).build(null)
)
@JvmField
val RESTORATION_TANK: BlockEntityType<RestorationTankBlockEntity> = this.create("restoration_tank",
BlockEntityType.Builder.create({ pos, state -> RestorationTankBlockEntity(pos, state, FossilMultiblockBuilder(pos)) },
CobblemonBlocks.RESTORATION_TANK
).build(null)
)
@JvmField
val FOSSIL_ANALYZER: BlockEntityType<FossilAnalyzerBlockEntity> = this.create("fossil_analyzer",
BlockEntityType.Builder.create({ pos, state -> FossilAnalyzerBlockEntity(pos, state, FossilMultiblockBuilder(pos)) },
CobblemonBlocks.FOSSIL_ANALYZER
).build(null)
)
@JvmField
val DISPLAY_CASE: BlockEntityType<DisplayCaseBlockEntity> = this.create("display_case",
BlockEntityType.Builder.create(::DisplayCaseBlockEntity, CobblemonBlocks.DISPLAY_CASE).build(null)
)
}
}
@@ -11,21 +11,13 @@ package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.apricorn.Apricorn
import com.cobblemon.mod.common.block.*
import com.cobblemon.mod.common.block.MintBlock.MintType
import com.cobblemon.mod.common.block.chest.GildedChestBlock
import com.cobblemon.mod.common.block.sign.CobblemonHangingSignBlock
import com.cobblemon.mod.common.block.sign.CobblemonSignBlock
import com.cobblemon.mod.common.block.sign.CobblemonWallHangingSignBlock
import com.cobblemon.mod.common.block.sign.CobblemonWallSignBlock
import com.cobblemon.mod.common.mixin.invoker.BlocksInvoker
import com.cobblemon.mod.common.mixin.invoker.DoorBlockInvoker
import com.cobblemon.mod.common.mixin.invoker.FireBlockInvoker
import com.cobblemon.mod.common.mixin.invoker.PressurePlateBlockInvoker
import com.cobblemon.mod.common.mixin.invoker.StairsBlockInvoker
import com.cobblemon.mod.common.mixin.invoker.TrapdoorBlockInvoker
import com.cobblemon.mod.common.mixin.invoker.*
import com.cobblemon.mod.common.platform.PlatformRegistry
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.block.*
import net.minecraft.block.enums.NoteBlockInstrument
import net.minecraft.block.piston.PistonBehavior
import net.minecraft.entity.effect.StatusEffects
import net.minecraft.registry.Registries
@@ -33,14 +25,11 @@ import net.minecraft.registry.Registry
import net.minecraft.registry.RegistryKey
import net.minecraft.registry.RegistryKeys
import net.minecraft.sound.BlockSoundGroup
import net.minecraft.util.Identifier
import net.minecraft.util.math.intprovider.UniformIntProvider
@Suppress("SameParameterValue", "HasPlatformType", "MemberVisibilityCanBePrivate", "unused")
object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<Block>>, Block>() {
override val registry: Registry<Block> = Registries.BLOCK
override val registryKey: RegistryKey<Registry<Block>> = RegistryKeys.BLOCK
@@ -55,8 +44,6 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
@JvmField
val FIRE_STONE_ORE = evolutionStoneOre("fire_stone_ore")
@JvmField
val NETHER_FIRE_STONE_ORE = evolutionStoneOre("nether_fire_stone_ore")
@JvmField
val ICE_STONE_ORE = evolutionStoneOre("ice_stone_ore")
@JvmField
val LEAF_STONE_ORE = evolutionStoneOre("leaf_stone_ore")
@@ -69,8 +56,6 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
@JvmField
val SUN_STONE_ORE = evolutionStoneOre("sun_stone_ore")
@JvmField
val TERRACOTTA_SUN_STONE_ORE = evolutionStoneOre("terracotta_sun_stone_ore")
@JvmField
val THUNDER_STONE_ORE = evolutionStoneOre("thunder_stone_ore")
@JvmField
val WATER_STONE_ORE = evolutionStoneOre("water_stone_ore")
@@ -106,33 +91,28 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
@JvmField
val STRIPPED_APRICORN_WOOD = log("stripped_apricorn_wood")
@JvmField
val APRICORN_PLANKS = this.create("apricorn_planks", Block(AbstractBlock.Settings.create().mapColor(MapColor.DIRT_BROWN).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
val APRICORN_PLANKS = this.create("apricorn_planks", Block(AbstractBlock.Settings.create().mapColor(MapColor.DIRT_BROWN).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
@JvmField
val APRICORN_LEAVES = leaves("apricorn_leaves")
@JvmField
val APRICORN_FENCE = this.create("apricorn_fence", FenceBlock(AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
val APRICORN_FENCE = this.create("apricorn_fence", FenceBlock(AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
@JvmField
val APRICORN_FENCE_GATE = this.create("apricorn_fence_gate", FenceGateBlock(APRICORN_WOOD_TYPE, AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
val APRICORN_FENCE_GATE = this.create("apricorn_fence_gate", FenceGateBlock(AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD), APRICORN_WOOD_TYPE))
@JvmField // Note At the time of 1.20.0 we don't need our own BlockSetType for Apricorn wood
val APRICORN_BUTTON = this.create("apricorn_button", BlocksInvoker.createWoodenButtonBlock(BlockSetType.OAK))
@JvmField
val APRICORN_PRESSURE_PLATE = this.create("apricorn_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(APRICORN_BLOCK_SET_TYPE, AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).noCollision().strength(0.5f).sounds(BlockSoundGroup.WOOD)))
val APRICORN_PRESSURE_PLATE = this.create("apricorn_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(PressurePlateBlock.ActivationRule.EVERYTHING, AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).noCollision().strength(0.5f).sounds(BlockSoundGroup.WOOD), APRICORN_BLOCK_SET_TYPE))
// Tag was removed be sure to add it back when implemented
//val APRICORN_SIGN = queue("apricorn_sign") { StandingSignBlock(AbstractBlock.Settings.of(Material.WOOD).noCollission().strength(1.0f).sounds(BlockSoundGroup.WOOD), APRICORN_WOOD_TYPE) }
//val APRICORN_WALL_SIGN = queue("apricorn_wall_sign") { WallSignBlock(AbstractBlock.Settings.of(Material.WOOD).noCollission().strength(1.0f).sounds(BlockSoundGroup.WOOD).dropsLike(APRICORN_SIGN), APRICORN_WOOD_TYPE) }
@JvmField
val APRICORN_SIGN = this.create("apricorn_sign", CobblemonSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_SIGN), APRICORN_WOOD_TYPE))
@JvmField
val APRICORN_WALL_SIGN = this.create("apricorn_wall_sign", CobblemonWallSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_WALL_SIGN), APRICORN_WOOD_TYPE))
@JvmField
val APRICORN_HANGING_SIGN = this.create("apricorn_hanging_sign", CobblemonHangingSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_WALL_HANGING_SIGN), APRICORN_WOOD_TYPE))
@JvmField
val APRICORN_WALL_HANGING_SIGN = this.create("apricorn_wall_hanging_sign", CobblemonWallHangingSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_HANGING_SIGN), APRICORN_WOOD_TYPE))
@JvmField
val APRICORN_SLAB = this.create("apricorn_slab", SlabBlock(AbstractBlock.Settings.create().mapColor(MapColor.OAK_TAN).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
val APRICORN_SLAB = this.create("apricorn_slab", SlabBlock(AbstractBlock.Settings.create().mapColor(MapColor.OAK_TAN).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
@JvmField
val APRICORN_STAIRS = this.create("apricorn_stairs", StairsBlockInvoker.`cobblemon$create`(APRICORN_PLANKS.defaultState, AbstractBlock.Settings.copy(APRICORN_PLANKS)))
@JvmField
val APRICORN_DOOR = this.create("apricorn_door", DoorBlockInvoker.`cobblemon$create`(APRICORN_BLOCK_SET_TYPE, AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).instrument(NoteBlockInstrument.BASS).strength(3.0F).sounds(BlockSoundGroup.WOOD).nonOpaque()))
val APRICORN_DOOR = this.create("apricorn_door", DoorBlockInvoker.`cobblemon$create`(AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).strength(3.0F).sounds(BlockSoundGroup.WOOD).nonOpaque(), APRICORN_BLOCK_SET_TYPE))
@JvmField
val APRICORN_TRAPDOOR = this.create("apricorn_trapdoor", TrapdoorBlockInvoker.`cobblemon$create`(APRICORN_BLOCK_SET_TYPE, AbstractBlock.Settings.create().mapColor(MapColor.OAK_TAN).instrument(NoteBlockInstrument.BASS).strength(3.0F).sounds(BlockSoundGroup.WOOD).nonOpaque().allowsSpawning { _, _, _, _ -> false }))
val APRICORN_TRAPDOOR = this.create("apricorn_trapdoor", TrapdoorBlockInvoker.`cobblemon$create`(AbstractBlock.Settings.create().mapColor(MapColor.OAK_TAN).strength(3.0F).sounds(BlockSoundGroup.WOOD).nonOpaque().allowsSpawning { _, _, _, _ -> false }, APRICORN_BLOCK_SET_TYPE))
private val PLANT_PROPERTIES = AbstractBlock.Settings.create().mapColor(MapColor.DARK_GREEN).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.GRASS).pistonBehavior(PistonBehavior.DESTROY)
@JvmField
@@ -151,272 +131,13 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
val YELLOW_APRICORN_SAPLING = this.create("yellow_apricorn_sapling", ApricornSaplingBlock(PLANT_PROPERTIES, Apricorn.YELLOW))
@JvmField
val MEDICINAL_LEEK = this.create("medicinal_leek", MedicinalLeekBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DULL_RED).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MEDICINAL_LEEK_SOUNDS)))
val MEDICINAL_LEEK = this.create("medicinal_leek", MedicinalLeekBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DULL_RED).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
@JvmField
val ENERGY_ROOT = this.create("energy_root", EnergyRootBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DIRT_BROWN).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.ENERGY_ROOT_SOUNDS)))
val ENERGY_ROOT = this.create("energy_root", EnergyRootBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DIRT_BROWN).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.ROOTS)))
@JvmField
val BIG_ROOT = this.create("big_root", BigRootBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DARK_GREEN).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.BIG_ROOT_SOUNDS)))
val BIG_ROOT = this.create("big_root", BigRootBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DARK_GREEN).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.ROOTS)))
@JvmField
val REVIVAL_HERB = this.create("revival_herb", RevivalHerbBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).mapColor(MapColor.DARK_GREEN).burnable().noCollision().breakInstantly().sounds(CobblemonSounds.REVIVAL_HERB_SOUNDS)))
@JvmField
val TUMBLESTONE_CLUSTER = tumblestoneBlock("tumblestone_cluster", GrowableStoneBlock.STAGE_3, 7, 3, null)
@JvmField
val LARGE_BUDDING_TUMBLESTONE = tumblestoneBlock("large_budding_tumblestone", GrowableStoneBlock.STAGE_2, 5, 3, TUMBLESTONE_CLUSTER)
@JvmField
val MEDIUM_BUDDING_TUMBLESTONE = tumblestoneBlock("medium_budding_tumblestone", GrowableStoneBlock.STAGE_1, 4, 3, LARGE_BUDDING_TUMBLESTONE)
@JvmField
val SMALL_BUDDING_TUMBLESTONE = tumblestoneBlock("small_budding_tumblestone", GrowableStoneBlock.STAGE_0, 3, 4, MEDIUM_BUDDING_TUMBLESTONE)
@JvmField
val SKY_TUMBLESTONE_CLUSTER = tumblestoneBlock("sky_tumblestone_cluster", GrowableStoneBlock.STAGE_3, 7, 3, null)
@JvmField
val LARGE_BUDDING_SKY_TUMBLESTONE = tumblestoneBlock("large_budding_sky_tumblestone", GrowableStoneBlock.STAGE_2, 5, 3, SKY_TUMBLESTONE_CLUSTER)
@JvmField
val MEDIUM_BUDDING_SKY_TUMBLESTONE = tumblestoneBlock("medium_budding_sky_tumblestone", GrowableStoneBlock.STAGE_1, 4, 3, LARGE_BUDDING_SKY_TUMBLESTONE)
@JvmField
val SMALL_BUDDING_SKY_TUMBLESTONE = tumblestoneBlock("small_budding_sky_tumblestone", GrowableStoneBlock.STAGE_0, 3, 4, MEDIUM_BUDDING_SKY_TUMBLESTONE)
@JvmField
val BLACK_TUMBLESTONE_CLUSTER = tumblestoneBlock("black_tumblestone_cluster", GrowableStoneBlock.STAGE_3, 7, 3, null)
@JvmField
val LARGE_BUDDING_BLACK_TUMBLESTONE = tumblestoneBlock("large_budding_black_tumblestone", GrowableStoneBlock.STAGE_2, 5, 3, BLACK_TUMBLESTONE_CLUSTER)
@JvmField
val MEDIUM_BUDDING_BLACK_TUMBLESTONE = tumblestoneBlock("medium_budding_black_tumblestone", GrowableStoneBlock.STAGE_1, 4, 3, LARGE_BUDDING_BLACK_TUMBLESTONE)
@JvmField
val SMALL_BUDDING_BLACK_TUMBLESTONE = tumblestoneBlock("small_budding_black_tumblestone", GrowableStoneBlock.STAGE_0, 3, 4, MEDIUM_BUDDING_BLACK_TUMBLESTONE)
@JvmField
val TUMBLESTONE_BLOCK = this.create("tumblestone_block", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_ORANGE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val SKY_TUMBLESTONE_BLOCK = this.create("sky_tumblestone_block", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.LIGHT_BLUE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val BLACK_TUMBLESTONE_BLOCK = this.create("black_tumblestone_block", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_BLACK)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val POLISHED_TUMBLESTONE = this.create("polished_tumblestone", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_ORANGE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val POLISHED_TUMBLESTONE_STAIRS = this.create("polished_tumblestone_stairs", StairsBlockInvoker.`cobblemon$create`(POLISHED_TUMBLESTONE.defaultState, AbstractBlock.Settings.copy(POLISHED_TUMBLESTONE)))
@JvmField
val POLISHED_TUMBLESTONE_SLAB = this.create("polished_tumblestone_slab", SlabBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_ORANGE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val POLISHED_TUMBLESTONE_WALL = this.create("polished_tumblestone_wall", WallBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_ORANGE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val CHISELED_POLISHED_TUMBLESTONE = this.create("chiseled_polished_tumblestone", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_ORANGE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val TUMBLESTONE_BRICKS = this.create("tumblestone_bricks", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_ORANGE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val TUMBLESTONE_BRICK_STAIRS = this.create("tumblestone_brick_stairs", StairsBlockInvoker.`cobblemon$create`(TUMBLESTONE_BRICKS.defaultState, AbstractBlock.Settings.copy(TUMBLESTONE_BRICKS)))
@JvmField
val TUMBLESTONE_BRICK_SLAB = this.create("tumblestone_brick_slab", SlabBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_ORANGE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val TUMBLESTONE_BRICK_WALL = this.create("tumblestone_brick_wall", WallBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_ORANGE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val CHISELED_TUMBLESTONE_BRICKS = this.create("chiseled_tumblestone_bricks", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_ORANGE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val POLISHED_SKY_TUMBLESTONE = this.create("polished_sky_tumblestone", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.LIGHT_BLUE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val POLISHED_SKY_TUMBLESTONE_STAIRS = this.create("polished_sky_tumblestone_stairs", StairsBlockInvoker.`cobblemon$create`(POLISHED_SKY_TUMBLESTONE.defaultState, AbstractBlock.Settings.copy(POLISHED_SKY_TUMBLESTONE)))
@JvmField
val POLISHED_SKY_TUMBLESTONE_SLAB = this.create("polished_sky_tumblestone_slab", SlabBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.LIGHT_BLUE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val POLISHED_SKY_TUMBLESTONE_WALL = this.create("polished_sky_tumblestone_wall", WallBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.LIGHT_BLUE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val CHISELED_POLISHED_SKY_TUMBLESTONE = this.create("chiseled_polished_sky_tumblestone", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.LIGHT_BLUE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val SKY_TUMBLESTONE_BRICKS = this.create("sky_tumblestone_bricks", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.LIGHT_BLUE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val SKY_TUMBLESTONE_BRICK_STAIRS = this.create("sky_tumblestone_brick_stairs", StairsBlockInvoker.`cobblemon$create`(
SKY_TUMBLESTONE_BRICKS.defaultState, AbstractBlock.Settings.copy(SKY_TUMBLESTONE_BRICKS)))
@JvmField
val SKY_TUMBLESTONE_BRICK_SLAB = this.create("sky_tumblestone_brick_slab", SlabBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.LIGHT_BLUE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val SKY_TUMBLESTONE_BRICK_WALL = this.create("sky_tumblestone_brick_wall", WallBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.LIGHT_BLUE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val CHISELED_SKY_TUMBLESTONE_BRICKS = this.create("chiseled_sky_tumblestone_bricks", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.LIGHT_BLUE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val POLISHED_BLACK_TUMBLESTONE = this.create("polished_black_tumblestone", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_BLACK)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val POLISHED_BLACK_TUMBLESTONE_STAIRS = this.create("polished_black_tumblestone_stairs", StairsBlockInvoker.`cobblemon$create`(POLISHED_BLACK_TUMBLESTONE.defaultState, AbstractBlock.Settings.copy(POLISHED_BLACK_TUMBLESTONE)))
@JvmField
val POLISHED_BLACK_TUMBLESTONE_SLAB = this.create("polished_black_tumblestone_slab", SlabBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_BLACK)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val POLISHED_BLACK_TUMBLESTONE_WALL = this.create("polished_black_tumblestone_wall", WallBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_BLACK)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val CHISELED_POLISHED_BLACK_TUMBLESTONE = this.create("chiseled_polished_black_tumblestone", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_BLACK)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val BLACK_TUMBLESTONE_BRICKS = this.create("black_tumblestone_bricks", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_BLACK)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val BLACK_TUMBLESTONE_BRICK_STAIRS = this.create("black_tumblestone_brick_stairs", StairsBlockInvoker.`cobblemon$create`(
BLACK_TUMBLESTONE_BRICKS.defaultState, AbstractBlock.Settings.copy(BLACK_TUMBLESTONE_BRICKS)))
@JvmField
val BLACK_TUMBLESTONE_BRICK_SLAB = this.create("black_tumblestone_brick_slab", SlabBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_BLACK)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val BLACK_TUMBLESTONE_BRICK_WALL = this.create("black_tumblestone_brick_wall", WallBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_BLACK)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
@JvmField
val CHISELED_BLACK_TUMBLESTONE_BRICKS = this.create("chiseled_black_tumblestone_bricks", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_BLACK)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(NoteBlockInstrument.BASEDRUM)
))
val REVIVAL_HERB = this.create("revival_herb", RevivalHerbBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).mapColor(MapColor.DARK_GREEN).burnable().noCollision().breakInstantly().sounds(BlockSoundGroup.CROP)))
@JvmField
val BLACK_APRICORN = apricornBlock("black_apricorn", Apricorn.BLACK)
@@ -433,138 +154,6 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
@JvmField
val YELLOW_APRICORN = apricornBlock("yellow_apricorn", Apricorn.YELLOW)
@JvmField
val RELIC_COIN_POUCH = create(
"relic_coin_pouch",
CoinPouchBlock(
AbstractBlock.Settings.create()
.sounds(CobblemonSounds.RELIC_COIN_POUCH_SOUNDS)
.pistonBehavior(PistonBehavior.DESTROY)
.strength(0.4f)
.nonOpaque(), true
)
)
@JvmField
val RELIC_COIN_SACK = create(
"relic_coin_sack",
CoinPouchBlock(
AbstractBlock.Settings.create()
.sounds(CobblemonSounds.RELIC_COIN_SACK_SOUNDS)
.pistonBehavior(PistonBehavior.DESTROY)
.strength(0.4f), false
))
@JvmField
val GILDED_CHEST = create(
"gilded_chest",
GildedChestBlock(
AbstractBlock.Settings.copy(Blocks.CHEST).nonOpaque().sounds(CobblemonSounds.GILDED_CHEST_SOUNDS),
GildedChestBlock.Type.RED
)
)
@JvmField
val BLUE_GILDED_CHEST = create(
"blue_gilded_chest",
GildedChestBlock(
AbstractBlock.Settings.copy(Blocks.CHEST).nonOpaque().sounds(CobblemonSounds.GILDED_CHEST_SOUNDS),
GildedChestBlock.Type.BLUE
)
)
@JvmField
val BLACK_GILDED_CHEST = create(
"black_gilded_chest",
GildedChestBlock(
AbstractBlock.Settings.copy(Blocks.CHEST).nonOpaque().sounds(CobblemonSounds.GILDED_CHEST_SOUNDS),
GildedChestBlock.Type.BLACK
)
)
@JvmField
val YELLOW_GILDED_CHEST = create(
"yellow_gilded_chest",
GildedChestBlock(
AbstractBlock.Settings.copy(Blocks.CHEST).nonOpaque().sounds(CobblemonSounds.GILDED_CHEST_SOUNDS),
GildedChestBlock.Type.YELLOW
)
)
@JvmField
val WHITE_GILDED_CHEST = create(
"white_gilded_chest",
GildedChestBlock(
AbstractBlock.Settings.copy(Blocks.CHEST).nonOpaque().sounds(CobblemonSounds.GILDED_CHEST_SOUNDS),
GildedChestBlock.Type.WHITE
)
)
@JvmField
val GREEN_GILDED_CHEST = create(
"green_gilded_chest",
GildedChestBlock(
AbstractBlock.Settings.copy(Blocks.CHEST).nonOpaque().sounds(CobblemonSounds.GILDED_CHEST_SOUNDS),
GildedChestBlock.Type.GREEN
)
)
@JvmField
val PINK_GILDED_CHEST = create(
"pink_gilded_chest",
GildedChestBlock(
AbstractBlock.Settings.copy(Blocks.CHEST).nonOpaque().sounds(CobblemonSounds.GILDED_CHEST_SOUNDS),
GildedChestBlock.Type.PINK
)
)
@JvmField
val GIMMIGHOUL_CHEST = create(
"gimmighoul_chest",
GildedChestBlock(
AbstractBlock.Settings.copy(Blocks.CHEST).nonOpaque().sounds(CobblemonSounds.GILDED_CHEST_SOUNDS),
GildedChestBlock.Type.FAKE
)
)
@JvmField
val MONITOR = create(
"monitor",
MonitorBlock(
AbstractBlock.Settings.create()
.mapColor(MapColor.IRON_GRAY)
.sounds(BlockSoundGroup.METAL)
.pistonBehavior(PistonBehavior.BLOCK)
.requiresTool()
.strength(5.0F, 6.0F)
.luminance { if (it.get(MonitorBlock.SCREEN) != MonitorBlock.MonitorScreen.OFF) 15 else 0 }
)
)
@JvmField
val FOSSIL_ANALYZER = create(
"fossil_analyzer",
FossilAnalyzerBlock(
AbstractBlock.Settings.create()
.mapColor(MapColor.IRON_GRAY)
.sounds(BlockSoundGroup.METAL)
.pistonBehavior(PistonBehavior.BLOCK)
.requiresTool()
.strength(5.0F, 6.0F)
.nonOpaque()
)
)
@JvmField
val RESTORATION_TANK = create(
"restoration_tank",
RestorationTankBlock(
AbstractBlock.Settings.create()
.mapColor(MapColor.IRON_GRAY)
.sounds(BlockSoundGroup.GLASS)
.pistonBehavior(PistonBehavior.BLOCK)
.requiresTool()
.strength(5.0F, 6.0F)
.nonOpaque()
)
)
@JvmField
val HEALING_MACHINE = create(
"healing_machine",
@@ -591,42 +180,19 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
.luminance { if ((it.get(PCBlock.ON) as Boolean) && (it.get(PCBlock.PART) == PCBlock.PCPart.TOP)) 10 else 0 }
)
)
val TM_MACHINE = create(
"tm_machine",
TMBlock(
AbstractBlock.Settings.create()
.mapColor(MapColor.GREEN)
.sounds(BlockSoundGroup.METAL)
.pistonBehavior(PistonBehavior.BLOCK)
.nonOpaque()
.luminance { if (it.get(TMBlock.ON) as Boolean) 10 else 0 }
)
)
@JvmField
val DISPLAY_CASE = create(
"display_case",
DisplayCaseBlock(
AbstractBlock.Settings.create()
.sounds(CobblemonSounds.DISPLAY_CASE_SOUNDS)
.nonOpaque()
.pistonBehavior(PistonBehavior.BLOCK)
.mapColor(MapColor.STONE_GRAY)
.strength(0.3f)
)
)
val RED_MINT = create("red_mint", MintBlock(MintType.RED, AbstractBlock.Settings.create().mapColor(MapColor.RED).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MINT_SOUNDS)))
val RED_MINT = create("red_mint", MintBlock(MintType.RED, AbstractBlock.Settings.create().mapColor(MapColor.RED).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
@JvmField
val BLUE_MINT = create("blue_mint", MintBlock(MintType.BLUE, AbstractBlock.Settings.create().mapColor(MapColor.BLUE).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MINT_SOUNDS)))
val BLUE_MINT = create("blue_mint", MintBlock(MintType.BLUE, AbstractBlock.Settings.create().mapColor(MapColor.BLUE).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
@JvmField
val CYAN_MINT = create("cyan_mint", MintBlock(MintType.CYAN, AbstractBlock.Settings.create().mapColor(MapColor.CYAN).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MINT_SOUNDS)))
val CYAN_MINT = create("cyan_mint", MintBlock(MintType.CYAN, AbstractBlock.Settings.create().mapColor(MapColor.CYAN).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
@JvmField
val PINK_MINT = create("pink_mint", MintBlock(MintType.PINK, AbstractBlock.Settings.create().mapColor(MapColor.PINK).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MINT_SOUNDS)))
val PINK_MINT = create("pink_mint", MintBlock(MintType.PINK, AbstractBlock.Settings.create().mapColor(MapColor.PINK).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
@JvmField
val GREEN_MINT = create("green_mint", MintBlock(MintType.GREEN, AbstractBlock.Settings.create().mapColor(MapColor.GREEN).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MINT_SOUNDS)))
val GREEN_MINT = create("green_mint", MintBlock(MintType.GREEN, AbstractBlock.Settings.create().mapColor(MapColor.GREEN).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
@JvmField
val WHITE_MINT = create("white_mint", MintBlock(MintType.WHITE, AbstractBlock.Settings.create().mapColor(MapColor.WHITE).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MINT_SOUNDS)))
val WHITE_MINT = create("white_mint", MintBlock(MintType.WHITE, AbstractBlock.Settings.create().mapColor(MapColor.WHITE).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
@JvmField
val PASTURE = create(
@@ -643,73 +209,12 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
)
@JvmField
val VIVICHOKE_SEEDS = this.create("vivichoke_seeds", VivichokeBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DARK_GREEN).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.VIVICHOKE_SOUNDS)))
val VIVICHOKE_SEEDS = this.create("vivichoke_seeds", VivichokeBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DARK_GREEN).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
@JvmField
val PEP_UP_FLOWER = this.create("pep_up_flower", FlowerBlock(StatusEffects.LEVITATION, 10F, AbstractBlock.Settings.create().mapColor(MapColor.DARK_GREEN).noCollision().breakInstantly().sounds(BlockSoundGroup.GRASS).offset(AbstractBlock.OffsetType.XZ).pistonBehavior(PistonBehavior.DESTROY)))
val PEP_UP_FLOWER = this.create("pep_up_flower", FlowerBlock(StatusEffects.LEVITATION, 10, AbstractBlock.Settings.create().mapColor(MapColor.DARK_GREEN).noCollision().breakInstantly().sounds(BlockSoundGroup.GRASS).offset(AbstractBlock.OffsetType.XZ).pistonBehavior(PistonBehavior.DESTROY)))
@JvmField
val POTTED_PEP_UP_FLOWER = this.create("potted_pep_up_flower", BlocksInvoker.createFlowerPotBlock(PEP_UP_FLOWER))
@JvmField
val NORMAL_TYPE_GEM_BLOCK = this.create("normal_type_gem_block", Block(AbstractBlock.Settings.copy(Blocks.AMETHYST_BLOCK)))
@JvmField
val NORMAL_TYPE_GEM = typeGem(
"normal_type_gem",
GrowableStoneBlock.STAGE_3,
7,
3,
null,
NORMAL_TYPE_GEM_BLOCK
)
@JvmField
val LARGE_BUDDING_NORMAL_TYPE_GEM = typeGem(
"large_budding_normal_type_gem",
GrowableStoneBlock.STAGE_2,
5,
3,
NORMAL_TYPE_GEM,
NORMAL_TYPE_GEM_BLOCK
)
@JvmField
val MEDIUM_BUDDING_NORMAL_TYPE_GEM = typeGem(
"medium_budding_normal_type_gem",
GrowableStoneBlock.STAGE_1,
4,
3,
LARGE_BUDDING_NORMAL_TYPE_GEM,
NORMAL_TYPE_GEM_BLOCK
)
@JvmField
val SMALL_BUDDING_NORMAL_TYPE_GEM = typeGem(
"small_budding_normal_type_gem",
GrowableStoneBlock.STAGE_0,
3,
4,
MEDIUM_BUDDING_NORMAL_TYPE_GEM,
NORMAL_TYPE_GEM_BLOCK
)
private fun typeGem(
name: String,
stage: Int,
height: Int,
xzOffset: Int,
nextStage: Block?,
baseBlock: Block
): TypeGemBlock {
return this.create(name, TypeGemBlock(
settings = AbstractBlock.Settings.create()
.pistonBehavior(PistonBehavior.DESTROY)
.nonOpaque()
.strength(1.5F)
.sounds(CobblemonSounds.TYPE_GEM_SOUNDS),
stage = stage,
height = height,
xzOffset = xzOffset,
nextStage = nextStage,
baseBlock = baseBlock
))
}
/**
* Returns a map of all the blocks that can be stripped with an axe in the format of input - output.
*
@@ -722,148 +227,24 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
private fun apricornBlock(name: String, apricorn: Apricorn): ApricornBlock = this.create(name, ApricornBlock(AbstractBlock.Settings.create().mapColor(apricorn.mapColor()).ticksRandomly().strength(Blocks.OAK_LOG.hardness, Blocks.OAK_LOG.blastResistance).sounds(BlockSoundGroup.WOOD).nonOpaque(), apricorn))
private fun tumblestoneBlock(name: String, stage: Int, height: Int, xzOffset: Int, nextStage: Block?) : Block {
return this.create(name, TumblestoneBlock(AbstractBlock.Settings.create()
.pistonBehavior(PistonBehavior.DESTROY)
.nonOpaque()
.strength(1.5F)
.sounds(CobblemonSounds.TUMBLESTONE_SOUNDS),
stage, height, xzOffset, nextStage))
}
private val berries = mutableMapOf<Identifier, BerryBlock>()
val AGUAV_BERRY = this.berryBlock("aguav")
val APICOT_BERRY = this.berryBlock("apicot")
val ASPEAR_BERRY = this.berryBlock("aspear")
val BABIRI_BERRY = this.berryBlock("babiri")
val BELUE_BERRY = this.berryBlock("belue")
val BLUK_BERRY = this.berryBlock("bluk")
val CHARTI_BERRY = this.berryBlock("charti")
val CHERI_BERRY = this.berryBlock("cheri")
val CHESTO_BERRY = this.berryBlock("chesto")
val CHILAN_BERRY = this.berryBlock("chilan")
val CHOPLE_BERRY = this.berryBlock("chople")
val COBA_BERRY = this.berryBlock("coba")
val COLBUR_BERRY = this.berryBlock("colbur")
val CORNN_BERRY = this.berryBlock("cornn")
val CUSTAP_BERRY = this.berryBlock("custap")
val DURIN_BERRY = this.berryBlock("durin")
val ENIGMA_BERRY = this.berryBlock("enigma")
val FIGY_BERRY = this.berryBlock("figy")
val GANLON_BERRY = this.berryBlock("ganlon")
val GREPA_BERRY = this.berryBlock("grepa")
val HABAN_BERRY = this.berryBlock("haban")
val HONDEW_BERRY = this.berryBlock("hondew")
val HOPO_BERRY = this.berryBlock("hopo")
val IAPAPA_BERRY = this.berryBlock("iapapa")
val JABOCA_BERRY = this.berryBlock("jaboca")
val KASIB_BERRY = this.berryBlock("kasib")
val KEBIA_BERRY = this.berryBlock("kebia")
val KEE_BERRY = this.berryBlock("kee")
val KELPSY_BERRY = this.berryBlock("kelpsy")
val LANSAT_BERRY = this.berryBlock("lansat")
val LEPPA_BERRY = this.berryBlock("leppa")
val LIECHI_BERRY = this.berryBlock("liechi")
val LUM_BERRY = this.berryBlock("lum")
val MAGO_BERRY = this.berryBlock("mago")
val MAGOST_BERRY = this.berryBlock("magost")
val MARANGA_BERRY = this.berryBlock("maranga")
val MICLE_BERRY = this.berryBlock("micle")
val NANAB_BERRY = this.berryBlock("nanab")
val NOMEL_BERRY = this.berryBlock("nomel")
val OCCA_BERRY = this.berryBlock("occa")
val ORAN_BERRY = this.berryBlock("oran")
val PAMTRE_BERRY = this.berryBlock("pamtre")
val PASSHO_BERRY = this.berryBlock("passho")
val PAYAPA_BERRY = this.berryBlock("payapa")
val PECHA_BERRY = this.berryBlock("pecha")
val PERSIM_BERRY = this.berryBlock("persim")
val PETAYA_BERRY = this.berryBlock("petaya")
val PINAP_BERRY = this.berryBlock("pinap")
val POMEG_BERRY = this.berryBlock("pomeg")
val QUALOT_BERRY = this.berryBlock("qualot")
val RABUTA_BERRY = this.berryBlock("rabuta")
val RAWST_BERRY = this.berryBlock("rawst")
val RAZZ_BERRY = this.berryBlock("razz")
val RINDO_BERRY = this.berryBlock("rindo")
val ROSELI_BERRY = this.berryBlock("roseli")
val ROWAP_BERRY = this.berryBlock("rowap")
val SALAC_BERRY = this.berryBlock("salac")
val SHUCA_BERRY = this.berryBlock("shuca")
val SITRUS_BERRY = this.berryBlock("sitrus")
val SPELON_BERRY = this.berryBlock("spelon")
val STARF_BERRY = this.berryBlock("starf")
val TAMATO_BERRY = this.berryBlock("tamato")
val TANGA_BERRY = this.berryBlock("tanga")
val TOUGA_BERRY = this.berryBlock("touga")
val WACAN_BERRY = this.berryBlock("wacan")
val WATMEL_BERRY = this.berryBlock("watmel")
val WEPEAR_BERRY = this.berryBlock("wepear")
val WIKI_BERRY = this.berryBlock("wiki")
val YACHE_BERRY = this.berryBlock("yache")
//val BINDING_SOIL = this.create("binding_soil", BindingSoilBlock(AbstractBlock.Settings.create()))
init {
/**
* Makes all blocks in array flammable by adding them to FireBlock's flammableRegistry.
* second value is burn chance and third value is spread chance
*/
arrayOf(
Triple(APRICORN_LOG, 5, 5),
Triple(STRIPPED_APRICORN_LOG, 5, 5),
Triple(APRICORN_WOOD, 5, 5),
Triple(STRIPPED_APRICORN_WOOD, 5, 5),
Triple(APRICORN_PLANKS, 5, 20),
Triple(APRICORN_LEAVES, 30, 60),
Triple(APRICORN_FENCE, 5, 20),
Triple(APRICORN_FENCE_GATE, 5, 20),
Triple(APRICORN_SLAB, 5, 20),
Triple(APRICORN_STAIRS, 5, 20)
).onEach{ data -> setFlammable(data.first, data.second, data.third) }
}
fun berries() = this.berries.toMap()
private fun berryBlock(name: String): BerryBlock {
val identifier = cobblemonResource("${name}_berry")
val block = this.create(identifier.path, BerryBlock(identifier, AbstractBlock.Settings.copy(Blocks.WHEAT).dynamicBounds().sounds(CobblemonSounds.BERRY_BUSH_SOUNDS).strength(0.2F)))
this.berries[identifier] = block
return block
}
/**
* Calls helper method from Vanilla
* Helper method for creating logs
* copied over from Vanilla
*/
private fun log(name: String, arg: MapColor = MapColor.DIRT_BROWN, arg2: MapColor = MapColor.DIRT_BROWN): Block {
private fun log(name: String, arg: MapColor = MapColor.DIRT_BROWN, arg2: MapColor = MapColor.DIRT_BROWN): PillarBlock {
val block = BlocksInvoker.createLogBlock(arg, arg2)
return this.create(name, block)
}
/**
* Method uses generic E in order to keep the block as the same return type.
* If E is not a block then it will not be set as flammable.
* Calls Vanilla implementation of registering a flammable block.
* Mixins looks cursed but it is java's fault.
*/
private fun <E> setFlammable(block: E, burnChance: Int, spreadChance: Int): E {
if(block !is Block) return block
private fun evolutionStoneOre(name: String) = this.create(name, ExperienceDroppingBlock(AbstractBlock.Settings.copy(Blocks.IRON_ORE), UniformIntProvider.create(1, 2)))
var fireBlock: FireBlock = Blocks.FIRE as FireBlock
//Cursed Mixin stuff
(fireBlock as FireBlockInvoker).registerNewFlammableBlock(block as Block, burnChance, spreadChance)
return block
}
private fun evolutionStoneOre(name: String) = this.create(name, ExperienceDroppingBlock(UniformIntProvider.create(1, 2), AbstractBlock.Settings.copy(Blocks.IRON_ORE)))
private fun deepslateEvolutionStoneOre(name: String) = this.create(name, ExperienceDroppingBlock(UniformIntProvider.create(1, 2), AbstractBlock.Settings.copy(Blocks.DEEPSLATE_IRON_ORE)))
private fun deepslateEvolutionStoneOre(name: String) = this.create(name, ExperienceDroppingBlock(AbstractBlock.Settings.copy(Blocks.DEEPSLATE_IRON_ORE), UniformIntProvider.create(1, 2)))
/**
* Helper method for creating leaves
* copied over from Vanilla
*/
private fun leaves(name: String): Block {
private fun leaves(name: String): LeavesBlock {
val block = BlocksInvoker.createLeavesBlock(BlockSoundGroup.GRASS)
return this.create(name, block)
}
@@ -8,6 +8,7 @@
package com.cobblemon.mod.common
import java.util.function.Supplier
import net.minecraft.block.Block
import net.minecraft.block.entity.BlockEntity
import net.minecraft.block.entity.BlockEntityType
@@ -18,14 +19,11 @@ import net.minecraft.client.particle.ParticleFactory
import net.minecraft.client.particle.SpriteProvider
import net.minecraft.client.render.RenderLayer
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory
import net.minecraft.client.render.entity.EntityRendererFactory
import net.minecraft.client.render.entity.model.EntityModelLayer
import net.minecraft.entity.Entity
import net.minecraft.entity.EntityType
import net.minecraft.item.Item
import net.minecraft.particle.ParticleEffect
import net.minecraft.particle.ParticleType
import java.util.function.Supplier
import net.minecraft.resource.SynchronousResourceReloader
interface CobblemonClientImplementation {
fun registerLayer(modelLayer: EntityModelLayer, supplier: Supplier<TexturedModelData>)
@@ -40,7 +38,5 @@ interface CobblemonClientImplementation {
fun registerBlockColors(provider: BlockColorProvider, vararg blocks: Block)
fun <T : BlockEntity> registerBlockEntityRenderer(type: BlockEntityType<out T>, factory: BlockEntityRendererFactory<T>)
fun <T : Entity> registerEntityRenderer(type: EntityType<out T>, factory: EntityRendererFactory<T>)
fun <T : BlockEntity> registerBlockEntityRenderer(type: BlockEntityType<T>, factory: BlockEntityRendererFactory<T>)
}
@@ -44,14 +44,6 @@ object CobblemonCommands {
TestPcSlotCommand.register(dispatcher)
TestPartySlotCommand.register(dispatcher)
ClearPartyCommand.register(dispatcher)
ClearPCCommand.register(dispatcher)
PokemonRestartCommand.register(dispatcher)
BedrockParticleCommand.register(dispatcher)
OpenDialogueCommand.register(dispatcher)
NPCEditCommand.register(dispatcher)
// Possibly lock down registration if and only if under dev environment or running in an environment
// with a certain system environment variable set
CobblemonInfoCommand.register(dispatcher)
}
}
@@ -9,11 +9,6 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.entity.boat.CobblemonBoatEntity
import com.cobblemon.mod.common.entity.boat.CobblemonChestBoatEntity
import com.cobblemon.mod.common.entity.fishing.PokeRodFishingBobberEntity
import com.cobblemon.mod.common.entity.generic.GenericBedrockEntity
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.platform.PlatformRegistry
@@ -50,52 +45,8 @@ object CobblemonEntities : PlatformRegistry<Registry<EntityType<*>>, RegistryKey
.build(EMPTY_POKEBALL_KEY.toString())
)
@JvmField
val BOAT_KEY = cobblemonResource("boat")
@JvmField
val BOAT: EntityType<CobblemonBoatEntity> = this.create(
BOAT_KEY.path,
EntityType.Builder.create(::CobblemonBoatEntity, SpawnGroup.MISC).dimensions(1.375F, 0.5625F).maxTrackingRange(10)
.build(BOAT_KEY.toString())
)
@JvmField
val CHEST_BOAT_KEY = cobblemonResource("chest_boat")
@JvmField
val CHEST_BOAT: EntityType<CobblemonChestBoatEntity> = this.create(
CHEST_BOAT_KEY.path,
EntityType.Builder.create(::CobblemonChestBoatEntity, SpawnGroup.MISC).dimensions(1.375F, 0.5625F).maxTrackingRange(10)
.build(CHEST_BOAT_KEY.toString())
)
@JvmField
val POKE_BOBBER_KEY = cobblemonResource("poke_bobber")
@JvmField
val POKE_BOBBER: EntityType<PokeRodFishingBobberEntity> = this.create(
POKE_BOBBER_KEY.path,
EntityType.Builder.create(::PokeRodFishingBobberEntity, SpawnGroup.MISC).dimensions(0.5F, 0.5F).maxTrackingRange(10)
.build(POKE_BOBBER_KEY.toString())
)
@JvmField
val GENERIC_BEDROCK_ENTITY_KEY = cobblemonResource("generic_bedrock")
@JvmField
val GENERIC_BEDROCK_ENTITY: EntityType<GenericBedrockEntity> = this.create(
GENERIC_BEDROCK_ENTITY_KEY.path,
EntityType.Builder.create({ _, world -> GenericBedrockEntity(world) }, SpawnGroup.MISC)
.build(GENERIC_BEDROCK_ENTITY_KEY.toString())
)
@JvmField
val NPC_KEY = cobblemonResource("npc")
@JvmField
val NPC: EntityType<NPCEntity> = create(
NPC_KEY.path,
EntityType.Builder.create({ _, world -> NPCEntity(world) }, SpawnGroup.CREATURE).build("$NPC_KEY")
)
fun registerAttributes(consumer: (EntityType<out LivingEntity>, DefaultAttributeContainer.Builder) -> Unit) {
consumer(POKEMON, PokemonEntity.createAttributes())
consumer(NPC, NPCEntity.createAttributes())
}
}
@@ -8,22 +8,22 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
import com.mojang.brigadier.arguments.ArgumentType
import kotlin.reflect.KClass
import net.minecraft.block.ComposterBlock
import net.minecraft.advancement.criterion.Criterion
import net.minecraft.command.argument.serialize.ArgumentSerializer
import net.minecraft.item.ItemConvertible
import net.minecraft.network.PacketByteBuf
import net.minecraft.network.listener.ClientPlayPacketListener
import net.minecraft.network.packet.Packet
import net.minecraft.registry.RegistryKey
import net.minecraft.registry.tag.TagKey
import net.minecraft.resource.ResourceManager
import net.minecraft.resource.ResourceReloader
import net.minecraft.resource.ResourceType
import net.minecraft.screen.ScreenHandlerType
import net.minecraft.server.MinecraftServer
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.text.Text
import net.minecraft.util.Identifier
import net.minecraft.world.GameRules
import net.minecraft.world.biome.Biome
@@ -65,10 +65,6 @@ interface CobblemonImplementation {
*/
fun registerSoundEvents()
fun registerDataComponents()
fun registerEntityDataSerializers()
/**
* TODO
*
@@ -107,7 +103,6 @@ interface CobblemonImplementation {
fun registerParticles()
/**
* Add a feature to the current platform implementation.
*
@@ -146,7 +141,7 @@ interface CobblemonImplementation {
* @param criteria
* @return
*/
fun registerCriteria()
fun <T : Criterion<*>> registerCriteria(criteria: T): T
/**
* TODO
@@ -158,8 +153,6 @@ interface CobblemonImplementation {
*/
fun registerResourceReloader(identifier: Identifier, reloader: ResourceReloader, type: ResourceType, dependencies: Collection<Identifier>)
fun registerScreenHandlerType(identifier: Identifier, screenHandlerType: ScreenHandlerType<*>)
/**
* TODO
*
@@ -167,66 +160,34 @@ interface CobblemonImplementation {
*/
fun server(): MinecraftServer?
/**
* Handles platform independent reloading of a [JsonDataRegistry].
*
* @param registry The [JsonDataRegistry] to reload.
* @param manager The [ResourceManager] to reload from.
*/
fun <T> reloadJsonRegistry(registry: JsonDataRegistry<T>, manager: ResourceManager): HashMap<Identifier, T>
/**
* Registers an item to the [ComposterBlock].
*
* @param item The [ItemConvertible] being registered.
* @param chance The chance % of increasing the composter level, 0 to 1 expected.
*/
fun registerCompostable(item: ItemConvertible, chance: Float)
/**
* Registers a builtin resource pack.
*
* @param id The unique [Identifier] of this pack.
* @param title The title displayed in the resource pack GUI, the description is still a part of the pack metadata.
* @param activationBehaviour The [ResourcePackActivationBehaviour] for this pack.
*/
fun registerBuiltinResourcePack(id: Identifier, title: Text, activationBehaviour: ResourcePackActivationBehaviour)
}
enum class ResourcePackActivationBehaviour {
/**
* The resource pack will start disabled.
*/
NORMAL,
/**
* The resource pack will start enabled.
*/
DEFAULT_ENABLED,
/**
* The resource pack will always be enabled.
* The user can reorder it but cannot remove it.
*/
ALWAYS_ENABLED;
}
enum class ModAPI {
FABRIC,
FORGE,
NEOFORGE
FORGE
}
interface NetworkManager {
fun registerClientBound()
fun registerServerBound()
fun <T: NetworkPacket<T>> createClientBound(identifier: Identifier, kClass: KClass<T>, encoder: (T, PacketByteBuf) -> Unit, decoder: (PacketByteBuf) -> T, handler: ClientNetworkPacketHandler<T>)
fun <T: NetworkPacket<T>> createServerBound(identifier: Identifier, kClass: KClass<T>, encoder: (T, PacketByteBuf) -> Unit, decoder: (PacketByteBuf) -> T, handler: ServerNetworkPacketHandler<T>)
fun sendPacketToPlayer(player: ServerPlayerEntity, packet: NetworkPacket<*>)
fun sendToServer(packet: NetworkPacket<*>)
fun sendPacketToServer(packet: NetworkPacket<*>)
fun <T : NetworkPacket<*>> asVanillaClientBound(packet: T): Packet<ClientPlayPacketListener>
}
enum class Environment {
CLIENT,
SERVER
}
}
@@ -1,53 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common
import com.cobblemon.mod.common.item.components.HeldItemCapableComponent
import com.cobblemon.mod.common.item.components.PokemonItemComponent
import com.cobblemon.mod.common.item.RodBaitComponent
import com.cobblemon.mod.common.item.components.TMMoveComponent
import com.cobblemon.mod.common.platform.PlatformRegistry
import net.minecraft.component.ComponentType
import net.minecraft.registry.Registries
import net.minecraft.registry.Registry
import net.minecraft.registry.RegistryKey
import net.minecraft.registry.RegistryKeys
import net.minecraft.util.Identifier
object CobblemonItemComponents : PlatformRegistry<Registry<ComponentType<*>>, RegistryKey<Registry<ComponentType<*>>>, ComponentType<*>>() {
val POKEMON_ITEM: ComponentType<PokemonItemComponent> = ComponentType.builder<PokemonItemComponent>()
.codec(PokemonItemComponent.CODEC)
.packetCodec(PokemonItemComponent.PACKET_CODEC)
.build()
val HELD_ITEM_REP: ComponentType<HeldItemCapableComponent> = ComponentType.builder<HeldItemCapableComponent>()
.codec(HeldItemCapableComponent.CODEC)
.packetCodec(HeldItemCapableComponent.PACKET_CODEC)
.build()
val BAIT: ComponentType<RodBaitComponent> = ComponentType.builder<RodBaitComponent>()
.codec(RodBaitComponent.CODEC)
.packetCodec(RodBaitComponent.PACKET_CODEC)
.build()
val TM_MOVE: ComponentType<TMMoveComponent> = ComponentType.builder<TMMoveComponent>()
.codec(TMMoveComponent.CODEC)
.packetCodec(TMMoveComponent.PACKET_CODEC)
.build()
fun register() {
Registry.register(Registries.DATA_COMPONENT_TYPE, Identifier.of("cobblemon:pokemon_item"), POKEMON_ITEM)
Registry.register(Registries.DATA_COMPONENT_TYPE, Identifier.of("cobblemon:bait"), BAIT)
Registry.register(Registries.DATA_COMPONENT_TYPE, Identifier.of("cobblemon:tm_move"), TM_MOVE)
}
override val registry = Registries.DATA_COMPONENT_TYPE
override val registryKey = RegistryKeys.DATA_COMPONENT_TYPE
}
File diff suppressed because it is too large Load Diff
@@ -10,13 +10,9 @@ package com.cobblemon.mod.common
import com.bedrockk.molang.Expression
import com.cobblemon.mod.common.api.data.DataRegistry
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.mechanics.BerriesMechanic
import com.cobblemon.mod.common.mechanics.PotionsMechanic
import com.cobblemon.mod.common.mechanics.RemediesMechanic
import com.cobblemon.mod.common.util.adapters.ExpressionAdapter
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.GsonBuilder
import net.minecraft.resource.ResourceManager
@@ -31,23 +27,14 @@ object CobblemonMechanics : DataRegistry {
val gson = GsonBuilder()
.setPrettyPrinting()
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
.create()
var remedies = RemediesMechanic()
var berries = BerriesMechanic()
var potions = PotionsMechanic()
override fun sync(player: ServerPlayerEntity) {}
override fun reload(manager: ResourceManager) {
remedies = loadMechanic(manager, "remedies", RemediesMechanic::class.java)
berries = loadMechanic(manager, "berries", BerriesMechanic::class.java)
potions = loadMechanic(manager, "potions", PotionsMechanic::class.java)
}
private fun <T> loadMechanic(manager: ResourceManager, name: String, clazz: Class<T>): T {
manager.getResourceOrThrow(cobblemonResource("mechanics/$name.json")).inputStream.use {
return gson.fromJson(it.reader(), clazz)
manager.getResourceOrThrow(cobblemonResource("mechanics/remedies.json")).inputStream.use {
remedies = gson.fromJson(it.reader(), RemediesMechanic::class.java)
}
}
}
@@ -1,35 +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
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.ListCodec
import com.mojang.serialization.codecs.PrimitiveCodec
import java.util.Optional
import net.minecraft.entity.ai.brain.MemoryModuleType
import net.minecraft.util.Uuids
object CobblemonMemories {
val memories = mutableMapOf<String, MemoryModuleType<*>>()
val BATTLING_POKEMON = register("battling_pokemon", ListCodec(Uuids.INT_STREAM_CODEC, 0, 31))
val NPC_BATTLING = register("npc_battling", PrimitiveCodec.BOOL)
fun <U> register(id: String, codec: Codec<U>): MemoryModuleType<U> {
val memoryModule = MemoryModuleType(Optional.of(codec))
memories[id] = memoryModule
return memoryModule
}
fun <U> register(id: String): MemoryModuleType<U> {
val memoryModule = MemoryModuleType<U>(Optional.empty())
memories[id] = memoryModule
return memoryModule
}
}
@@ -8,33 +8,26 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.client.net.PlayerInteractOptionsHandler
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
import com.cobblemon.mod.common.client.net.SetClientPlayerDataHandler
import com.cobblemon.mod.common.client.net.animation.PlayPosableAnimationHandler
import com.cobblemon.mod.common.client.net.battle.*
import com.cobblemon.mod.common.client.net.data.DataRegistrySyncPacketHandler
import com.cobblemon.mod.common.client.net.data.UnlockReloadPacketHandler
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormParticleHandler
import com.cobblemon.mod.common.client.net.gui.InteractPokemonUIPacketHandler
import com.cobblemon.mod.common.client.net.gui.SummaryUIPacketHandler
import com.cobblemon.mod.common.client.net.callback.move.OpenMoveCallbackHandler
import com.cobblemon.mod.common.client.net.callback.party.OpenPartyCallbackHandler
import com.cobblemon.mod.common.client.net.callback.partymove.OpenPartyMoveCallbackHandler
import com.cobblemon.mod.common.client.net.data.DataRegistrySyncPacketHandler
import com.cobblemon.mod.common.client.net.data.UnlockReloadPacketHandler
import com.cobblemon.mod.common.client.net.dialogue.DialogueClosedHandler
import com.cobblemon.mod.common.client.net.dialogue.DialogueOpenedHandler
import com.cobblemon.mod.common.client.net.effect.RunPosableMoLangHandler
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormEntityParticleHandler
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormParticleHandler
import com.cobblemon.mod.common.client.net.gui.CraftBlankTMPacketHandler
import com.cobblemon.mod.common.client.net.gui.CraftTMPacketHandler
import com.cobblemon.mod.common.client.net.gui.InteractPokemonUIPacketHandler
import com.cobblemon.mod.common.client.net.gui.SummaryUIPacketHandler
import com.cobblemon.mod.common.client.net.npc.CloseNPCEditorHandler
import com.cobblemon.mod.common.client.net.npc.OpenNPCEditorHandler
import com.cobblemon.mod.common.client.net.pasture.ClosePastureHandler
import com.cobblemon.mod.common.client.net.pasture.OpenPastureHandler
import com.cobblemon.mod.common.client.net.pasture.PokemonPasturedHandler
import com.cobblemon.mod.common.client.net.pasture.PokemonUnpasturedHandler
import com.cobblemon.mod.common.client.net.pokemon.update.PokemonUpdatePacketHandler
import com.cobblemon.mod.common.client.net.settings.ServerSettingsPacketHandler
import com.cobblemon.mod.common.client.net.sound.PokemonCryHandler
import com.cobblemon.mod.common.client.net.sound.UnvalidatedPlaySoundS2CPacketHandler
import com.cobblemon.mod.common.client.net.spawn.SpawnExtraDataEntityHandler
import com.cobblemon.mod.common.client.net.starter.StarterUIPacketHandler
@@ -58,24 +51,16 @@ import com.cobblemon.mod.common.client.net.trade.TradeOfferExpiredHandler
import com.cobblemon.mod.common.client.net.trade.TradeOfferNotificationHandler
import com.cobblemon.mod.common.client.net.trade.TradeStartedHandler
import com.cobblemon.mod.common.client.net.trade.TradeUpdatedHandler
import com.cobblemon.mod.common.net.PacketRegisterInfo
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimationPacket
import com.cobblemon.mod.common.net.messages.client.battle.*
import com.cobblemon.mod.common.net.messages.client.callback.OpenMoveCallbackPacket
import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyCallbackPacket
import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyMoveCallbackPacket
import com.cobblemon.mod.common.net.messages.client.data.*
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueClosedPacket
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueOpenedPacket
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
import com.cobblemon.mod.common.net.messages.client.data.AbilityRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.MovesRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.PropertiesCompletionRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.SpeciesRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.UnlockReloadPacket
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
import com.cobblemon.mod.common.net.messages.client.fishing.FishingBaitRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.fossil.FossilRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.fossil.NaturalMaterialRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.npc.CloseNPCEditorPacket
import com.cobblemon.mod.common.net.messages.client.npc.OpenNPCEditorPacket
import com.cobblemon.mod.common.net.messages.client.pasture.ClosePasturePacket
import com.cobblemon.mod.common.net.messages.client.pasture.OpenPasturePacket
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonPasturedPacket
@@ -85,8 +70,8 @@ import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.Add
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.ClearEvolutionsPacket
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.RemoveEvolutionPacket
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
import com.cobblemon.mod.common.net.messages.client.sound.PokemonCryPacket
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnGenericBedrockPacket
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokeballPacket
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokemonPacket
import com.cobblemon.mod.common.net.messages.client.starter.OpenStarterUIPacket
@@ -111,28 +96,20 @@ import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferExpiredPacke
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferNotificationPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
import com.cobblemon.mod.common.net.messages.client.ui.CraftBlankTMPacket
import com.cobblemon.mod.common.net.messages.client.ui.CraftTMPacket
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
import com.cobblemon.mod.common.net.messages.server.BenchMovePacket
import com.cobblemon.mod.common.net.messages.server.RequestMoveSwapPacket
import com.cobblemon.mod.common.net.messages.server.RequestPlayerInteractionsPacket
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectCancelledPacket
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectedPacket
import com.cobblemon.mod.common.net.messages.server.callback.party.PartyPokemonSelectedPacket
import com.cobblemon.mod.common.net.messages.server.callback.party.PartySelectCancelledPacket
import com.cobblemon.mod.common.net.messages.server.callback.partymove.PartyMoveSelectCancelledPacket
import com.cobblemon.mod.common.net.messages.server.callback.partymove.PartyPokemonMoveSelectedPacket
import com.cobblemon.mod.common.net.messages.server.dialogue.EscapeDialoguePacket
import com.cobblemon.mod.common.net.messages.server.dialogue.InputToDialoguePacket
import com.cobblemon.mod.common.net.messages.server.npc.SaveNPCPacket
import com.cobblemon.mod.common.net.messages.server.pasture.PasturePokemonPacket
import com.cobblemon.mod.common.net.messages.server.pasture.UnpastureAllPokemonPacket
import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPacket
@@ -156,20 +133,14 @@ import com.cobblemon.mod.common.net.messages.server.trade.ChangeTradeAcceptanceP
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket
import com.cobblemon.mod.common.net.serverhandling.ChallengeHandler
import com.cobblemon.mod.common.net.serverhandling.RequestInteractionsHandler
import com.cobblemon.mod.common.net.serverhandling.battle.BattleSelectActionsHandler
import com.cobblemon.mod.common.net.serverhandling.battle.RemoveSpectatorHandler
import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectCancelledHandler
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectedHandler
import com.cobblemon.mod.common.net.serverhandling.callback.party.PartyPokemonSelectedHandler
import com.cobblemon.mod.common.net.serverhandling.callback.party.PartySelectCancelledHandler
import com.cobblemon.mod.common.net.serverhandling.callback.partymove.PartyMoveSelectCancelledHandler
import com.cobblemon.mod.common.net.serverhandling.callback.partymove.PartyPokemonMoveSelectedHandler
import com.cobblemon.mod.common.net.serverhandling.dialogue.EscapeDialogueHandler
import com.cobblemon.mod.common.net.serverhandling.dialogue.InputToDialogueHandler
import com.cobblemon.mod.common.net.serverhandling.evolution.AcceptEvolutionHandler
import com.cobblemon.mod.common.net.serverhandling.npc.SaveNPCHandler
import com.cobblemon.mod.common.net.serverhandling.pasture.PasturePokemonHandler
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpastureAllPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpasturePokemonHandler
@@ -196,7 +167,12 @@ import com.cobblemon.mod.common.net.serverhandling.trade.ChangeTradeAcceptanceHa
import com.cobblemon.mod.common.net.serverhandling.trade.OfferTradeHandler
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler
import com.cobblemon.mod.common.util.server
import kotlin.reflect.KClass
import net.minecraft.network.PacketByteBuf
import net.minecraft.network.listener.ClientPlayPacketListener
import net.minecraft.network.packet.Packet
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
/**
* Registers Cobblemon network packets.
@@ -206,247 +182,228 @@ import net.minecraft.server.network.ServerPlayerEntity
* @author Hiroku, Licious
* @since November 27th, 2021
*/
object CobblemonNetwork {
object CobblemonNetwork : NetworkManager {
fun ServerPlayerEntity.sendPacket(packet: NetworkPacket<*>) = sendPacketToPlayer(this, packet)
fun sendToServer(packet: NetworkPacket<*>) = Cobblemon.implementation.networkManager.sendToServer(packet)
fun sendToServer(packet: NetworkPacket<*>) = this.sendPacketToServer(packet)
fun sendToAllPlayers(packet: NetworkPacket<*>) = sendPacketToPlayers(server()!!.playerManager.playerList, packet)
fun sendPacketToPlayers(players: Iterable<ServerPlayerEntity>, packet: NetworkPacket<*>) = players.forEach { sendPacketToPlayer(it, packet) }
val s2cPayloads = generateS2CPacketInfoList()
val c2sPayloads = generateC2SPacketInfoList()
private fun generateS2CPacketInfoList(): List<PacketRegisterInfo<*>> {
val list = mutableListOf<PacketRegisterInfo<*>>()
override fun registerClientBound() {
// Pokemon Update Packets
list.add(PacketRegisterInfo(FriendshipUpdatePacket.ID, FriendshipUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(MoveSetUpdatePacket.ID, MoveSetUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(NatureUpdatePacket.ID, NatureUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(ShinyUpdatePacket.ID, ShinyUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(SpeciesUpdatePacket.ID, SpeciesUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(NicknameUpdatePacket.ID, NicknameUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(HealthUpdatePacket.ID, HealthUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(ExperienceUpdatePacket.ID, ExperienceUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(StatusUpdatePacket.ID, StatusUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(CaughtBallUpdatePacket.ID, CaughtBallUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(BenchedMovesUpdatePacket.ID, BenchedMovesUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(GenderUpdatePacket.ID, GenderUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(AspectsUpdatePacket.ID, AspectsUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(AbilityUpdatePacket.ID, AbilityUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(EVsUpdatePacket.ID, EVsUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(IVsUpdatePacket.ID, IVsUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(HeldItemUpdatePacket.ID, HeldItemUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(PokemonStateUpdatePacket.ID, PokemonStateUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(TetheringUpdatePacket.ID, TetheringUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(TradeableUpdatePacket.ID, TradeableUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(SpeciesFeatureUpdatePacket.ID, SpeciesFeatureUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(OriginalTrainerUpdatePacket.ID, OriginalTrainerUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(FormUpdatePacket.ID, FormUpdatePacket::decode, PokemonUpdatePacketHandler()))
this.createClientBound(FriendshipUpdatePacket.ID, FriendshipUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(MoveSetUpdatePacket.ID, MoveSetUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(NatureUpdatePacket.ID, NatureUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(ShinyUpdatePacket.ID, ShinyUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(SpeciesUpdatePacket.ID, SpeciesUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(NicknameUpdatePacket.ID, NicknameUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(HealthUpdatePacket.ID, HealthUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(ExperienceUpdatePacket.ID, ExperienceUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(StatusUpdatePacket.ID, StatusUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(CaughtBallUpdatePacket.ID, CaughtBallUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(BenchedMovesUpdatePacket.ID, BenchedMovesUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(GenderUpdatePacket.ID, GenderUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(AspectsUpdatePacket.ID, AspectsUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(AbilityUpdatePacket.ID, AbilityUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(EVsUpdatePacket.ID, EVsUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(IVsUpdatePacket.ID, IVsUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(HeldItemUpdatePacket.ID, HeldItemUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(PokemonStateUpdatePacket.ID, PokemonStateUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(TetheringUpdatePacket.ID, TetheringUpdatePacket::decode, PokemonUpdatePacketHandler())
// Evolution start
list.add(PacketRegisterInfo(AddEvolutionPacket.ID, AddEvolutionPacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(ClearEvolutionsPacket.ID, ClearEvolutionsPacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(RemoveEvolutionPacket.ID, RemoveEvolutionPacket::decode, PokemonUpdatePacketHandler()))
this.createClientBound(AddEvolutionPacket.ID, AddEvolutionPacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(ClearEvolutionsPacket.ID, ClearEvolutionsPacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(RemoveEvolutionPacket.ID, RemoveEvolutionPacket::decode, PokemonUpdatePacketHandler())
// Evolution End
// Storage Packets
list.add(PacketRegisterInfo(InitializePartyPacket.ID, InitializePartyPacket::decode, InitializePartyHandler))
list.add(PacketRegisterInfo(SetPartyPokemonPacket.ID, SetPartyPokemonPacket::decode, SetPartyPokemonHandler))
list.add(PacketRegisterInfo(MoveClientPartyPokemonPacket.ID, MoveClientPartyPokemonPacket::decode, MoveClientPartyPokemonHandler))
list.add(PacketRegisterInfo(SetPartyReferencePacket.ID, SetPartyReferencePacket::decode, SetPartyReferenceHandler))
list.add(PacketRegisterInfo(InitializePCPacket.ID, InitializePCPacket::decode, InitializePCHandler))
list.add(PacketRegisterInfo(MoveClientPCPokemonPacket.ID, MoveClientPCPokemonPacket::decode, MoveClientPCPokemonHandler))
list.add(PacketRegisterInfo(SetPCBoxPokemonPacket.ID, SetPCBoxPokemonPacket::decode, SetPCBoxPokemonHandler))
list.add(PacketRegisterInfo(SetPCPokemonPacket.ID, SetPCPokemonPacket::decode, SetPCPokemonHandler))
list.add(PacketRegisterInfo(OpenPCPacket.ID, OpenPCPacket::decode, OpenPCHandler))
list.add(PacketRegisterInfo(ClosePCPacket.ID, ClosePCPacket::decode, ClosePCHandler))
list.add(PacketRegisterInfo(SwapClientPokemonPacket.ID, SwapClientPokemonPacket::decode, SwapClientPokemonHandler))
list.add(PacketRegisterInfo(RemoveClientPokemonPacket.ID, RemoveClientPokemonPacket::decode, RemoveClientPokemonHandler))
this.createClientBound(InitializePartyPacket.ID, InitializePartyPacket::decode, InitializePartyHandler)
this.createClientBound(SetPartyPokemonPacket.ID, SetPartyPokemonPacket::decode, SetPartyPokemonHandler)
this.createClientBound(MoveClientPartyPokemonPacket.ID, MoveClientPartyPokemonPacket::decode, MoveClientPartyPokemonHandler)
this.createClientBound(SetPartyReferencePacket.ID, SetPartyReferencePacket::decode, SetPartyReferenceHandler)
this.createClientBound(InitializePCPacket.ID, InitializePCPacket::decode, InitializePCHandler)
this.createClientBound(MoveClientPCPokemonPacket.ID, MoveClientPCPokemonPacket::decode, MoveClientPCPokemonHandler)
this.createClientBound(SetPCBoxPokemonPacket.ID, SetPCBoxPokemonPacket::decode, SetPCBoxPokemonHandler)
this.createClientBound(SetPCPokemonPacket.ID, SetPCPokemonPacket::decode, SetPCPokemonHandler)
this.createClientBound(OpenPCPacket.ID, OpenPCPacket::decode, OpenPCHandler)
this.createClientBound(ClosePCPacket.ID, ClosePCPacket::decode, ClosePCHandler)
this.createClientBound(SwapClientPokemonPacket.ID, SwapClientPokemonPacket::decode, SwapClientPokemonHandler)
this.createClientBound(RemoveClientPokemonPacket.ID, RemoveClientPokemonPacket::decode, RemoveClientPokemonHandler)
// UI Packets
list.add(PacketRegisterInfo(SummaryUIPacket.ID, SummaryUIPacket::decode, SummaryUIPacketHandler))
list.add(PacketRegisterInfo(InteractPokemonUIPacket.ID, InteractPokemonUIPacket::decode, InteractPokemonUIPacketHandler))
list.add(PacketRegisterInfo(PlayerInteractOptionsPacket.ID, PlayerInteractOptionsPacket::decode, PlayerInteractOptionsHandler))
this.createClientBound(SummaryUIPacket.ID, SummaryUIPacket::decode, SummaryUIPacketHandler)
this.createClientBound(InteractPokemonUIPacket.ID, InteractPokemonUIPacket::decode, InteractPokemonUIPacketHandler)
// Starter packets
list.add(PacketRegisterInfo(OpenStarterUIPacket.ID, OpenStarterUIPacket::decode, StarterUIPacketHandler))
list.add(PacketRegisterInfo(SetClientPlayerDataPacket.ID, SetClientPlayerDataPacket::decode, SetClientPlayerDataHandler))
this.createClientBound(OpenStarterUIPacket.ID, OpenStarterUIPacket::decode, StarterUIPacketHandler)
this.createClientBound(SetClientPlayerDataPacket.ID, SetClientPlayerDataPacket::decode, SetClientPlayerDataHandler)
// Battle packets
list.add(PacketRegisterInfo(BattleEndPacket.ID, BattleEndPacket::decode, BattleEndHandler))
list.add(PacketRegisterInfo(BattleInitializePacket.ID, BattleInitializePacket::decode, BattleInitializeHandler))
list.add(PacketRegisterInfo(BattleQueueRequestPacket.ID, BattleQueueRequestPacket::decode, BattleQueueRequestHandler))
list.add(PacketRegisterInfo(BattleFaintPacket.ID, BattleFaintPacket::decode, BattleFaintHandler))
list.add(PacketRegisterInfo(BattleMakeChoicePacket.ID, BattleMakeChoicePacket::decode, BattleMakeChoiceHandler))
list.add(PacketRegisterInfo(BattleHealthChangePacket.ID, BattleHealthChangePacket::decode, BattleHealthChangeHandler))
list.add(PacketRegisterInfo(BattleSetTeamPokemonPacket.ID, BattleSetTeamPokemonPacket::decode, BattleSetTeamPokemonHandler))
list.add(PacketRegisterInfo(BattleSwitchPokemonPacket.ID, BattleSwitchPokemonPacket::decode, BattleSwitchPokemonHandler))
list.add(PacketRegisterInfo(BattleMessagePacket.ID, BattleMessagePacket::decode, BattleMessageHandler))
list.add(PacketRegisterInfo(BattleCaptureStartPacket.ID, BattleCaptureStartPacket::decode, BattleCaptureStartHandler))
list.add(PacketRegisterInfo(BattleCaptureEndPacket.ID, BattleCaptureEndPacket::decode, BattleCaptureEndHandler))
list.add(PacketRegisterInfo(BattleCaptureShakePacket.ID, BattleCaptureShakePacket::decode, BattleCaptureShakeHandler))
list.add(PacketRegisterInfo(BattleApplyPassResponsePacket.ID, BattleApplyPassResponsePacket::decode, BattleApplyPassResponseHandler))
list.add(PacketRegisterInfo(BattleChallengeNotificationPacket.ID, BattleChallengeNotificationPacket::decode, BattleChallengeNotificationHandler))
list.add(PacketRegisterInfo(BattleUpdateTeamPokemonPacket.ID, BattleUpdateTeamPokemonPacket::decode, BattleUpdateTeamPokemonHandler))
list.add(PacketRegisterInfo(BattlePersistentStatusPacket.ID, BattlePersistentStatusPacket::decode, BattlePersistentStatusHandler))
list.add(PacketRegisterInfo(BattleMadeInvalidChoicePacket.ID, BattleMadeInvalidChoicePacket::decode, BattleMadeInvalidChoiceHandler))
list.add(PacketRegisterInfo(BattleMusicPacket.ID, BattleMusicPacket::decode, BattleMusicHandler))
list.add(PacketRegisterInfo(BattleChallengeExpiredPacket.ID, BattleChallengeExpiredPacket::decode, BattleChallengeExpiredHandler))
list.add(PacketRegisterInfo(BattleReplacePokemonPacket.ID, BattleReplacePokemonPacket::decode, BattleReplacePokemonHandler))
list.add(PacketRegisterInfo(BattleTransformPokemonPacket.ID, BattleTransformPokemonPacket::decode, BattleTransformPokemonHandler))
this.createClientBound(BattleEndPacket.ID, BattleEndPacket::decode, BattleEndHandler)
this.createClientBound(BattleInitializePacket.ID, BattleInitializePacket::decode, BattleInitializeHandler)
this.createClientBound(BattleQueueRequestPacket.ID, BattleQueueRequestPacket::decode, BattleQueueRequestHandler)
this.createClientBound(BattleFaintPacket.ID, BattleFaintPacket::decode, BattleFaintHandler)
this.createClientBound(BattleMakeChoicePacket.ID, BattleMakeChoicePacket::decode, BattleMakeChoiceHandler)
this.createClientBound(BattleHealthChangePacket.ID, BattleHealthChangePacket::decode, BattleHealthChangeHandler)
this.createClientBound(BattleSetTeamPokemonPacket.ID, BattleSetTeamPokemonPacket::decode, BattleSetTeamPokemonHandler)
this.createClientBound(BattleSwitchPokemonPacket.ID, BattleSwitchPokemonPacket::decode, BattleSwitchPokemonHandler)
this.createClientBound(BattleMessagePacket.ID, BattleMessagePacket::decode, BattleMessageHandler)
this.createClientBound(BattleCaptureStartPacket.ID, BattleCaptureStartPacket::decode, BattleCaptureStartHandler)
this.createClientBound(BattleCaptureEndPacket.ID, BattleCaptureEndPacket::decode, BattleCaptureEndHandler)
this.createClientBound(BattleCaptureShakePacket.ID, BattleCaptureShakePacket::decode, BattleCaptureShakeHandler)
this.createClientBound(BattleApplyPassResponsePacket.ID, BattleApplyPassResponsePacket::decode, BattleApplyPassResponseHandler)
this.createClientBound(BattleChallengeNotificationPacket.ID, BattleChallengeNotificationPacket::decode, BattleChallengeNotificationHandler)
this.createClientBound(BattleUpdateTeamPokemonPacket.ID, BattleUpdateTeamPokemonPacket::decode, BattleUpdateTeamPokemonHandler)
this.createClientBound(BattlePersistentStatusPacket.ID, BattlePersistentStatusPacket::decode, BattlePersistentStatusHandler)
this.createClientBound(BattleMadeInvalidChoicePacket.ID, BattleMadeInvalidChoicePacket::decode, BattleMadeInvalidChoiceHandler)
this.createClientBound(BattleMusicPacket.ID, BattleMusicPacket::decode, BattleMusicHandler)
this.createClientBound(BattleChallengeExpiredPacket.ID, BattleChallengeExpiredPacket::decode, BattleChallengeExpiredHandler)
// Settings packets
list.add(PacketRegisterInfo(ServerSettingsPacket.ID, ServerSettingsPacket::decode, ServerSettingsPacketHandler))
this.createClientBound(ServerSettingsPacket.ID, ServerSettingsPacket::decode, ServerSettingsPacketHandler)
// Data registries
list.add(PacketRegisterInfo(AbilityRegistrySyncPacket.ID, AbilityRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(MovesRegistrySyncPacket.ID, MovesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(SpeciesRegistrySyncPacket.ID, SpeciesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(PropertiesCompletionRegistrySyncPacket.ID, PropertiesCompletionRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(UnlockReloadPacket.ID, UnlockReloadPacket::decode, UnlockReloadPacketHandler))
list.add(PacketRegisterInfo(BerryRegistrySyncPacket.ID, BerryRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(StandardSpeciesFeatureSyncPacket.ID, StandardSpeciesFeatureSyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(GlobalSpeciesFeatureSyncPacket.ID, GlobalSpeciesFeatureSyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(SpeciesFeatureAssignmentSyncPacket.ID, SpeciesFeatureAssignmentSyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(NaturalMaterialRegistrySyncPacket.ID, NaturalMaterialRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(FossilRegistrySyncPacket.ID, FossilRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(NPCRegistrySyncPacket.ID, NPCRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(PokeRodRegistrySyncPacket.ID, PokeRodRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(ScriptRegistrySyncPacket.ID, ScriptRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(FishingBaitRegistrySyncPacket.ID, FishingBaitRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
this.createClientBound(AbilityRegistrySyncPacket.ID, AbilityRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
this.createClientBound(MovesRegistrySyncPacket.ID, MovesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
this.createClientBound(SpeciesRegistrySyncPacket.ID, SpeciesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
this.createClientBound(PropertiesCompletionRegistrySyncPacket.ID, PropertiesCompletionRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
this.createClientBound(UnlockReloadPacket.ID, UnlockReloadPacket::decode, UnlockReloadPacketHandler)
// Effects
list.add(PacketRegisterInfo(SpawnSnowstormParticlePacket.ID, SpawnSnowstormParticlePacket::decode, SpawnSnowstormParticleHandler))
list.add(PacketRegisterInfo(SpawnSnowstormEntityParticlePacket.ID, SpawnSnowstormEntityParticlePacket::decode, SpawnSnowstormEntityParticleHandler))
list.add(PacketRegisterInfo(RunPosableMoLangPacket.ID, RunPosableMoLangPacket::decode, RunPosableMoLangHandler))
this.createClientBound(SpawnSnowstormParticlePacket.ID, SpawnSnowstormParticlePacket::decode, SpawnSnowstormParticleHandler)
// Hax
list.add(PacketRegisterInfo(UnvalidatedPlaySoundS2CPacket.ID, UnvalidatedPlaySoundS2CPacket::decode, UnvalidatedPlaySoundS2CPacketHandler))
list.add(PacketRegisterInfo(SpawnPokemonPacket.ID, SpawnPokemonPacket::decode, SpawnExtraDataEntityHandler()))
list.add(PacketRegisterInfo(SpawnPokeballPacket.ID, SpawnPokeballPacket::decode, SpawnExtraDataEntityHandler()))
list.add(PacketRegisterInfo(ToastPacket.ID, ToastPacket::decode, ToastPacketHandler))
list.add(PacketRegisterInfo(SpawnGenericBedrockPacket.ID, SpawnGenericBedrockPacket::decode, SpawnExtraDataEntityHandler()))
this.createClientBound(UnvalidatedPlaySoundS2CPacket.ID, UnvalidatedPlaySoundS2CPacket::decode, UnvalidatedPlaySoundS2CPacketHandler)
this.createClientBound(SpawnPokemonPacket.ID, SpawnPokemonPacket::decode, SpawnExtraDataEntityHandler())
this.createClientBound(SpawnPokeballPacket.ID, SpawnPokeballPacket::decode, SpawnExtraDataEntityHandler())
this.createClientBound(ToastPacket.ID, ToastPacket::decode, ToastPacketHandler)
// Trade packets
list.add(PacketRegisterInfo(TradeAcceptanceChangedPacket.ID, TradeAcceptanceChangedPacket::decode, TradeAcceptanceChangedHandler))
list.add(PacketRegisterInfo(TradeCancelledPacket.ID, TradeCancelledPacket::decode, TradeCancelledHandler))
list.add(PacketRegisterInfo(TradeCompletedPacket.ID, TradeCompletedPacket::decode, TradeCompletedHandler))
list.add(PacketRegisterInfo(TradeUpdatedPacket.ID, TradeUpdatedPacket::decode, TradeUpdatedHandler))
list.add(PacketRegisterInfo(TradeOfferNotificationPacket.ID, TradeOfferNotificationPacket::decode, TradeOfferNotificationHandler))
list.add(PacketRegisterInfo(TradeOfferExpiredPacket.ID, TradeOfferExpiredPacket::decode, TradeOfferExpiredHandler))
list.add(PacketRegisterInfo(TradeStartedPacket.ID, TradeStartedPacket::decode, TradeStartedHandler))
this.createClientBound(TradeAcceptanceChangedPacket.ID, TradeAcceptanceChangedPacket::decode, TradeAcceptanceChangedHandler)
this.createClientBound(TradeCancelledPacket.ID, TradeCancelledPacket::decode, TradeCancelledHandler)
this.createClientBound(TradeCompletedPacket.ID, TradeCompletedPacket::decode, TradeCompletedHandler)
this.createClientBound(TradeUpdatedPacket.ID, TradeUpdatedPacket::decode, TradeUpdatedHandler)
this.createClientBound(TradeOfferNotificationPacket.ID, TradeOfferNotificationPacket::decode, TradeOfferNotificationHandler)
this.createClientBound(TradeOfferExpiredPacket.ID, TradeOfferExpiredPacket::decode, TradeOfferExpiredHandler)
this.createClientBound(TradeStartedPacket.ID, TradeStartedPacket::decode, TradeStartedHandler)
// Pasture
list.add(PacketRegisterInfo(OpenPasturePacket.ID, OpenPasturePacket::decode, OpenPastureHandler))
list.add(PacketRegisterInfo(ClosePasturePacket.ID, ClosePasturePacket::decode, ClosePastureHandler))
list.add(PacketRegisterInfo(PokemonPasturedPacket.ID, PokemonPasturedPacket::decode, PokemonPasturedHandler))
list.add(PacketRegisterInfo(PokemonUnpasturedPacket.ID, PokemonUnpasturedPacket::decode, PokemonUnpasturedHandler))
this.createClientBound(OpenPasturePacket.ID, OpenPasturePacket::decode, OpenPastureHandler)
this.createClientBound(ClosePasturePacket.ID, ClosePasturePacket::decode, ClosePastureHandler)
this.createClientBound(PokemonPasturedPacket.ID, PokemonPasturedPacket::decode, PokemonPasturedHandler)
this.createClientBound(PokemonUnpasturedPacket.ID, PokemonUnpasturedPacket::decode, PokemonUnpasturedHandler)
// Behaviours
list.add(PacketRegisterInfo(PlayPosableAnimationPacket.ID, PlayPosableAnimationPacket::decode, PlayPosableAnimationHandler))
this.createClientBound(PokemonCryPacket.ID, PokemonCryPacket::decode, PokemonCryHandler)
// Move select packets
list.add(PacketRegisterInfo(OpenMoveCallbackPacket.ID, OpenMoveCallbackPacket::decode, OpenMoveCallbackHandler))
this.createClientBound(OpenMoveCallbackPacket.ID, OpenMoveCallbackPacket::decode, OpenMoveCallbackHandler)
// Party select packets
list.add(PacketRegisterInfo(OpenPartyCallbackPacket.ID, OpenPartyCallbackPacket::decode, OpenPartyCallbackHandler))
this.createClientBound(OpenPartyCallbackPacket.ID, OpenPartyCallbackPacket::decode, OpenPartyCallbackHandler)
// Party move select packets
list.add(PacketRegisterInfo(OpenPartyMoveCallbackPacket.ID, OpenPartyMoveCallbackPacket::decode, OpenPartyMoveCallbackHandler))
// Dialogue packets
list.add(PacketRegisterInfo(DialogueClosedPacket.ID, DialogueClosedPacket::decode, DialogueClosedHandler))
list.add(PacketRegisterInfo(DialogueOpenedPacket.ID, DialogueOpenedPacket::decode, DialogueOpenedHandler))
// NPCs
list.add(PacketRegisterInfo(CloseNPCEditorPacket.ID, CloseNPCEditorPacket::decode, CloseNPCEditorHandler))
list.add(PacketRegisterInfo(OpenNPCEditorPacket.ID, OpenNPCEditorPacket::decode, OpenNPCEditorHandler))
return list
this.createClientBound(OpenPartyMoveCallbackPacket.ID, OpenPartyMoveCallbackPacket::decode, OpenPartyMoveCallbackHandler)
}
private fun generateC2SPacketInfoList(): List<PacketRegisterInfo<*>> {
val list = mutableListOf<PacketRegisterInfo<*>>()
override fun registerServerBound() {
// Pokemon Update Packets
list.add(PacketRegisterInfo(SetNicknamePacket.ID, SetNicknamePacket::decode, SetNicknameHandler))
this.createServerBound(SetNicknamePacket.ID, SetNicknamePacket::decode, SetNicknameHandler)
// Evolution Packets
list.add(PacketRegisterInfo(AcceptEvolutionPacket.ID, AcceptEvolutionPacket::decode, AcceptEvolutionHandler))
this.createServerBound(AcceptEvolutionPacket.ID, AcceptEvolutionPacket::decode, AcceptEvolutionHandler)
// Interaction Packets
list.add(PacketRegisterInfo(InteractPokemonPacket.ID, InteractPokemonPacket::decode, InteractPokemonHandler))
list.add(PacketRegisterInfo(RequestPlayerInteractionsPacket.ID, RequestPlayerInteractionsPacket::decode, RequestInteractionsHandler))
this.createServerBound(InteractPokemonPacket.ID, InteractPokemonPacket::decode, InteractPokemonHandler)
// Storage Packets
list.add(PacketRegisterInfo(SendOutPokemonPacket.ID, SendOutPokemonPacket::decode, SendOutPokemonHandler))
list.add(PacketRegisterInfo(RequestMoveSwapPacket.ID, RequestMoveSwapPacket::decode, RequestMoveSwapHandler))
list.add(PacketRegisterInfo(BenchMovePacket.ID, BenchMovePacket::decode, BenchMoveHandler))
list.add(PacketRegisterInfo(BattleChallengePacket.ID, BattleChallengePacket::decode, ChallengeHandler))
this.createServerBound(SendOutPokemonPacket.ID, SendOutPokemonPacket::decode, SendOutPokemonHandler)
this.createServerBound(RequestMoveSwapPacket.ID, RequestMoveSwapPacket::decode, RequestMoveSwapHandler)
this.createServerBound(BenchMovePacket.ID, BenchMovePacket::decode, BenchMoveHandler)
this.createServerBound(BattleChallengePacket.ID, BattleChallengePacket::decode, ChallengeHandler)
list.add(PacketRegisterInfo(MovePCPokemonToPartyPacket.ID, MovePCPokemonToPartyPacket::decode, MovePCPokemonToPartyHandler))
list.add(PacketRegisterInfo(MovePartyPokemonToPCPacket.ID, MovePartyPokemonToPCPacket::decode, MovePartyPokemonToPCHandler))
list.add(PacketRegisterInfo(ReleasePartyPokemonPacket.ID, ReleasePartyPokemonPacket::decode, ReleasePartyPokemonHandler))
list.add(PacketRegisterInfo(ReleasePCPokemonPacket.ID, ReleasePCPokemonPacket::decode, ReleasePCPokemonHandler))
list.add(PacketRegisterInfo(UnlinkPlayerFromPCPacket.ID, UnlinkPlayerFromPCPacket::decode, UnlinkPlayerFromPCHandler))
this.createServerBound(MovePCPokemonToPartyPacket.ID, MovePCPokemonToPartyPacket::decode, MovePCPokemonToPartyHandler)
this.createServerBound(MovePartyPokemonToPCPacket.ID, MovePartyPokemonToPCPacket::decode, MovePartyPokemonToPCHandler)
this.createServerBound(ReleasePartyPokemonPacket.ID, ReleasePartyPokemonPacket::decode, ReleasePartyPokemonHandler)
this.createServerBound(ReleasePCPokemonPacket.ID, ReleasePCPokemonPacket::decode, ReleasePCPokemonHandler)
this.createServerBound(UnlinkPlayerFromPCPacket.ID, UnlinkPlayerFromPCPacket::decode, UnlinkPlayerFromPCHandler)
// Starter packets
list.add(PacketRegisterInfo(SelectStarterPacket.ID, SelectStarterPacket::decode, SelectStarterPacketHandler))
list.add(PacketRegisterInfo(RequestStarterScreenPacket.ID, RequestStarterScreenPacket::decode, RequestStarterScreenHandler))
this.createServerBound(SelectStarterPacket.ID, SelectStarterPacket::decode, SelectStarterPacketHandler)
this.createServerBound(RequestStarterScreenPacket.ID, RequestStarterScreenPacket::decode, RequestStarterScreenHandler)
list.add(PacketRegisterInfo(SwapPCPokemonPacket.ID, SwapPCPokemonPacket::decode, SwapPCPokemonHandler))
list.add(PacketRegisterInfo(SwapPartyPokemonPacket.ID, SwapPartyPokemonPacket::decode, SwapPartyPokemonHandler))
this.createServerBound(SwapPCPokemonPacket.ID, SwapPCPokemonPacket::decode, SwapPCPokemonHandler)
this.createServerBound(SwapPartyPokemonPacket.ID, SwapPartyPokemonPacket::decode, SwapPartyPokemonHandler)
list.add(PacketRegisterInfo(MovePCPokemonPacket.ID, MovePCPokemonPacket::decode, MovePCPokemonHandler))
list.add(PacketRegisterInfo(MovePartyPokemonPacket.ID, MovePartyPokemonPacket::decode, MovePartyPokemonHandler))
this.createServerBound(MovePCPokemonPacket.ID, MovePCPokemonPacket::decode, MovePCPokemonHandler)
this.createServerBound(MovePartyPokemonPacket.ID, MovePartyPokemonPacket::decode, MovePartyPokemonHandler)
list.add(PacketRegisterInfo(SwapPCPartyPokemonPacket.ID, SwapPCPartyPokemonPacket::decode, SwapPCPartyPokemonHandler))
this.createServerBound(SwapPCPartyPokemonPacket.ID, SwapPCPartyPokemonPacket::decode, SwapPCPartyPokemonHandler)
// Battle packets
list.add(PacketRegisterInfo(BattleSelectActionsPacket.ID, BattleSelectActionsPacket::decode, BattleSelectActionsHandler))
list.add(PacketRegisterInfo(SpectateBattlePacket.ID, SpectateBattlePacket::decode, SpectateBattleHandler))
list.add(PacketRegisterInfo(RemoveSpectatorPacket.ID, RemoveSpectatorPacket::decode, RemoveSpectatorHandler))
this.createServerBound(BattleSelectActionsPacket.ID, BattleSelectActionsPacket::decode, BattleSelectActionsHandler)
// Trade
list.add(PacketRegisterInfo(AcceptTradeRequestPacket.ID, AcceptTradeRequestPacket::decode, AcceptTradeRequestHandler))
list.add(PacketRegisterInfo(CancelTradePacket.ID, CancelTradePacket::decode, CancelTradeHandler))
list.add(PacketRegisterInfo(ChangeTradeAcceptancePacket.ID, ChangeTradeAcceptancePacket::decode, ChangeTradeAcceptanceHandler))
list.add(PacketRegisterInfo(OfferTradePacket.ID, OfferTradePacket::decode, OfferTradeHandler))
list.add(PacketRegisterInfo(UpdateTradeOfferPacket.ID, UpdateTradeOfferPacket::decode, UpdateTradeOfferHandler))
this.createServerBound(AcceptTradeRequestPacket.ID, AcceptTradeRequestPacket::decode, AcceptTradeRequestHandler)
this.createServerBound(CancelTradePacket.ID, CancelTradePacket::decode, CancelTradeHandler)
this.createServerBound(ChangeTradeAcceptancePacket.ID, ChangeTradeAcceptancePacket::decode, ChangeTradeAcceptanceHandler)
this.createServerBound(OfferTradePacket.ID, OfferTradePacket::decode, OfferTradeHandler)
this.createServerBound(UpdateTradeOfferPacket.ID, UpdateTradeOfferPacket::decode, UpdateTradeOfferHandler)
// Pasture
list.add(PacketRegisterInfo(PasturePokemonPacket.ID, PasturePokemonPacket::decode, PasturePokemonHandler))
list.add(PacketRegisterInfo(UnpasturePokemonPacket.ID, UnpasturePokemonPacket::decode, UnpasturePokemonHandler))
list.add(PacketRegisterInfo(UnpastureAllPokemonPacket.ID, UnpastureAllPokemonPacket::decode, UnpastureAllPokemonHandler))
this.createServerBound(PasturePokemonPacket.ID, PasturePokemonPacket::decode, PasturePokemonHandler)
this.createServerBound(UnpasturePokemonPacket.ID, UnpasturePokemonPacket::decode, UnpasturePokemonHandler)
this.createServerBound(UnpastureAllPokemonPacket.ID, UnpastureAllPokemonPacket::decode, UnpastureAllPokemonHandler)
// Move select packets
list.add(PacketRegisterInfo(MoveSelectedPacket.ID, MoveSelectedPacket::decode, MoveSelectedHandler))
list.add(PacketRegisterInfo(MoveSelectCancelledPacket.ID, MoveSelectCancelledPacket::decode, MoveSelectCancelledHandler))
this.createServerBound(MoveSelectedPacket.ID, MoveSelectedPacket::decode, MoveSelectedHandler)
this.createServerBound(MoveSelectCancelledPacket.ID, MoveSelectCancelledPacket::decode, MoveSelectCancelledHandler)
// Party select packets
list.add(PacketRegisterInfo(PartyPokemonSelectedPacket.ID, PartyPokemonSelectedPacket::decode, PartyPokemonSelectedHandler))
list.add(PacketRegisterInfo(PartySelectCancelledPacket.ID, PartySelectCancelledPacket::decode, PartySelectCancelledHandler))
this.createServerBound(PartyPokemonSelectedPacket.ID, PartyPokemonSelectedPacket::decode, PartyPokemonSelectedHandler)
this.createServerBound(PartySelectCancelledPacket.ID, PartySelectCancelledPacket::decode, PartySelectCancelledHandler)
// Party move select packets
list.add(PacketRegisterInfo(PartyPokemonMoveSelectedPacket.ID, PartyPokemonMoveSelectedPacket::decode, PartyPokemonMoveSelectedHandler))
list.add(PacketRegisterInfo(PartyMoveSelectCancelledPacket.ID, PartyMoveSelectCancelledPacket::decode, PartyMoveSelectCancelledHandler))
// TM Machine packets
// convert to new format
list.add(PacketRegisterInfo(CraftTMPacket.ID, CraftTMPacket::decode, CraftTMPacketHandler))
list.add(PacketRegisterInfo(CraftBlankTMPacket.ID, CraftBlankTMPacket::decode, CraftBlankTMPacketHandler))
// Dialogue packets
list.add(PacketRegisterInfo(EscapeDialoguePacket.ID, EscapeDialoguePacket::decode, EscapeDialogueHandler))
list.add(PacketRegisterInfo(InputToDialoguePacket.ID, InputToDialoguePacket::decode, InputToDialogueHandler))
// NPC packets
list.add(PacketRegisterInfo(SaveNPCPacket.ID, SaveNPCPacket::decode, SaveNPCHandler))
return list
this.createServerBound(PartyPokemonMoveSelectedPacket.ID, PartyPokemonMoveSelectedPacket::decode, PartyPokemonMoveSelectedHandler)
this.createServerBound(PartyMoveSelectCancelledPacket.ID, PartyMoveSelectCancelledPacket::decode, PartyMoveSelectCancelledHandler)
}
fun sendPacketToPlayer(player: ServerPlayerEntity, packet: NetworkPacket<*>) = Cobblemon.implementation.networkManager.sendPacketToPlayer(player, packet)
private inline fun <reified T : NetworkPacket<T>> createClientBound(identifier: Identifier, noinline decoder: (PacketByteBuf) -> T, handler: ClientNetworkPacketHandler<T>) {
Cobblemon.implementation.networkManager.createClientBound(identifier, T::class, { message, buffer -> message.encode(buffer) }, decoder, handler)
}
private inline fun <reified T : NetworkPacket<T>> createServerBound(identifier: Identifier, noinline decoder: (PacketByteBuf) -> T, handler: ServerNetworkPacketHandler<T>) {
Cobblemon.implementation.networkManager.createServerBound(identifier, T::class, { message, buffer -> message.encode(buffer) }, decoder, handler)
}
override fun <T : NetworkPacket<T>> createClientBound(
identifier: Identifier,
kClass: KClass<T>,
encoder: (T, PacketByteBuf) -> Unit,
decoder: (PacketByteBuf) -> T,
handler: ClientNetworkPacketHandler<T>
) {
Cobblemon.implementation.networkManager.createClientBound(identifier, kClass, encoder, decoder, handler)
}
override fun <T : NetworkPacket<T>> createServerBound(
identifier: Identifier,
kClass: KClass<T>,
encoder: (T, PacketByteBuf) -> Unit,
decoder: (PacketByteBuf) -> T,
handler: ServerNetworkPacketHandler<T>
) {
Cobblemon.implementation.networkManager.createServerBound(identifier, kClass, encoder, decoder, handler)
}
override fun sendPacketToPlayer(player: ServerPlayerEntity, packet: NetworkPacket<*>) = Cobblemon.implementation.networkManager.sendPacketToPlayer(player, packet)
override fun sendPacketToServer(packet: NetworkPacket<*>) = Cobblemon.implementation.networkManager.sendPacketToServer(packet)
override fun <T : NetworkPacket<*>> asVanillaClientBound(packet: T): Packet<ClientPlayPacketListener> = Cobblemon.implementation.networkManager.asVanillaClientBound(packet)
}
@@ -1,29 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common
import com.cobblemon.mod.common.entity.sensor.BattlingPokemonSensor
import com.cobblemon.mod.common.entity.sensor.NPCBattlingSensor
import java.util.function.Supplier
import net.minecraft.entity.Entity
import net.minecraft.entity.ai.brain.sensor.Sensor
import net.minecraft.entity.ai.brain.sensor.SensorType
object CobblemonSensors {
val sensors = mutableMapOf<String, SensorType<*>>()
val NPC_BATTLING = register("npc_battling", ::NPCBattlingSensor)
val BATTLING_POKEMON = register("battling_pokemon", ::BattlingPokemonSensor)
fun <E : Entity, U : Sensor<E>> register(id: String, supplier: Supplier<U>): SensorType<U> {
val sensor = SensorType(supplier)
sensors[id] = sensor
return sensor
}
}
@@ -14,9 +14,7 @@ import net.minecraft.registry.Registries
import net.minecraft.registry.Registry
import net.minecraft.registry.RegistryKey
import net.minecraft.registry.RegistryKeys
import net.minecraft.sound.BlockSoundGroup
import net.minecraft.sound.SoundEvent
import net.minecraft.sound.SoundEvents
object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Registry<SoundEvent>>, SoundEvent>() {
@@ -56,10 +54,6 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
val POKE_BALL_SEND_OUT = this.create("poke_ball.send_out")
@JvmField
val POKE_BALL_RECALL = this.create("poke_ball.recall")
@JvmField
val POKE_BALL_THROW = this.create("poke_ball.throw")
@JvmField
val POKE_BALL_TRAIL = this.create("poke_ball.trail")
@JvmField
val ITEM_USE = this.create("item.use")
@@ -67,8 +61,6 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
val CAN_EVOLVE = this.create("pokemon.can_evolve")
@JvmField
val EVOLVING = this.create("pokemon.evolving")
@JvmField
val EVOLVE = this.create("evolution.evolve")
@JvmField
val PVN_BATTLE = this.create("battle.pvn.default")
@@ -85,304 +77,7 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
val MEDICINE_PILLS_USE = this.create("medicine_pills.use")
@JvmField
val MEDICINE_SPRAY_USE = this.create("medicine_spray.use")
@JvmField
val MEDICINE_FEATHER_USE = this.create("medicine_feather.use")
@JvmField
val BERRY_HARVEST = this.create("berry.harvest")
@JvmField
val BERRY_EAT = this.create("berry.eat")
@JvmField
val MULCH_PLACE = this.create("mulch.place")
@JvmField
val MULCH_REMOVE = this.create("mulch.remove")
@JvmField
val FOSSIL_MACHINE_ACTIVATE = this.create("fossil_machine.activate")
@JvmField
val FOSSIL_MACHINE_ACTIVE_LOOP = this.create("fossil_machine.active_loop")
@JvmField
val FOSSIL_MACHINE_ASSEMBLE = this.create("fossil_machine.assemble")
@JvmField
val FOSSIL_MACHINE_DNA_FULL = this.create("fossil_machine.dna_full")
@JvmField
val FOSSIL_MACHINE_FINISHED = this.create("fossil_machine.finished")
@JvmField
val FOSSIL_MACHINE_INSERT_DNA = this.create("fossil_machine.insert_dna")
@JvmField
val FOSSIL_MACHINE_INSERT_DNA_SMALL = this.create("fossil_machine.insert_dna_small")
@JvmField
val FOSSIL_MACHINE_INSERT_FOSSIL = this.create("fossil_machine.insert_fossil")
@JvmField
val FOSSIL_MACHINE_RETRIEVE_FOSSIL = this.create("fossil_machine.retrieve_fossil")
@JvmField
val FOSSIL_MACHINE_RETRIEVE_POKEMON = this.create("fossil_machine.retrieve_pokemon")
@JvmField
val FOSSIL_MACHINE_UNPROTECTED = this.create("fossil_machine.unprotected")
@JvmField
val RELIC_COIN_SACK_BREAK = this.create("relic_coin_sack.break")
@JvmField
val RELIC_COIN_SACK_HIT = this.create("relic_coin_sack.hit")
@JvmField
val RELIC_COIN_SACK_STEP = this.create("relic_coin_sack.step")
@JvmField
val RELIC_COIN_SACK_PLACE = this.create("relic_coin_sack.place")
@JvmField
val RELIC_COIN_POUCH_BREAK = this.create("relic_coin_pouch.break")
@JvmField
val RELIC_COIN_POUCH_PLACE = this.create("relic_coin_pouch.place")
@JvmField
val FISHING_NOTIFICATION = this.create("fishing.notification")
@JvmField
val FISHING_SPLASH_BIG = this.create("fishing.splash_big")
@JvmField
val FISHING_SPLASH_SMALL = this.create("fishing.splash_small")
@JvmField
val FISHING_BOBBER_LAND = this.create("fishing.bobber_land")
@JvmField
val FISHING_ROD_CAST = this.create("fishing.rod_cast")
@JvmField
val FISHING_ROD_REEL_IN = this.create("fishing.rod_reel_in")
@JvmField
val TUMBLESTONE_BREAK = this.create("tumblestone.break")
@JvmField
val TUMBLESTONE_BLOCK_BREAK = this.create("tumblestone.block_break")
@JvmField
val TUMBLESTONE_HIT = this.create("tumblestone.hit")
@JvmField
val TUMBLESTONE_PLACE = this.create("tumblestone.place")
@JvmField
val TUMBLESTONE_STEP = this.create("tumblestone.step")
@JvmField
val GIMMIGHOUL_GIVE_ITEM_SMALL = this.create("gimmighoul.give_item_small")
@JvmField
val GIMMIGHOUL_REVEAL = this.create("gimmighoul.reveal")
@JvmField
val BERRY_BUSH_BREAK = this.create("berry_bush.break")
@JvmField
val BERRY_BUSH_PLACE = this.create("berry_bush.place")
@JvmField
val BIG_ROOT_BREAK = this.create("big_root.break")
@JvmField
val ENERGY_ROOT_PLACE = this.create("energy_root.place")
@JvmField
val VIVICHOKE_BREAK = this.create("vivichoke.break")
@JvmField
val VIVICHOKE_PLACE = this.create("vivichoke.place")
@JvmField
val MINT_BREAK = this.create("mint.break")
@JvmField
val MINT_PLACE = this.create("mint.place")
@JvmField
val REVIVAL_HERB_BREAK = this.create("revival_herb.break")
@JvmField
val REVIVAL_HERB_PLACE = this.create("revival_herb.place")
@JvmField
val MEDICINAL_LEEK_BREAK = this.create("medicinal_leek.break")
@JvmField
val MEDICINAL_LEEK_PLACE = this.create("medicinal_leek.plant")
@JvmField
val GILDED_CHEST_OPEN = this.create("gilded_chest.open")
@JvmField
val GILDED_CHEST_CLOSE = this.create("gilded_chest.close")
@JvmField
val GILDED_CHEST_STEP = this.create("gilded_chest.step")
@JvmField
val GILDED_CHEST_HIT = this.create("gilded_chest.hit")
@JvmField
val GILDED_CHEST_BREAK = this.create("gilded_chest.break")
@JvmField
val GILDED_CHEST_PLACE = this.create("gilded_chest.place")
@JvmField
val RELIC_COIN_SACK_SOUNDS = BlockSoundGroup(1f, 1f,
RELIC_COIN_SACK_BREAK,
RELIC_COIN_SACK_STEP,
RELIC_COIN_SACK_PLACE,
RELIC_COIN_SACK_HIT,
RELIC_COIN_SACK_STEP
)
@JvmField
val RELIC_COIN_POUCH_SOUNDS = BlockSoundGroup(1f, 1f,
RELIC_COIN_POUCH_BREAK,
RELIC_COIN_SACK_STEP,
RELIC_COIN_POUCH_PLACE,
RELIC_COIN_SACK_HIT,
RELIC_COIN_SACK_STEP
)
@JvmField
val IMPACT_NORMAL = this.create("impact.normal")
@JvmField
val IMPACT_BUG = this.create("impact.bug")
@JvmField
val IMPACT_DARK = this.create("impact.dark")
@JvmField
val IMPACT_DRAGON = this.create("impact.dragon")
@JvmField
val IMPACT_ELECTRIC = this.create("impact.electric")
@JvmField
val IMPACT_FAIRY = this.create("impact.fairy")
@JvmField
val IMPACT_FIGHTING = this.create("impact.fighting")
@JvmField
val IMPACT_FIRE = this.create("impact.fire")
@JvmField
val IMPACT_FLYING = this.create("impact.flying")
@JvmField
val IMPACT_GHOST = this.create("impact.ghost")
@JvmField
val IMPACT_GRASS = this.create("impact.grass")
@JvmField
val IMPACT_GROUND = this.create("impact.ground")
@JvmField
val IMPACT_ICE = this.create("impact.ice")
@JvmField
val IMPACT_POISON = this.create("impact.poison")
@JvmField
val IMPACT_PSYCHIC = this.create("impact.psychic")
@JvmField
val IMPACT_ROCK = this.create("impact.rock")
@JvmField
val IMPACT_STEEL = this.create("impact.steel")
@JvmField
val IMPACT_WATER = this.create("impact.water")
@JvmField
val TUMBLESTONE_SOUNDS = BlockSoundGroup(1f, 1f,
TUMBLESTONE_BREAK,
TUMBLESTONE_STEP,
TUMBLESTONE_PLACE,
TUMBLESTONE_HIT,
TUMBLESTONE_STEP
)
@JvmField
val TUMBLESTONE_BLOCK_SOUNDS = BlockSoundGroup(1f, 1f,
TUMBLESTONE_BLOCK_BREAK,
TUMBLESTONE_STEP,
TUMBLESTONE_PLACE,
TUMBLESTONE_HIT,
TUMBLESTONE_STEP
)
@JvmField
val TM_USE = this.create("tm.use")
@JvmField
val TMM_CRAFT = this.create("tmm.craft")
@JvmField
val TMM_CRAFT_BLANK = this.create("tmm.craft_blank")
@JvmField
val TMM_OFF = this.create("tmm.off")
@JvmField
val TMM_ON = this.create("tmm.on")
@JvmField
val TYPE_GEM_SOUNDS = TUMBLESTONE_BLOCK_SOUNDS
@JvmField
val BERRY_BUSH_SOUNDS = BlockSoundGroup(1f, 1f,
BERRY_BUSH_BREAK,
SoundEvents.BLOCK_GRASS_STEP,
BERRY_BUSH_PLACE,
SoundEvents.BLOCK_GRASS_HIT,
SoundEvents.BLOCK_GRASS_STEP
)
@JvmField
val BIG_ROOT_SOUNDS = BlockSoundGroup(1f, 1f,
BIG_ROOT_BREAK,
SoundEvents.BLOCK_ROOTS_STEP,
SoundEvents.BLOCK_ROOTS_PLACE,
SoundEvents.BLOCK_ROOTS_HIT,
SoundEvents.BLOCK_ROOTS_FALL
)
@JvmField
val ENERGY_ROOT_SOUNDS = BlockSoundGroup(1f, 1f,
SoundEvents.BLOCK_ROOTS_BREAK,
SoundEvents.BLOCK_ROOTS_STEP,
ENERGY_ROOT_PLACE,
SoundEvents.BLOCK_ROOTS_HIT,
SoundEvents.BLOCK_ROOTS_FALL
)
@JvmField
val MEDICINAL_LEEK_SOUNDS = BlockSoundGroup(1f, 1f,
MEDICINAL_LEEK_BREAK,
SoundEvents.BLOCK_GRASS_STEP,
MEDICINAL_LEEK_PLACE,
SoundEvents.BLOCK_GRASS_HIT,
SoundEvents.BLOCK_GRASS_FALL
)
@JvmField
val VIVICHOKE_SOUNDS = BlockSoundGroup(1f, 1f,
VIVICHOKE_BREAK,
SoundEvents.BLOCK_GRASS_STEP,
VIVICHOKE_PLACE,
SoundEvents.BLOCK_GRASS_HIT,
SoundEvents.BLOCK_GRASS_FALL
)
@JvmField
val MINT_SOUNDS = BlockSoundGroup(1f, 1f,
MINT_BREAK,
SoundEvents.BLOCK_GRASS_STEP,
MINT_PLACE,
SoundEvents.BLOCK_GRASS_HIT,
SoundEvents.BLOCK_GRASS_FALL
)
@JvmField
val REVIVAL_HERB_SOUNDS = BlockSoundGroup(1f, 1f,
REVIVAL_HERB_BREAK,
SoundEvents.BLOCK_GRASS_STEP,
REVIVAL_HERB_PLACE,
SoundEvents.BLOCK_GRASS_HIT,
SoundEvents.BLOCK_GRASS_FALL
)
@JvmField
val GILDED_CHEST_SOUNDS = BlockSoundGroup(1f, 1f,
GILDED_CHEST_BREAK,
GILDED_CHEST_STEP,
GILDED_CHEST_PLACE,
GILDED_CHEST_HIT,
GILDED_CHEST_STEP
)
@JvmField
val DISPLAY_CASE_ADD_ITEM = this.create("display_case.add_item")
@JvmField
val DISPLAY_CASE_REMOVE_ITEM = this.create("display_case.remove_item")
@JvmField
val DISPLAY_CASE_BREAK = this.create("display_case.break")
@JvmField
val DISPLAY_CASE_HIT = this.create("display_case.hit")
@JvmField
val DISPLAY_CASE_PLACE = this.create("display_case.place")
@JvmField
val DISPLAY_CASE_STEP = this.create("display_case.step")
@JvmField
val DISPLAY_CASE_SOUNDS = BlockSoundGroup(1f, 1f,
DISPLAY_CASE_BREAK,
DISPLAY_CASE_STEP,
DISPLAY_CASE_PLACE,
DISPLAY_CASE_HIT,
DISPLAY_CASE_STEP
)
private fun create(name: String): SoundEvent = this.create(name, SoundEvent.of(cobblemonResource(name)))
}
@@ -32,14 +32,7 @@ object CobblemonTradeOffers {
* @return The resulting list.
*/
fun tradeOffersFor(profession: VillagerProfession): List<VillagerTradeOffer> = when (profession) {
VillagerProfession.FARMER -> listOf(
VillagerTradeOffer(VillagerProfession.FARMER, 3, listOf(TradeOffers.SellItemFactory(CobblemonItems.VIVICHOKE_SEEDS, 24, 1, 1, 6)))
)
VillagerProfession.FISHERMAN -> listOf(
VillagerTradeOffer(VillagerProfession.FISHERMAN, 5, listOf(
TradeOffers.SellItemFactory(CobblemonItems.POKEROD_SMITHING_TEMPLATE, 12, 3, 30)
))
)
VillagerProfession.FARMER -> listOf(VillagerTradeOffer(VillagerProfession.FARMER, 3, listOf(TradeOffers.SellItemFactory(CobblemonItems.VIVICHOKE_SEEDS, 32, 1, 1, 6))))
else -> emptyList()
}
@@ -49,7 +42,7 @@ object CobblemonTradeOffers {
* @return The resulting list.
*/
fun resolveWanderingTradeOffers(): List<WandererTradeOffer> = listOf(
WandererTradeOffer(false, listOf(TradeOffers.SellItemFactory(CobblemonItems.VIVICHOKE_SEEDS, 24, 1, 1, 6)))
WandererTradeOffer(false, listOf(TradeOffers.SellItemFactory(CobblemonItems.VIVICHOKE_SEEDS, 32, 1, 1, 6)))
)
/**
@@ -8,13 +8,10 @@
package com.cobblemon.mod.common.advancement
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.advancement.criterion.*
import com.cobblemon.mod.common.platform.PlatformRegistry
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.advancement.criterion.Criterion
import net.minecraft.registry.Registries
import net.minecraft.registry.Registry
import net.minecraft.registry.RegistryKey
import net.minecraft.registry.RegistryKeys
/**
* Contains all the advancement criteria in Cobblemon.
@@ -22,40 +19,58 @@ import net.minecraft.registry.RegistryKeys
* @author Licious
* @since October 26th, 2022
*/
object CobblemonCriteria : PlatformRegistry<Registry<Criterion<*>>, RegistryKey<Registry<Criterion<*>>>, Criterion<*>>(){
val PICK_STARTER = this.create("pick_starter", SimpleCriterionTrigger(PokemonCriterion.CODEC))
object CobblemonCriteria {
val PICK_STARTER = this.create(
SimpleCriterionTrigger(
cobblemonResource("pick_starter"),
PickStarterCriterionCondition::class.java
)
)
val CATCH_POKEMON = this.create(
SimpleCriterionTrigger(
cobblemonResource("catch_pokemon"),
CaughtPokemonCriterionCondition::class.java
)
)
val CATCH_SHINY_POKEMON = this.create(
SimpleCriterionTrigger(
cobblemonResource("catch_shiny_pokemon"),
SimpleCountableCriterionCondition::class.java
)
)
val EGG_HATCH = this.create(
SimpleCriterionTrigger(
cobblemonResource("eggs_hatched"),
SimpleCountableCriterionCondition::class.java
)
)
val EVOLVE_POKEMON = this.create(
SimpleCriterionTrigger(
cobblemonResource("pokemon_evolved"),
SimpleCountableCriterionCondition::class.java
)
)
val WIN_BATTLE = this.create(
SimpleCriterionTrigger(
cobblemonResource("battles_won"),
SimpleCountableCriterionCondition::class.java
)
)
val CATCH_POKEMON = this.create("catch_pokemon", SimpleCriterionTrigger(CaughtPokemonCriterion.CODEC))
val DEFEAT_POKEMON = this.create(
SimpleCriterionTrigger(
cobblemonResource("pokemon_defeated"),
SimpleCountableCriterionCondition::class.java
)
)
val CATCH_SHINY_POKEMON = this.create("catch_shiny_pokemon", SimpleCriterionTrigger(CountableCriterion.CODEC))
val COLLECT_ASPECT = this.create(
AspectCriterionTrigger(
cobblemonResource("aspects_collected"),
AspectCriterionCondition::class.java
)
)
val EGG_HATCH = this.create("eggs_hatched", SimpleCriterionTrigger(CountableCriterion.CODEC))
private fun <T : Criterion<*>> create(criteria: T): T = Cobblemon.implementation.registerCriteria(criteria)
val EVOLVE_POKEMON = this.create("pokemon_evolved", SimpleCriterionTrigger(EvolvePokemonCriterion.CODEC))
val WIN_BATTLE = this.create("battles_won", SimpleCriterionTrigger(BattleCountableCriterion.CODEC))
val DEFEAT_POKEMON = this.create("pokemon_defeated", SimpleCriterionTrigger(CountableCriterion.CODEC))
val COLLECT_ASPECT = this.create("aspects_collected", SimpleCriterionTrigger(AspectCriterion.CODEC))
val POKEMON_INTERACT = this.create("pokemon_interact", SimpleCriterionTrigger(PokemonInteractCriterion.CODEC))
val PARTY_CHECK = this.create("party", SimpleCriterionTrigger(PartyCheckCriterion.CODEC))
val LEVEL_UP = this.create("level_up", SimpleCriterionTrigger(LevelUpCriterion.CODEC))
val PASTURE_USE = this.create("pasture_use", SimpleCriterionTrigger(PokemonCriterion.CODEC))
val RESURRECT_POKEMON = this.create("resurrect_pokemon", SimpleCriterionTrigger(PokemonCriterion.CODEC))
val TRADE_POKEMON = this.create("trade_pokemon", SimpleCriterionTrigger(TradePokemonCriterion.CODEC))
val CAST_POKE_ROD = this.create("cast_poke_rod", SimpleCriterionTrigger(CastPokeRodCriterionCondition.CODEC))
// Advancement criteria for [grow_tumblestone.json]
val PLANT_TUMBLESTONE = this.create("plant_tumblestone", SimpleCriterionTrigger(PlantTumblestoneCriterion.CODEC))
override val registry = Registries.CRITERION
override val registryKey = RegistryKeys.CRITERION
}
@@ -8,61 +8,38 @@
package com.cobblemon.mod.common.advancement.criterion
import com.cobblemon.mod.common.util.cobblemonResource
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import net.minecraft.predicate.entity.LootContextPredicate
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
import net.minecraft.util.dynamic.Codecs
import java.util.Optional
class AspectCriterion(
playerCtx: Optional<LootContextPredicate>,
val pokemon: Identifier,
val aspects: List<String>
): SimpleCriterionCondition<MutableMap<Identifier, MutableSet<String>>>(playerCtx) {
open class AspectCriterionTrigger(identifier: Identifier, criterionClass: Class<AspectCriterionCondition>) : SimpleCriterionTrigger<MutableMap<Identifier, MutableSet<String>>, AspectCriterionCondition>(identifier, criterionClass) {
companion object {
val CODEC: Codec<AspectCriterion> = RecordCodecBuilder.create { it.group(
//All three of these codecs used to use Codecs.createStrictOptionalFieldCodec, that no longer exists
LootContextPredicate.CODEC.optionalFieldOf("player").forGetter(AspectCriterion::playerCtx),
Identifier.CODEC.optionalFieldOf("pokemon", cobblemonResource("pikachu")).forGetter(AspectCriterion::pokemon),
Codec.STRING.listOf().optionalFieldOf("aspects", listOf()).forGetter(AspectCriterion::aspects)
) .apply(it, ::AspectCriterion) }
}
class AspectCriterionCondition(id: Identifier, predicate: LootContextPredicate) : SimpleCriterionCondition<MutableMap<Identifier, MutableSet<String>>>(id, predicate) {
var pokemon = Identifier("cobblemon:pikachu")
var aspects = mutableListOf<String>()
override fun toJson(json: JsonObject) {
json.add("aspects", JsonArray(aspects.size).also {
aspects.forEach { aspect -> it.add(aspect) }
})
json.addProperty("pokemon", pokemon.toString())
}
override fun fromJson(json: JsonObject) {
aspects.clear()
json.getAsJsonArray("aspects").forEach { element ->
aspects.add(element.asString)
}
pokemon = json.get("pokemon").asString.asIdentifierDefaultingNamespace()
}
override fun matches(player: ServerPlayerEntity, context: MutableMap<Identifier, MutableSet<String>>): Boolean {
val caughtAspects = context.getOrDefault(pokemon, mutableSetOf())
return this.aspects.all { it in caughtAspects }
}
}
//open class AspectCriterionTrigger(identifier: Identifier, criterionClass: Class<AspectCriterionCondition>) : SimpleCriterionTrigger<MutableMap<Identifier, MutableSet<String>>, AspectCriterionCondition>(identifier, criterionClass) {
//
//}
//
//class AspectCriterionCondition(id: Identifier, predicate: LootContextPredicate) : SimpleCriterionCondition<MutableMap<Identifier, MutableSet<String>>>(id, predicate) {
// var pokemon = Identifier.of("cobblemon:pikachu")
// var aspects = mutableListOf<String>()
// override fun toJson(json: JsonObject) {
// json.add("aspects", JsonArray(aspects.size).also {
// aspects.forEach { aspect -> it.add(aspect) }
// })
// json.addProperty("pokemon", pokemon.toString())
// }
//
// override fun fromJson(json: JsonObject) {
// aspects.clear()
// json.getAsJsonArray("aspects").forEach { element ->
// aspects.add(element.asString)
// }
// pokemon = json.get("pokemon").asString.asIdentifierDefaultingNamespace()
// }
//
// override fun matches(player: ServerPlayerEntity, context: MutableMap<Identifier, MutableSet<String>>): Boolean {
// val caughtAspects = context.getOrDefault(pokemon, mutableSetOf())
// return this.aspects.all { it in caughtAspects }
// }
//
//}
}
@@ -1,114 +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.advancement.criterion
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.predicate.entity.LootContextPredicate
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.dynamic.Codecs
import java.util.Optional
open class BattleCountableContext(var battle : PokemonBattle, times : Int) : CountableContext(times)
class BattleCountableCriterion(
playerCtx: Optional<LootContextPredicate>,
val battleTypes: List<String>,
count: Int
): CountableCriterion<BattleCountableContext>(playerCtx, count) {
companion object {
val CODEC: Codec<BattleCountableCriterion> = RecordCodecBuilder.create { it.group(
LootContextPredicate.CODEC.optionalFieldOf("player").forGetter(BattleCountableCriterion::playerCtx),
Codec.STRING.listOf().optionalFieldOf("battle_types", listOf("any")).forGetter(BattleCountableCriterion::battleTypes),
Codec.INT.optionalFieldOf( "count", 0).forGetter(BattleCountableCriterion::count)
).apply(it, ::BattleCountableCriterion) }
}
override fun matches(player: ServerPlayerEntity, context: BattleCountableContext): Boolean {
var typeCheck = false
val advancementData = Cobblemon.playerData.get(player).advancementData
if (battleTypes.isEmpty() || battleTypes.contains("any")) {
typeCheck = true
}
if (battleTypes.contains("pvp")) {
typeCheck = context.battle.isPvP
context.times = advancementData.totalPvPBattleVictoryCount
}
if (battleTypes.contains("pvw")) {
typeCheck = context.battle.isPvW
context.times = advancementData.totalPvWBattleVictoryCount
}
if (battleTypes.contains("pvn")) {
typeCheck = context.battle.isPvN
context.times = advancementData.totalPvWBattleVictoryCount
}
if (battleTypes.size > 1) {
context.times = advancementData.totalBattleVictoryCount
}
return typeCheck && super.matches(player, context)
}
}
//open class BattleCountableCriterionTrigger(identifier: Identifier, criterionClass: Class<BattleCountableCriterion>) : SimpleCriterionTrigger<BattleCountableContext, BattleCountableCriterion>(identifier, criterionClass) {
//
//}
//
//class BattleCountableCriterion(id: Identifier, predicate: LootContextPredicate) : CountableCriterion<BattleCountableContext>(id, predicate) {
//
// private var battleTypes = mutableListOf("any")
//
// override fun fromJson(json: JsonObject) {
// super.fromJson(json)
// if(!json.get("battle_types").isJsonNull) {
// battleTypes.clear()
// json.get("battle_types").asJsonArray.asList().forEach() {
// battleTypes.add(it.asString)
// }
// }
// }
//
// override fun toJson(json: JsonObject) {
// super.toJson(json)
// json.add("battle_types", battleTypes.toJsonArray())
// }
//
// override fun matches(player: ServerPlayerEntity, context: BattleCountableContext): Boolean {
// var typeCheck = false
// val advancementData = Cobblemon.playerData.get(player).advancementData
// if (battleTypes.isEmpty() || battleTypes.contains("any")) {
// typeCheck = true
// }
// if (battleTypes.contains("pvp")) {
// typeCheck = context.battle.isPvP
// context.times = advancementData.totalPvPBattleVictoryCount
// }
// if (battleTypes.contains("pvw")) {
// typeCheck = context.battle.isPvW
// context.times = advancementData.totalPvWBattleVictoryCount
// }
// if (battleTypes.contains("pvn")) {
// typeCheck = context.battle.isPvN
// context.times = advancementData.totalPvWBattleVictoryCount
// }
// if (battleTypes.size > 1) {
// context.times = advancementData.totalBattleVictoryCount
// }
// return context.times >= count && typeCheck
// }
//}
@@ -1,33 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.advancement.criterion
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.PrimitiveCodec
import com.mojang.serialization.codecs.RecordCodecBuilder
import java.util.Optional
import net.minecraft.predicate.entity.EntityPredicate
import net.minecraft.predicate.entity.LootContextPredicate
import net.minecraft.server.network.ServerPlayerEntity
class CastPokeRodCriterionCondition(
playerCtx: Optional<LootContextPredicate>,
val hasBait: Boolean
): SimpleCriterionCondition<Boolean>(playerCtx) {
companion object {
val CODEC: Codec<CastPokeRodCriterionCondition> = RecordCodecBuilder.create { it.group(
EntityPredicate.LOOT_CONTEXT_PREDICATE_CODEC.optionalFieldOf("player").forGetter(CastPokeRodCriterionCondition::playerCtx),
PrimitiveCodec.BOOL.fieldOf("hasBait").forGetter(CastPokeRodCriterionCondition::hasBait)
).apply(it, ::CastPokeRodCriterionCondition) }
}
override fun matches(player: ServerPlayerEntity, context: Boolean): Boolean {
return hasBait == context
}
}
@@ -8,13 +8,10 @@
package com.cobblemon.mod.common.advancement.criterion
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.predicate.entity.EntityPredicate
import com.google.gson.JsonObject
import net.minecraft.predicate.entity.LootContextPredicate
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.dynamic.Codecs
import java.util.Optional
import net.minecraft.util.Identifier
/**
* A context that is used when you require a [CountableContext] along with some type string.
@@ -24,38 +21,19 @@ import java.util.Optional
*/
open class CountablePokemonTypeContext(times: Int, var type: String) : CountableContext(times)
class CaughtPokemonCriterion(
playerCtx: Optional<LootContextPredicate>,
val type: String,
count: Int
): CountableCriterion<CountablePokemonTypeContext>(playerCtx, count) {
class CaughtPokemonCriterionCondition(id: Identifier, predicate: LootContextPredicate) : CountableCriterionCondition<CountablePokemonTypeContext>(id, predicate) {
var type = "any"
override fun toJson(json: JsonObject) {
super.toJson(json)
json.addProperty("type", type)
}
companion object {
val CODEC: Codec<CaughtPokemonCriterion> = RecordCodecBuilder.create { it.group(
EntityPredicate.LOOT_CONTEXT_PREDICATE_CODEC.optionalFieldOf("player").forGetter(CaughtPokemonCriterion::playerCtx),
Codec.STRING.optionalFieldOf("type", "any").forGetter(CaughtPokemonCriterion::type),
Codec.INT.optionalFieldOf("count", 0).forGetter(CaughtPokemonCriterion::count)
).apply(it, ::CaughtPokemonCriterion) }
override fun fromJson(json: JsonObject) {
super.fromJson(json)
type = json.get("type")?.asString ?: "any"
}
override fun matches(player: ServerPlayerEntity, context: CountablePokemonTypeContext): Boolean {
return super.matches(player, context) && (context.type == type || type == "any")
return super.matches(player, context) && context.type == type
}
}
//class CaughtPokemonCriterionCondition(id: Identifier, predicate: LootContextPredicate) : CountableCriterionCondition<CountablePokemonTypeContext>(id, predicate) {
// var type = "any"
// override fun toJson(json: JsonObject) {
// super.toJson(json)
// json.addProperty("type", type)
// }
//
// override fun fromJson(json: JsonObject) {
// super.fromJson(json)
// type = json.get("type")?.asString ?: "any"
// }
//
// override fun matches(player: ServerPlayerEntity, context: CountablePokemonTypeContext): Boolean {
// return super.matches(player, context) && (context.type == type || type == "any")
// }
//}
}
@@ -8,69 +8,48 @@
package com.cobblemon.mod.common.advancement.criterion
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.predicate.entity.EntityPredicate
import com.google.gson.JsonObject
import net.minecraft.predicate.entity.LootContextPredicate
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.dynamic.Codecs
import java.util.Optional
import net.minecraft.util.Identifier
open class CountableContext(var times: Int)
/**
* A type of advancement criterion condition that requires some number of completions. This can be extended to add
* more conditions than just the count.
*
* @author Hiroku
* @since November 4th, 2022
*/
abstract class CountableCriterionCondition<T : CountableContext>(id: Identifier, predicate: LootContextPredicate) : SimpleCriterionCondition<T>(id, predicate) {
var count = 0
override fun fromJson(json: JsonObject) {
count = json.get("count")?.asInt ?: 0
}
open class CountableCriterion<T : CountableContext>(
playerCtx: Optional<LootContextPredicate>,
val count: Int
): SimpleCriterionCondition<T>(playerCtx) {
companion object {
val CODEC: Codec<CountableCriterion<CountableContext>> = RecordCodecBuilder.create { it.group(
EntityPredicate.LOOT_CONTEXT_PREDICATE_CODEC.optionalFieldOf("player").forGetter(CountableCriterion<CountableContext>::playerCtx),
Codec.INT.optionalFieldOf("count", 0).forGetter(CountableCriterion<CountableContext>::count)
).apply(it, ::CountableCriterion) }
override fun toJson(json: JsonObject) {
json.addProperty("count", count)
}
override fun matches(player: ServerPlayerEntity, context: T) = context.times >= count
}
///**
// * A type of advancement criterion condition that requires some number of completions. This can be extended to add
// * more conditions than just the count.
// *
// * @author Hiroku
// * @since November 4th, 2022
// */
//abstract class CountableCriterionCondition<T : CountableContext>(id: Identifier, predicate: LootContextPredicate) : SimpleCriterionCondition<T>(id, predicate) {
// var count = 0
// override fun fromJson(json: JsonObject) {
// count = json.get("count")?.asInt ?: 0
// }
//
// override fun toJson(json: JsonObject) {
// json.addProperty("count", count)
// }
//
// override fun matches(player: ServerPlayerEntity, context: T) = context.times >= count
//}
//
///**
// * A concrete subclass of [CountableCriterionCondition] so that you can have advancements that really just need the
// * count and nothing else.
// *
// * This is just a quirk of using generics like this, don't worry about it. The criterion conditions that get used must
// * not be generic typed.
// *
// * @author Hiroku
// * @since November 4th, 2022
// */
//class SimpleCountableCriterionCondition(id: Identifier, predicate: LootContextPredicate) : CountableCriterionCondition<CountableContext>(id, predicate)
//fun SimpleCriterionTrigger<CountableContext, SimpleCountableCriterionCondition>.trigger(player: ServerPlayerEntity, times: Int) = trigger(player, CountableContext(times))
//
///**
// * Some type of context that has a count associated with it, representing how many times the trigger has occurred.
// *
// * @author Hiroku
// * @since November 4th, 2022
// */
//open class CountableContext(var times: Int)
/**
* A concrete subclass of [CountableCriterionCondition] so that you can have advancements that really just need the
* count and nothing else.
*
* This is just a quirk of using generics like this, don't worry about it. The criterion conditions that get used must
* not be generic typed.
*
* @author Hiroku
* @since November 4th, 2022
*/
class SimpleCountableCriterionCondition(id: Identifier, predicate: LootContextPredicate) : CountableCriterionCondition<CountableContext>(id, predicate)
fun SimpleCriterionTrigger<CountableContext, SimpleCountableCriterionCondition>.trigger(player: ServerPlayerEntity, times: Int) = trigger(player, CountableContext(times))
/**
* Some type of context that has a count associated with it, representing how many times the trigger has occurred.
*
* @author Hiroku
* @since November 4th, 2022
*/
open class CountableContext(var times: Int)
@@ -1,65 +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.advancement.criterion
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.predicate.entity.LootContextPredicate
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
import net.minecraft.util.dynamic.Codecs
import java.util.Optional
class EvolvePokemonContext(val species : Identifier, val evolution : Identifier, times: Int) : CountableContext(times)
class EvolvePokemonCriterion(
playerCtx: Optional<LootContextPredicate>,
val species: String,
val evolution: String,
count: Int
): CountableCriterion<EvolvePokemonContext>(playerCtx, count) {
companion object {
val CODEC: Codec<EvolvePokemonCriterion> = RecordCodecBuilder.create { it.group(
LootContextPredicate.CODEC.optionalFieldOf("player").forGetter(EvolvePokemonCriterion::playerCtx),
Codec.STRING.optionalFieldOf("species", "any").forGetter(EvolvePokemonCriterion::species),
Codec.STRING.optionalFieldOf("evolution", "any").forGetter(EvolvePokemonCriterion::evolution),
Codec.INT.optionalFieldOf("count", 0).forGetter(EvolvePokemonCriterion::count)
).apply(it, ::EvolvePokemonCriterion) }
}
override fun matches(player: ServerPlayerEntity, context: EvolvePokemonContext): Boolean {
return context.times >= count && (context.species == species.asIdentifierDefaultingNamespace() || species == "any") &&
(context.evolution == evolution.asIdentifierDefaultingNamespace() || evolution == "any")
}
}
//class EvolvePokemonCriterion(id: Identifier, entity: LootContextPredicate) : CountableCriterion<EvolvePokemonContext>(id, entity) {
// var species = "any"
// var evolution = "any"
// override fun toJson(json: JsonObject) {
// super.toJson(json)
// json.addProperty("species", species)
// json.addProperty("evolution", evolution)
// }
//
// override fun fromJson(json: JsonObject) {
// super.fromJson(json)
// species = json.get("species")?.asString ?: "any"
// evolution = json.get("evolution")?.asString ?: "any"
// }
//
// override fun matches(player: ServerPlayerEntity, context: EvolvePokemonContext): Boolean {
// return context.times >= count && (context.species == species.asIdentifierDefaultingNamespace() || species == "any") &&
// (context.evolution == evolution.asIdentifierDefaultingNamespace() || evolution == "any")
// }
//}
//
//open class EvolvePokemonContext(val species : Identifier, val evolution : Identifier, times: Int) : CountableContext(times)
@@ -1,70 +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.advancement.criterion
import com.cobblemon.mod.common.pokemon.Pokemon
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.predicate.entity.EntityPredicate
import net.minecraft.predicate.entity.LootContextPredicate
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.dynamic.Codecs
import java.util.Optional
class LevelUpContext(val level: Int, val pokemon: Pokemon)
class LevelUpCriterion(
playerCtx: Optional<LootContextPredicate>,
val level: Int,
val evolved: Boolean
): SimpleCriterionCondition<LevelUpContext>(playerCtx) {
companion object {
val CODEC: Codec<LevelUpCriterion> = RecordCodecBuilder.create { it.group(
EntityPredicate.LOOT_CONTEXT_PREDICATE_CODEC.optionalFieldOf("player").forGetter(LevelUpCriterion::playerCtx),
Codec.INT.optionalFieldOf("level", 0).forGetter(LevelUpCriterion::level),
Codec.BOOL.optionalFieldOf("evolved", true).forGetter(LevelUpCriterion::evolved)
).apply(it, ::LevelUpCriterion) }
}
override fun matches(player: ServerPlayerEntity, context: LevelUpContext): Boolean {
val preEvo = context.pokemon.preEvolution == null
val hasEvolution = !context.pokemon.evolutions.none()
var evolutionCheck = true
if (preEvo || hasEvolution) {
evolutionCheck = preEvo != hasEvolution
}
return level == context.level && evolutionCheck == evolved
}
}
/*class LevelUpCriterionCondition(id: Identifier, entity: LootContextPredicate) : SimpleCriterionCondition<LevelUpContext>(id, entity) {
var level = 0
var evolved = true
override fun toJson(json: JsonObject) {
json.addProperty("level", level)
json.addProperty("has_evolved", evolved)
}
override fun fromJson(json: JsonObject) {
level = json.get("level")?.asInt ?: 0
evolved = json.get("has_evolved")?.asBoolean ?: true
}
override fun matches(player: ServerPlayerEntity, context: LevelUpContext): Boolean {
val preEvo = context.pokemon.preEvolution == null
val hasEvolution = !context.pokemon.evolutions.none()
var evolutionCheck = true
if (preEvo || hasEvolution) {
evolutionCheck = !(preEvo == hasEvolution)
}
return level == context.level && evolutionCheck == evolved
}
}*/
@@ -1,102 +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.advancement.criterion
import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.predicate.entity.EntityPredicate
import net.minecraft.predicate.entity.LootContextPredicate
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
import net.minecraft.util.dynamic.Codecs
import java.util.Optional
class PartyCheckCriterion(
playerCtx: Optional<LootContextPredicate>,
val party: List<Identifier>,
): SimpleCriterionCondition<PlayerPartyStore>(playerCtx) {
companion object {
val CODEC: Codec<PartyCheckCriterion> = RecordCodecBuilder.create { it.group(
EntityPredicate.LOOT_CONTEXT_PREDICATE_CODEC.optionalFieldOf("player").forGetter(PartyCheckCriterion::playerCtx),
Identifier.CODEC.listOf().optionalFieldOf("id", listOf()).forGetter(PartyCheckCriterion::party)
).apply(it, ::PartyCheckCriterion) }
}
override fun matches(player: ServerPlayerEntity, context: PlayerPartyStore): Boolean {
val matches = mutableListOf<Identifier>()
party.forEach {
if (it == "any".asIdentifierDefaultingNamespace()) {
matches.add(it)
}
}
val partyCount = context.count()
if (matches.containsAll(party) && party.size == partyCount && matches.size == partyCount) return true
context.iterator().forEach {
if (party.contains(it.species.resourceIdentifier)) {
matches.add(it.species.resourceIdentifier)
}
}
return matches.containsAll(party) && matches.size == partyCount
}
}
/*class PartyCheckCriterion(id: Identifier, entity: LootContextPredicate) : SimpleCriterionCondition<PartyCheckContext>(id, entity){
val party = mutableListOf<Identifier>()
override fun toJson(json: JsonObject) {
json.add("party", JsonArray(party.size).also {
party.forEach { pokemon -> it.add(pokemon.toString()) }
})
}
override fun fromJson(json: JsonObject) {
party.clear()
json.getAsJsonArray("party").forEach { element ->
party.add(element.asString.asIdentifierDefaultingNamespace())
}
}
override fun matches(player: ServerPlayerEntity, context: PartyCheckContext): Boolean {
val playerParty = player.party()
val matches = mutableListOf<Identifier>()
party.forEach {
if (it == "any".asIdentifierDefaultingNamespace()) {
matches.add(it)
}
}
val partyCount = playerParty.count()
if (matches.containsAll(party) && party.size == partyCount && matches.size == partyCount) return true
playerParty.iterator().forEach {
if (party.contains(it.species.resourceIdentifier)) {
matches.add(it.species.resourceIdentifier)
}
}
return matches.containsAll(party) && matches.size == partyCount
}
}
open class PartyCheckContext(val party : PlayerPartyStore)*/
@@ -10,27 +10,26 @@ package com.cobblemon.mod.common.advancement.criterion
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.pokemon.Pokemon
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.predicate.entity.EntityPredicate
import com.google.gson.JsonObject
import net.minecraft.predicate.entity.LootContextPredicate
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.dynamic.Codecs
import java.util.Optional
import net.minecraft.util.Identifier
class PokemonCriterion(
playerCtx: Optional<LootContextPredicate>,
val properties: PokemonProperties
): SimpleCriterionCondition<Pokemon>(playerCtx) {
companion object {
val CODEC: Codec<PokemonCriterion> = RecordCodecBuilder.create { it.group(
EntityPredicate.LOOT_CONTEXT_PREDICATE_CODEC.optionalFieldOf("player").forGetter(PokemonCriterion::playerCtx),
PokemonProperties.CODEC.optionalFieldOf("properties", PokemonProperties()).forGetter(PokemonCriterion::properties)
).apply(it, ::PokemonCriterion) }
/**
* A criteria that is triggered when a player picks a starter.
*
* @author Licious, Hiroku
* @since October 26th, 2022
*/
class PickStarterCriterionCondition(id: Identifier, predicate: LootContextPredicate) : SimpleCriterionCondition<Pokemon>(id, predicate) {
var properties = PokemonProperties()
override fun toJson(json: JsonObject) {
json.addProperty("properties", properties.originalString)
}
override fun matches(player: ServerPlayerEntity, context: Pokemon): Boolean {
return properties.matches(context)
override fun fromJson(json: JsonObject) {
properties = PokemonProperties.parse(json.get("properties")?.asString ?: "")
}
override fun matches(player: ServerPlayerEntity, context: Pokemon) = properties.matches(context)
}
@@ -1,71 +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.advancement.criterion
import com.cobblemon.mod.common.block.TumblestoneBlock
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.predicate.entity.LootContextPredicate
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.dynamic.Codecs
import net.minecraft.util.math.BlockPos
import java.util.Optional
class PlantTumblestoneContext(val pos: BlockPos, val block: TumblestoneBlock)
class PlantTumblestoneCriterion(
playerCtx: Optional<LootContextPredicate>
): SimpleCriterionCondition<PlantTumblestoneContext>(playerCtx) {
companion object {
val CODEC: Codec<PlantTumblestoneCriterion> = RecordCodecBuilder.create { it.group(
LootContextPredicate.CODEC.optionalFieldOf("player").forGetter(PlantTumblestoneCriterion::playerCtx)
).apply(it, ::PlantTumblestoneCriterion) }
}
override fun matches(player: ServerPlayerEntity, context: PlantTumblestoneContext): Boolean {
return context.block.canGrow(context.pos, player.world)
}
}
///**
// * A criterion condition for when a tumblestone block is planted
// * @param id The identifier of the criterion
// * @param predicate The predicate for the criterion
// *
// * @author Aethen
// * @since 02/28/2024
// */
//class PlantTumblestoneCriterionCondition(id: Identifier, predicate: LootContextPredicate) :
// SimpleCriterionCondition<PlantTumblestoneContext>(id, predicate) {
// override fun toJson(json: JsonObject) {
// // Add properties to json if needed. None needed for this criterion
// }
//
// override fun fromJson(json: JsonObject) {
// // Parse properties from json if needed. None needed for this criterion
// }
//
// /**
// * Checks if the tumblestone block can grow at the given position
// * @param player The player that planted the tumblestone block
// * @param context The context of the criterion
// * @return True if the tumblestone block can grow at the given position, false otherwise
// */
// override fun matches(player: ServerPlayerEntity, context: PlantTumblestoneContext): Boolean {
// return context.tumbleStoneBlock.canGrow(context.pos, player.world)
// }
//}
//
///**
// * The context of the [PlantTumblestoneCriterionCondition]
// * @param pos The position of the tumblestone block
// * @param tumbleStoneBlock The tumblestone block
// */
//open class PlantTumblestoneContext(var pos: BlockPos, var tumbleStoneBlock: TumblestoneBlock)
@@ -1,41 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.advancement.criterion
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.predicate.entity.EntityPredicate
import net.minecraft.predicate.entity.LootContextPredicate
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
import net.minecraft.util.dynamic.Codecs
import java.util.Optional
class PokemonInteractContext(val type: Identifier, val item: Identifier)
class PokemonInteractCriterion(
playerCtx: Optional<LootContextPredicate>,
val type: Optional<String>,
val item: Optional<String>
): SimpleCriterionCondition<PokemonInteractContext>(playerCtx) {
companion object {
val CODEC: Codec<PokemonInteractCriterion> = RecordCodecBuilder.create { it.group(
EntityPredicate.LOOT_CONTEXT_PREDICATE_CODEC.optionalFieldOf("player").forGetter(PokemonInteractCriterion::playerCtx),
Codec.STRING.optionalFieldOf("type").forGetter(PokemonInteractCriterion::type),
Codec.STRING.optionalFieldOf("item").forGetter(PokemonInteractCriterion::item)
).apply(it, ::PokemonInteractCriterion) }
}
override fun matches(player: ServerPlayerEntity, context: PokemonInteractContext): Boolean {
val otherType = this.type.orElse("any")
val otherItem = this.item.orElse("any")
return (context.type == otherType.asIdentifierDefaultingNamespace() || otherType == "any") && (context.type == otherItem.asIdentifierDefaultingNamespace() || otherItem == "any")
}
}
@@ -8,28 +8,61 @@
package com.cobblemon.mod.common.advancement.criterion
import com.mojang.serialization.Codec
import com.google.gson.JsonObject
import net.minecraft.advancement.criterion.AbstractCriterion
import net.minecraft.advancement.criterion.AbstractCriterionConditions
import net.minecraft.predicate.entity.AdvancementEntityPredicateDeserializer
import net.minecraft.predicate.entity.AdvancementEntityPredicateSerializer
import net.minecraft.predicate.entity.LootContextPredicate
import net.minecraft.server.network.ServerPlayerEntity
import java.util.Optional
import net.minecraft.util.Identifier
class SimpleCriterionTrigger<T, C : SimpleCriterionCondition<T>>(
val codec: Codec<C>,
/**
* A wrapping around the AbstractCriterion system of Minecraft. This allows the same base class to be used
* for all advancements by wrapping the advancement-specific contextual data in the generic T, the instance of
* the advancement conditions in the generic C, and allowing the condition to do all serialization, deserialization,
* and matching of context against conditions.
*
* @author Hiroku
* @since November 4th, 2022
*/
open class SimpleCriterionTrigger<T, C : SimpleCriterionCondition<T>>(
val _id: Identifier,
val criterionClass: Class<C>
) : AbstractCriterion<C>() {
override fun getConditionsCodec() = codec
fun trigger(player: ServerPlayerEntity, context: T) {
return this.trigger(player) {
it.matches(player, context)
}
override fun getId() = _id
override fun conditionsFromJson(
obj: JsonObject,
playerPredicate: LootContextPredicate,
predicateDeserializer: AdvancementEntityPredicateDeserializer
): C {
val instance = criterionClass.getConstructor(Identifier::class.java, LootContextPredicate::class.java).newInstance(id, playerPredicate)
instance.fromJson(obj)
return instance
}
fun trigger(player: ServerPlayerEntity, context: T) = this.trigger(player) { it.matches(player, context) }
}
/**
* The base of the conditions for Cobblemon's wrapping around Minecraft advancements. This is parameterized by whatever
* contextual information this condition needs to be checked, and must handle serialization and deserialization from JSON.
*
* @author Hiroku
* @since November 4th, 2022
*/
abstract class SimpleCriterionCondition<T>(
val playerCtx: Optional<LootContextPredicate>
) : AbstractCriterion.Conditions {
override fun player() = playerCtx
id: Identifier,
playerPredicate: LootContextPredicate
): AbstractCriterionConditions(id, playerPredicate) {
override fun toJson(predicateSerializer: AdvancementEntityPredicateSerializer): JsonObject {
val json = super.toJson(predicateSerializer)
toJson(json)
return json
}
abstract fun toJson(json: JsonObject)
abstract fun fromJson(json: JsonObject)
abstract fun matches(player: ServerPlayerEntity, context: T): Boolean
}
@@ -1,94 +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.advancement.criterion
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.predicate.entity.EntityPredicate
import net.minecraft.predicate.entity.LootContextPredicate
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.dynamic.Codecs
import java.util.Optional
class TradePokemonContext(val traded: Pokemon, val received: Pokemon)
class TradePokemonCriterion(
playerCtx: Optional<LootContextPredicate>,
val traded: String,
val received: String,
val tradedHeldItem: String,
val receivedHeldItem: String
): SimpleCriterionCondition<TradePokemonContext>(playerCtx) {
companion object {
val CODEC: Codec<TradePokemonCriterion> = RecordCodecBuilder.create { it.group(
EntityPredicate.LOOT_CONTEXT_PREDICATE_CODEC.optionalFieldOf("player").forGetter(TradePokemonCriterion::playerCtx),
Codec.STRING.optionalFieldOf("traded", "any").forGetter(TradePokemonCriterion::traded),
Codec.STRING.optionalFieldOf("received", "any").forGetter(TradePokemonCriterion::received),
Codec.STRING.optionalFieldOf("traded_held_item", "minecraft:air").forGetter(TradePokemonCriterion::tradedHeldItem),
Codec.STRING.optionalFieldOf("received_held_item", "minecraft:air").forGetter(TradePokemonCriterion::receivedHeldItem)
).apply(it, ::TradePokemonCriterion) }
}
override fun matches(player: ServerPlayerEntity, context: TradePokemonContext): Boolean {
val heldItem1 = context.traded.heldItem().item.registryEntry.registryKey().value
val heldItem2 = context.received.heldItem().item.registryEntry.registryKey().value
if (traded != "any" && context.traded.species.resourceIdentifier != traded.asIdentifierDefaultingNamespace()) {
return false
}
if (received != "any" && context.received.species.resourceIdentifier != received.asIdentifierDefaultingNamespace()) {
return false
}
if (heldItem1 != tradedHeldItem.asIdentifierDefaultingNamespace() && heldItem1 != "minecraft:air".asIdentifierDefaultingNamespace()) {
return false
}
if (heldItem2 != receivedHeldItem.asIdentifierDefaultingNamespace() && heldItem2 != "minecraft:air".asIdentifierDefaultingNamespace()) {
return false
}
return true
}
}
/*class TradePokemonCriterionCondition(id: Identifier, entity: LootContextPredicate) : SimpleCriterionCondition<TradePokemonContext>(id, entity) {
var traded = "any"
var received = "any"
var tradedHeldItem = "any"
var receivedHeldItem = "any"
override fun toJson(json: JsonObject) {
json.addProperty("traded", traded)
json.addProperty("received", received)
json.addProperty("traded_held_item", tradedHeldItem)
json.addProperty("received_held_item", receivedHeldItem)
}
override fun fromJson(json: JsonObject) {
traded = json.get("traded")?.asString ?: "any"
received = json.get("received")?.asString ?: "any"
tradedHeldItem = json.get("traded_held_item")?.asString ?: "minecraft:air"
receivedHeldItem = json.get("received_held_item")?.asString ?: "minecraft:air"
}
override fun matches(player: ServerPlayerEntity, context: TradePokemonContext): Boolean {
val heldItem1 = context.traded.heldItem().item.registryEntry.registryKey().value
val heldItem2 = context.received.heldItem().item.registryEntry.registryKey().value
return (context.traded.species.resourceIdentifier == traded.asIdentifierDefaultingNamespace() || traded == "any") &&
(context.received.species.resourceIdentifier == received.asIdentifierDefaultingNamespace() || received == "any") &&
(heldItem1 == tradedHeldItem.asIdentifierDefaultingNamespace() || heldItem1 == "minecraft:air".asIdentifierDefaultingNamespace()) &&
(heldItem2 == receivedHeldItem.asIdentifierDefaultingNamespace() || heldItem2 == "minecraft:air".asIdentifierDefaultingNamespace())
}
}
open class TradePokemonContext(val traded: Pokemon, val received: Pokemon)*/
@@ -9,7 +9,6 @@
package com.cobblemon.mod.common.api.abilities
import com.cobblemon.mod.common.api.Priority
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.DataKeys
import com.google.gson.JsonObject
import net.minecraft.nbt.NbtCompound
@@ -22,7 +21,7 @@ import net.minecraft.nbt.NbtCompound
* @author Qu
* @since January 9th, 2022
*/
open class Ability internal constructor(var template: AbilityTemplate, forced: Boolean) {
open class Ability internal constructor(var template: AbilityTemplate, var forced: Boolean) {
val name: String
get() = template.name
@@ -35,26 +34,16 @@ open class Ability internal constructor(var template: AbilityTemplate, forced: B
/**
* This represents the last known index of this backing ability in the species data.
* @see [Pokemon.updateAbility].
*/
var forced: Boolean = forced
internal set
/**
* This represents the last known index of this backing ability in the species data.
*
* @see [Pokemon.updateAbility].
* If -1 the ability will attempt to find the correct index or reroll itself, this is done in order to be compatible with existing data
* The value can be mutated however this is not recommended by API users.
*/
var index: Int = -1
internal set
/**
* The last known priority of this ability in the species data.
*
* @see [Pokemon.updateAbility].
* The value can be mutated however this is not recommended by API users.
*/
var priority = Priority.LOWEST
internal set
open fun saveToNBT(nbt: NbtCompound): NbtCompound {
nbt.putString(DataKeys.POKEMON_ABILITY_NAME, name)
@@ -73,23 +62,19 @@ open class Ability internal constructor(var template: AbilityTemplate, forced: B
}
open fun loadFromNBT(nbt: NbtCompound): Ability {
this.template = Abilities.getOrException(nbt.getString(DataKeys.POKEMON_ABILITY_NAME))
this.forced = nbt.getBoolean(DataKeys.POKEMON_ABILITY_FORCED)
forced = nbt.getBoolean(DataKeys.POKEMON_ABILITY_FORCED)
if (nbt.contains(DataKeys.POKEMON_ABILITY_INDEX) && nbt.contains(DataKeys.POKEMON_ABILITY_PRIORITY)) {
this.index = nbt.getInt(DataKeys.POKEMON_ABILITY_INDEX)
this.priority = Priority.valueOf(nbt.getString(DataKeys.POKEMON_ABILITY_PRIORITY))
}
return this
}
open fun loadFromJSON(json: JsonObject): Ability {
this.template = Abilities.getOrException(json.get(DataKeys.POKEMON_ABILITY_NAME).asString)
this.forced = json.get(DataKeys.POKEMON_ABILITY_FORCED)?.asBoolean ?: false
forced = json.get(DataKeys.POKEMON_ABILITY_FORCED)?.asBoolean ?: false
if (json.has(DataKeys.POKEMON_ABILITY_INDEX) && json.has(DataKeys.POKEMON_ABILITY_PRIORITY)) {
this.index = json.get(DataKeys.POKEMON_ABILITY_INDEX).asInt
this.priority = Priority.valueOf(json.get(DataKeys.POKEMON_ABILITY_PRIORITY).asString)
}
return this
}
}
@@ -28,6 +28,7 @@ class AbilityTemplate(
*/
fun create(forced: Boolean = false) = builder(this, forced)
/**
* Returns the Ability and loads the given NBT Tag into it.
*
@@ -41,5 +42,4 @@ class AbilityTemplate(
* Ability extensions need to write and read their needed data from here.
*/
fun create(json: JsonObject) = create().loadFromJSON(json)
}
@@ -35,7 +35,7 @@ interface SleepDepth {
override fun shouldWake(pokemonEntity: PokemonEntity): Boolean {
val nearbyPlayers = pokemonEntity.world.getPlayers(TargetPredicate.createNonAttackable(), pokemonEntity, Box.of(pokemonEntity.pos, 16.0, 16.0, 16.0))
return nearbyPlayers.any { !it.isSneaking }
return nearbyPlayers.none { !it.isSneaking }
}
}
@@ -13,13 +13,8 @@ import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.block.ApricornBlock
import com.cobblemon.mod.common.block.ApricornSaplingBlock
import com.cobblemon.mod.common.item.ApricornItem
import com.cobblemon.mod.common.world.feature.CobblemonConfiguredFeatures
import com.mojang.serialization.Codec
import net.minecraft.block.MapColor
import net.minecraft.item.BlockItem
import net.minecraft.registry.RegistryKey
import net.minecraft.util.StringIdentifiable
import net.minecraft.world.gen.feature.ConfiguredFeature
/**
* Contains the different Apricorn variants and util methods to get their item, block, seedling and sapling form.
@@ -27,7 +22,7 @@ import net.minecraft.world.gen.feature.ConfiguredFeature
* @author Licious
* @since October 29th, 2022
*/
enum class Apricorn : StringIdentifiable {
enum class Apricorn {
BLACK,
BLUE,
@@ -87,20 +82,4 @@ enum class Apricorn : StringIdentifiable {
YELLOW -> MapColor.YELLOW
}
fun configuredFeature(): RegistryKey<ConfiguredFeature<*, *>> = when(this) {
BLACK -> CobblemonConfiguredFeatures.BLACK_APRICORN_TREE_KEY
BLUE -> CobblemonConfiguredFeatures.BLUE_APRICORN_TREE_KEY
GREEN -> CobblemonConfiguredFeatures.GREEN_APRICORN_TREE_KEY
PINK -> CobblemonConfiguredFeatures.PINK_APRICORN_TREE_KEY
RED -> CobblemonConfiguredFeatures.RED_APRICORN_TREE_KEY
WHITE -> CobblemonConfiguredFeatures.WHITE_APRICORN_TREE_KEY
YELLOW -> CobblemonConfiguredFeatures.YELLOW_APRICORN_TREE_KEY
}
override fun asString() = this.name.lowercase()
companion object {
val CODEC: Codec<Apricorn> = StringIdentifiable.createBasicCodec(::values)
}
}
@@ -10,8 +10,6 @@ package com.cobblemon.mod.common.api.battles.interpreter
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
import com.cobblemon.mod.common.api.moves.MoveTemplate
import com.cobblemon.mod.common.api.moves.Moves
import com.cobblemon.mod.common.battles.ActiveBattlePokemon
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import java.util.UUID
@@ -135,31 +133,28 @@ class BattleMessage(rawMessage: String) {
return this.actorAndActivePokemon(pnx, battle)
}
/**
* Queries an argument at the given [index] for a 'pnx' and uuid that will be parsed into a [BattlePokemon].
*
* @param index The index of the argument referencing the [BattlePokemon].
* @param battle The [PokemonBattle] being queried.
* @return The [BattlePokemon] if the argument exists and is successfully parsed; otherwise null.
/*
Example:
|-curestatus|p1: a8e5710e-6835-4387-99d3-331b45f848e6|slp|[msg]
|-curestatus|p1: 0686b20d-3019-4167-92e2-786834245743|slp|[msg]
// Function used to grab BattlePokemon (As we need to be able to grab non active pokemon to cure their status)
// by using playerNumber(actorID) and pokemon uuid(pokemonID)
*/
fun battlePokemon(index: Int, battle: PokemonBattle): BattlePokemon? {
val (actorID, pokemonID) = this.pnxAndUuid(index) ?: return null
return this.battlePokemon(actorID, pokemonID, battle)
fun getBattlePokemon(index: Int, battle: PokemonBattle): BattlePokemon? {
val actorAndPokemonID = this.argumentAt(index)?.takeIf { it.length >= 2 }?.split(": ") ?: return null
if (actorAndPokemonID.count() < 2) return null
val actorID = actorAndPokemonID[0]
val pokemonID = actorAndPokemonID[1]
return this.getBattlePokemon(actorID, pokemonID, battle)
}
/**
* Queries an optional argument identified by [optionalArg] for a 'pnx' and uuid that will be parsed into a [BattlePokemon].
*
* @param optionalArg The id of the optional argument referencing the [BattlePokemon].
* @param battle The [PokemonBattle] being queried.
* @return The [BattlePokemon] if the argument exists and is successfully parsed; otherwise null.
*/
fun battlePokemonFromOptional(battle: PokemonBattle, optionalArg: String = "of"): BattlePokemon? {
val optional = this.optionalArguments.get(optionalArg) ?: return null
val pokemonID = optional.takeIf { it.length >= 2 }?.split(":")?.takeIf { it.size == 2 } ?: return null
val pnx = pokemonID[0].takeIf { it.matches(PNX_MATCHER) || it.matches(PN_MATCHER) } ?: return null
val uuid = pokemonID[1].trim()
return this.battlePokemon(pnx, uuid, battle)
fun getSourceBattlePokemon(battle: PokemonBattle): BattlePokemon? {
val sourcePokemonArgument = this.optionalArguments.get("of") ?: return null
val actorAndPokemonID = sourcePokemonArgument.takeIf { it.length >= 2 }?.split(": ") ?: return null
if (actorAndPokemonID.count() < 2) return null
val actorID = actorAndPokemonID[0]
val pokemonID = actorAndPokemonID[1]
return this.getBattlePokemon(actorID, pokemonID, battle)
}
/**
@@ -170,7 +165,7 @@ class BattleMessage(rawMessage: String) {
*/
fun pnxAndUuid(index: Int): Pair<String, String>? {
val argument = this.argumentAt(index)?.takeIf { it.length >= 2 }?.split(":")?.takeIf { it.size == 2 } ?: return null
val pnx = argument[0].takeIf { it.matches(PNX_MATCHER) || it.matches(PN_MATCHER) } ?: return null
val pnx = argument[0].takeIf { it.matches(PNX_MATCHER) } ?: return null
val uuid = argument[1].trim()
return pnx to uuid
}
@@ -199,11 +194,6 @@ class BattleMessage(rawMessage: String) {
return Effect.parse(data)
}
fun moveAt(index: Int): MoveTemplate? {
val argument = argumentAt(index)?.lowercase()?.replace("[^a-z0-9]".toRegex(), "") ?: return null
return Moves.getByName(argument)
}
/**
* Queries an optional argument with given [argumentName] for a 'pnx' that will be parsed into a [BattleActor] and [ActiveBattlePokemon].
*
@@ -237,7 +227,7 @@ class BattleMessage(rawMessage: String) {
null
}
private fun battlePokemon(pnx: String, pokemonID: String, battle: PokemonBattle): BattlePokemon? = try {
private fun getBattlePokemon(pnx: String, pokemonID: String, battle: PokemonBattle): BattlePokemon? = try {
battle.getBattlePokemon(pnx, pokemonID)
} catch (_: Exception) {
null
@@ -8,9 +8,6 @@
package com.cobblemon.mod.common.api.battles.model
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.Cobblemon.LOGGER
import com.cobblemon.mod.common.CobblemonNetwork
@@ -21,7 +18,6 @@ import com.cobblemon.mod.common.api.battles.model.actor.EntityBackedBattleActor
import com.cobblemon.mod.common.api.battles.model.actor.FleeableBattleActor
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.battles.BattleFledEvent
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.api.text.red
@@ -31,7 +27,6 @@ import com.cobblemon.mod.common.battles.BattleCaptureAction
import com.cobblemon.mod.common.battles.BattleFormat
import com.cobblemon.mod.common.battles.BattleRegistry
import com.cobblemon.mod.common.battles.BattleSide
import com.cobblemon.mod.common.battles.ForfeitActionResponse
import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
import com.cobblemon.mod.common.battles.dispatch.BattleDispatch
import com.cobblemon.mod.common.battles.dispatch.DispatchResult
@@ -39,21 +34,22 @@ import com.cobblemon.mod.common.battles.dispatch.GO
import com.cobblemon.mod.common.battles.dispatch.WaitDispatch
import com.cobblemon.mod.common.battles.interpreter.ContextManager
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.battles.runner.ShowdownService
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.battles.runner.ShowdownService
import com.cobblemon.mod.common.net.messages.client.battle.BattleEndPacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleMessagePacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleMusicPacket
import com.cobblemon.mod.common.pokemon.evolution.progress.DefeatEvolutionProgress
import com.cobblemon.mod.common.pokemon.evolution.progress.LastBattleCriticalHitsEvolutionProgress
import com.cobblemon.mod.common.pokemon.evolution.requirements.DefeatRequirement
import com.cobblemon.mod.common.util.battleLang
import com.cobblemon.mod.common.util.getPlayer
import java.io.File
import net.minecraft.entity.Entity
import java.util.UUID
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ConcurrentLinkedDeque
import net.minecraft.server.network.ServerPlayerEntity
import java.util.concurrent.ConcurrentLinkedQueue
import net.minecraft.text.Text
import java.io.File
import kotlin.io.path.Path
import kotlin.io.path.writeLines
import net.minecraft.server.network.ServerPlayerEntity
/**
* Individual battle instance
@@ -61,28 +57,20 @@ import net.minecraft.text.Text
* @since January 16th, 2022
* @author Deltric, Hiroku
*/
@Suppress("unused", "MemberVisibilityCanBePrivate")
open class PokemonBattle(
val format: BattleFormat,
val side1: BattleSide,
val side2: BattleSide
) {
/** Whether logging will be silenced for this battle. */
/** Whether or not logging will be silenced for this battle. */
var mute = true
val struct = this.asMoLangValue()
val runtime = MoLangRuntime().also { it.environment.query = struct }
val onEndHandlers: MutableList<(PokemonBattle) -> Unit> = mutableListOf()
init {
side1.battle = this
side2.battle = this
this.actors.forEach { actor ->
actor.battle = this
actor.pokemonList.forEach { battlePokemon ->
battlePokemon.effectedPokemon.evolutionProxy.current().progress()
.filterIsInstance<LastBattleCriticalHitsEvolutionProgress>()
.forEach { it.reset() }
battlePokemon.criticalHits = 0
}
}
}
@@ -96,30 +84,22 @@ open class PokemonBattle(
val playerUUIDs: Iterable<UUID>
get() = actors.flatMap { it.getPlayerUUIDs() }
val players = playerUUIDs.mapNotNull { it.getPlayer() }
val spectators = mutableSetOf<UUID>()
val spectators = mutableListOf<UUID>()
val battleId = UUID.randomUUID()
val showdownMessages = mutableListOf<String>()
val battleLog = mutableListOf<String>()
val chatLog = mutableListOf<Text>()
var started = false
var winners = listOf<BattleActor>()
var losers = listOf<BattleActor>()
var ended = false
// TEMP battle showcase stuff
var announcingRules = false
var turn: Int = 1
private set
private var ticks: Int = 0
set(value) { field = value.coerceAtMost(Int.MAX_VALUE) } // go outside
/** The current duration of the battle in seconds. */
val time: Int get() = ticks % 20
var dispatchResult = GO
val dispatches = ConcurrentLinkedDeque<BattleDispatch>()
val dispatches = ConcurrentLinkedQueue<BattleDispatch>()
val afterDispatches = mutableListOf<() -> Unit>()
val captureActions = mutableListOf<BattleCaptureAction>()
@@ -176,7 +156,7 @@ open class PokemonBattle(
fun getActor(player: ServerPlayerEntity) = actors.firstOrNull { it.isForPlayer(player) }
/**
* Gets a [BattleActor] and an [ActiveBattlePokemon] from a pnx key, e.g. p2a
* Gets a BattleActor and an [ActiveBattlePokemon] from a pnx key, e.g. p2a
*
* Returns null if either the pn or x is invalid.
*/
@@ -189,11 +169,6 @@ open class PokemonBattle(
return actor to pokemon
}
/**
* Gets a [BattlePokemon] from a pnx key and uuid.
*
* Returns null if the pnx key is invalid or the uuid does not exist.
*/
fun getBattlePokemon(pnx: String, pokemonID: String): BattlePokemon {
val actor = actors.find { it.showdownId == pnx.substring(0, 2) }
?: throw IllegalStateException("Invalid pnx: $pnx - unknown actor")
@@ -202,8 +177,11 @@ open class PokemonBattle(
}
fun broadcastChatMessage(component: Text) {
chatLog.add(component)
sendSpectatorUpdate(BattleMessagePacket(component))
spectators.forEach { spectatorId ->
spectatorId.getPlayer()?.let {
CobblemonNetwork.sendPacketToPlayer(it, BattleMessagePacket(component))
}
}
return actors.forEach { it.sendMessage(component) }
}
@@ -233,16 +211,11 @@ open class PokemonBattle(
faintedPokemons.forEach { faintedPokemon ->
for (opponentPokemon in opponentNonFaintedPokemons) {
val facedFainted = opponentPokemon.facedOpponents.contains(faintedPokemon)
val defeatProgress = DefeatEvolutionProgress()
val pokemon = opponentPokemon.effectedPokemon
if (facedFainted) {
pokemon.lockedEvolutions.forEach { evolution ->
evolution.requirements.filterIsInstance<DefeatRequirement>().forEach { defeatRequirement ->
if (defeatRequirement.target.matches(faintedPokemon.effectedPokemon)) {
val progress = pokemon.evolutionProxy.current().progressFirstOrCreate({ it is DefeatEvolutionProgress && it.currentProgress().target == defeatRequirement.target }) { DefeatEvolutionProgress() }
progress.updateProgress(DefeatEvolutionProgress.Progress(defeatRequirement.target, progress.currentProgress().amount + 1))
}
}
}
if (facedFainted && defeatProgress.shouldKeep(pokemon)) {
val progress = pokemon.evolutionProxy.current().progressFirstOrCreate({ it is DefeatEvolutionProgress && it.currentProgress().target.matches(faintedPokemon.effectedPokemon) }) { defeatProgress }
progress.updateProgress(DefeatEvolutionProgress.Progress(progress.currentProgress().target, progress.currentProgress().amount + 1))
}
val multiplier = when {
// ToDo when Exp. All is implement if enabled && !facedFainted return 2.0, probably should be a configurable value too, this will have priority over the Exp. Share
@@ -274,8 +247,8 @@ open class PokemonBattle(
}
}
sendUpdate(BattleEndPacket())
sendUpdate(BattleMusicPacket(null))
BattleRegistry.closeBattle(this)
onEndHandlers.forEach { it(this) }
}
fun finishCaptureAction(captureAction: BattleCaptureAction) {
@@ -341,12 +314,6 @@ open class PokemonBattle(
fun dispatch(dispatcher: () -> DispatchResult) {
dispatches.add(BattleDispatch { dispatcher() })
}
fun dispatchToFront(dispatcher: () -> DispatchResult) {
dispatches.addFirst(BattleDispatch { dispatcher() })
}
fun dispatchGo(dispatcher: () -> Unit) {
@@ -363,14 +330,6 @@ open class PokemonBattle(
}
}
fun dispatchFuture(future: () -> CompletableFuture<*>) {
val dispatch = BattleDispatch {
val generatedFuture = future()
return@BattleDispatch DispatchResult { generatedFuture.isDone }
}
dispatches.add(dispatch)
}
fun dispatchInsert(dispatcher: () -> Iterable<BattleDispatch>) {
dispatch {
val newDispatches = dispatcher()
@@ -386,10 +345,6 @@ open class PokemonBattle(
dispatches.add(dispatcher)
}
fun dispatchToFront(dispatcher: BattleDispatch) {
dispatches.addFirst(dispatcher)
}
fun doWhenClear(action: () -> Unit) {
afterDispatches.add(action)
}
@@ -414,9 +369,8 @@ open class PokemonBattle(
return
}
if (started) {
ticks++
if (isPvW && !ended && dispatches.isEmpty()) checkFlee()
if (started && isPvW && !ended && dispatches.isEmpty()) {
checkFlee()
}
}
@@ -458,24 +412,13 @@ open class PokemonBattle(
}
fun checkForInputDispatch() {
if (checkForfeit()) return // ignore actors that are still choosing, their choices don't matter anymore
val readyToInput = (actors.any { !it.mustChoose && it.responses.isNotEmpty() } && actors.none { it.mustChoose })
val readyToInput = actors.any { !it.mustChoose && it.responses.isNotEmpty() } && actors.none { it.mustChoose }
if (readyToInput && captureActions.isEmpty()) {
actors.filter { it.responses.isNotEmpty() }.forEach { it.writeShowdownResponse() }
actors.forEach { it.responses.clear() ; it.request = null }
}
}
/** Forces Showdown to end the battle when a [BattleActor] chooses to forfeit. */
private fun checkForfeit(): Boolean {
val forfeit = actors.find { it.responses.any { it is ForfeitActionResponse } }
return forfeit?.let {
this.dispatchWaiting { this.broadcastChatMessage(battleLang("forfeit", it.getName()).red()) }
writeShowdownAction(">forcelose ${it.showdownId}")
true
} ?: false
}
/**
* Creates a [Text] representation of an error to interpret a battle message.
* This also logs the error, the goal of this function is to make sure users see missing interpretations and report them to us.
@@ -506,12 +449,4 @@ open class PokemonBattle(
LOGGER.error("Missing interpretation on '{}' action: \nPublic » {}\nPrivate » {}", publicMessage.id, publicMessage.rawMessage, privateMessage.rawMessage)
return Text.literal("Missing interpretation on '${publicMessage.id}' action please report to the developers").red()
}
fun addQueryFunctions(queryStruct: QueryStruct): QueryStruct {
queryStruct.addFunction("pvp") { DoubleValue(isPvP) }
queryStruct.addFunction("pvn") { DoubleValue(isPvN) }
queryStruct.addFunction("pvw") { DoubleValue(isPvW) }
queryStruct.addFunction("has_rule") { params -> DoubleValue(params.getString(0) in format.ruleSet) }
return queryStruct
}
}
}
@@ -26,20 +26,13 @@ abstract class AIBattleActor(
super.sendUpdate(packet)
if (packet is BattleMakeChoicePacket) {
this.onChoiceRequested()
}
}
/**
* Called when the AI is requested to make a choice.
*/
open fun onChoiceRequested() {
try {
setActionResponses(request!!.iterate(this.activePokemon, battleAI::choose))
} catch (exception: IllegalActionChoiceException) {
LOGGER.error("AI was unable to choose a move, we're going to need to pass!")
exception.printStackTrace()
setActionResponses(request!!.iterate(this.activePokemon) { _, _, _ -> PassActionResponse })
try {
setActionResponses(request!!.iterate(this.activePokemon, battleAI::choose))
} catch (exception: IllegalActionChoiceException) {
LOGGER.error("AI was unable to choose a move, we're going to need to pass!")
exception.printStackTrace()
setActionResponses(request!!.iterate(this.activePokemon) { _, _, _ -> PassActionResponse })
}
}
}
}
@@ -145,7 +145,4 @@ abstract class BattleActor(
}
open fun awardExperience(battlePokemon: BattlePokemon, experience: Int) {}
open fun sendUpdate(packet: NetworkPacket<*>) {}
open fun win(otherWinners: List<BattleActor>, losers: List<BattleActor>) {}
open fun lose(winners: List<BattleActor>, otherLosers: List<BattleActor>) {}
}
@@ -1,106 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.berry
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.berry.spawncondition.BerrySpawnCondition
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.mulch.MulchVariant
import com.cobblemon.mod.common.api.pokemon.stats.Stat
import com.cobblemon.mod.common.api.pokemon.status.Status
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.net.messages.client.data.BerryRegistrySyncPacket
import com.cobblemon.mod.common.pokemon.adapters.CobblemonStatTypeAdapter
import com.cobblemon.mod.common.util.adapters.*
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import java.awt.Color
import net.minecraft.predicate.NumberRange
import net.minecraft.registry.RegistryKeys
import net.minecraft.registry.tag.TagKey
import net.minecraft.resource.ResourceType
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
import net.minecraft.util.math.Box
import net.minecraft.util.math.Vec3d
import net.minecraft.world.biome.Biome
/**
* The data registry for [Berry].
*
* @author Licious
* @since November 28th, 2022
*/
object Berries : JsonDataRegistry<Berry> {
override val id: Identifier = cobblemonResource("berries")
override val type: ResourceType = ResourceType.SERVER_DATA
override val observable = SimpleObservable<Berries>()
override val gson = GsonBuilder()
.disableHtmlEscaping()
.setPrettyPrinting()
.registerTypeAdapter(MulchVariant::class.java, MulchVariantAdapter)
.registerTypeAdapter(NumberRange.DoubleRange::class.java, FloatNumberRangeAdapter)
.registerTypeAdapter(Status::class.java, StatusAdapter)
.registerTypeAdapter(TypeToken.getParameterized(Collection::class.java, Box::class.java).type, BoxCollectionAdapter)
.registerTypeAdapter(Box::class.java, BoxAdapter)
.registerTypeAdapter(Vec3d::class.java, VerboseVec3dAdapter)
.registerTypeAdapter(Identifier::class.java, IdentifierAdapter)
.registerTypeAdapter(GrowthFactor::class.java, CobblemonGrowthFactorAdapter)
.registerTypeAdapter(IntRange::class.java, VerboseIntRangeAdapter)
.registerTypeAdapter(Color::class.java, LiteralHexColorAdapter)
.registerTypeAdapter(Stat::class.java, CobblemonStatTypeAdapter)
.registerTypeAdapter(TypeToken.getParameterized(TagKey::class.java, Biome::class.java).type, TagKeyAdapter(RegistryKeys.BIOME))
.registerTypeAdapter(BerrySpawnCondition::class.java, CobblemonBerrySpawnConditionAdapter)
.create()
override val typeToken: TypeToken<Berry> = TypeToken.get(Berry::class.java)
override val resourcePath = "berries"
private val berries = hashMapOf<Identifier, Berry>()
override fun reload(data: Map<Identifier, Berry>) {
this.berries.clear()
data.forEach { (identifier, berry) ->
try {
berry.identifier = identifier
berry.validate()
this.berries[identifier] = berry
} catch (e: Exception) {
Cobblemon.LOGGER.error("Skipped loading the {} berry", identifier, e)
}
}
Cobblemon.LOGGER.info("Loaded {} berries", this.berries.size)
this.observable.emit(this)
}
override fun sync(player: ServerPlayerEntity) {
BerryRegistrySyncPacket(this.all()).sendToPlayer(player)
}
fun all() = this.berries.values.toList()
/**
* Gets a berry if loaded.
*
* @param identifier The identifier of the berry.
* @return The [Berry] if loaded otherwise null.
*/
fun getByIdentifier(identifier: Identifier): Berry? = this.berries[identifier]
/**
* Gets a berry if loaded.
*
* @param name The path of the identifier of the berry under the [Cobblemon.MODID] namespace.
* @return The [Berry] if loaded otherwise null.
*/
fun getByName(name: String): Berry? = this.getByIdentifier(cobblemonResource(name))
}
@@ -1,370 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.berry
import com.cobblemon.mod.common.CobblemonBlocks
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.api.berry.spawncondition.BerrySpawnCondition
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.berry.BerryYieldCalculationEvent
import com.cobblemon.mod.common.api.mulch.MulchVariant
import com.cobblemon.mod.common.block.BerryBlock
import com.cobblemon.mod.common.block.entity.BerryBlockEntity
import com.cobblemon.mod.common.item.berry.BerryItem
import com.cobblemon.mod.common.pokemon.Nature
import com.cobblemon.mod.common.util.readBox
import com.cobblemon.mod.common.util.readEnumConstant
import com.cobblemon.mod.common.util.readEnumSet
import com.cobblemon.mod.common.util.readIdentifier
import com.cobblemon.mod.common.util.readList
import com.cobblemon.mod.common.util.readMap
import com.cobblemon.mod.common.util.writeBox
import com.cobblemon.mod.common.util.writeCollection
import com.cobblemon.mod.common.util.writeEnumConstant
import com.cobblemon.mod.common.util.writeEnumSet
import com.cobblemon.mod.common.util.writeIdentifier
import com.cobblemon.mod.common.util.writeMap
import com.google.gson.annotations.SerializedName
import net.minecraft.network.RegistryByteBuf
import java.awt.Color
import java.util.EnumSet
import kotlin.math.min
import net.minecraft.block.Block
import net.minecraft.block.BlockState
import net.minecraft.client.model.ModelPart
import net.minecraft.entity.LivingEntity
import net.minecraft.network.PacketByteBuf
import net.minecraft.registry.tag.TagKey
import net.minecraft.util.Identifier
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Box
import net.minecraft.util.math.Vec3d
import net.minecraft.util.shape.VoxelShape
import net.minecraft.util.shape.VoxelShapes
import net.minecraft.world.World
import net.minecraft.world.biome.Biome
/**
* Represents the data behind a berry.
*
* @property identifier The [Identifier] of this berry.
* @property baseYield The [IntRange] possible for the berry tree before [bonusYield] is calculated.
* @property preferredBiomeTags The [TagKey]s of the berries preffered biomes. Determines spawning and yield
* @property growthTime The [IntRange] possible in minutes for how long the berry tree takes to grow frome age 0 to age 3
* @property refreshRate The [IntRange] possible in minutes for how long the berry tree takes to grow from age 3 to age 5
* @property favoriteMulches The types of mulches that benefit this berries yield
* @property growthFactors An array of [GrowthFactor]s that will affect this berry. The client is not aware of these.
* @property mutations A map of the partner berry as the key and the value as the resulting mutation with this berry.
* @property growthPoints A collection of [GrowthPoint]s for the berry flowers and fruit.
* @property sproutShapeBoxes A collection of [Box]es that make up the tree [VoxelShape] during the sprouting stages.
* @property matureShapeBoxes A collection of [Box]es that make up the tree [VoxelShape] during the mature stages.
* @property flavors The [Flavor] values.
* @property tintIndexes Determines tints at specific indexes if any.
* @property flowerModelIdentifier The [Identifier] for the model of the berry in flower form.
* @property flowerTexture The [Identifier] for the texture of the berry in flower form. This is resolved into a [ModelPart] on the client.
* @property fruitModelIdentifier The [Identifier] for the model of the berry in flower form. This is resolved into a [ModelPart] on the client.
* @property fruitTexture The [Identifier] for the texture of the berry in flower form.
* @property stageOnePositioning Transformation of the berry model for age 0
*
* @throws IllegalArgumentException if the any yield range argument is not a positive range.
*/
class Berry(
identifier: Identifier,
val baseYield: IntRange,
val preferredBiomeTags: List<TagKey<Biome>>,
val growthTime: IntRange,
val refreshRate: IntRange,
val favoriteMulches: EnumSet<MulchVariant>,
val growthFactors: Collection<GrowthFactor>,
val spawnConditions: List<BerrySpawnCondition>,
var growthPoints: Array<GrowthPoint>,
val randomizedGrowthPoints: Boolean = true,
val mutations: Map<Identifier, Identifier>,
@SerializedName("sproutShape")
private val sproutShapeBoxes: Collection<Box>,
@SerializedName("matureShape")
private val matureShapeBoxes: Collection<Box>,
private val flavors: Map<Flavor, Int>,
val tintIndexes: Map<Int, Color>,
@SerializedName("flowerModel")
val flowerModelIdentifier: Identifier,
val flowerTexture: Identifier,
@SerializedName("fruitModel")
val fruitModelIdentifier: Identifier,
val fruitTexture: Identifier,
val stageOnePositioning: GrowthPoint,
val weight: Float,
val boneMealChance: Float
) {
@Transient
var identifier: Identifier = identifier
internal set
@Transient
private lateinit var shapedFlower: HashMap<Int, VoxelShape>
@Transient
private lateinit var shapedFruit: HashMap<Int, VoxelShape>
/**
* The [VoxelShape] of the tree during the sprouting stages.
*/
@Transient
lateinit var sproutShape: VoxelShape
private set
/**
* The [VoxelShape] of the tree during the mature stages.
*/
@Transient
lateinit var matureShape: VoxelShape
private set
init {
this.validate()
}
/**
* Finds the [BerryItem] that uses this berry for data.
*
* @return The [BerryItem] if existing.
*/
fun item(): BerryItem? = CobblemonItems.berries()[this.identifier]
/**
* Finds the [BerryBlock] that uses this berry for data.
*
* @return The [BerryBlock] if existing.
*/
fun block(): BerryBlock? = CobblemonBlocks.berries()[this.identifier]
/**
* Query the value of a certain flavor.
*
* @param flavor The [Flavor] being queried.
* @return The value if any or 0.
*/
fun flavor(flavor: Flavor): Int = this.flavors[flavor] ?: 0
fun dislikedBy(nature: Nature): Boolean {
val dislikedFlavor = nature.dislikedFlavor ?: return false
return flavor(dislikedFlavor) > 0
}
/**
* Calculates the yield for a berry tree being planted or replanted after a life cycle.
* Triggers [BerryYieldCalculationEvent].
*
* @param world The [World] the tree is present in.
* @param state The [BlockState] of the tree.
* @param pos The [BlockPos] of the tree.
* @param placer The [LivingEntity] tending to the tree, if any.
* @return The total berry stack count.
*/
fun calculateYield(world: World, state: BlockState, pos: BlockPos, placer: LivingEntity? = null): Int {
val base = this.baseYield.random()
val bonus = this.bonusYield(world, state, pos)
var yield = base + bonus.first
val treeEntity = world.getBlockEntity(pos) as BerryBlockEntity
if (BerryBlock.getMulch(treeEntity) == MulchVariant.RICH) {
//I hope the upper bound isnt exclusive, especially when there's a method called nextBetweenExclusive
yield += world.random.nextBetween(1, 3)
treeEntity.decrementMulchDuration(world, pos, state)
}
val event = BerryYieldCalculationEvent(this, world, state, pos, placer, yield, bonus.second)
CobblemonEvents.BERRY_YIELD.post(event) { yield = it.yield }
return yield
}
/**
* Calculates and returns the minimum possible yield by summing [baseYield] and [growthFactors] minimum values.
*
* @return The minimum possible yield.
*/
fun minYield() = this.baseYield.first + this.growthFactors.sumOf { it.minYield() }
/**
* Calculates and returns the maximum possible yield by summing [baseYield] and [growthFactors] max values.
*
* @return The maximum possible yield.
*/
fun maxYield() = this.baseYield.last + this.growthFactors.sumOf { it.maxYield() }
/**
* Checks if this berry can mutate with the given [partner].
* For the berry the mutations may produce use [mutationWith].
*
* @param partner The [Berry] being checked as a possible mutation partner.
* @return If a mutation is possible.
*/
fun canMutateWith(partner: Berry) = this.mutationWith(partner) != null
/**
* Query for the possible mutation with the given [partner].
*
* @param partner The [Berry] being mutated with.
* @return The resulting [Berry] if the mutation is possible.
*/
fun mutationWith(partner: Berry): Berry? {
val berryIdentifier = this.mutations[partner.identifier] ?: return null
return Berries.getByIdentifier(berryIdentifier)
}
/**
* Query for a possible partner to mutate into the given [resulting].
*
* @param resulting The [Berry] the mutation should result in.
* @return The [Berry] that mutates with this berry into the given [resulting] if possible.
*/
fun partnerForMutation(resulting: Berry): Berry? {
return this.mutations.firstNotNullOfOrNull { (partner, result) ->
if (result == resulting.identifier)
Berries.getByIdentifier(partner)
else
null
}
}
// A cheat since gson doesn't invoke init block
internal fun validate() {
if (this.baseYield.first < 0 || this.baseYield.last < 0) {
throw IllegalArgumentException("A berry base yield must be a positive range")
}
if (this.growthTime.first < 0 || this.growthTime.last < 0) {
throw IllegalArgumentException("The growth time must be a positive range")
}
if (this.refreshRate.first < 0 || this.refreshRate.last < 0) {
throw IllegalArgumentException("The refresh rate must be a positive range")
}
/*
if (this.lifeCycles.first < 0 || this.lifeCycles.last < 0) {
throw IllegalArgumentException("A berry life cycle must be a positive range")
}
*/
this.growthFactors.forEach { it.validateArguments() }
val maxYield = this.maxYield()
if (this.growthPoints.size < maxYield) {
throw IllegalArgumentException("Anchor points must have enough elements for the max possible yield of $maxYield you've provided ${this.growthPoints.size} points")
}
this.shapedFlower = hashMapOf()
this.shapedFruit = hashMapOf()
this.sproutShape = this.createAndUniteShapes(this.sproutShapeBoxes)
this.matureShape = this.createAndUniteShapes(this.matureShapeBoxes)
}
internal fun encode(buffer: RegistryByteBuf) {
buffer.writeIdentifier(this.identifier)
buffer.writeInt(this.baseYield.first)
buffer.writeInt(this.baseYield.last)
buffer.writeEnumSet(favoriteMulches, MulchVariant::class.java)
//buffer.writeInt(this.lifeCycles.first)
//buffer.writeInt(this.lifeCycles.last)
buffer.writeInt(this.growthTime.first)
buffer.writeInt(this.growthTime.last)
buffer.writeInt(this.refreshRate.first)
buffer.writeInt(this.refreshRate.last)
buffer.writeCollection(this.growthPoints.toList()) { writer, value ->
writer.writeDouble(value.position.x)
writer.writeDouble(value.position.y)
writer.writeDouble(value.position.z)
writer.writeDouble(value.rotation.x)
writer.writeDouble(value.rotation.y)
writer.writeDouble(value.rotation.z)
}
buffer.writeBoolean(this.randomizedGrowthPoints)
buffer.writeMap(this.mutations, { writer, key -> writer.writeIdentifier(key) }, { writer, value -> writer.writeIdentifier(value) })
buffer.writeCollection(this.sproutShapeBoxes) { writer, value ->
writer.writeBox(value)
}
buffer.writeCollection(this.matureShapeBoxes) { writer, value ->
writer.writeBox(value)
}
buffer.writeMap(this.flavors, { writer, key -> writer.writeEnumConstant(key) }, { writer, value -> writer.writeInt(value) })
buffer.writeMap(this.tintIndexes, { writer, key -> writer.writeInt(key) }, { writer, value -> writer.writeInt(value.rgb) })
buffer.writeIdentifier(this.flowerModelIdentifier)
buffer.writeIdentifier(this.flowerTexture)
buffer.writeIdentifier(this.fruitModelIdentifier)
buffer.writeIdentifier(this.fruitTexture)
buffer.writeDouble(stageOnePositioning.position.x)
buffer.writeDouble(stageOnePositioning.position.y)
buffer.writeDouble(stageOnePositioning.position.z)
buffer.writeDouble(stageOnePositioning.rotation.x)
buffer.writeDouble(stageOnePositioning.rotation.y)
buffer.writeDouble(stageOnePositioning.rotation.z)
buffer.writeFloat(boneMealChance)
}
/**
* Calculates the bonus yield for the berry tree.
*
* @param world The [World] the tree is present in.
* @param state The [BlockState] of the tree.
* @param pos The [BlockPos] of the tree.
* @return The bonus yield, the growth factors that passed.
*/
private fun bonusYield(world: World, state: BlockState, pos: BlockPos): Pair<Int, Collection<GrowthFactor>> {
var bonus = 0
val passed = arrayListOf<GrowthFactor>()
val treeEntity = world.getBlockEntity(pos) as? BerryBlockEntity ?: return 0 to passed
val mulchVariant = BerryBlock.getMulch(treeEntity)
val hasBiomeMulch = mulchVariant in favoriteMulches
this.growthFactors.forEach { factor ->
if (factor.isValid(world, state, pos)) {
bonus += factor.yield()
passed += factor
} else if (hasBiomeMulch) {
bonus += factor.yield()
}
}
return bonus to passed
}
private fun createAndUniteShapes(boxes: Collection<Box>): VoxelShape {
var shape: VoxelShape? = null
boxes.forEach { box ->
shape = if (shape == null) {
Block.createCuboidShape(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ)
} else {
VoxelShapes.union(shape, Block.createCuboidShape(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ))
}
}
return shape ?: VoxelShapes.fullCube()
}
companion object {
internal fun decode(buffer: RegistryByteBuf): Berry {
val identifier = buffer.readIdentifier()
val baseYield = IntRange(buffer.readInt(), buffer.readInt())
val favMulchs = buffer.readEnumSet(MulchVariant::class.java)
//val lifeCycles = IntRange(buffer.readInt(), buffer.readInt())
val growthTime = IntRange(buffer.readInt(), buffer.readInt())
val refreshRate = IntRange(buffer.readInt(), buffer.readInt())
val growthPoints = buffer.readList { reader ->
GrowthPoint(Vec3d(reader.readDouble(), reader.readDouble(), reader.readDouble()), Vec3d(reader.readDouble(), reader.readDouble(), reader.readDouble()))
}.toTypedArray()
val randomizedGrowthPoints = buffer.readBoolean()
val mutations = buffer.readMap({ reader -> reader.readIdentifier() }, { reader -> reader.readIdentifier() })
val sproutShapeBoxes = buffer.readList { it.readBox() }
val matureShapeBoxes = buffer.readList { it.readBox() }
val flavors = buffer.readMap({ reader -> reader.readEnumConstant(Flavor::class.java) }, { reader -> reader.readInt() })
val tintIndexes = buffer.readMap({ reader -> reader.readInt() }, { reader -> Color(reader.readInt()) })
val flowerModelIdentifier = buffer.readIdentifier()
val flowerTexture = buffer.readIdentifier()
val fruitModelIdentifier = buffer.readIdentifier()
val fruitTexture = buffer.readIdentifier()
val stageOneYPos = GrowthPoint(Vec3d(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()), Vec3d(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()))
val boneMealChance = buffer.readFloat()
return Berry(identifier, baseYield, emptyList(), growthTime, refreshRate, favMulchs, emptySet(), emptyList(), growthPoints, randomizedGrowthPoints, mutations, sproutShapeBoxes, matureShapeBoxes, flavors, tintIndexes, flowerModelIdentifier, flowerTexture, fruitModelIdentifier, fruitTexture, stageOneYPos, 0F, boneMealChance)
}
}
}
@@ -1,47 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.berry
import com.cobblemon.mod.common.CobblemonBlocks
import com.cobblemon.mod.common.block.BerryBlock
import com.cobblemon.mod.common.world.feature.BerryGroveFeature
import com.google.common.cache.CacheBuilder
import com.google.common.cache.CacheLoader
import com.google.common.cache.LoadingCache
import net.minecraft.registry.entry.RegistryEntry
import net.minecraft.world.biome.Biome
object BerryHelper {
private val CACHE_LOADER = object : CacheLoader<RegistryEntry<Biome>, List<BerryBlock>>() {
override fun load(key: RegistryEntry<Biome>): List<BerryBlock> {
return naturalBerries.filter { berryBlock ->
val berry = berryBlock.berry()
berry?.spawnConditions?.any { it.canSpawn(berry, key) } ?: false
}
}
}
private val naturalBerries = CobblemonBlocks.berries().values.filter {
(it.berry()?.spawnConditions?.size ?: 0) > 0
}
private val validBerryCache: LoadingCache<RegistryEntry<Biome>, List<BerryBlock>> = CacheBuilder.newBuilder()
.maximumSize(4)
.build(CACHE_LOADER)
fun getBerriesForBiome(biome: RegistryEntry<Biome>): List<BerryBlock> {
return validBerryCache.get(biome)
}
fun getNaturallyGeneratingBerries(): List<BerryBlock> {
return naturalBerries
}
}
@@ -1,26 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.berry
/**
* Represents the different flavors associated with berries and other Pokémon consumables.
* See the [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Flavor) article for more information.
*
* @author Licious
* @since November 28th, 2022
*/
enum class Flavor {
SPICY,
DRY,
SWEET,
BITTER,
SOUR
}
@@ -1,61 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.berry
import net.minecraft.block.BlockState
import net.minecraft.util.math.BlockPos
import net.minecraft.world.WorldView
/**
* Represents a condition that impacts extra berry yield.
*
* @author Licious
* @since December 2nd, 2022
*/
interface GrowthFactor {
/**
* Validates the arguments contained in this factor, this is invoked during loading.
*
* @throws IllegalArgumentException If an argument isn't valid.
*/
fun validateArguments()
/**
* Checks if this factor should yield a bonus.
*
* @param world The [WorldView] the berry tree is in.
* @param state The [BlockState] of the berry tree.
* @param pos The [BlockPos] of the berry tree.
* @return If the bonus should activate.
*/
fun isValid(world: WorldView, state: BlockState, pos: BlockPos): Boolean
/**
* Resolves the amount of bonus berries to grow if [isValid] was true.
*
* @return The amount of extra berries to grow.
*/
fun yield(): Int
/**
* Returns the minimum possible yield for this factor.
*
* @return The minimum possible yield for this factor.
*/
fun minYield(): Int
/**
* Returns the maximum possible yield for this factor.
*
* @return The maximum possible yield for this factor.
*/
fun maxYield(): Int
}
@@ -1,25 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.berry
import net.minecraft.util.math.Vec3d
/**
* Represents a position in a berry tree where a berry will flower then fruit.
*
* @property position The coordinates of the berry in the tree block.
* @property rotation The degree value for the rotation each axis.
*
* @author Licious
* @since December 19th, 2022
*/
data class GrowthPoint(
val position: Vec3d,
val rotation: Vec3d
)

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