mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-22 07:06:23 -04:00
Compare commits
24
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9cdf91c97f | ||
|
|
3f5b659616 | ||
|
|
ee20f012e6 | ||
|
|
12dcc98cf9 | ||
|
|
8c92defc90 | ||
|
|
95509df022 | ||
|
|
bb20890b26 | ||
|
|
50d60674bb | ||
|
|
ff994f69f2 | ||
|
|
73448d4737 | ||
|
|
42099d3ae5 | ||
|
|
bc23ab8eb4 | ||
|
|
6c860d8e93 | ||
|
|
de6b713adf | ||
|
|
6f5c2575f3 | ||
|
|
b23afd17c2 | ||
|
|
74541c1bcb | ||
|
|
56c3ff55ca | ||
|
|
c5b82d1ad4 | ||
|
|
1237b51059 | ||
|
|
9529fe66ac | ||
|
|
7058ac21cb | ||
|
|
b5d0cddc82 | ||
|
|
2f918220e9 |
@@ -2,48 +2,22 @@
|
||||
## [1.7.2 (MONTH Xth, YEAR)](#1-7-2)
|
||||
|
||||
### Additions
|
||||
- Added riding statistics: `Distance by Pokémon on Land`, `Distance by Pokémon in Air` and `Distance by Pokémon in Liquid`.
|
||||
- Added the Partner Mark, which party Pokémon have a very small chance to earn as the player walks, provided they have enough friendship.
|
||||
- Added trades for Saccharine Saplings, Hearty Grains, Chipped Pot, and Masterpiece Teacup to the Wandering Trader.
|
||||
- Added brewing recipe for Throat Spray.
|
||||
- Added official Controlify Support
|
||||
- Added new effects
|
||||
- Mental Restoration: Reduces "Time Since Last Rest" statistic, which controls Insomnia, by half a minute per second per effect level
|
||||
- Negative Effect Cleanse: Removes all negative effects
|
||||
- Effect Cleanse: Removes all effects
|
||||
- Added more seasonings for sinister tea
|
||||
- Mental Herb - Mental Restoration I for 10 seconds
|
||||
- White Herb - Negative Effect Cleanse
|
||||
- Milk - Effect Cleanse
|
||||
- Moomoo Milk - Effect Cleanse
|
||||
|
||||
### Changes
|
||||
- Ride sounds have been separated into stereo for passengers and mono for other players. Riding will now sound more spacious.
|
||||
|
||||
### Fixes
|
||||
- Fixed orientation not getting reset after crashing while flying and getting back on the Pokémon.
|
||||
- Fixed Furfrou not being trimmable on NeoForge.
|
||||
- Fixed shiny Pokémon not respecting the silent flag on spawn.
|
||||
- Fixed honey from Saccharine Leaves being harvestable at less than the max age.
|
||||
- Items given from interacting with Saccharine Leaves are placed in the active hotbar slot if possible.
|
||||
- Fix all Pokémon being saved to chunks and never despawning.
|
||||
- Fixed PokeSnacks crashing if there was no available spawn.
|
||||
- Fixed Pokémon spawn influences not being specific to regional forms
|
||||
- Fixed crashing when viewing another player in spectator mode
|
||||
- Fixed missing apricorn textures for Adorn blocks
|
||||
- Fixed crashing when riding due to malformed json file, instead resetting it
|
||||
- Fixed mochi items consuming two items at a time
|
||||
- Fix item interaction sometimes not working properly when playing on servers.
|
||||
- Fixed Soothe Bell not being properly tagged as a held item.
|
||||
- Fixed Mint Leaves not being usable for filling the Resurrection Machine.
|
||||
- Added Saccharine Boats and Saccharine Boat with Chests to relevant boat tags.
|
||||
|
||||
### Developer
|
||||
- Changed the `owner` parameter in the `OwnerQueryRequirement` interface from `ServerPlayer` to `Player`. This method is now also called on the client to verify whether a Pokémon interaction succeeded, so make sure to update your implementations to handle both server and client contexts.
|
||||
|
||||
### Molang & Datapacks
|
||||
- Ride sounds can now be set as exclusive to passengers
|
||||
- Ride sounds no longer play when submerged unless specified with a new setting
|
||||
|
||||
### Particles
|
||||
|
||||
|
||||
@@ -32,10 +32,6 @@ repositories {
|
||||
maven(url = "https://api.modrinth.com/maven")
|
||||
maven(url = "https://maven.neoforged.net/releases")
|
||||
maven(url = "https://maven.gegy.dev")
|
||||
exclusiveContent {
|
||||
forRepository { maven(url = "https://maven.isxander.dev/releases") }
|
||||
filter { includeGroup("dev.isxander") }
|
||||
}
|
||||
mavenLocal()
|
||||
}
|
||||
|
||||
@@ -58,6 +54,8 @@ dependencies {
|
||||
// Flywheel has no common dep so just pick one and don't use any platform specific code in common
|
||||
// modCompileOnly(libs.flywheelFabric)
|
||||
|
||||
modCompileOnly(files("temp/vivecraft-1.21.1-1.3.4.jar")) // TODO: Switch this to a proper dependency when Vivecraft gets a maven repo
|
||||
|
||||
// Showdown
|
||||
modCompileOnly(libs.graal)
|
||||
|
||||
@@ -66,11 +64,6 @@ dependencies {
|
||||
|
||||
// Unit Testing
|
||||
testImplementation(libs.bundles.unitTesting)
|
||||
|
||||
// Controlify Compat, same as flywheel so we pick one and only use the api
|
||||
modCompileOnlyApi("dev.isxander:controlify:2.4.3+1.21.1-fabric") {
|
||||
isTransitive = false
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<Test> {
|
||||
|
||||
@@ -11,15 +11,11 @@ package com.cobblemon.mod.common.mixin;
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.OrientationControllable;
|
||||
import com.cobblemon.mod.common.PlayerSpawnerAccessor;
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle;
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.PlayerSpawner;
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.PlayerSpawnerFactory;
|
||||
import com.cobblemon.mod.common.api.stats.CobblemonStats;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules;
|
||||
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
@@ -93,32 +89,4 @@ public abstract class ServerPlayerMixin implements PlayerSpawnerAccessor {
|
||||
private boolean cobblemon$cancelSavingPokemonMounts(boolean original, @Local(ordinal=0) Entity entity) {
|
||||
return original && !(entity instanceof PokemonEntity);
|
||||
}
|
||||
|
||||
@WrapOperation(method = "checkRidingStatistics", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;getVehicle()Lnet/minecraft/world/entity/Entity;"))
|
||||
public Entity cobblemon$checkRidingStatistics(ServerPlayer player, Operation<Entity> original, @Local int distance) {
|
||||
var entity = original.call(player);
|
||||
if (!(entity instanceof PokemonEntity pokemonEntity)) {
|
||||
return entity;
|
||||
}
|
||||
|
||||
var ridingController = pokemonEntity.getRidingController();
|
||||
if (ridingController == null) return entity;
|
||||
|
||||
var activeContext = ridingController.getContext();
|
||||
if (activeContext == null) return entity;
|
||||
|
||||
var ridingStyle = activeContext.getStyle();
|
||||
CobblemonStats.CobblemonStat stat = switch (ridingStyle) {
|
||||
case RidingStyle.LAND -> CobblemonStats.RIDING_LAND;
|
||||
case RidingStyle.AIR -> CobblemonStats.RIDING_AIR;
|
||||
case RidingStyle.LIQUID -> CobblemonStats.RIDING_LIQUID;
|
||||
default -> null;
|
||||
};
|
||||
|
||||
if (stat != null) {
|
||||
player.awardStat(CobblemonStats.getStat(stat), distance);
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,14 +21,12 @@ import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import com.mojang.blaze3d.Blaze3D;
|
||||
import kotlin.Pair;
|
||||
import kotlin.jvm.functions.Function4;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.MouseHandler;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.SmoothDouble;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.joml.Vector2d;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@@ -148,12 +146,6 @@ public abstract class MouseHandlerMixin {
|
||||
pokeVehicle.clampPassengerRotation(player);
|
||||
}
|
||||
|
||||
for(Function4<LocalPlayer, Double, Double, Double, Vector2d> rideFun : CobblemonClient.INSTANCE.getRidingTurnInputHandler().values()) {
|
||||
Vector2d vec = rideFun.invoke(player, cursorDeltaX, cursorDeltaY, d);
|
||||
cursorDeltaX = vec.x;
|
||||
cursorDeltaY = vec.y;
|
||||
}
|
||||
|
||||
// If the ride is not orientation controllable then return and perform the normal turnPlayer logic
|
||||
if (!(vehicle instanceof OrientationControllable controllableVehicle) || !controllableVehicle.getOrientationController().isActive()) {
|
||||
xMouseSmoother.reset();
|
||||
|
||||
@@ -77,6 +77,7 @@ import com.cobblemon.mod.common.config.constraint.IntConstraint
|
||||
import com.cobblemon.mod.common.config.starter.StarterConfig
|
||||
import com.cobblemon.mod.common.data.CobblemonDataProvider
|
||||
import com.cobblemon.mod.common.events.*
|
||||
import com.cobblemon.mod.common.integration.vivecraft.CobblemonVR
|
||||
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
|
||||
import com.cobblemon.mod.common.permission.LaxPermissionValidator
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
@@ -130,10 +131,12 @@ object Cobblemon {
|
||||
const val MODID = CobblemonBuildDetails.MOD_ID
|
||||
const val VERSION = CobblemonBuildDetails.VERSION
|
||||
const val CONFIG_PATH = "config/$MODID/main.json"
|
||||
|
||||
@JvmField
|
||||
val LOGGER: Logger = LogManager.getLogger()
|
||||
|
||||
lateinit var implementation: CobblemonImplementation
|
||||
|
||||
@Deprecated("This field is now a config value", ReplaceWith("Cobblemon.config.captureCalculator"))
|
||||
var captureCalculator: CaptureCalculator
|
||||
get() = this.config.captureCalculator
|
||||
@@ -163,21 +166,49 @@ object Cobblemon {
|
||||
val serverPlayerStructs = mutableMapOf<UUID, ObjectValue<Player>>()
|
||||
|
||||
val statistics: CobblemonStats = CobblemonStats
|
||||
var cobblemonVR: CobblemonVR? = null
|
||||
|
||||
@JvmStatic
|
||||
val builtinPacks = listOf<CobblemonPack>(
|
||||
CobblemonPack(id = "adorncompatibility", name = "Adorn Compatibility", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.ALWAYS_ENABLED, neededMods = setOf("adorn")),
|
||||
CobblemonPack(id = "gyaradosjump", name = "Gyarados Jump Patterns", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED),
|
||||
CobblemonPack(id = "regionbiasforms", name = "Region Bias Forms", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED),
|
||||
CobblemonPack(id = "uniqueshinyforms", name = "Shinies for Magikarp Jump", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.NORMAL),
|
||||
CobblemonPack(
|
||||
id = "adorncompatibility",
|
||||
name = "Adorn Compatibility",
|
||||
packType = PackType.CLIENT_RESOURCES,
|
||||
activationBehaviour = ResourcePackActivationBehaviour.ALWAYS_ENABLED,
|
||||
neededMods = setOf("adorn")
|
||||
),
|
||||
CobblemonPack(
|
||||
id = "gyaradosjump",
|
||||
name = "Gyarados Jump Patterns",
|
||||
packType = PackType.CLIENT_RESOURCES,
|
||||
activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED
|
||||
),
|
||||
CobblemonPack(
|
||||
id = "regionbiasforms",
|
||||
name = "Region Bias Forms",
|
||||
packType = PackType.CLIENT_RESOURCES,
|
||||
activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED
|
||||
),
|
||||
CobblemonPack(
|
||||
id = "uniqueshinyforms",
|
||||
name = "Shinies for Magikarp Jump",
|
||||
packType = PackType.CLIENT_RESOURCES,
|
||||
activationBehaviour = ResourcePackActivationBehaviour.NORMAL
|
||||
),
|
||||
|
||||
CobblemonPack(id = "repurposedstructurescobblemon", name = "Repurposed Structures Cobblemon", packType = PackType.SERVER_DATA, activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED, neededMods = setOf("repurposed_structures")),
|
||||
CobblemonPack(
|
||||
id = "repurposedstructurescobblemon",
|
||||
name = "Repurposed Structures Cobblemon",
|
||||
packType = PackType.SERVER_DATA,
|
||||
activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED,
|
||||
neededMods = setOf("repurposed_structures")
|
||||
),
|
||||
)
|
||||
|
||||
fun preInitialize(implementation: CobblemonImplementation) {
|
||||
this.implementation = implementation
|
||||
|
||||
this.LOGGER.info("Launching Cobblemon ${CobblemonBuildDetails.VERSION}${if(CobblemonBuildDetails.SNAPSHOT) "-SNAPSHOT" else ""} ")
|
||||
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}")
|
||||
@@ -201,7 +232,6 @@ object Cobblemon {
|
||||
implementation.registerEntityDataSerializers()
|
||||
implementation.registerCriteria()
|
||||
implementation.registerEntitySubPredicates()
|
||||
implementation.registerMobEffects()
|
||||
DispenserBehaviorRegistry.registerDispenserBehaviors()
|
||||
|
||||
DropEntry.register("command", CommandDropEntry::class.java)
|
||||
@@ -242,7 +272,10 @@ object Cobblemon {
|
||||
}
|
||||
|
||||
PlatformEvents.RIGHT_CLICK_ENTITY.subscribe { event ->
|
||||
if (event.player.getItemInHand(event.hand).item is NameTagItem && event.entity.type.`is`(CobblemonEntityTypeTags.CANNOT_HAVE_NAME_TAG)) {
|
||||
if (event.player.getItemInHand(event.hand).item is NameTagItem && event.entity.type.`is`(
|
||||
CobblemonEntityTypeTags.CANNOT_HAVE_NAME_TAG
|
||||
)
|
||||
) {
|
||||
event.cancel()
|
||||
}
|
||||
}
|
||||
@@ -253,7 +286,10 @@ object Cobblemon {
|
||||
pokemon.lockedEvolutions
|
||||
.filterIsInstance<BlockClickEvolution>()
|
||||
.forEach { evolution ->
|
||||
evolution.attemptEvolution(pokemon, BlockClickEvolution.BlockInteractionContext(block, player.level()))
|
||||
evolution.attemptEvolution(
|
||||
pokemon,
|
||||
BlockClickEvolution.BlockInteractionContext(block, player.level())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -313,6 +349,11 @@ object Cobblemon {
|
||||
SlowpokeTailRegrowthSpeciesFeatureProvider
|
||||
)
|
||||
|
||||
if (implementation.isModInstalled("vivecraft")) { // VR integration
|
||||
cobblemonVR = CobblemonVR()
|
||||
cobblemonVR?.init()
|
||||
}
|
||||
|
||||
CustomPokemonProperty.register(UncatchableProperty)
|
||||
CustomPokemonProperty.register(BattleCloneProperty)
|
||||
CustomPokemonProperty.register(PokemonFlagProperty)
|
||||
@@ -332,7 +373,7 @@ object Cobblemon {
|
||||
}
|
||||
|
||||
PlatformEvents.SERVER_TICK_POST.subscribe {
|
||||
ServerTaskTracker.update(1/20F)
|
||||
ServerTaskTracker.update(1 / 20F)
|
||||
ServerRealTimeTaskTracker.update()
|
||||
}
|
||||
PlatformEvents.SERVER_TICK_PRE.subscribe {
|
||||
@@ -376,10 +417,22 @@ object Cobblemon {
|
||||
.applyConnectionString(ConnectionString(config.mongoDBConnectionString))
|
||||
.build()
|
||||
mongoClient = MongoClients.create(mongoClientSettings)
|
||||
val generalMongoFactory = CachedPlayerDataStoreFactory(PlayerDataMongoBackend(mongoClient, config.mongoDBDatabaseName, "PlayerDataCollection"))
|
||||
val generalMongoFactory = CachedPlayerDataStoreFactory(
|
||||
PlayerDataMongoBackend(
|
||||
mongoClient,
|
||||
config.mongoDBDatabaseName,
|
||||
"PlayerDataCollection"
|
||||
)
|
||||
)
|
||||
generalMongoFactory.setup(server)
|
||||
|
||||
val pokedexMongoFactory = CachedPlayerDataStoreFactory(DexDataMongoBackend(mongoClient, config.mongoDBDatabaseName, "PokeDexCollection"))
|
||||
val pokedexMongoFactory = CachedPlayerDataStoreFactory(
|
||||
DexDataMongoBackend(
|
||||
mongoClient,
|
||||
config.mongoDBDatabaseName,
|
||||
"PokeDexCollection"
|
||||
)
|
||||
)
|
||||
pokedexMongoFactory.setup(server)
|
||||
|
||||
playerDataManager.setFactory(generalMongoFactory, PlayerInstancedDataStoreTypes.GENERAL)
|
||||
@@ -501,6 +554,7 @@ object Cobblemon {
|
||||
field.set(config, field.get(defaultConfig))
|
||||
}
|
||||
}
|
||||
|
||||
is IntConstraint -> {
|
||||
var value = field.get(config)
|
||||
if (value is Int) {
|
||||
@@ -553,20 +607,76 @@ object Cobblemon {
|
||||
}
|
||||
|
||||
private fun registerArgumentTypes() {
|
||||
this.implementation.registerCommandArgument(cobblemonResource("pokemon"), SpeciesArgumentType::class, SingletonArgumentInfo.contextFree(SpeciesArgumentType::species))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("pokemon_properties"), PokemonPropertiesArgumentType::class, SingletonArgumentInfo.contextFree(PokemonPropertiesArgumentType::properties))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("spawn_bucket"), SpawnBucketArgumentType::class, SingletonArgumentInfo.contextFree(SpawnBucketArgumentType::spawnBucket))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("move"), MoveArgumentType::class, SingletonArgumentInfo.contextFree(MoveArgumentType::move))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("party_slot"), PartySlotArgumentType::class, SingletonArgumentInfo.contextFree(PartySlotArgumentType::partySlot))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("pokemon_store"), PokemonStoreArgumentType::class, SingletonArgumentInfo.contextFree(PokemonStoreArgumentType::pokemonStore))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("dialogue"), DialogueArgumentType::class, SingletonArgumentInfo.contextFree(DialogueArgumentType::dialogue))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("form"), FormArgumentType::class, SingletonArgumentInfo.contextFree(FormArgumentType::form))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("dex"), DexArgumentType::class, SingletonArgumentInfo.contextFree (DexArgumentType::dex))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("npc_class"), NPCClassArgumentType::class, SingletonArgumentInfo.contextFree(NPCClassArgumentType::npcClass))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("wallpaper"), UnlockablePCBoxWallpaperArgumentType::class, SingletonArgumentInfo.contextFree(UnlockablePCBoxWallpaperArgumentType::wallpaper))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("mark"), MarkArgumentType::class, SingletonArgumentInfo.contextFree(MarkArgumentType::mark))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("transform_type"), TransformTypeArgumentType::class, SingletonArgumentInfo.contextFree(TransformTypeArgumentType::transformType))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("model_part"), ModelPartArgumentType::class, SingletonArgumentInfo.contextFree(ModelPartArgumentType::modelPart))
|
||||
this.implementation.registerCommandArgument(
|
||||
cobblemonResource("pokemon"),
|
||||
SpeciesArgumentType::class,
|
||||
SingletonArgumentInfo.contextFree(SpeciesArgumentType::species)
|
||||
)
|
||||
this.implementation.registerCommandArgument(
|
||||
cobblemonResource("pokemon_properties"),
|
||||
PokemonPropertiesArgumentType::class,
|
||||
SingletonArgumentInfo.contextFree(PokemonPropertiesArgumentType::properties)
|
||||
)
|
||||
this.implementation.registerCommandArgument(
|
||||
cobblemonResource("spawn_bucket"),
|
||||
SpawnBucketArgumentType::class,
|
||||
SingletonArgumentInfo.contextFree(SpawnBucketArgumentType::spawnBucket)
|
||||
)
|
||||
this.implementation.registerCommandArgument(
|
||||
cobblemonResource("move"),
|
||||
MoveArgumentType::class,
|
||||
SingletonArgumentInfo.contextFree(MoveArgumentType::move)
|
||||
)
|
||||
this.implementation.registerCommandArgument(
|
||||
cobblemonResource("party_slot"),
|
||||
PartySlotArgumentType::class,
|
||||
SingletonArgumentInfo.contextFree(PartySlotArgumentType::partySlot)
|
||||
)
|
||||
this.implementation.registerCommandArgument(
|
||||
cobblemonResource("pokemon_store"),
|
||||
PokemonStoreArgumentType::class,
|
||||
SingletonArgumentInfo.contextFree(PokemonStoreArgumentType::pokemonStore)
|
||||
)
|
||||
this.implementation.registerCommandArgument(
|
||||
cobblemonResource("dialogue"),
|
||||
DialogueArgumentType::class,
|
||||
SingletonArgumentInfo.contextFree(DialogueArgumentType::dialogue)
|
||||
)
|
||||
this.implementation.registerCommandArgument(
|
||||
cobblemonResource("form"),
|
||||
FormArgumentType::class,
|
||||
SingletonArgumentInfo.contextFree(FormArgumentType::form)
|
||||
)
|
||||
this.implementation.registerCommandArgument(
|
||||
cobblemonResource("dex"),
|
||||
DexArgumentType::class,
|
||||
SingletonArgumentInfo.contextFree(DexArgumentType::dex)
|
||||
)
|
||||
this.implementation.registerCommandArgument(
|
||||
cobblemonResource("npc_class"),
|
||||
NPCClassArgumentType::class,
|
||||
SingletonArgumentInfo.contextFree(NPCClassArgumentType::npcClass)
|
||||
)
|
||||
this.implementation.registerCommandArgument(
|
||||
cobblemonResource("wallpaper"),
|
||||
UnlockablePCBoxWallpaperArgumentType::class,
|
||||
SingletonArgumentInfo.contextFree(UnlockablePCBoxWallpaperArgumentType::wallpaper)
|
||||
)
|
||||
this.implementation.registerCommandArgument(
|
||||
cobblemonResource("mark"),
|
||||
MarkArgumentType::class,
|
||||
SingletonArgumentInfo.contextFree(MarkArgumentType::mark)
|
||||
)
|
||||
this.implementation.registerCommandArgument(
|
||||
cobblemonResource("transform_type"),
|
||||
TransformTypeArgumentType::class,
|
||||
SingletonArgumentInfo.contextFree(TransformTypeArgumentType::transformType)
|
||||
)
|
||||
this.implementation.registerCommandArgument(
|
||||
cobblemonResource("model_part"),
|
||||
ModelPartArgumentType::class,
|
||||
SingletonArgumentInfo.contextFree(ModelPartArgumentType::modelPart)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -117,11 +117,6 @@ interface CobblemonImplementation {
|
||||
|
||||
fun registerEntitySubPredicates()
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
fun registerMobEffects()
|
||||
|
||||
|
||||
/**
|
||||
* Add a feature to the current platform implementation.
|
||||
|
||||
@@ -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
|
||||
|
||||
import com.cobblemon.mod.common.api.cooking.effects.CleanseAllEffect
|
||||
import com.cobblemon.mod.common.api.cooking.effects.CleanseNegativeEffect
|
||||
import com.cobblemon.mod.common.api.cooking.effects.MentalRestorationEffect
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
|
||||
object CobblemonMobEffects : PlatformRegistry<Registry<MobEffect>, ResourceKey<Registry<MobEffect>>, MobEffect>() {
|
||||
override val registry: Registry<MobEffect> = BuiltInRegistries.MOB_EFFECT
|
||||
override val resourceKey: ResourceKey<Registry<MobEffect>> = Registries.MOB_EFFECT
|
||||
|
||||
@JvmField
|
||||
val CLEANSE_NEGATIVE = create("cleanse_negative", CleanseNegativeEffect())
|
||||
|
||||
@JvmField
|
||||
val MENTAL_RESTORATION = create("mental_restoration", MentalRestorationEffect())
|
||||
|
||||
@JvmField
|
||||
val CLEANSE_ALL = create("cleanse_all", CleanseAllEffect())
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
-22
@@ -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.api.cooking.effects
|
||||
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
import net.minecraft.world.effect.MobEffectCategory
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
class CleanseAllEffect : MobEffect(MobEffectCategory.BENEFICIAL, 0xFFFFFF) {
|
||||
override fun isInstantenous() = true
|
||||
override fun applyInstantenousEffect(source: Entity?, indirect: Entity?, target: LivingEntity, amplifier: Int, proximity: Double) {
|
||||
target.removeAllEffects()
|
||||
}
|
||||
override fun shouldApplyEffectTickThisTick(duration: Int, amplifier: Int) = false
|
||||
}
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cooking.effects
|
||||
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
import net.minecraft.world.effect.MobEffectCategory
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
class CleanseNegativeEffect : MobEffect(MobEffectCategory.BENEFICIAL, 0xFFFFFF) {
|
||||
override fun isInstantenous() = true
|
||||
override fun applyInstantenousEffect(source: Entity?, indirect: Entity?, target: LivingEntity, amplifier: Int, proximity: Double) {
|
||||
val snapshot = target.activeEffects.toList()
|
||||
for (ei in snapshot) {
|
||||
if (ei.effect.value().category == MobEffectCategory.HARMFUL) {
|
||||
target.removeEffect(ei.effect)
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun shouldApplyEffectTickThisTick(duration: Int, amplifier: Int) = false
|
||||
}
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cooking.effects
|
||||
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.stats.Stats
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
import net.minecraft.world.effect.MobEffectCategory
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
class MentalRestorationEffect : MobEffect(MobEffectCategory.BENEFICIAL, 0xAA66FF) {
|
||||
override fun applyEffectTick(entity: LivingEntity, amplifier: Int): Boolean {
|
||||
if (entity is ServerPlayer) {
|
||||
val stats = entity.stats
|
||||
val statType = Stats.CUSTOM.get(Stats.TIME_SINCE_REST)
|
||||
val current = stats.getValue(statType)
|
||||
val reduction = 31 * (amplifier + 1)// reduce by half a minute every second per level (30 ticks removed per tick + 1 to account for the tick passing)
|
||||
val newValue = Math.max(current - reduction, 0)
|
||||
stats.setValue(entity, statType, newValue)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun shouldApplyEffectTickThisTick(duration: Int, amplifier: Int): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
+2
-7
@@ -12,10 +12,10 @@ import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.pokemon.requirement.OwnerQueryRequirement
|
||||
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.data.PokemonInteractionsSyncPacket
|
||||
import com.cobblemon.mod.common.pokemon.adapters.CobblemonRequirementAdapter
|
||||
import com.cobblemon.mod.common.pokemon.evolution.adapters.LegacyItemConditionWrapperAdapter
|
||||
import com.cobblemon.mod.common.pokemon.requirements.PokemonPropertiesRequirement
|
||||
@@ -51,12 +51,7 @@ object PokemonInteractions : JsonDataRegistry<PokemonInteractionSet> {
|
||||
val speciesInteractions = mutableListOf<PokemonInteractionSet>()
|
||||
val generalInteractions = mutableListOf<PokemonInteractionSet>()
|
||||
|
||||
override fun sync(player: ServerPlayer) {
|
||||
PokemonInteractionsSyncPacket(
|
||||
speciesInteractions,
|
||||
generalInteractions,
|
||||
).sendToPlayer(player)
|
||||
}
|
||||
override fun sync(player: ServerPlayer) {}
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, PokemonInteractionSet>) {
|
||||
speciesInteractions.clear()
|
||||
|
||||
+19
-88
@@ -15,10 +15,11 @@ import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
|
||||
import com.cobblemon.mod.common.pokemon.adapters.CobblemonRequirementAdapter
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.giveOrDropItemStack
|
||||
import com.cobblemon.mod.common.util.withPlayerValue
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.sounds.SoundSource
|
||||
@@ -27,83 +28,30 @@ import net.minecraft.world.entity.EquipmentSlot
|
||||
import net.minecraft.world.entity.item.ItemEntity
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
/**
|
||||
* A
|
||||
*/
|
||||
data class PokemonInteractionSet(
|
||||
val requirements: List<Requirement> = listOf(),
|
||||
val interactions: List<PokemonInteraction> = listOf(),
|
||||
) {
|
||||
fun encode(buffer: FriendlyByteBuf) {
|
||||
buffer.writeCollection(requirements) { it, requirement ->
|
||||
CobblemonRequirementAdapter.encode(requirement, it)
|
||||
}
|
||||
buffer.writeCollection(interactions) { it, interaction ->
|
||||
interaction.encode(it)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: FriendlyByteBuf): PokemonInteractionSet {
|
||||
val requirements = buffer.readList { it ->
|
||||
CobblemonRequirementAdapter.decode(it)
|
||||
}
|
||||
val interactions = buffer.readList { it ->
|
||||
PokemonInteraction.decode(it)
|
||||
}
|
||||
|
||||
return PokemonInteractionSet(
|
||||
requirements,
|
||||
interactions,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val interactions: List<PokemonInteraction> = listOf()
|
||||
)
|
||||
data class PokemonInteraction(
|
||||
val grouping: ResourceLocation,
|
||||
val requirements: List<Requirement> = listOf(),
|
||||
val effects: List<InteractionEffect> = listOf(),
|
||||
val cooldown: ExpressionLike = "0".asExpressionLike()
|
||||
) {
|
||||
fun encode(buffer: FriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(grouping)
|
||||
buffer.writeCollection(requirements) { it, requirement ->
|
||||
CobblemonRequirementAdapter.encode(requirement, it)
|
||||
}
|
||||
buffer.writeExpressionLike(cooldown)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: FriendlyByteBuf): PokemonInteraction {
|
||||
val grouping = buffer.readResourceLocation()
|
||||
val requirements = buffer.readList { it ->
|
||||
CobblemonRequirementAdapter.decode(it)
|
||||
}
|
||||
|
||||
// No need to sync these for now
|
||||
val effects = emptyList<InteractionEffect>()
|
||||
val cooldown = buffer.readExpressionLike()
|
||||
|
||||
return PokemonInteraction(
|
||||
grouping,
|
||||
requirements,
|
||||
effects,
|
||||
cooldown,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
interface InteractionEffect {
|
||||
fun applyEffect(pokemon: PokemonEntity, player: ServerPlayer)
|
||||
}
|
||||
|
||||
class DropItemEffect(val item: ResourceLocation, val amount: IntRange?) : InteractionEffect {
|
||||
class DropItemEffect(val item: ResourceLocation, val amount: IntRange?): InteractionEffect {
|
||||
override fun applyEffect(
|
||||
pokemon: PokemonEntity,
|
||||
player: ServerPlayer
|
||||
) {
|
||||
val item = player.registryAccess().registryOrThrow(Registries.ITEM).get(item) ?: throw IllegalArgumentException(
|
||||
"Cannot load item with id: $item"
|
||||
)
|
||||
val item = player.registryAccess().registryOrThrow(Registries.ITEM).get(item) ?: throw IllegalArgumentException("Cannot load item with id: $item")
|
||||
val stack = ItemStack(item)
|
||||
stack.count = amount?.randomOrNull() ?: 1
|
||||
if (stack.isEmpty)
|
||||
@@ -120,14 +68,12 @@ class DropItemEffect(val item: ResourceLocation, val amount: IntRange?) : Intera
|
||||
}
|
||||
}
|
||||
|
||||
class GiveItemEffect(val item: ResourceLocation, val amount: IntRange?) : InteractionEffect {
|
||||
class GiveItemEffect(val item: ResourceLocation, val amount: IntRange?): InteractionEffect {
|
||||
override fun applyEffect(
|
||||
pokemon: PokemonEntity,
|
||||
player: ServerPlayer
|
||||
) {
|
||||
val item = player.registryAccess().registryOrThrow(Registries.ITEM).get(item) ?: throw IllegalArgumentException(
|
||||
"Cannot load item with id: $item"
|
||||
)
|
||||
val item = player.registryAccess().registryOrThrow(Registries.ITEM).get(item) ?: throw IllegalArgumentException("Cannot load item with id: $item")
|
||||
val stack = ItemStack(item)
|
||||
stack.count = amount?.randomOrNull() ?: 1
|
||||
if (stack.isEmpty)
|
||||
@@ -140,29 +86,14 @@ class GiveItemEffect(val item: ResourceLocation, val amount: IntRange?) : Intera
|
||||
}
|
||||
}
|
||||
|
||||
class PlaySoundEffect(
|
||||
val sound: ResourceLocation,
|
||||
val soundSource: SoundSource?,
|
||||
val playAround: Boolean = true,
|
||||
val distance: Double = 64.0,
|
||||
val volume: Float = 1.0F,
|
||||
val pitch: Float = 1.0F
|
||||
) : InteractionEffect {
|
||||
class PlaySoundEffect(val sound: ResourceLocation, val soundSource: SoundSource?, val playAround: Boolean = true, val distance: Double = 64.0, val volume: Float = 1.0F, val pitch: Float = 1.0F): InteractionEffect {
|
||||
override fun applyEffect(
|
||||
pokemon: PokemonEntity,
|
||||
player: ServerPlayer
|
||||
) {
|
||||
val packet = UnvalidatedPlaySoundS2CPacket(
|
||||
sound,
|
||||
soundSource ?: SoundSource.NEUTRAL,
|
||||
pokemon.x,
|
||||
pokemon.y,
|
||||
pokemon.z,
|
||||
volume,
|
||||
pitch
|
||||
)
|
||||
val packet = UnvalidatedPlaySoundS2CPacket(sound, soundSource ?: SoundSource.NEUTRAL, pokemon.x, pokemon.y, pokemon.z, volume, pitch)
|
||||
if (playAround) {
|
||||
packet.sendToPlayersAround(pokemon.x, pokemon.y, pokemon.z, distance, pokemon.level().dimension())
|
||||
packet.sendToPlayersAround( pokemon.x, pokemon.y, pokemon.z, distance, pokemon.level().dimension())
|
||||
} else {
|
||||
packet.sendToPlayer(player)
|
||||
}
|
||||
@@ -173,7 +104,7 @@ class PlaySoundEffect(
|
||||
}
|
||||
}
|
||||
|
||||
class ShrinkItemEffect(val amount: Int = 1) : InteractionEffect {
|
||||
class ShrinkItemEffect(val amount: Int = 1): InteractionEffect {
|
||||
override fun applyEffect(
|
||||
pokemon: PokemonEntity,
|
||||
player: ServerPlayer
|
||||
@@ -189,7 +120,7 @@ class ShrinkItemEffect(val amount: Int = 1) : InteractionEffect {
|
||||
}
|
||||
}
|
||||
|
||||
class ScriptEffect(val script: ExpressionLike) : InteractionEffect {
|
||||
class ScriptEffect(val script: ExpressionLike): InteractionEffect {
|
||||
override fun applyEffect(
|
||||
pokemon: PokemonEntity,
|
||||
player: ServerPlayer
|
||||
|
||||
@@ -779,20 +779,6 @@ object MoLangFunctions {
|
||||
battleStartResult.ifSuccessful { returnValue = it.struct }
|
||||
return@put returnValue
|
||||
}
|
||||
map.put("get_custom_stat") { params ->
|
||||
val statName = params.getString(0)
|
||||
|
||||
val resourceLocation = ResourceLocation.tryParse(statName) ?: return@put DoubleValue.ZERO
|
||||
val statResourceLocation = BuiltInRegistries.CUSTOM_STAT.get(resourceLocation) ?: return@put DoubleValue.ZERO
|
||||
|
||||
val exists = net.minecraft.stats.Stats.CUSTOM.contains(statResourceLocation)
|
||||
if (!exists) return@put DoubleValue.ZERO
|
||||
|
||||
val stat = net.minecraft.stats.Stats.CUSTOM.get(statResourceLocation)
|
||||
val value = player.stats.getValue(stat)
|
||||
|
||||
DoubleValue(value)
|
||||
}
|
||||
}
|
||||
map
|
||||
}
|
||||
@@ -1753,35 +1739,22 @@ object MoLangFunctions {
|
||||
pokemon.removeCosmeticItem()
|
||||
}
|
||||
map.put("add_marks") { params ->
|
||||
var appliedMark = false
|
||||
for (param in params.params) {
|
||||
val identifier = param.asString().asIdentifierDefaultingNamespace()
|
||||
val mark = Marks.getByIdentifier(identifier)
|
||||
if (mark != null) {
|
||||
pokemon.exchangeMark(mark, true)
|
||||
appliedMark = true
|
||||
}
|
||||
if (mark != null) pokemon.exchangeMark(mark, true)
|
||||
}
|
||||
|
||||
DoubleValue(appliedMark)
|
||||
}
|
||||
map.put("add_marks_with_chance") { params ->
|
||||
var appliedMark = false
|
||||
for (param in params.params) {
|
||||
val identifier = param.asString().asIdentifierDefaultingNamespace()
|
||||
val mark = Marks.getByIdentifier(identifier)
|
||||
|
||||
mark?.let {
|
||||
val probability = it.chance.coerceIn(0F, 1F) * 100
|
||||
val randomValue = Random.nextDouble(0.0, 100.0)
|
||||
if (randomValue < probability) {
|
||||
pokemon.exchangeMark(it, true)
|
||||
appliedMark = true
|
||||
}
|
||||
if (randomValue < probability) pokemon.exchangeMark(it, true)
|
||||
}
|
||||
}
|
||||
|
||||
DoubleValue(appliedMark)
|
||||
}
|
||||
map.put("add_potential_marks") { params ->
|
||||
for (param in params.params) {
|
||||
|
||||
+4
-5
@@ -12,7 +12,6 @@ import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
|
||||
/**
|
||||
* A [Requirement] that expects a [LivingEntity] to be attached to the [Pokemon].
|
||||
@@ -27,7 +26,7 @@ interface OwnerQueryRequirement : Requirement {
|
||||
override fun check(pokemon: Pokemon): Boolean {
|
||||
val owner = pokemon.getOwnerEntity() ?: return false
|
||||
return when (owner) {
|
||||
is Player -> {
|
||||
is ServerPlayer -> {
|
||||
this.checkPlayer(pokemon, owner)
|
||||
}
|
||||
is NPCEntity -> {
|
||||
@@ -38,13 +37,13 @@ interface OwnerQueryRequirement : Requirement {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given [Pokemon] & [Player] satisfies the requirement.
|
||||
* Checks if the given [Pokemon] & [ServerPlayer] satisfies the requirement.
|
||||
*
|
||||
* @param pokemon The [Pokemon] being queried.
|
||||
* @param owner The [Player] that owns this [Pokemon].
|
||||
* @param owner The [ServerPlayer] that owns this [Pokemon].
|
||||
* @return If the requirement was satisfied.
|
||||
*/
|
||||
fun checkPlayer(pokemon: Pokemon, owner: Player): Boolean
|
||||
fun checkPlayer(pokemon: Pokemon, owner: ServerPlayer): Boolean
|
||||
|
||||
/**
|
||||
* Checks if the given [Pokemon] & [NPCEntity] satisfies the requirement.
|
||||
|
||||
+6
-8
@@ -22,7 +22,6 @@ import com.cobblemon.mod.common.api.riding.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.api.riding.sound.RideSoundSettingsList
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.blockPositionsAsListRounded
|
||||
@@ -145,12 +144,11 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
) {
|
||||
val sprintTimerTickLength = 7 // Emulate vanillas tick timer length
|
||||
var hasDoubleTapped = false
|
||||
val forward = Minecraft.getInstance().player?.input?.up == true
|
||||
|
||||
// If you are not sprinting and you just pressed down and theres no
|
||||
if (!state.forwardHeldLastTick.get() && forward && !state.sprinting.get() && state.sprintTickTimer.get() == 0) {
|
||||
if (!state.forwardHeldLastTick.get() && Minecraft.getInstance().options.keyUp.isDown() && !state.sprinting.get() && state.sprintTickTimer.get() == 0) {
|
||||
state.sprintTickTimer.set(sprintTimerTickLength)
|
||||
} else if (!state.forwardHeldLastTick.get() && forward && state.sprintTickTimer.get() != 0) { // If has double tapped
|
||||
} else if (!state.forwardHeldLastTick.get() && Minecraft.getInstance().options.keyUp.isDown() && state.sprintTickTimer.get() != 0) { // If has double tapped
|
||||
hasDoubleTapped = true
|
||||
}else if(!state.sprinting.get() && state.sprintTickTimer.get() > 0) {
|
||||
state.sprintTickTimer.set(state.sprintTickTimer.get() - 1)
|
||||
@@ -158,9 +156,9 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
state.sprintTickTimer.set(0)
|
||||
}
|
||||
|
||||
val tryingToSprint = hasDoubleTapped || CobblemonClient.ridingSprintHandler.any { it.value.invoke() }
|
||||
val tryingToSprint = (Minecraft.getInstance().options.keySprint.isDown() && Minecraft.getInstance().options.keyUp.isDown()) || hasDoubleTapped
|
||||
|
||||
if (state.stamina.get() <= 0.0f || !forward) {
|
||||
if (state.stamina.get() <= 0.0f || !Minecraft.getInstance().options.keyUp.isDown()) {
|
||||
// If stamina runs out or the player is not holding forward then stop sprinting
|
||||
state.sprinting.set(false)
|
||||
if (state.stamina.get() <= 0.0f) {
|
||||
@@ -174,8 +172,8 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
state.sprinting.set(true)
|
||||
}
|
||||
|
||||
// Take note of whether forward was held last tick
|
||||
state.forwardHeldLastTick.set(forward)
|
||||
// Take not of whether forward was held last tick
|
||||
state.forwardHeldLastTick.set(Minecraft.getInstance().options.keyUp.isDown())
|
||||
}
|
||||
|
||||
fun tickStamina(
|
||||
|
||||
@@ -12,7 +12,6 @@ package com.cobblemon.mod.common.api.riding.sound
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.composite.CompositeBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.composite.CompositeState
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.getIsSubmerged
|
||||
import com.cobblemon.mod.common.util.resolveDouble
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance
|
||||
@@ -66,21 +65,6 @@ class RideLoopSound(val ride: PokemonEntity, val soundSettings: RideSoundSetting
|
||||
return
|
||||
}
|
||||
|
||||
// Mute the sound if it's not meant to play for the passenger
|
||||
if (this.isPassenger && !this.soundSettings.playForPassengers) {
|
||||
this.volume = 0.0f
|
||||
return
|
||||
}
|
||||
|
||||
// Mute sounds when submerged unless they support underwater sounds, underwater sounds don't play above water
|
||||
if (this.ride.getIsSubmerged() && !this.soundSettings.submerged) {
|
||||
this.volume = 0.0f
|
||||
return
|
||||
} else if (!this.ride.getIsSubmerged() && this.soundSettings.submerged) {
|
||||
this.volume = 0.0f
|
||||
return
|
||||
}
|
||||
|
||||
// Perform data driven pitch and volume calculation
|
||||
this.volume = ((soundSettings.volumeExpr.let { ride.runtime.resolveDouble(it) })).toFloat()
|
||||
this.volume *= this.fade
|
||||
|
||||
-8
@@ -27,9 +27,7 @@ data class RideSoundSettings(
|
||||
val soundLocation: ResourceLocation,
|
||||
@SerializedName("volumeExpr") private val _volumeExpr: Expression? = "1.0".asExpression(),
|
||||
@SerializedName("pitchExpr") private val _pitchExpr: Expression? = "1.0".asExpression(),
|
||||
val playForPassengers: Boolean = true,
|
||||
val playForNonPassengers: Boolean = false,
|
||||
val submerged: Boolean = false,
|
||||
val muffleEnabled: Boolean = false,
|
||||
@SerializedName("attenuationModel") private val _attenuationModel: RideAttenuationModel? = RideAttenuationModel.NONE
|
||||
): Encodable {
|
||||
@@ -48,9 +46,7 @@ data class RideSoundSettings(
|
||||
buffer.writeResourceLocation(soundLocation)
|
||||
buffer.writeExpression(volumeExpr)
|
||||
buffer.writeExpression(pitchExpr)
|
||||
buffer.writeBoolean(playForPassengers)
|
||||
buffer.writeBoolean(playForNonPassengers)
|
||||
buffer.writeBoolean(submerged)
|
||||
buffer.writeBoolean(muffleEnabled)
|
||||
buffer.writeEnum(attenuationModel)
|
||||
}
|
||||
@@ -61,9 +57,7 @@ data class RideSoundSettings(
|
||||
val soundLocation = buffer.readResourceLocation()
|
||||
val volumeExpr = buffer.readExpression()
|
||||
val pitchExpr = buffer.readExpression()
|
||||
val playForPassengers = buffer.readBoolean()
|
||||
val playForNonPassengers = buffer.readBoolean()
|
||||
val submerged = buffer.readBoolean()
|
||||
val muffleEnabled = buffer.readBoolean()
|
||||
val attenuationModel = buffer.readEnum(RideAttenuationModel::class.java)
|
||||
|
||||
@@ -71,9 +65,7 @@ data class RideSoundSettings(
|
||||
soundLocation,
|
||||
volumeExpr,
|
||||
pitchExpr,
|
||||
playForPassengers,
|
||||
playForNonPassengers,
|
||||
submerged,
|
||||
muffleEnabled,
|
||||
attenuationModel
|
||||
)
|
||||
|
||||
@@ -8,58 +8,30 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.stats
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.stats.StatFormatter
|
||||
|
||||
object CobblemonStats {
|
||||
val stats = mutableMapOf<String, CobblemonStat>()
|
||||
val stats = mutableMapOf<String, ResourceLocation>()
|
||||
|
||||
@JvmField
|
||||
var CAPTURED: CobblemonStat = CobblemonStat("captured")
|
||||
@JvmField
|
||||
val SHINIES_CAPTURED: CobblemonStat = CobblemonStat("shinies_captured")
|
||||
@JvmField
|
||||
val RELEASED: CobblemonStat = CobblemonStat("released")
|
||||
@JvmField
|
||||
val EVOLVED: CobblemonStat = CobblemonStat("evolved")
|
||||
@JvmField
|
||||
val LEVEL_UP: CobblemonStat = CobblemonStat("level_up")
|
||||
@JvmField
|
||||
val BATTLES_WON: CobblemonStat = CobblemonStat("battles_won")
|
||||
@JvmField
|
||||
val BATTLES_LOST: CobblemonStat = CobblemonStat("battles_lost")
|
||||
@JvmField
|
||||
val BATTLES_FLED: CobblemonStat = CobblemonStat("battles_fled")
|
||||
@JvmField
|
||||
val BATTLES_TOTAL: CobblemonStat = CobblemonStat("battles_total")
|
||||
@JvmField
|
||||
val DEX_ENTRIES: CobblemonStat = CobblemonStat("dex_entries")
|
||||
@JvmField
|
||||
val EGGS_COLLECTED: CobblemonStat = CobblemonStat("eggs_collected")
|
||||
@JvmField
|
||||
val EGGS_HATCHED: CobblemonStat = CobblemonStat("eggs_hatched")
|
||||
@JvmField
|
||||
val TRADED: CobblemonStat = CobblemonStat("traded")
|
||||
@JvmField
|
||||
val FOSSILS_REVIVED: CobblemonStat = CobblemonStat("fossils_revived")
|
||||
@JvmField
|
||||
val TIMES_RIDDEN: CobblemonStat = CobblemonStat("times_ridden")
|
||||
@JvmField
|
||||
val ROD_CASTS: CobblemonStat = CobblemonStat("rod_casts")
|
||||
@JvmField
|
||||
val REEL_INS: CobblemonStat = CobblemonStat("reel_ins")
|
||||
@JvmField
|
||||
val POKEMON_INTERACTED_WITH: CobblemonStat = CobblemonStat("pokemon_interacted_with")
|
||||
@JvmField
|
||||
val RIDING_LAND: CobblemonStat = CobblemonStat("riding_land", StatFormatter.DISTANCE)
|
||||
@JvmField
|
||||
val RIDING_AIR: CobblemonStat = CobblemonStat("riding_air", StatFormatter.DISTANCE)
|
||||
@JvmField
|
||||
val RIDING_LIQUID: CobblemonStat = CobblemonStat("riding_liquid", StatFormatter.DISTANCE)
|
||||
|
||||
//TODO block, stats (interact, gimmi)
|
||||
var CAPTURED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "captured") //makeCustomStat("captured", StatFormatter.DEFAULT)
|
||||
val SHINIES_CAPTURED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "shinies_captured") //makeCustomStat("shinies_captured", StatFormatter.DEFAULT)
|
||||
val RELEASED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "released") //makeCustomStat("released", StatFormatter.DEFAULT)
|
||||
val EVOLVED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "evolved") //makeCustomStat("evolved", StatFormatter.DEFAULT)
|
||||
val LEVEL_UP: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "level_up") //makeCustomStat("level_up", StatFormatter.DEFAULT)
|
||||
val BATTLES_WON: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "battles_won") //makeCustomStat("battles_won", StatFormatter.DEFAULT)
|
||||
val BATTLES_LOST: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "battles_lost") //makeCustomStat("battles_lost", StatFormatter.DEFAULT)
|
||||
val BATTLES_FLED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "battles_fled") //makeCustomStat("battles_fled", StatFormatter.DEFAULT)
|
||||
val BATTLES_TOTAL: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "battles_total") //makeCustomStat("battles_total", StatFormatter.DEFAULT)
|
||||
val DEX_ENTRIES: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "dex_entries") //makeCustomStat("dex_entries", StatFormatter.DEFAULT)
|
||||
val EGGS_COLLECTED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "eggs_collected") //makeCustomStat("eggs_collected", StatFormatter.DEFAULT)
|
||||
val EGGS_HATCHED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "eggs_hatched") //makeCustomStat("eggs_hatched", StatFormatter.DEFAULT)
|
||||
val TRADED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "traded") //makeCustomStat("traded", StatFormatter.DEFAULT)
|
||||
val FOSSILS_REVIVED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "fossils_revived") //makeCustomStat("fossils_revived", StatFormatter.DEFAULT)
|
||||
val TIMES_RIDDEN: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "times_ridden")
|
||||
val ROD_CASTS: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "rod_casts")
|
||||
val REEL_INS: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "reel_ins")
|
||||
val POKEMON_INTERACTED_WITH: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "pokemon_interacted_with") //makeCustomStat("pokemon_interacted_with", StatFormatter.DEFAULT)
|
||||
//TODO block, stats (interact, gimmi), riding (styles?)
|
||||
|
||||
fun registerStats() {
|
||||
stats["captured"] = CAPTURED
|
||||
@@ -80,22 +52,5 @@ object CobblemonStats {
|
||||
stats["rod_casts"] = ROD_CASTS
|
||||
stats["reel_ins"] = REEL_INS
|
||||
stats["pokemon_interacted_with"] = POKEMON_INTERACTED_WITH
|
||||
stats["riding_land"] = RIDING_LAND
|
||||
stats["riding_air"] = RIDING_AIR
|
||||
stats["riding_liquid"] = RIDING_LIQUID
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getStat(cobblemonStat: CobblemonStat) : ResourceLocation {
|
||||
val resourceLocation = cobblemonStat.resourceLocation
|
||||
val stat = BuiltInRegistries.CUSTOM_STAT.get(resourceLocation)
|
||||
if (stat == null) {
|
||||
Cobblemon.LOGGER.error("Could not find stat with id {}", resourceLocation)
|
||||
}
|
||||
return stat ?: throw NullPointerException("Could not find stat with id $resourceLocation")
|
||||
}
|
||||
|
||||
data class CobblemonStat(val path: String, val formatter: StatFormatter = StatFormatter.DEFAULT) {
|
||||
val resourceLocation: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
|
||||
package com.cobblemon.mod.common.client
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.Cobblemon.cobblemonVR
|
||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||
import com.cobblemon.mod.common.CobblemonBlocks
|
||||
import com.cobblemon.mod.common.CobblemonClientImplementation
|
||||
@@ -27,6 +29,7 @@ import com.cobblemon.mod.common.client.gui.PartyOverlayDataControl
|
||||
import com.cobblemon.mod.common.client.gui.RideControlsOverlay
|
||||
import com.cobblemon.mod.common.client.gui.battle.BattleOverlay
|
||||
import com.cobblemon.mod.common.client.gui.cookingpot.CookingPotScreen
|
||||
import com.cobblemon.mod.common.client.integration.vivecraft.CobblemonVRClient
|
||||
import com.cobblemon.mod.common.client.particle.BedrockParticleOptionsRepository
|
||||
import com.cobblemon.mod.common.client.render.ClientPlayerIcon
|
||||
import com.cobblemon.mod.common.client.render.DeferredRenderer
|
||||
@@ -72,9 +75,9 @@ import com.cobblemon.mod.common.client.tooltips.TooltipManager
|
||||
import com.cobblemon.mod.common.client.trade.ClientTrade
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.integration.vivecraft.CobblemonVR
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.isLookingAt
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.color.block.BlockColor
|
||||
@@ -84,19 +87,16 @@ import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.client.model.BoatModel
|
||||
import net.minecraft.client.model.ChestBoatModel
|
||||
import net.minecraft.client.model.PlayerModel
|
||||
import net.minecraft.client.player.LocalPlayer
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.client.renderer.blockentity.HangingSignRenderer
|
||||
import net.minecraft.client.renderer.blockentity.SignRenderer
|
||||
import net.minecraft.client.renderer.entity.EntityRenderer
|
||||
import net.minecraft.client.renderer.entity.LivingEntityRenderer
|
||||
import net.minecraft.client.resources.PlayerSkin
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.packs.resources.ResourceManager
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.AABB
|
||||
import org.joml.Vector2d
|
||||
|
||||
object CobblemonClient {
|
||||
|
||||
@@ -116,8 +116,6 @@ object CobblemonClient {
|
||||
val battleOverlay: BattleOverlay by lazy { BattleOverlay() }
|
||||
val pokedexUsageContext: PokedexUsageContext by lazy { PokedexUsageContext() }
|
||||
val rideControlsOverlay: RideControlsOverlay by lazy { RideControlsOverlay() }
|
||||
val ridingTurnInputHandler: MutableMap<ResourceLocation, (LocalPlayer, Double, Double, Double) -> Vector2d> = mutableMapOf()
|
||||
val ridingSprintHandler: MutableMap<ResourceLocation, () -> Boolean> = mutableMapOf()
|
||||
|
||||
fun onLogin() {
|
||||
clientPlayerData = ClientGeneralPlayerData()
|
||||
@@ -158,6 +156,10 @@ object CobblemonClient {
|
||||
this.registerTooltipManagers()
|
||||
this.registerMenuScreens()
|
||||
|
||||
if (Cobblemon.implementation.isModInstalled("vivecraft")) { // VR integration
|
||||
CobblemonVRClient.init()
|
||||
}
|
||||
|
||||
LOGGER.info("Registering custom BuiltinItemRenderers")
|
||||
CobblemonBuiltinItemRendererRegistry.register(CobblemonItems.POKEMON_MODEL, PokemonItemRenderer())
|
||||
|
||||
@@ -193,7 +195,9 @@ object CobblemonClient {
|
||||
|
||||
nearbyPokemon?.forEach { entity ->
|
||||
if (entity is PokemonEntity && !entity.isSilent && !entity.passengers.contains(player)) {
|
||||
if (player.isLookingAt(entity) && !player.isSpectator && entity.pokemon.shiny) entity.delegate.spawnShinyParticle(player)
|
||||
if (player.isLookingAt(entity) && !player.isSpectator && entity.pokemon.shiny) entity.delegate.spawnShinyParticle(
|
||||
player
|
||||
)
|
||||
entity.delegate.spawnAspectParticle()
|
||||
}
|
||||
}
|
||||
@@ -201,8 +205,6 @@ object CobblemonClient {
|
||||
ClientPlayerIcon.onTick()
|
||||
PartyOverlayDataControl.tick(event.client.isPaused)
|
||||
}
|
||||
|
||||
ridingSprintHandler.put(cobblemonResource("normal")) { Minecraft.getInstance().options.keySprint.isDown }
|
||||
}
|
||||
|
||||
private fun registerTooltipManagers() {
|
||||
@@ -377,7 +379,10 @@ object CobblemonClient {
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.DISPLAY_CASE, ::DisplayCaseRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.LECTERN, ::LecternBlockEntityRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.CAMPFIRE, ::CampfireBlockEntityRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.POKE_SNACK, ::PokeSnackBlockEntityRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(
|
||||
CobblemonBlockEntities.POKE_SNACK,
|
||||
::PokeSnackBlockEntityRenderer
|
||||
)
|
||||
}
|
||||
|
||||
private fun registerEntityRenderers() {
|
||||
@@ -406,7 +411,11 @@ object CobblemonClient {
|
||||
|
||||
private fun registerItemColors() {
|
||||
implementation.registerItemColors(AprijuiceItemColorProvider, *CobblemonItems.aprijuices.toTypedArray())
|
||||
implementation.registerItemColors(PokeSnackItemColorProvider, CobblemonItems.POKE_SNACK, CobblemonItems.POKE_CAKE)
|
||||
implementation.registerItemColors(
|
||||
PokeSnackItemColorProvider,
|
||||
CobblemonItems.POKE_SNACK,
|
||||
CobblemonItems.POKE_CAKE
|
||||
)
|
||||
implementation.registerItemColors(PokeBaitItemColorProvider, CobblemonItems.POKE_BAIT)
|
||||
implementation.registerItemColors(PonigiriItemColorProvider, CobblemonItems.PONIGIRI)
|
||||
implementation.registerItemColors(SinisterTeaItemColorProvider, CobblemonItems.SINISTER_TEA)
|
||||
|
||||
+2
-2
@@ -74,12 +74,12 @@ class InteractWheelButton(
|
||||
y = y,
|
||||
width = width,
|
||||
height = height,
|
||||
vOffset = if ((isHovered(mouseX.toFloat(), mouseY.toFloat()) || isFocused) && isEnabled) height else 0,
|
||||
vOffset = if (isHovered(mouseX.toFloat(), mouseY.toFloat()) && isEnabled) height else 0,
|
||||
textureHeight = height * 2,
|
||||
alpha = if (isEnabled) 1f else 0.4F
|
||||
)
|
||||
|
||||
if(isEnabled && (isHovered(mouseX.toFloat(), mouseY.toFloat()) || isFocused)){
|
||||
if(isEnabled && isHovered(mouseX.toFloat(), mouseY.toFloat())){
|
||||
tooltipText?.let {
|
||||
context.renderTooltip(Minecraft.getInstance().font, Component.translatable(it), mouseX, mouseY)
|
||||
}
|
||||
|
||||
+4
-4
@@ -23,9 +23,9 @@ class InteractWheelGUI(private val options: Multimap<Orientation, InteractWheelO
|
||||
private val backgroundResource = cobblemonResource("textures/gui/interact/interact_wheel_base.png")
|
||||
}
|
||||
|
||||
val buttons = mutableListOf<InteractWheelButton>()
|
||||
var maxPage = 1
|
||||
var currentPage = 0
|
||||
private val buttons = mutableListOf<InteractWheelButton>()
|
||||
private var maxPage = 1
|
||||
private var currentPage = 0
|
||||
override fun renderBlurredBackground(delta: Float) { }
|
||||
override fun renderMenuBackground(context: GuiGraphics) {}
|
||||
|
||||
@@ -77,7 +77,7 @@ class InteractWheelGUI(private val options: Multimap<Orientation, InteractWheelO
|
||||
currentPage = page
|
||||
buttons.forEach { removeWidget(it) }
|
||||
buttons.clear()
|
||||
val orientations = Orientation.entries.toTypedArray()
|
||||
val orientations = Orientation.values()
|
||||
orientations.forEach { orientation ->
|
||||
val option = options[orientation].toList().getOrNull(page)
|
||||
addButton(orientation, option)
|
||||
|
||||
-319
@@ -1,319 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.integration.controlify
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.CobblemonClient.ridingTurnInputHandler
|
||||
import com.cobblemon.mod.common.client.gui.battle.BattleGUI
|
||||
import com.cobblemon.mod.common.client.gui.behaviour.BehaviourEditorScreen
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen
|
||||
import com.cobblemon.mod.common.client.gui.cookingpot.CookingPotScreen
|
||||
import com.cobblemon.mod.common.client.gui.debug.riding.RidingStatsDebugGUI
|
||||
import com.cobblemon.mod.common.client.gui.dialogue.DialogueScreen
|
||||
import com.cobblemon.mod.common.client.gui.interact.battleRequest.BattleConfigureGUI
|
||||
import com.cobblemon.mod.common.client.gui.interact.moveselect.MoveSelectGUI
|
||||
import com.cobblemon.mod.common.client.gui.interact.partyselect.PartySelectGUI
|
||||
import com.cobblemon.mod.common.client.gui.interact.wheel.InteractWheelGUI
|
||||
import com.cobblemon.mod.common.client.gui.npc.NPCEditorScreen
|
||||
import com.cobblemon.mod.common.client.gui.pc.PCGUI
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUI
|
||||
import com.cobblemon.mod.common.client.gui.pokenav.PokeNav
|
||||
import com.cobblemon.mod.common.client.gui.snapshots.SnapshotWarningScreen
|
||||
import com.cobblemon.mod.common.client.gui.startselection.StarterSelectionScreen
|
||||
import com.cobblemon.mod.common.client.gui.summary.Summary
|
||||
import com.cobblemon.mod.common.client.gui.trade.TradeGUI
|
||||
import com.cobblemon.mod.common.client.integration.controlify.gui.CobblemonGUIProcessor
|
||||
import com.cobblemon.mod.common.client.integration.controlify.gui.InteractWheelProcessor
|
||||
import com.cobblemon.mod.common.client.keybind.CobblemonKeyBinds
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import dev.isxander.controlify.api.ControlifyApi
|
||||
import dev.isxander.controlify.api.bind.ControlifyBindApi
|
||||
import dev.isxander.controlify.api.bind.InputBindingBuilder
|
||||
import dev.isxander.controlify.api.bind.InputBindingSupplier
|
||||
import dev.isxander.controlify.api.entrypoint.ControlifyEntrypoint
|
||||
import dev.isxander.controlify.api.entrypoint.InitContext
|
||||
import dev.isxander.controlify.api.entrypoint.PreInitContext
|
||||
import dev.isxander.controlify.bindings.BindContext
|
||||
import dev.isxander.controlify.bindings.ControlifyBindings
|
||||
import dev.isxander.controlify.bindings.RadialIcons
|
||||
import dev.isxander.controlify.screenop.ScreenProcessorFactory
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.client.player.LocalPlayer
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.item.Items
|
||||
import org.joml.Vector2d
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.full.primaryConstructor
|
||||
|
||||
class CobblemonControlifyEntrypoint : ControlifyEntrypoint {
|
||||
override fun onControlifyInit(initContext: InitContext) {
|
||||
ridingTurnInputHandler.put(
|
||||
cobblemonResource("compat.controlify"),
|
||||
({ localPlayer: LocalPlayer, xDelta: Double, yDelta: Double, deltaTime: Double ->
|
||||
val vec = Vector2d(xDelta, yDelta)
|
||||
val controller = initContext.controlify().currentController.getOrNull()
|
||||
val vehicle = localPlayer.vehicle
|
||||
if (vehicle is OrientationControllable && vehicle.orientationController.isActive() && initContext.controlify().currentInputMode().isController && controller != null){
|
||||
val multiplier = deltaTime * 1500
|
||||
val config = controller.input().getOrNull()?.config()?.config()
|
||||
val vSensitivity = config?.vLookSensitivity ?: 0.9f
|
||||
val hSensitivity = config?.hLookSensitivity ?: 1f
|
||||
|
||||
// Should never be null once bindings are set
|
||||
var vAxis = (RIDING_DOWN!!.on(controller).analogueNow() - RIDING_UP!!.on(controller).analogueNow()).toDouble()
|
||||
var hAxis = (RIDING_RIGHT!!.on(controller).analogueNow() - RIDING_LEFT!!.on(controller).analogueNow()).toDouble()
|
||||
|
||||
vAxis *= multiplier * vSensitivity
|
||||
hAxis *= multiplier * hSensitivity
|
||||
vec.x = hAxis
|
||||
vec.y = vAxis
|
||||
}
|
||||
vec
|
||||
})
|
||||
)
|
||||
|
||||
CobblemonClient.ridingSprintHandler.put(
|
||||
cobblemonResource("compat.controlify")
|
||||
) {
|
||||
initContext.controlify().currentController.getOrNull()?.let { ControlifyBindings.SPRINT.on(it).digitalNow() } == true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onControlifyPreInit(initContext: PreInitContext) {
|
||||
val bindings = ControlifyBindApi.get()
|
||||
bindings.registerBindContext(ORIENTATION_CONTROLLER_ACTIVE)
|
||||
|
||||
RIDING_UP =
|
||||
bindings.registerBinding { builder: InputBindingBuilder ->
|
||||
builder
|
||||
.id(cobblemonResource("riding_up"))
|
||||
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
|
||||
.name(Component.translatable("controlify.bind.cobblemon.riding_up"))
|
||||
.allowedContexts(ORIENTATION_CONTROLLER_ACTIVE, BindContext.IN_GAME)
|
||||
}
|
||||
|
||||
RIDING_DOWN =
|
||||
bindings.registerBinding { builder: InputBindingBuilder ->
|
||||
builder
|
||||
.id(cobblemonResource("riding_down"))
|
||||
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
|
||||
.name(Component.translatable("controlify.bind.cobblemon.riding_down"))
|
||||
.allowedContexts(ORIENTATION_CONTROLLER_ACTIVE, BindContext.IN_GAME)
|
||||
}
|
||||
|
||||
RIDING_LEFT =
|
||||
bindings.registerBinding { builder: InputBindingBuilder ->
|
||||
builder
|
||||
.id(cobblemonResource("riding_left"))
|
||||
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
|
||||
.name(Component.translatable("controlify.bind.cobblemon.riding_left"))
|
||||
.allowedContexts(ORIENTATION_CONTROLLER_ACTIVE, BindContext.IN_GAME)
|
||||
}
|
||||
|
||||
RIDING_RIGHT =
|
||||
bindings.registerBinding { builder: InputBindingBuilder ->
|
||||
builder
|
||||
.id(cobblemonResource("riding_right"))
|
||||
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
|
||||
.name(Component.translatable("controlify.bind.cobblemon.riding_right"))
|
||||
.allowedContexts(ORIENTATION_CONTROLLER_ACTIVE, BindContext.IN_GAME)
|
||||
}
|
||||
|
||||
HIDE_PARTY =
|
||||
bindings.registerBinding { builder: InputBindingBuilder ->
|
||||
builder
|
||||
.id(cobblemonResource("hide_party"))
|
||||
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
|
||||
.name(Component.translatable("key.cobblemon.hideparty"))
|
||||
.allowedContexts(BindContext.IN_GAME)
|
||||
.radialCandidate(RadialIcons.getItem(Items.BARRIER))
|
||||
.addKeyCorrelation(CobblemonKeyBinds.HIDE_PARTY)
|
||||
.keyEmulation(CobblemonKeyBinds.HIDE_PARTY)
|
||||
}
|
||||
|
||||
SUMMARY =
|
||||
bindings.registerBinding { builder: InputBindingBuilder ->
|
||||
builder
|
||||
.id(cobblemonResource("summary"))
|
||||
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
|
||||
.name(Component.translatable("key.cobblemon.summary"))
|
||||
.allowedContexts(BindContext.IN_GAME)
|
||||
.radialCandidate(RadialIcons.getItem(CobblemonItems.GREAT_BALL))
|
||||
.addKeyCorrelation(CobblemonKeyBinds.SUMMARY)
|
||||
.keyEmulation(CobblemonKeyBinds.SUMMARY)
|
||||
}
|
||||
|
||||
PARTY_OVERLAY_DOWN =
|
||||
bindings.registerBinding { builder: InputBindingBuilder ->
|
||||
builder
|
||||
.id(cobblemonResource("party_overlay_down"))
|
||||
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
|
||||
.name(Component.translatable("key.cobblemon.downshiftparty"))
|
||||
.allowedContexts(HAS_POKEMON, BindContext.IN_GAME)
|
||||
.radialCandidate(RadialIcons.EMPTY)
|
||||
.addKeyCorrelation(CobblemonKeyBinds.PARTY_OVERLAY_DOWN)
|
||||
.keyEmulation(CobblemonKeyBinds.PARTY_OVERLAY_DOWN)
|
||||
}
|
||||
|
||||
PARTY_OVERLAY_UP =
|
||||
bindings.registerBinding { builder: InputBindingBuilder ->
|
||||
builder
|
||||
.id(cobblemonResource("party_overlay_up"))
|
||||
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
|
||||
.name(Component.translatable("key.cobblemon.upshiftparty"))
|
||||
.allowedContexts(HAS_POKEMON, BindContext.IN_GAME)
|
||||
.radialCandidate(RadialIcons.EMPTY)
|
||||
.addKeyCorrelation(CobblemonKeyBinds.PARTY_OVERLAY_UP)
|
||||
.keyEmulation(CobblemonKeyBinds.PARTY_OVERLAY_DOWN)
|
||||
}
|
||||
|
||||
SEND_OUT_POKEMON =
|
||||
bindings.registerBinding { builder: InputBindingBuilder ->
|
||||
builder
|
||||
.id(cobblemonResource("send_out_pokemon"))
|
||||
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
|
||||
.name(Component.translatable("key.cobblemon.throwpartypokemon"))
|
||||
.allowedContexts(HAS_POKEMON, BindContext.IN_GAME)
|
||||
.radialCandidate(RadialIcons.getItem(CobblemonItems.POKE_BALL))
|
||||
.addKeyCorrelation(CobblemonKeyBinds.SEND_OUT_POKEMON)
|
||||
.keyEmulation(CobblemonKeyBinds.SEND_OUT_POKEMON)
|
||||
}
|
||||
|
||||
|
||||
RIDING_FREELOOK =
|
||||
bindings.registerBinding { builder: InputBindingBuilder ->
|
||||
builder
|
||||
.id(cobblemonResource("riding_freelook"))
|
||||
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
|
||||
.name(Component.translatable("key.cobblemon.ridingfreelook"))
|
||||
.allowedContexts(RIDING_POKEMON, BindContext.IN_GAME)
|
||||
.radialCandidate(RadialIcons.EMPTY)
|
||||
.addKeyCorrelation(CobblemonKeyBinds.RIDING_FREELOOK)
|
||||
.keyEmulation(CobblemonKeyBinds.RIDING_FREELOOK)
|
||||
}
|
||||
|
||||
INTERACT_WHEEL_UP_AXIS =
|
||||
bindings.registerBinding { builder: InputBindingBuilder ->
|
||||
builder
|
||||
.id(cobblemonResource("interact_wheel_up"))
|
||||
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
|
||||
.name(Component.translatable("controlify.bind.cobblemon.interact_wheel_up"))
|
||||
.allowedContexts(INTERACT_WHEEL_SCREEN, BindContext.IN_GAME)
|
||||
}
|
||||
|
||||
INTERACT_WHEEL_DOWN_AXIS =
|
||||
bindings.registerBinding { builder: InputBindingBuilder ->
|
||||
builder
|
||||
.id(cobblemonResource("interact_wheel_down"))
|
||||
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
|
||||
.name(Component.translatable("controlify.bind.cobblemon.interact_wheel_down"))
|
||||
.allowedContexts(INTERACT_WHEEL_SCREEN, BindContext.IN_GAME)
|
||||
}
|
||||
|
||||
INTERACT_WHEEL_RIGHT_AXIS =
|
||||
bindings.registerBinding { builder: InputBindingBuilder ->
|
||||
builder
|
||||
.id(cobblemonResource("interact_wheel_right"))
|
||||
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
|
||||
.name(Component.translatable("controlify.bind.cobblemon.interact_wheel_right"))
|
||||
.allowedContexts(INTERACT_WHEEL_SCREEN, BindContext.IN_GAME)
|
||||
}
|
||||
|
||||
INTERACT_WHEEL_LEFT_AXIS =
|
||||
bindings.registerBinding { builder: InputBindingBuilder ->
|
||||
builder
|
||||
.id(cobblemonResource("interact_wheel_left"))
|
||||
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
|
||||
.name(Component.translatable("controlify.bind.cobblemon.interact_wheel_left"))
|
||||
.allowedContexts(INTERACT_WHEEL_SCREEN, BindContext.IN_GAME)
|
||||
}
|
||||
|
||||
|
||||
addProcessor(InteractWheelGUI::class, InteractWheelProcessor::class)
|
||||
// This is the lazy way to do all of these (just using the vmouse), if someone with more time and dedication did this that would be better
|
||||
addProcessor(BattleGUI::class, CobblemonGUIProcessor::class)
|
||||
addProcessor(BehaviourEditorScreen::class, CobblemonGUIProcessor::class)
|
||||
addProcessor(CobblemonConfigScreen::class, CobblemonGUIProcessor::class)
|
||||
addProcessor(CookingPotScreen::class, CobblemonGUIProcessor::class)
|
||||
addProcessor(RidingStatsDebugGUI::class, CobblemonGUIProcessor::class)
|
||||
addProcessor(DialogueScreen::class, CobblemonGUIProcessor::class)
|
||||
addProcessor(BattleConfigureGUI::class, CobblemonGUIProcessor::class)
|
||||
addProcessor(MoveSelectGUI::class, CobblemonGUIProcessor::class)
|
||||
addProcessor(PartySelectGUI::class, CobblemonGUIProcessor::class)
|
||||
addProcessor(NPCEditorScreen::class, CobblemonGUIProcessor::class)
|
||||
addProcessor(PCGUI::class, CobblemonGUIProcessor::class)
|
||||
addProcessor(PokedexGUI::class, CobblemonGUIProcessor::class)
|
||||
addProcessor(PokeNav::class, CobblemonGUIProcessor::class)
|
||||
addProcessor(SnapshotWarningScreen::class, CobblemonGUIProcessor::class)
|
||||
addProcessor(StarterSelectionScreen::class, CobblemonGUIProcessor::class)
|
||||
addProcessor(Summary::class, CobblemonGUIProcessor::class)
|
||||
addProcessor(TradeGUI::class, CobblemonGUIProcessor::class)
|
||||
}
|
||||
|
||||
override fun onControllersDiscovered(controlifyApi: ControlifyApi) {
|
||||
}
|
||||
|
||||
// This is jank, but I did it after I got my wisdom teeth extracted so tbh I think I did good enough, but I won't be offended if someone changes it to something sane.
|
||||
fun addProcessor(t: KClass<out Screen>, processorClazz: KClass<out CobblemonGUIProcessor>) {
|
||||
ScreenProcessorFactory.registerProvider(t.java) {
|
||||
processorClazz.primaryConstructor?.call(it)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
var RIDING_UP: InputBindingSupplier? = null
|
||||
var RIDING_DOWN: InputBindingSupplier? = null
|
||||
var RIDING_RIGHT: InputBindingSupplier? = null
|
||||
var RIDING_LEFT: InputBindingSupplier? = null
|
||||
var HIDE_PARTY: InputBindingSupplier? = null
|
||||
var SUMMARY: InputBindingSupplier? = null
|
||||
var PARTY_OVERLAY_DOWN: InputBindingSupplier? = null
|
||||
var PARTY_OVERLAY_UP: InputBindingSupplier? = null
|
||||
var SEND_OUT_POKEMON: InputBindingSupplier? = null
|
||||
var RIDING_FREELOOK: InputBindingSupplier? = null
|
||||
var INTERACT_WHEEL_UP_AXIS: InputBindingSupplier? = null
|
||||
var INTERACT_WHEEL_DOWN_AXIS: InputBindingSupplier? = null
|
||||
var INTERACT_WHEEL_LEFT_AXIS: InputBindingSupplier? = null
|
||||
var INTERACT_WHEEL_RIGHT_AXIS: InputBindingSupplier? = null
|
||||
|
||||
val RIDING_POKEMON: BindContext = BindContext(
|
||||
cobblemonResource("riding"),
|
||||
{ mc: Minecraft ->
|
||||
mc.player?.vehicle is PokemonEntity
|
||||
}
|
||||
)
|
||||
|
||||
val ORIENTATION_CONTROLLER_ACTIVE: BindContext = BindContext(
|
||||
cobblemonResource("orientation_controller_active"),
|
||||
{ mc: Minecraft ->
|
||||
val localPlayer = mc.player
|
||||
if (localPlayer == null) return@BindContext false
|
||||
val vehicle = localPlayer.vehicle
|
||||
vehicle is OrientationControllable && vehicle.getOrientationController().isActive()
|
||||
}
|
||||
)
|
||||
|
||||
val HAS_POKEMON: BindContext = BindContext(
|
||||
cobblemonResource("has_pokemon"),
|
||||
{mc: Minecraft ->
|
||||
!CobblemonClient.storage.party.isEmpty()
|
||||
}
|
||||
)
|
||||
|
||||
val INTERACT_WHEEL_SCREEN: BindContext = BindContext(
|
||||
cobblemonResource("wheel_screen"),
|
||||
{ it.screen is InteractWheelGUI}
|
||||
)
|
||||
}
|
||||
}
|
||||
-22
@@ -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.client.integration.controlify.gui
|
||||
|
||||
import com.cobblemon.mod.common.client.integration.controlify.gui.component.ControllerComponentManager
|
||||
import dev.isxander.controlify.screenop.ScreenProcessor
|
||||
import dev.isxander.controlify.virtualmouse.VirtualMouseBehaviour
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
|
||||
open class CobblemonGUIProcessor(open val screen: Screen) : ScreenProcessor<Screen>(screen) {
|
||||
val controllerComponentManager = ControllerComponentManager(screen)
|
||||
|
||||
override fun virtualMouseBehaviour(): VirtualMouseBehaviour {
|
||||
return VirtualMouseBehaviour.DISABLED
|
||||
}
|
||||
}
|
||||
-70
@@ -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.client.integration.controlify.gui
|
||||
|
||||
import com.cobblemon.mod.common.client.gui.interact.wheel.InteractWheelGUI
|
||||
import com.cobblemon.mod.common.client.integration.controlify.CobblemonControlifyEntrypoint
|
||||
import dev.isxander.controlify.controller.ControllerEntity
|
||||
import dev.isxander.controlify.controller.haptic.HapticEffects
|
||||
import dev.isxander.controlify.screenop.ScreenControllerEventListener
|
||||
import net.minecraft.util.Mth
|
||||
import kotlin.math.abs
|
||||
|
||||
|
||||
// Lots of this is taken from the RadialMenu in Controlify to make this screen feel consistent with it
|
||||
class InteractWheelProcessor(override val screen: InteractWheelGUI) : CobblemonGUIProcessor(screen), ScreenControllerEventListener {
|
||||
private var selectedButton = -1
|
||||
private var idleTicks: Int = 0
|
||||
private var idleTicksTimeout: Int? = null
|
||||
|
||||
init {
|
||||
addEventListener(this)
|
||||
}
|
||||
|
||||
override fun onControllerInput(controller: ControllerEntity) {
|
||||
if (idleTicksTimeout == null) {
|
||||
idleTicksTimeout = controller.input().orElseThrow().confObj().radialButtonFocusTimeoutTicks
|
||||
}
|
||||
|
||||
// If not created from entrypoint then something is very wrong
|
||||
val x = CobblemonControlifyEntrypoint.INTERACT_WHEEL_RIGHT_AXIS!!.on(controller).analogueNow()
|
||||
- CobblemonControlifyEntrypoint.INTERACT_WHEEL_LEFT_AXIS!!.on(controller).analogueNow()
|
||||
val y = CobblemonControlifyEntrypoint.INTERACT_WHEEL_DOWN_AXIS!!.on(controller).analogueNow()
|
||||
- CobblemonControlifyEntrypoint.INTERACT_WHEEL_UP_AXIS!!.on(controller).analogueNow()
|
||||
val threshold = controller.input().orElseThrow().config().config().buttonActivationThreshold
|
||||
|
||||
if (abs(x) >= threshold || abs(y) >= threshold) {
|
||||
val angle = Mth.wrapDegrees(Mth.RAD_TO_DEG * Mth.atan2(y.toDouble(), x.toDouble()) - 90f) + 180f
|
||||
val buttonCount = screen.buttons.size
|
||||
val each = 360f / buttonCount
|
||||
|
||||
val newSelected = Mth.floor((angle + each / 2f) / each) % buttonCount
|
||||
if (newSelected != selectedButton) {
|
||||
selectedButton = newSelected
|
||||
controller.hdHaptics().ifPresent { haptics -> haptics.playHaptic(HapticEffects.NAVIGATE) }
|
||||
}
|
||||
|
||||
for (button in 0..<buttonCount) {
|
||||
val selected = button == selectedButton
|
||||
screen.buttons[button].isFocused = selected
|
||||
}
|
||||
|
||||
idleTicks = 0
|
||||
} else {
|
||||
idleTicks = idleTicks+ 1
|
||||
if (idleTicks>= idleTicksTimeout!! && selectedButton != -1) {
|
||||
selectedButton = -1
|
||||
for (button in screen.buttons) {
|
||||
button.isFocused = false
|
||||
}
|
||||
controller.hdHaptics().ifPresent { haptics -> haptics.playHaptic(HapticEffects.NAVIGATE) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
package com.cobblemon.mod.common.client.integration.controlify.gui.component
|
||||
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
|
||||
class ControllerComponent<T : Screen> {
|
||||
var left: (T) -> ControllerComponent<T>? = { null }
|
||||
var right: (T) -> ControllerComponent<T>? = { null }
|
||||
var up: (T) -> ControllerComponent<T>? = { null }
|
||||
var down: (T) -> ControllerComponent<T>? = { null }
|
||||
|
||||
var associatedGUIElement: GuiEventListener? = null
|
||||
|
||||
fun pairLeft(leftComponent: ControllerComponent<T>) {
|
||||
left = { leftComponent }
|
||||
leftComponent.right = { this }
|
||||
}
|
||||
|
||||
fun pairRight(rightComponent: ControllerComponent<T>) {
|
||||
right = { rightComponent }
|
||||
rightComponent.left = { this }
|
||||
}
|
||||
|
||||
fun pairUp(upComponent: ControllerComponent<T>) {
|
||||
up = { upComponent }
|
||||
upComponent.down = { this }
|
||||
}
|
||||
|
||||
fun pairDown(downComponent: ControllerComponent<T>) {
|
||||
down = { downComponent }
|
||||
downComponent.up = { this }
|
||||
}
|
||||
}
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
package com.cobblemon.mod.common.client.integration.controlify.gui.component
|
||||
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
|
||||
class ControllerComponentManager<T : Screen>(val screen: T) {
|
||||
var focused: ControllerComponent<T>?
|
||||
get() = focused
|
||||
set(value) {
|
||||
focused = value
|
||||
focused?.associatedGUIElement?.let { screen.focused = it }
|
||||
}
|
||||
|
||||
fun left() = focused?.left?.invoke(screen)?.let { focused = it }
|
||||
fun right() = focused?.right?.invoke(screen)?.let { focused = it }
|
||||
fun up() = focused?.up?.invoke(screen)?.let { focused = it }
|
||||
fun down() = focused?.down?.invoke(screen)?.let { focused = it }
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.cobblemon.mod.common.client.integration.vivecraft
|
||||
|
||||
import com.cobblemon.mod.common.client.integration.vivecraft.party.PartyOnArm
|
||||
import com.cobblemon.mod.common.client.integration.vivecraft.proximity.ProximityManager
|
||||
import com.cobblemon.mod.common.client.integration.vivecraft.proximity.ProximityRegistration
|
||||
import com.cobblemon.mod.common.client.integration.vivecraft.listener.proximity.PokeRodBaitListener
|
||||
import org.vivecraft.api.data.VRBodyPart
|
||||
|
||||
class CobblemonVRClient {
|
||||
|
||||
companion object {
|
||||
fun init() {
|
||||
PartyOnArm.init()
|
||||
ProximityManager.init()
|
||||
ProximityManager.register(
|
||||
ProximityRegistration(
|
||||
bodyA = VRBodyPart.MAIN_HAND,
|
||||
bodyB = VRBodyPart.OFF_HAND,
|
||||
distanceThreshold = 0.25f,
|
||||
angleThreshold = 120f,
|
||||
listener = PokeRodBaitListener("Main-OffHand")
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package com.cobblemon.mod.common.client.integration.vivecraft.listener.proximity
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonNetwork
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.client.integration.vivecraft.proximity.ProximityListener
|
||||
import com.cobblemon.mod.common.client.integration.vivecraft.proximity.ProximityRegistration
|
||||
import com.cobblemon.mod.common.net.messages.server.pokerod.ApplyBaitPacket
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import org.vivecraft.api.data.VRBodyPart
|
||||
import org.vivecraft.api.data.VRPose
|
||||
|
||||
class PokeRodBaitListener(private val name: String) : ProximityListener {
|
||||
//TODO: Also add that if 1 is Rod the other needs to be seasoning
|
||||
override fun isActive(registration: ProximityRegistration): Boolean {
|
||||
val player = Minecraft.getInstance().player ?: return false
|
||||
val handA: InteractionHand = VRBodyPart.toInteractionHand(registration.bodyA) ?: return false
|
||||
val itemStackA: ItemStack = player.getItemInHand(handA)
|
||||
|
||||
val handB: InteractionHand = VRBodyPart.toInteractionHand(registration.bodyB) ?: return false
|
||||
val itemStackB: ItemStack = player.getItemInHand(handB)
|
||||
|
||||
return itemStackA.`is`(CobblemonItemTags.POKE_RODS) || itemStackB.`is`(CobblemonItemTags.POKE_RODS)
|
||||
}
|
||||
|
||||
override fun onEnter(bodyA: VRBodyPart, bodyB: VRBodyPart, pose: VRPose) {
|
||||
Cobblemon.LOGGER.info("[$name] Enter: $bodyA <-> $bodyB")
|
||||
}
|
||||
|
||||
override fun onExit(bodyA: VRBodyPart, bodyB: VRBodyPart, pose: VRPose) {
|
||||
Cobblemon.LOGGER.info("[$name] Exit: $bodyA <-> $bodyB")
|
||||
}
|
||||
|
||||
override fun onTick(bodyA: VRBodyPart, bodyB: VRBodyPart, pose: VRPose) {
|
||||
Cobblemon.LOGGER.info("[$name] Proximity: $bodyA <-> $bodyB")
|
||||
CobblemonNetwork.sendToServer(ApplyBaitPacket())
|
||||
}
|
||||
}
|
||||
+237
@@ -0,0 +1,237 @@
|
||||
package com.cobblemon.mod.common.client.integration.vivecraft.listener.swing
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.vivecraft.api.client.VRClientAPI
|
||||
import org.vivecraft.api.client.tracker.swing.SwingContext
|
||||
import org.vivecraft.api.client.tracker.swing.SwingListener
|
||||
import org.vivecraft.api.data.VRBodyPart
|
||||
import kotlin.math.abs
|
||||
|
||||
/**
|
||||
* Listener that classifies directional swings (up, down, forward, backward, left, right)
|
||||
* using Vivecraft VR pose history and invokes handler methods for each direction.
|
||||
*
|
||||
* @param forwardDotThreshold Dot product threshold used to classify forward/back/left/right directions.
|
||||
* @param historyTicks Number of ticks used to compute velocity from historical poses.
|
||||
*/
|
||||
abstract class DirectionalSwingListener(
|
||||
private val forwardDotThreshold: Double = 0.3,
|
||||
private val historyTicks: Int = 10
|
||||
) : SwingListener {
|
||||
|
||||
protected val minecraft: Minecraft = Minecraft.getInstance()
|
||||
protected val clientData: VRClientAPI = VRClientAPI.instance()
|
||||
|
||||
/**
|
||||
* Compute the net movement vector for the specified body part over the given number of ticks.
|
||||
* Returns null if historical pose data is unavailable, insufficient, or movement is negligible.
|
||||
*
|
||||
* @param bodyPart The VR body part to compute movement for.
|
||||
* @param ticks The number of ticks of history to consider.
|
||||
* @return The movement vector or null if unavailable/insignificant.
|
||||
*/
|
||||
private fun changeForVelocity(bodyPart: VRBodyPart, ticks: Int = historyTicks): Vec3? {
|
||||
val history = clientData.historicalVRPoses ?: return null
|
||||
if (history.ticksOfHistory() < ticks) return null
|
||||
|
||||
val delta = history.netMovement(bodyPart, ticks)
|
||||
delta?.lengthSqr()?.let { if (it < 1e-6) return null }
|
||||
|
||||
return delta
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an upward swing is detected.
|
||||
*
|
||||
* @param useHand The hand used for the swing.
|
||||
* @param handVel The velocity vector of the hand during the swing.
|
||||
* @param player The player performing the swing.
|
||||
* @return True if the upward action was handled, false otherwise.
|
||||
*/
|
||||
protected open fun onUpwardSwing(
|
||||
useHand: InteractionHand,
|
||||
player: Player
|
||||
): Boolean {
|
||||
Cobblemon.LOGGER.info(
|
||||
"Ignoring swing: upward movement. player={}, hand={}",
|
||||
player, useHand
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a downward swing is detected.
|
||||
*
|
||||
* @param useHand The hand used for the swing.
|
||||
* @param handVel The velocity vector of the hand during the swing.
|
||||
* @param player The player performing the swing.
|
||||
* @return True if the downward action was handled, false otherwise.
|
||||
*/
|
||||
protected open fun onDownwardSwing(
|
||||
useHand: InteractionHand,
|
||||
handVel: Vec3,
|
||||
player: Player
|
||||
): Boolean {
|
||||
Cobblemon.LOGGER.info(
|
||||
"Ignoring swing: downward movement. handVel={}, player={}, hand={}",
|
||||
handVel, player, useHand
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a forward swing is detected.
|
||||
*
|
||||
* @param useHand The hand used for the swing.
|
||||
* @param handVel The velocity vector of the hand during the swing.
|
||||
* @param player The player performing the swing.
|
||||
* @return True if the forward action was handled, false otherwise.
|
||||
*/
|
||||
protected open fun onForwardSwing(
|
||||
useHand: InteractionHand,
|
||||
handVel: Vec3,
|
||||
player: Player
|
||||
): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a backward swing is detected.
|
||||
*
|
||||
* @param useHand The hand used for the swing.
|
||||
* @param handVel The velocity vector of the hand during the swing.
|
||||
* @param player The player performing the swing.
|
||||
* @return True if the backward action was handled, false otherwise.
|
||||
*/
|
||||
protected open fun onBackwardSwing(
|
||||
useHand: InteractionHand,
|
||||
handVel: Vec3,
|
||||
player: Player
|
||||
): Boolean {
|
||||
Cobblemon.LOGGER.info(
|
||||
"Ignoring swing: backward movement. handVel={}, player={}, hand={}",
|
||||
handVel, player, useHand
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a leftward swing is detected.
|
||||
*
|
||||
* @param useHand The hand used for the swing.
|
||||
* @param handVel The velocity vector of the hand during the swing.
|
||||
* @param player The player performing the swing.
|
||||
* @return True if the leftward action was handled, false otherwise.
|
||||
*/
|
||||
protected open fun onLeftSwing(
|
||||
useHand: InteractionHand,
|
||||
handVel: Vec3,
|
||||
player: Player
|
||||
): Boolean {
|
||||
Cobblemon.LOGGER.info(
|
||||
"Ignoring swing: leftward movement. handVel={}, player={}, hand={}",
|
||||
handVel, player, useHand
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a rightward swing is detected.
|
||||
*
|
||||
* @param useHand The hand used for the swing.
|
||||
* @param handVel The velocity vector of the hand during the swing.
|
||||
* @param player The player performing the swing.
|
||||
* @return True if the rightward action was handled, false otherwise.
|
||||
*/
|
||||
protected open fun onRightSwing(
|
||||
useHand: InteractionHand,
|
||||
handVel: Vec3,
|
||||
player: Player
|
||||
): Boolean {
|
||||
Cobblemon.LOGGER.info(
|
||||
"Ignoring swing: rightward movement. handVel={}, player={}, hand={}",
|
||||
handVel, player, useHand
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the given item stack is valid for processing by this swing listener.
|
||||
* Subclasses must implement this to specify which items they handle.
|
||||
* @param itemStack The item stack to validate.
|
||||
* @return True if the item stack is valid, false otherwise.
|
||||
*/
|
||||
protected abstract fun isValidItem(itemStack: ItemStack): Boolean
|
||||
|
||||
/**
|
||||
* Called when a swing ends. Validates the held item, computes hand velocity from historical poses,
|
||||
* handles vertical swings first (upward/downward) and then classifies horizontal direction:
|
||||
* forward/backward by dot with player look direction; left/right by projecting onto a right vector
|
||||
* computed from world up and forward. Ambiguous swings are ignored.
|
||||
*
|
||||
* @param context Vivecraft swing context containing body part information.
|
||||
*/
|
||||
override fun onSwingEnd(context: SwingContext?) {
|
||||
val player = minecraft.player ?: return
|
||||
val ctx = context ?: return
|
||||
val useHand: InteractionHand = VRBodyPart.toInteractionHand(ctx.bodyPart) ?: return
|
||||
val itemStack: ItemStack = player.getItemInHand(useHand)
|
||||
|
||||
if (!isValidItem(itemStack)) return
|
||||
|
||||
val handVel = changeForVelocity(ctx.bodyPart) ?: run {
|
||||
Cobblemon.LOGGER.info(
|
||||
"Ignoring swing: insufficient historical pose data for velocity. bodyPart={}, player={}",
|
||||
ctx.bodyPart, player
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
val vertical = handVel.y
|
||||
if (vertical > 0.0) {
|
||||
if (onUpwardSwing(useHand, player)) return
|
||||
} else if (vertical < 0.0) {
|
||||
if (onDownwardSwing(useHand, handVel, player)) return
|
||||
}
|
||||
|
||||
val forward = player.lookAngle.normalize()
|
||||
val handDir = handVel.normalize()
|
||||
val forwardDot = handDir.dot(forward)
|
||||
|
||||
val worldUp = Vec3(0.0, 1.0, 0.0)
|
||||
val right = forward.cross(worldUp).let {
|
||||
if (it.lengthSqr() < 1e-6) Vec3(1.0, 0.0, 0.0) else it.normalize()
|
||||
}
|
||||
val rightDot = handDir.dot(right)
|
||||
|
||||
if (forwardDot > forwardDotThreshold) {
|
||||
if (onForwardSwing(useHand, handVel, player)) return
|
||||
return
|
||||
}
|
||||
|
||||
if (forwardDot < -forwardDotThreshold) {
|
||||
if (onBackwardSwing(useHand, handVel, player)) return
|
||||
return
|
||||
}
|
||||
|
||||
if (abs(rightDot) > forwardDotThreshold) {
|
||||
if (rightDot > 0.0) {
|
||||
if (onRightSwing(useHand, handVel, player)) return
|
||||
} else {
|
||||
if (onLeftSwing(useHand, handVel, player)) return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
Cobblemon.LOGGER.info(
|
||||
"Ignoring swing: ambiguous direction. forwardDot={}, rightDot={}, handVel={}, player={}",
|
||||
forwardDot, rightDot, handVel, player
|
||||
)
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.cobblemon.mod.common.client.integration.vivecraft.listener.swing
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.net.messages.server.pokeball.SendOutPokeBallPacket
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class PokeBallSwingListener : DirectionalSwingListener() {
|
||||
|
||||
override fun isValidItem(itemStack: ItemStack): Boolean =
|
||||
itemStack.`is`(CobblemonItemTags.POKE_BALLS)
|
||||
|
||||
override fun onForwardSwing(
|
||||
useHand: InteractionHand,
|
||||
handVel: Vec3,
|
||||
player: Player
|
||||
): Boolean {
|
||||
CobblemonNetwork.sendToServer(SendOutPokeBallPacket())
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onDownwardSwing(useHand: InteractionHand, handVel: Vec3, player: Player): Boolean {
|
||||
CobblemonNetwork.sendToServer(SendOutPokeBallPacket())
|
||||
return super.onDownwardSwing(useHand, handVel, player)
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.cobblemon.mod.common.client.integration.vivecraft.listener.swing
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.net.messages.server.pokerod.CastPokeRodPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokerod.ReelPokeRodPacket
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class PokeRodSwingListener : DirectionalSwingListener() {
|
||||
|
||||
override fun isValidItem(itemStack: ItemStack): Boolean =
|
||||
itemStack.`is`(CobblemonItemTags.POKE_RODS)
|
||||
|
||||
override fun onUpwardSwing(useHand: InteractionHand, player: Player): Boolean {
|
||||
CobblemonNetwork.sendToServer(ReelPokeRodPacket(useHand == InteractionHand.MAIN_HAND))
|
||||
return super.onUpwardSwing(useHand, player)
|
||||
}
|
||||
|
||||
override fun onForwardSwing(useHand: InteractionHand, handVel: Vec3, player: Player): Boolean {
|
||||
CobblemonNetwork.sendToServer(CastPokeRodPacket(useHand == InteractionHand.MAIN_HAND))
|
||||
return super.onForwardSwing(useHand, handVel, player)
|
||||
}
|
||||
|
||||
override fun onDownwardSwing(useHand: InteractionHand, handVel: Vec3, player: Player): Boolean {
|
||||
CobblemonNetwork.sendToServer(CastPokeRodPacket(useHand == InteractionHand.MAIN_HAND))
|
||||
return super.onDownwardSwing(useHand, handVel, player)
|
||||
}
|
||||
}
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
package com.cobblemon.mod.common.client.integration.vivecraft.party
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.platform.events.ClientTickEvent
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import com.cobblemon.mod.common.platform.events.RenderEvent
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.mojang.math.Axis
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.player.LocalPlayer
|
||||
import net.minecraft.client.renderer.LightTexture
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Vector3f
|
||||
import org.vivecraft.api.VRAPI
|
||||
import org.vivecraft.api.client.InteractModule
|
||||
import org.vivecraft.api.client.VRClientAPI
|
||||
import org.vivecraft.api.data.VRBodyPartData
|
||||
import java.util.function.Consumer
|
||||
|
||||
class PartyOnArm : InteractModule {
|
||||
|
||||
val fakePartyEntities: Array<Entity?> = arrayOfNulls(6)
|
||||
var selectedIndex = -1
|
||||
|
||||
private fun onTick(tickEvent: ClientTickEvent.Post) {
|
||||
val client = tickEvent.client
|
||||
client.player ?: return
|
||||
val playerData = VRClientAPI.instance().postTickWorldPose ?: return
|
||||
val offHandData = playerData.offHand
|
||||
|
||||
// Keep up-to-date fakePartyEntities, which is done so we always have a Pokemon or PokeBall entity available to
|
||||
// render and keep it ticking so we have proper animations.
|
||||
val party = CobblemonClient.storage.party
|
||||
|
||||
// Handle the selected index, placing either a Pokemon or null
|
||||
if (selectedIndex > -1) {
|
||||
val actual = party.get(selectedIndex)
|
||||
if (actual == null) {
|
||||
fakePartyEntities[selectedIndex] = null
|
||||
} else if (fakePartyEntities[selectedIndex] is PokemonEntity) {
|
||||
fakePartyEntities[selectedIndex]!!.tick()
|
||||
} else {
|
||||
fakePartyEntities[selectedIndex] = PokemonEntity(client.level!!, actual)
|
||||
}
|
||||
}
|
||||
// Handle the other indices, placing a pokeball or null
|
||||
for (i in 0..5) {
|
||||
if (i != selectedIndex) {
|
||||
val actual = party.get(i)
|
||||
if (actual == null) {
|
||||
fakePartyEntities[i] = null
|
||||
} else if (fakePartyEntities[i] !is EmptyPokeBallEntity) {
|
||||
val pokeBall = EmptyPokeBallEntity(actual.caughtBall, client.level!!)
|
||||
pokeBall.captureState = EmptyPokeBallEntity.CaptureState.FALL
|
||||
fakePartyEntities[i] = pokeBall
|
||||
} else {
|
||||
fakePartyEntities[i]!!.tick()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check primary hand for overlap with any of the Pokemon
|
||||
val centerPos = getCenterPos(offHandData)
|
||||
selectedIndex = -1
|
||||
for (i in 0..5) {
|
||||
if (party.get(i) != null) {
|
||||
val pokemonPos = getPokemonPos(centerPos, playerData.offHand, i)
|
||||
if (playerData.mainHand.pos.distanceToSqr(pokemonPos) < DIST_SELECT_SQR) {
|
||||
selectedIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onRender(renderEvent: RenderEvent) {
|
||||
if (renderEvent.stage != RenderEvent.Stage.AFTER_ENTITIES) return
|
||||
val mc = Minecraft.getInstance()
|
||||
val bufferSource = mc.renderBuffers().bufferSource()
|
||||
val guiGraphics = GuiGraphics(mc, mc.renderBuffers().bufferSource())
|
||||
val cameraPos = renderEvent.camera.getPosition()
|
||||
val poseStack = guiGraphics.pose()
|
||||
val partialTick = renderEvent.tickCounter.getGameTimeDeltaPartialTick(true)
|
||||
val offHandData = VRClientAPI.instance().getWorldRenderPose()?.offHand ?: return
|
||||
|
||||
val centerPos = getCenterPos(offHandData)
|
||||
|
||||
|
||||
for (i in 0..5) {
|
||||
val pokemon = fakePartyEntities[i]
|
||||
if (pokemon != null) {
|
||||
poseStack.pushPose()
|
||||
val pokemonPos = getPokemonPos(centerPos, offHandData, i)
|
||||
val renderPos = Vec3(
|
||||
-cameraPos.x + pokemonPos.x,
|
||||
-cameraPos.y + pokemonPos.y,
|
||||
-cameraPos.z + pokemonPos.z,
|
||||
)
|
||||
poseStack.translate(renderPos.x, renderPos.y, renderPos.z)
|
||||
poseStack.scale(0.05f, 0.05f, 0.05f)
|
||||
poseStack.mulPose(Axis.YN.rotation(offHandData.yaw.toFloat()))
|
||||
poseStack.mulPose(Axis.XN.rotation(offHandData.pitch.toFloat()))
|
||||
poseStack.mulPose(Axis.ZP.rotation(offHandData.roll.toFloat() + Math.PI.toFloat()))
|
||||
mc.entityRenderDispatcher.getRenderer(pokemon).render(pokemon, 0f, partialTick, poseStack, bufferSource,
|
||||
LightTexture.FULL_BRIGHT)
|
||||
poseStack.popPose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCenterPos(pose: VRBodyPartData): Vec3 {
|
||||
return pose.pos.subtract(pose.dir.scale(0.125))
|
||||
}
|
||||
|
||||
private fun getPokemonPos(centerPos: Vec3, controllerData: VRBodyPartData, index: Int): Vec3 {
|
||||
var pos = centerPos
|
||||
// Move to bottom of hand
|
||||
var downVecF = Vector3f(0f, -0.0625f, 0f)
|
||||
downVecF.rotate(Axis.ZP.rotation(controllerData.roll.toFloat()))
|
||||
downVecF.rotate(Axis.XN.rotation(controllerData.pitch.toFloat()))
|
||||
downVecF.rotate(Axis.YN.rotation(controllerData.yaw.toFloat()))
|
||||
pos = pos.add(Vec3(downVecF.x.toDouble(), downVecF.y.toDouble(), downVecF.z.toDouble()))
|
||||
// Move right or left based on index
|
||||
val rightF = Vector3f(0f, 0f, 1f) // Default forward vector of Minecraft
|
||||
rightF.rotate(Axis.YN.rotation(Math.PI.toFloat() / 2f))
|
||||
rightF.rotate(Axis.ZP.rotation(controllerData.roll.toFloat()))
|
||||
rightF.rotate(Axis.XN.rotation(controllerData.pitch.toFloat()))
|
||||
rightF.rotate(Axis.YN.rotation(controllerData.yaw.toFloat()))
|
||||
val right = Vec3(rightF.x.toDouble(), rightF.y.toDouble(), rightF.z.toDouble())
|
||||
if (index > 2) {
|
||||
pos = pos.add(right.scale(-0.0625))
|
||||
} else {
|
||||
pos = pos.add(right.scale(0.0625))
|
||||
}
|
||||
// Offset by -hand direction if on left, 0 if center, or +hand direction if right
|
||||
return pos.add(controllerData.dir.scale(DIST_BETWEEN_HORIZONTAL * (index % 3 - 1)))
|
||||
}
|
||||
|
||||
override fun getId(): ResourceLocation {
|
||||
return INTERACT_ID
|
||||
}
|
||||
|
||||
override fun isActive(
|
||||
player: LocalPlayer,
|
||||
hand: InteractionHand,
|
||||
handPosition: Vec3
|
||||
): Boolean {
|
||||
return hand == InteractionHand.MAIN_HAND && selectedIndex > -1
|
||||
}
|
||||
|
||||
override fun onPress(
|
||||
player: LocalPlayer,
|
||||
hand: InteractionHand
|
||||
): Boolean {
|
||||
// UUID lookup is done at press time since the Pokemon may have switched since initially hovered over, such
|
||||
// as via commands.
|
||||
val uuid = CobblemonClient.storage.party.get(selectedIndex)?.uuid ?: return false
|
||||
CobblemonClient.storage.switchToPokemon(uuid)
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DIST_BETWEEN_HORIZONTAL: Double = 0.125
|
||||
const val DIST_BETWEEN_VERTICAL: Float = 0.05f
|
||||
const val DIST_SELECT_SQR: Double = 0.1 * 0.1
|
||||
|
||||
val INTERACT_ID = ResourceLocation(Cobblemon.MODID, "party_on_arm_interact_module")
|
||||
|
||||
private val INSTANCE = PartyOnArm()
|
||||
|
||||
fun init() {
|
||||
PlatformEvents.RENDER.subscribe(Consumer { renderEvent: RenderEvent? -> INSTANCE.onRender(renderEvent!!) })
|
||||
PlatformEvents.CLIENT_TICK_POST.subscribe(Consumer { tickEvent: ClientTickEvent.Post? ->
|
||||
INSTANCE.onTick(
|
||||
tickEvent!!
|
||||
)
|
||||
})
|
||||
VRAPI.instance().register(INSTANCE)
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.cobblemon.mod.common.client.integration.vivecraft.proximity
|
||||
|
||||
import org.vivecraft.api.data.VRBodyPart
|
||||
import org.vivecraft.api.data.VRPose
|
||||
|
||||
// TODO: Make an PR to Vivecraft that adds this feature directly to Vivecraft
|
||||
interface ProximityListener {
|
||||
fun isActive(registration: ProximityRegistration): Boolean = true
|
||||
fun onEnter(bodyA: VRBodyPart, bodyB: VRBodyPart, pose: VRPose)
|
||||
fun onExit(bodyA: VRBodyPart, bodyB: VRBodyPart, pose: VRPose)
|
||||
fun onTick(bodyA: VRBodyPart, bodyB: VRBodyPart, pose: VRPose)
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package com.cobblemon.mod.common.client.integration.vivecraft.proximity
|
||||
|
||||
import com.cobblemon.mod.common.platform.events.ClientTickEvent
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import org.vivecraft.api.client.VRClientAPI
|
||||
import kotlin.math.acos
|
||||
|
||||
// TODO: Make an PR to Vivecraft that adds this feature directly to Vivecraft
|
||||
class ProximityManager {
|
||||
private val registrations = mutableListOf<ProximityRegistration>()
|
||||
private val previousInProximity = mutableMapOf<ProximityRegistration, Boolean>()
|
||||
private val api: VRClientAPI = VRClientAPI.instance()
|
||||
|
||||
fun register(registration: ProximityRegistration) {
|
||||
registrations += registration
|
||||
previousInProximity.putIfAbsent(registration, false)
|
||||
}
|
||||
|
||||
fun unregister(registration: ProximityRegistration) {
|
||||
registrations -= registration
|
||||
previousInProximity.remove(registration)
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
registrations.clear()
|
||||
previousInProximity.clear()
|
||||
}
|
||||
|
||||
fun isActive(registration: ProximityRegistration): Boolean {
|
||||
return registration.listener.isActive(registration)
|
||||
}
|
||||
|
||||
fun onTick(tickEvent: ClientTickEvent.Post) {
|
||||
val vrPose = api.getPostTickWorldPose() ?: return
|
||||
|
||||
for (reg in registrations) {
|
||||
if (!isActive(reg)) continue
|
||||
val poseA = vrPose.getBodyPartData(reg.bodyA) ?: continue
|
||||
val poseB = vrPose.getBodyPartData(reg.bodyB) ?: continue
|
||||
|
||||
val distance = poseA.pos.distanceTo(poseB.pos)
|
||||
|
||||
val dot = poseA.dir.dot(poseB.dir).coerceIn(-1.0, 1.0)
|
||||
val angleDeg = Math.toDegrees(acos(dot)).toFloat()
|
||||
val angleOk = angleDeg <= reg.angleThreshold
|
||||
|
||||
val nowInProximity = distance <= reg.distanceThreshold && angleOk
|
||||
val wasInProximity = previousInProximity[reg] ?: false
|
||||
|
||||
if (!wasInProximity && nowInProximity) {
|
||||
reg.listener.onEnter(reg.bodyA, reg.bodyB, vrPose)
|
||||
} else if (wasInProximity && !nowInProximity) {
|
||||
reg.listener.onExit(reg.bodyA, reg.bodyB, vrPose)
|
||||
}
|
||||
|
||||
if (nowInProximity) {
|
||||
reg.listener.onTick(reg.bodyA, reg.bodyB, vrPose)
|
||||
}
|
||||
|
||||
previousInProximity[reg] = nowInProximity
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val INSTANCE = ProximityManager()
|
||||
|
||||
fun init() {
|
||||
PlatformEvents.CLIENT_TICK_POST.subscribe { tickEvent: ClientTickEvent.Post? ->
|
||||
INSTANCE.onTick(
|
||||
tickEvent!!
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun register(registration: ProximityRegistration) = INSTANCE.register(registration)
|
||||
fun unregister(registration: ProximityRegistration) = INSTANCE.unregister(registration)
|
||||
fun clearAll() = INSTANCE.clear()
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.cobblemon.mod.common.client.integration.vivecraft.proximity
|
||||
|
||||
import org.vivecraft.api.data.VRBodyPart
|
||||
|
||||
// TODO: Make an PR to Vivecraft that adds this feature directly to Vivecraft
|
||||
data class ProximityRegistration(
|
||||
val bodyA: VRBodyPart,
|
||||
val bodyB: VRBodyPart,
|
||||
val distanceThreshold: Float,
|
||||
val angleThreshold: Float = 180f,
|
||||
val listener: ProximityListener
|
||||
)
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.net.data
|
||||
|
||||
import com.cobblemon.mod.common.api.interaction.PokemonInteractions
|
||||
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.data.PokemonInteractionsSyncPacket
|
||||
import net.minecraft.client.Minecraft
|
||||
|
||||
object PokemonInteractionsSyncHandler : ClientNetworkPacketHandler<PokemonInteractionsSyncPacket> {
|
||||
|
||||
override fun handle(
|
||||
packet: PokemonInteractionsSyncPacket,
|
||||
client: Minecraft,
|
||||
) {
|
||||
PokemonInteractions.speciesInteractions.clear()
|
||||
PokemonInteractions.speciesInteractions.addAll(packet.speciesInteractions)
|
||||
PokemonInteractions.generalInteractions.clear()
|
||||
PokemonInteractions.generalInteractions.addAll(packet.generalInteractions)
|
||||
}
|
||||
}
|
||||
+5
-21
@@ -8,8 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.persisted
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import java.io.BufferedReader
|
||||
import java.io.BufferedWriter
|
||||
@@ -33,14 +31,7 @@ object ClientPersistedData {
|
||||
fun readSnapshotsData() : SnapshotAcknowledgementData? {
|
||||
if (snapshotsPath.exists()) {
|
||||
BufferedReader(InputStreamReader(FileInputStream(snapshotsPath.toFile()))).use { reader ->
|
||||
try {
|
||||
return gson.fromJson(reader, SnapshotAcknowledgementData::class.java)
|
||||
} catch (exception: Exception) {
|
||||
LOGGER.error("Failed to load snapshots.json... Resetting File")
|
||||
val data = SnapshotAcknowledgementData(Cobblemon.VERSION, false)
|
||||
writeSnapshotsData(data)
|
||||
return data
|
||||
}
|
||||
return gson.fromJson(reader, SnapshotAcknowledgementData::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,23 +46,16 @@ object ClientPersistedData {
|
||||
fun readRidingPerspectivesData() : RidingPerspectiveData? {
|
||||
if (ridingPerspectivesPath.exists()) {
|
||||
BufferedReader(InputStreamReader(FileInputStream(ridingPerspectivesPath.toFile()))).use { reader ->
|
||||
try {
|
||||
return gson.fromJson(reader, RidingPerspectiveData::class.java)
|
||||
} catch (exception: Exception) {
|
||||
LOGGER.error("Failed to load riding_perspectives.json... Resetting File")
|
||||
val data = RidingPerspectiveData()
|
||||
saveRidingPerspectivesData(data)
|
||||
return data
|
||||
}
|
||||
return gson.fromJson(reader, RidingPerspectiveData::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun saveRidingPerspectivesData(data: RidingPerspectiveData) {
|
||||
fun saveRidingPerspectivesData() {
|
||||
ridingPerspectivesPath.toFile().parentFile.mkdirs()
|
||||
BufferedWriter(FileWriter(ridingPerspectivesPath.toFile())).use { writer -> gson.toJson(data, writer) }
|
||||
BufferedWriter(FileWriter(ridingPerspectivesPath.toFile())).use { writer -> gson.toJson(ridingPerspectives, writer) }
|
||||
}
|
||||
|
||||
data class SnapshotAcknowledgementData(val version: String, val dontShowAgain: Boolean)
|
||||
@@ -80,7 +64,7 @@ object ClientPersistedData {
|
||||
) {
|
||||
fun updatePerspective(key: ResourceLocation, cameraType: CameraType) {
|
||||
perspectives[key] = cameraType
|
||||
saveRidingPerspectivesData(this)
|
||||
saveRidingPerspectivesData()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1208,13 +1208,14 @@ open class PokemonEntity(
|
||||
}
|
||||
}
|
||||
|
||||
if (hand == InteractionHand.MAIN_HAND) {
|
||||
if (player.isShiftKeyDown && player is ServerPlayer) {
|
||||
if (hand == InteractionHand.MAIN_HAND && player is ServerPlayer) {
|
||||
if (player.isShiftKeyDown) {
|
||||
showInteractionWheel(player, itemStack)
|
||||
return InteractionResult.sidedSuccess(level().isClientSide)
|
||||
}
|
||||
else if (this.ownerUUID == player.uuid && this.attemptItemInteraction(player, player.getItemInHand(hand))) {
|
||||
return InteractionResult.sidedSuccess(level().isClientSide)
|
||||
else if (pokemon.getOwnerPlayer() == player) {
|
||||
// TODO #105
|
||||
if (this.attemptItemInteraction(player, player.getItemInHand(hand))) return InteractionResult.SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1390,24 +1391,18 @@ open class PokemonEntity(
|
||||
return bagItemLike.handleInteraction(player, battlePokemon, stack)
|
||||
}
|
||||
|
||||
if (this.isBusy) {
|
||||
if (player !is ServerPlayer || this.isBusy) {
|
||||
return false
|
||||
}
|
||||
|
||||
val interaction = PokemonInteractions.findInteraction(this)
|
||||
|
||||
if (interaction != null && !pokemon.isOnInteractionCooldown(interaction.grouping)) {
|
||||
if (player is ServerPlayer) {
|
||||
interaction.effects.forEach { it.applyEffect(this, player) }
|
||||
pokemon.interactionCooldowns.put(interaction.grouping, runtime.resolveInt(interaction.cooldown))
|
||||
}
|
||||
|
||||
interaction.effects.forEach { it.applyEffect(this, player) }
|
||||
pokemon.interactionCooldowns.put(interaction.grouping, runtime.resolveInt(interaction.cooldown))
|
||||
return true
|
||||
}
|
||||
|
||||
if (player !is ServerPlayer) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Evolution item logic
|
||||
if (pokemon.getOwnerPlayer() == player) {
|
||||
val context = ItemInteractionEvolution.ItemInteractionContext(stack, player.level())
|
||||
|
||||
@@ -30,13 +30,21 @@ import com.cobblemon.mod.common.api.events.battles.BattleStartedEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleVictoryEvent
|
||||
import com.cobblemon.mod.common.api.events.fishing.PokerodCastEvent
|
||||
import com.cobblemon.mod.common.api.events.fishing.PokerodReelEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.*
|
||||
import com.cobblemon.mod.common.api.events.pokemon.CollectEggEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.FossilRevivedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.HatchEggEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.LevelUpEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.PokemonCapturedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.PokemonGainedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.RidePokemonEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.TradeEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEvent
|
||||
import com.cobblemon.mod.common.api.events.storage.ReleasePokemonEvent
|
||||
import com.cobblemon.mod.common.api.stats.CobblemonStats.getStat
|
||||
import com.cobblemon.mod.common.util.getPlayer
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import java.util.*
|
||||
import java.util.UUID
|
||||
|
||||
object StatHandler : EventHandler {
|
||||
override fun registerListeners() {
|
||||
@@ -92,13 +100,13 @@ object StatHandler : EventHandler {
|
||||
|
||||
fun onBattleStart(event : BattleStartedEvent) {
|
||||
event.battle.players.forEach { player ->
|
||||
player.awardStat(getStat(Cobblemon.statistics.BATTLES_TOTAL))
|
||||
player.awardStat(this.getStat(getStat(Cobblemon.statistics.BATTLES_TOTAL)))
|
||||
}
|
||||
}
|
||||
|
||||
fun onDexEntryGain(event : PokemonGainedEvent) {
|
||||
val player = event.pokemon.getOwnerPlayer()
|
||||
player?.awardStat(getStat(Cobblemon.statistics.DEX_ENTRIES))
|
||||
player?.awardStat(getStat(getStat(Cobblemon.statistics.DEX_ENTRIES)))
|
||||
}
|
||||
|
||||
fun onCollectEgg(event : CollectEggEvent) {
|
||||
@@ -131,4 +139,12 @@ object StatHandler : EventHandler {
|
||||
fun onReelIn(event : PokerodReelEvent) {
|
||||
event.player.awardStat(getStat(Cobblemon.statistics.REEL_INS))
|
||||
}
|
||||
|
||||
fun getStat(resourceLocation: ResourceLocation) : ResourceLocation {
|
||||
val stat = BuiltInRegistries.CUSTOM_STAT.get(resourceLocation)
|
||||
if (stat == null) {
|
||||
Cobblemon.LOGGER.error("Could not find stat with id {}", resourceLocation)
|
||||
}
|
||||
return stat ?: throw NullPointerException("Could not find stat with id $resourceLocation")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.cobblemon.mod.common.integration.vivecraft
|
||||
|
||||
import com.cobblemon.mod.common.client.integration.vivecraft.listener.swing.PokeBallSwingListener
|
||||
import com.cobblemon.mod.common.client.integration.vivecraft.listener.swing.PokeRodSwingListener
|
||||
import org.vivecraft.api.VRAPI
|
||||
|
||||
class CobblemonVR {
|
||||
|
||||
fun init() {
|
||||
VRAPI.instance()
|
||||
.register(PokeBallSwingListener())
|
||||
|
||||
VRAPI.instance()
|
||||
.register(PokeRodSwingListener())
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import net.minecraft.world.level.Level
|
||||
import kotlin.math.cos
|
||||
|
||||
class PokeBallItem(
|
||||
val pokeBall: PokeBall
|
||||
val pokeBall: PokeBall
|
||||
) : CobblemonItem(Properties().apply {
|
||||
when (pokeBall.name) {
|
||||
// Master balls are a netherite product and should be fire immune
|
||||
@@ -43,7 +43,7 @@ class PokeBallItem(
|
||||
return InteractionResultHolder.sidedSuccess(itemStack, world.isClientSide)
|
||||
}
|
||||
|
||||
private fun throwPokeBall(world: Level, player: ServerPlayer) {
|
||||
fun throwPokeBall(world: Level, player: ServerPlayer) {
|
||||
val pokeBallEntity = EmptyPokeBallEntity(pokeBall, player.level(), player).apply {
|
||||
val overhandFactor: Float = if (player.xRot < 0) {
|
||||
5f * cos(player.xRot.toRadians())
|
||||
@@ -57,4 +57,5 @@ class PokeBallItem(
|
||||
}
|
||||
world.addFreshEntity(pokeBallEntity)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,7 +25,9 @@ class MochiItem(stat: Stats): EVIncreaseItem(stat, 4) {
|
||||
}
|
||||
|
||||
pokemon.feedPokemon(1)
|
||||
|
||||
|
||||
stack.consume(1, player)
|
||||
|
||||
return super.applyToPokemon(player, stack, pokemon)
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,8 @@ class PokerodItem(val pokeRodId: ResourceLocation, settings: Properties) : Fishi
|
||||
|
||||
if (baitCount > 1) {
|
||||
baitStack.count = baitCount - 1
|
||||
stack.set(CobblemonItemComponents.BAIT, RodBaitComponent(baitStack)
|
||||
stack.set(
|
||||
CobblemonItemComponents.BAIT, RodBaitComponent(baitStack)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -149,90 +150,163 @@ class PokerodItem(val pokeRodId: ResourceLocation, settings: Properties) : Fishi
|
||||
}
|
||||
|
||||
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
|
||||
|
||||
val itemStack = user.getItemInHand(hand)
|
||||
val offHandItem = user.getItemInHand(InteractionHand.OFF_HAND)
|
||||
|
||||
// Check if offhand item is valid bait and the rod is not in use, if so then apply bait from offhand
|
||||
if (!world.isClientSide && user.fishing == null && SpawnBaitEffects.isFishingBait(offHandItem)) {
|
||||
CobblemonEvents.BAIT_SET_PRE.postThen(BaitSetEvent(itemStack, offHandItem), { event ->
|
||||
return InteractionResultHolder.fail(itemStack)
|
||||
}, {
|
||||
playAttachSound(user)
|
||||
attemptApplyOffhandBait(world, user, itemStack, offHandItem)?.let { return it }
|
||||
|
||||
// if there is bait on the rod already then drop it on the ground before applying offhand bait
|
||||
val baitStack = getBaitStackOnRod(itemStack)
|
||||
if (user.fishing != null) {
|
||||
attemptReel(world, user, hand, itemStack)?.let { return it }
|
||||
} else {
|
||||
attemptCast(world, user, hand, itemStack)?.let { return it }
|
||||
}
|
||||
|
||||
if (baitStack != ItemStack.EMPTY && offHandItem.item != baitStack.item) {
|
||||
user.drop(baitStack, true) // Drop the full stack
|
||||
return InteractionResultHolder.sidedSuccess(itemStack, world.isClientSide)
|
||||
}
|
||||
|
||||
// apply single bait item from offhand
|
||||
val singleBait = offHandItem.copy()
|
||||
singleBait.count = 1
|
||||
setBait(itemStack, singleBait)
|
||||
offHandItem.shrink(1)
|
||||
fun applyBait(
|
||||
rodStack: ItemStack,
|
||||
baitSource: ItemStack,
|
||||
player: Player?
|
||||
): Boolean {
|
||||
if (baitSource.isEmpty || !SpawnBaitEffects.isFishingBait(baitSource)) return false
|
||||
|
||||
val existingBait = getBaitStackOnRod(rodStack)
|
||||
if (!existingBait.isEmpty && existingBait.item == baitSource.item) return false
|
||||
|
||||
var applied = false
|
||||
|
||||
CobblemonEvents.BAIT_SET_PRE.postThen(
|
||||
BaitSetEvent(rodStack, baitSource),
|
||||
{ return false },
|
||||
{
|
||||
if (!existingBait.isEmpty && player != null) {
|
||||
player.drop(existingBait, true)
|
||||
}
|
||||
})
|
||||
|
||||
val singleBait = baitSource.copy()
|
||||
singleBait.count = 1
|
||||
setBait(rodStack, singleBait)
|
||||
|
||||
baitSource.shrink(1)
|
||||
applied = true
|
||||
}
|
||||
)
|
||||
|
||||
return applied
|
||||
}
|
||||
|
||||
fun attemptApplyOffhandBait(
|
||||
world: Level,
|
||||
user: Player,
|
||||
rodStack: ItemStack,
|
||||
offHandItem: ItemStack
|
||||
): InteractionResultHolder<ItemStack>? {
|
||||
if (world.isClientSide) return null
|
||||
if (user.fishing != null) return null
|
||||
|
||||
val applied = applyBait(
|
||||
rodStack = rodStack,
|
||||
baitSource = offHandItem,
|
||||
player = user
|
||||
)
|
||||
|
||||
if (applied) {
|
||||
playAttachSound(user)
|
||||
return InteractionResultHolder.sidedSuccess(rodStack, false)
|
||||
}
|
||||
|
||||
var i: Int
|
||||
if (user.fishing != null) { // if the bobber is out yet
|
||||
if (!world.isClientSide) {
|
||||
CobblemonEvents.POKEROD_REEL.postThen(
|
||||
PokerodReelEvent(user, itemStack),
|
||||
{ event -> return InteractionResultHolder.fail(itemStack) },
|
||||
{ event ->
|
||||
i = user.fishing!!.retrieve(itemStack)
|
||||
itemStack.hurtAndBreak(i, user, hand.toEquipmentSlot())
|
||||
world.playSoundServer(
|
||||
Vec3(user.x,
|
||||
user.y,
|
||||
user.z),
|
||||
CobblemonSounds.FISHING_ROD_REEL_IN,
|
||||
SoundSource.PLAYERS,
|
||||
1.0f,
|
||||
1.0f / (world.getRandom().nextFloat() * 0.4f + 0.8f)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
world.playSound(null as Player?, user.x, user.y, user.z, CobblemonSounds.FISHING_ROD_REEL_IN, SoundSource.PLAYERS, 1.0f, 1.0f)
|
||||
user.gameEvent(GameEvent.ITEM_INTERACT_FINISH)
|
||||
} else { // if the bobber is not out yet
|
||||
fun attemptReel(
|
||||
world: Level,
|
||||
user: Player,
|
||||
hand: InteractionHand,
|
||||
itemStack: ItemStack
|
||||
): InteractionResultHolder<ItemStack>? {
|
||||
if (user.fishing == null) return null
|
||||
|
||||
if (!world.isClientSide) {
|
||||
val lureLevel = world.enchantmentRegistry.getHolder(Enchantments.LURE).map { EnchantmentHelper.getItemEnchantmentLevel(it, itemStack) }.orElse(0)
|
||||
val luckLevel = world.enchantmentRegistry.getHolder(Enchantments.LUCK_OF_THE_SEA).map { EnchantmentHelper.getItemEnchantmentLevel(it, itemStack) }.orElse(0)
|
||||
|
||||
val bobberEntity = PokeRodFishingBobberEntity(
|
||||
user,
|
||||
pokeRodId,
|
||||
getBaitStackOnRod(itemStack),
|
||||
world,
|
||||
luckLevel,
|
||||
lureLevel,
|
||||
itemStack
|
||||
)
|
||||
CobblemonEvents.POKEROD_CAST_PRE.postThen(
|
||||
PokerodCastEvent.Pre(itemStack, bobberEntity, getBaitStackOnRod(itemStack)),
|
||||
{ event -> return InteractionResultHolder.fail(itemStack) },
|
||||
{ event ->
|
||||
world.addFreshEntity(bobberEntity)
|
||||
var baitId = getBaitStackOnRod(itemStack).takeUnless { it.isEmpty }?.itemHolder?.unwrapKey()?.orElse(null)?.location() ?: cobblemonResource("empty_bait")
|
||||
CobblemonCriteria.CAST_POKE_ROD.trigger(user as ServerPlayer, CastPokeRodContext(baitId))
|
||||
|
||||
CobblemonEvents.POKEROD_CAST_POST.post(
|
||||
PokerodCastEvent.Post(itemStack, bobberEntity, getBaitStackOnRod(itemStack))
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
user.awardStat(Stats.ITEM_USED.get(this))
|
||||
user.gameEvent(GameEvent.ITEM_INTERACT_START)
|
||||
if (!world.isClientSide) {
|
||||
CobblemonEvents.POKEROD_REEL.postThen(
|
||||
PokerodReelEvent(user, itemStack),
|
||||
{ event -> return InteractionResultHolder.fail(itemStack) },
|
||||
{ event ->
|
||||
val i = user.fishing!!.retrieve(itemStack)
|
||||
itemStack.hurtAndBreak(i, user, hand.toEquipmentSlot())
|
||||
world.playSoundServer(
|
||||
Vec3(user.x, user.y, user.z),
|
||||
CobblemonSounds.FISHING_ROD_REEL_IN,
|
||||
SoundSource.PLAYERS,
|
||||
1.0f,
|
||||
1.0f / (world.getRandom().nextFloat() * 0.4f + 0.8f)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
world.playSound(
|
||||
null as Player?,
|
||||
user.x,
|
||||
user.y,
|
||||
user.z,
|
||||
CobblemonSounds.FISHING_ROD_REEL_IN,
|
||||
SoundSource.PLAYERS,
|
||||
1.0f,
|
||||
1.0f
|
||||
)
|
||||
user.gameEvent(GameEvent.ITEM_INTERACT_FINISH)
|
||||
|
||||
return InteractionResultHolder.sidedSuccess(itemStack, world.isClientSide)
|
||||
}
|
||||
|
||||
fun attemptCast(
|
||||
world: Level,
|
||||
user: Player,
|
||||
hand: InteractionHand,
|
||||
itemStack: ItemStack
|
||||
): InteractionResultHolder<ItemStack>? {
|
||||
if (user.fishing != null) return null
|
||||
|
||||
if (!world.isClientSide) {
|
||||
val lureLevel = world.enchantmentRegistry.getHolder(Enchantments.LURE)
|
||||
.map { EnchantmentHelper.getItemEnchantmentLevel(it, itemStack) }
|
||||
.orElse(0)
|
||||
val luckLevel = world.enchantmentRegistry.getHolder(Enchantments.LUCK_OF_THE_SEA)
|
||||
.map { EnchantmentHelper.getItemEnchantmentLevel(it, itemStack) }
|
||||
.orElse(0)
|
||||
|
||||
val bobberEntity = PokeRodFishingBobberEntity(
|
||||
user,
|
||||
pokeRodId,
|
||||
getBaitStackOnRod(itemStack),
|
||||
world,
|
||||
luckLevel,
|
||||
lureLevel,
|
||||
itemStack
|
||||
)
|
||||
|
||||
CobblemonEvents.POKEROD_CAST_PRE.postThen(
|
||||
PokerodCastEvent.Pre(itemStack, bobberEntity, getBaitStackOnRod(itemStack)),
|
||||
{ event -> return InteractionResultHolder.fail(itemStack) },
|
||||
{ event ->
|
||||
world.addFreshEntity(bobberEntity)
|
||||
val baitId = getBaitStackOnRod(itemStack).takeUnless { it.isEmpty }
|
||||
?.itemHolder?.unwrapKey()?.orElse(null)?.location()
|
||||
?: cobblemonResource("empty_bait")
|
||||
CobblemonCriteria.CAST_POKE_ROD.trigger(user as ServerPlayer, CastPokeRodContext(baitId))
|
||||
|
||||
CobblemonEvents.POKEROD_CAST_POST.post(
|
||||
PokerodCastEvent.Post(itemStack, bobberEntity, getBaitStackOnRod(itemStack))
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
user.awardStat(Stats.ITEM_USED.get(this))
|
||||
user.gameEvent(GameEvent.ITEM_INTERACT_START)
|
||||
|
||||
return InteractionResultHolder.sidedSuccess(itemStack, world.isClientSide)
|
||||
}
|
||||
|
||||
|
||||
+3
-10
@@ -35,16 +35,9 @@ class SinisterTeaItem : Item(
|
||||
val effectsComponent = stack.get(CobblemonItemComponents.MOB_EFFECTS)
|
||||
|
||||
if (effectsComponent != null) {
|
||||
for (raw in effectsComponent.mobEffects) {
|
||||
val inst = MobEffectInstance(raw)
|
||||
val holder = inst.effect
|
||||
val effect = holder.value()
|
||||
|
||||
if (effect.isInstantenous) {
|
||||
effect.applyInstantenousEffect(user as? Player, null, user, inst.amplifier, 1.0)
|
||||
} else {
|
||||
user.addEffect(inst)
|
||||
}
|
||||
for (effect in effectsComponent.mobEffects) {
|
||||
val effectCopy = MobEffectInstance(effect)
|
||||
user.addEffect(effectCopy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.net.messages.client.data
|
||||
|
||||
import com.cobblemon.mod.common.api.interaction.PokemonInteractionSet
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class PokemonInteractionsSyncPacket(
|
||||
val speciesInteractions: List<PokemonInteractionSet>,
|
||||
val generalInteractions: List<PokemonInteractionSet>,
|
||||
) : NetworkPacket<PokemonInteractionsSyncPacket> {
|
||||
override val id = ID
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeCollection(speciesInteractions) { it, speciesInteraction ->
|
||||
speciesInteraction.encode(it)
|
||||
}
|
||||
buffer.writeCollection(generalInteractions) { it, generalInteraction ->
|
||||
generalInteraction.encode(it)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("pokemon_interactions_sync")
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): PokemonInteractionsSyncPacket {
|
||||
val speciesInteractions = buffer.readList { it ->
|
||||
PokemonInteractionSet.decode(it)
|
||||
}
|
||||
val generalInteractions = buffer.readList { it ->
|
||||
PokemonInteractionSet.decode(it)
|
||||
}
|
||||
|
||||
return PokemonInteractionsSyncPacket(
|
||||
speciesInteractions,
|
||||
generalInteractions,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-3
@@ -21,9 +21,7 @@ class PokemonStateUpdatePacket(pokemon: () -> Pokemon?, value: PokemonState): Si
|
||||
value.writeToBuffer(buffer)
|
||||
}
|
||||
|
||||
override fun set(pokemon: Pokemon, value: PokemonState) {
|
||||
pokemon.state = value
|
||||
}
|
||||
override fun set(pokemon: Pokemon, value: PokemonState) { pokemon.state = value }
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("state_update")
|
||||
|
||||
+10
-24
@@ -13,24 +13,30 @@ import com.cobblemon.mod.common.api.mark.Marks
|
||||
import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.entity.PlatformType
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readEnumConstant
|
||||
import com.cobblemon.mod.common.util.readIdentifier
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.readText
|
||||
import com.cobblemon.mod.common.util.writeEnumConstant
|
||||
import com.cobblemon.mod.common.util.writeIdentifier
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import com.cobblemon.mod.common.util.writeText
|
||||
import java.util.UUID
|
||||
import net.minecraft.client.multiplayer.ClientLevel
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.Entity
|
||||
import java.util.*
|
||||
|
||||
class SpawnPokemonPacket(
|
||||
var ownerId: UUID?,
|
||||
var pokemonUUID: UUID,
|
||||
var storageUUID: UUID?,
|
||||
var scaleModifier: Float,
|
||||
var speciesId: ResourceLocation,
|
||||
var gender: Gender,
|
||||
@@ -55,7 +61,6 @@ class SpawnPokemonPacket(
|
||||
var tickSpawned: Int,
|
||||
var rideBoosts: Map<RidingStat, Float>,
|
||||
var rideStamina: Float,
|
||||
var silent: Boolean,
|
||||
vanillaSpawnPacket: ClientboundAddEntityPacket,
|
||||
) : SpawnExtraDataEntityPacket<SpawnPokemonPacket, PokemonEntity>(vanillaSpawnPacket) {
|
||||
|
||||
@@ -64,7 +69,6 @@ class SpawnPokemonPacket(
|
||||
constructor(entity: PokemonEntity, vanillaSpawnPacket: ClientboundAddEntityPacket) : this(
|
||||
entity.ownerUUID,
|
||||
entity.pokemon.uuid,
|
||||
entity.pokemon.storeCoordinates.get()?.store?.uuid,
|
||||
entity.pokemon.scaleModifier,
|
||||
entity.exposedSpecies.resourceIdentifier,
|
||||
entity.pokemon.gender,
|
||||
@@ -89,14 +93,12 @@ class SpawnPokemonPacket(
|
||||
entity.tickCount,
|
||||
entity.entityData.get(PokemonEntity.RIDE_BOOSTS),
|
||||
entity.entityData.get(PokemonEntity.RIDE_STAMINA),
|
||||
entity.isSilent,
|
||||
vanillaSpawnPacket
|
||||
)
|
||||
|
||||
override fun encodeEntityData(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeNullable(ownerId) { _, v -> buffer.writeUUID(v) }
|
||||
buffer.writeUUID(this.pokemonUUID)
|
||||
buffer.writeNullable(this.storageUUID) { pb, value -> pb.writeUUID(value) }
|
||||
buffer.writeFloat(this.scaleModifier)
|
||||
buffer.writeIdentifier(this.speciesId)
|
||||
buffer.writeEnumConstant(this.gender)
|
||||
@@ -125,21 +127,10 @@ class SpawnPokemonPacket(
|
||||
{ _, value -> buffer.writeFloat(value) }
|
||||
)
|
||||
buffer.writeFloat(rideStamina)
|
||||
buffer.writeBoolean(silent)
|
||||
}
|
||||
|
||||
override fun applyData(entity: PokemonEntity, level: ClientLevel) {
|
||||
entity.ownerUUID = ownerId
|
||||
|
||||
// Reuse the stored Pokémon instance to avoid creating a duplicate,
|
||||
// preventing client/entity desync issues.
|
||||
this@SpawnPokemonPacket.storageUUID?.let {
|
||||
val storedPokemon = CobblemonClient.storage.locatePokemon(it, this@SpawnPokemonPacket.pokemonUUID)
|
||||
if (storedPokemon != null) {
|
||||
entity.pokemon = storedPokemon
|
||||
}
|
||||
}
|
||||
|
||||
entity.pokemon.apply {
|
||||
uuid = this@SpawnPokemonPacket.pokemonUUID
|
||||
scaleModifier = this@SpawnPokemonPacket.scaleModifier
|
||||
@@ -171,7 +162,6 @@ class SpawnPokemonPacket(
|
||||
entity.entityData.set(PokemonEntity.RIDE_BOOSTS, rideBoosts)
|
||||
entity.entityData.set(PokemonEntity.RIDE_STAMINA, rideStamina)
|
||||
entity.entityData.set(PokemonEntity.SCALE_MODIFIER, scaleModifier)
|
||||
entity.isSilent = silent
|
||||
|
||||
entity.ejectPassengers()
|
||||
passengers.forEach {
|
||||
@@ -189,7 +179,6 @@ class SpawnPokemonPacket(
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): SpawnPokemonPacket {
|
||||
val ownerId = buffer.readNullable { buffer.readUUID() }
|
||||
val pokemonUUID = buffer.readUUID()
|
||||
val storageUUID = buffer.readNullable { buffer.readUUID() }
|
||||
val scaleModifier = buffer.readFloat()
|
||||
val speciesId = buffer.readIdentifier()
|
||||
val gender = buffer.readEnumConstant(Gender::class.java)
|
||||
@@ -217,13 +206,11 @@ class SpawnPokemonPacket(
|
||||
{ buffer.readFloat() }
|
||||
)
|
||||
val rideStamina = buffer.readFloat()
|
||||
val silent = buffer.readBoolean()
|
||||
val vanillaPacket = decodeVanillaPacket(buffer)
|
||||
|
||||
return SpawnPokemonPacket(
|
||||
ownerId,
|
||||
pokemonUUID,
|
||||
storageUUID,
|
||||
scaleModifier,
|
||||
speciesId,
|
||||
gender,
|
||||
@@ -248,7 +235,6 @@ class SpawnPokemonPacket(
|
||||
tickSpawned,
|
||||
rideBoosts,
|
||||
rideStamina,
|
||||
silent,
|
||||
vanillaPacket
|
||||
)
|
||||
}
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.cobblemon.mod.common.net.messages.server.pokeball
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class SendOutPokeBallPacket() : NetworkPacket<SendOutPokeBallPacket> {
|
||||
override val id = ID
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("send_out_pokeball")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = SendOutPokeBallPacket()
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.cobblemon.mod.common.net.messages.server.pokerod
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class ApplyBaitPacket() : NetworkPacket<ApplyBaitPacket> {
|
||||
override val id = ID
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("apply_bait")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = ApplyBaitPacket()
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.cobblemon.mod.common.net.messages.server.pokerod
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class CastPokeRodPacket(val mainHand: Boolean) : NetworkPacket<CastPokeRodPacket> {
|
||||
override val id = ID
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeBoolean(mainHand)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("cast_pokerod")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = CastPokeRodPacket(buffer.readBoolean())
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.cobblemon.mod.common.net.messages.server.pokerod
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class ReelPokeRodPacket(val mainHand: Boolean) : NetworkPacket<ReelPokeRodPacket> {
|
||||
override val id = ID
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeBoolean(mainHand)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("reel_pokerod")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = ReelPokeRodPacket(buffer.readBoolean())
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.net.serverhandling.pokeball
|
||||
|
||||
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.item.PokeBallItem
|
||||
import com.cobblemon.mod.common.net.messages.server.pokeball.SendOutPokeBallPacket
|
||||
import com.cobblemon.mod.common.util.isServerSide
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
object SendOutPokeBallHandler : ServerNetworkPacketHandler<SendOutPokeBallPacket> {
|
||||
|
||||
override fun handle(packet: SendOutPokeBallPacket, server: MinecraftServer, player: ServerPlayer) {
|
||||
(player.mainHandItem.item as? PokeBallItem)?.let { pokeball ->
|
||||
if (player.level().isServerSide()) {
|
||||
pokeball.throwPokeBall(player.level(), player)
|
||||
}
|
||||
// TODO: player.mainHandItem.consume(1, player)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package com.cobblemon.mod.common.net.serverhandling.pokerod
|
||||
|
||||
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.item.interactive.PokerodItem
|
||||
import com.cobblemon.mod.common.net.messages.server.pokerod.ApplyBaitPacket
|
||||
import com.cobblemon.mod.common.util.isServerSide
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.InteractionHand
|
||||
|
||||
object ApplyBaitHandler : ServerNetworkPacketHandler<ApplyBaitPacket> {
|
||||
|
||||
override fun handle(packet: ApplyBaitPacket, server: MinecraftServer, player: ServerPlayer) {
|
||||
|
||||
val mainHandItem = player.getItemInHand(InteractionHand.MAIN_HAND)
|
||||
val offHandItem = player.getItemInHand(InteractionHand.OFF_HAND)
|
||||
|
||||
println("[ApplyBaitHandler] Main hand: ${mainHandItem.item}")
|
||||
println("[ApplyBaitHandler] Off hand: ${offHandItem.item}")
|
||||
|
||||
(mainHandItem.item as? PokerodItem)?.let { pokerod ->
|
||||
if (player.level().isServerSide()) {
|
||||
pokerod.applyBait(
|
||||
mainHandItem,
|
||||
offHandItem,
|
||||
player
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
(offHandItem.item as? PokerodItem)?.let { pokerod ->
|
||||
if (player.level().isServerSide()) {
|
||||
pokerod.applyBait(
|
||||
offHandItem,
|
||||
mainHandItem,
|
||||
player
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.net.serverhandling.pokerod
|
||||
|
||||
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.item.PokeBallItem
|
||||
import com.cobblemon.mod.common.item.interactive.PokerodItem
|
||||
import com.cobblemon.mod.common.net.messages.server.pokeball.SendOutPokeBallPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokerod.CastPokeRodPacket
|
||||
import com.cobblemon.mod.common.util.isServerSide
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.InteractionHand
|
||||
|
||||
object CastPokeRodHandler : ServerNetworkPacketHandler<CastPokeRodPacket> {
|
||||
|
||||
override fun handle(packet: CastPokeRodPacket, server: MinecraftServer, player: ServerPlayer) {
|
||||
val hand = if (packet.mainHand) InteractionHand.MAIN_HAND else InteractionHand.OFF_HAND
|
||||
(player.getItemInHand(hand).item as? PokerodItem)?.let { pokerod ->
|
||||
if (player.level().isServerSide()) pokerod.attemptCast(
|
||||
player.level(),
|
||||
player,
|
||||
hand,
|
||||
player.getItemInHand(hand)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.net.serverhandling.pokerod
|
||||
|
||||
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.item.PokeBallItem
|
||||
import com.cobblemon.mod.common.item.interactive.PokerodItem
|
||||
import com.cobblemon.mod.common.net.messages.server.pokeball.SendOutPokeBallPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokerod.CastPokeRodPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokerod.ReelPokeRodPacket
|
||||
import com.cobblemon.mod.common.util.isServerSide
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.InteractionHand
|
||||
|
||||
object ReelPokeRodHandler : ServerNetworkPacketHandler<ReelPokeRodPacket> {
|
||||
|
||||
override fun handle(packet: ReelPokeRodPacket, server: MinecraftServer, player: ServerPlayer) {
|
||||
val hand = if (packet.mainHand) InteractionHand.MAIN_HAND else InteractionHand.OFF_HAND
|
||||
(player.getItemInHand(hand).item as? PokerodItem)?.let { pokerod ->
|
||||
if (player.level().isServerSide()) pokerod.attemptReel(
|
||||
player.level(),
|
||||
player,
|
||||
hand,
|
||||
player.getItemInHand(hand)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ data class RenderEvent(
|
||||
|
||||
/** Represents when a layer is rendered by [LevelRenderer.renderLevel]. Ordinal corresponds with its render order. */
|
||||
enum class Stage {
|
||||
AFTER_ENTITIES,
|
||||
TRANSLUCENT
|
||||
}
|
||||
}
|
||||
@@ -1437,11 +1437,6 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
}
|
||||
|
||||
fun getOwnerEntity(): LivingEntity? {
|
||||
if (isClient) {
|
||||
val ownerUUID = entity?.ownerUUID ?: return null
|
||||
return entity?.level()?.getPlayerByUUID(ownerUUID)
|
||||
}
|
||||
|
||||
return storeCoordinates.get()?.let {
|
||||
if (isPlayerOwned()) {
|
||||
server()?.playerList?.getPlayer(it.store.uuid)
|
||||
|
||||
+7
-55
@@ -8,22 +8,13 @@
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.adapters
|
||||
|
||||
import com.cobblemon.mod.common.api.interaction.InteractionEffect
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.pokemon.adapters.RequirementAdapter
|
||||
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
|
||||
import com.cobblemon.mod.common.pokemon.evolution.adapters.LegacyItemConditionWrapperAdapter
|
||||
import com.cobblemon.mod.common.pokemon.requirements.*
|
||||
import com.cobblemon.mod.common.util.adapters.*
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import com.google.common.collect.HashBiMap
|
||||
import com.google.gson.*
|
||||
import net.minecraft.advancements.critereon.ItemPredicate
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.LowerCaseEnumTypeAdapterFactory
|
||||
import com.google.gson.JsonDeserializationContext
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonSerializationContext
|
||||
import java.lang.reflect.Type
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
@@ -69,60 +60,21 @@ object CobblemonRequirementAdapter : RequirementAdapter {
|
||||
this.registerType(OwnerHoldsItemRequirement.ADAPTER_VARIANT, OwnerHoldsItemRequirement::class)
|
||||
}
|
||||
|
||||
val gson: Gson by lazy {
|
||||
GsonBuilder()
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter)
|
||||
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter)
|
||||
.registerTypeAdapter(Requirement::class.java, CobblemonRequirementAdapter)
|
||||
.registerTypeAdapter(InteractionEffect::class.java, InteractionEffectAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(IntRange::class.java, IntRangeAdapter)
|
||||
.registerTypeAdapterFactory(LowerCaseEnumTypeAdapterFactory())
|
||||
.setPrettyPrinting()
|
||||
.create()
|
||||
}
|
||||
|
||||
override fun <T : Requirement> registerType(id: String, type: KClass<T>) {
|
||||
this.types[id.lowercase()] = type
|
||||
}
|
||||
|
||||
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Requirement {
|
||||
val variant = json.asJsonObject.get(VARIANT).asString.lowercase()
|
||||
val type = getRequirementType(variant)
|
||||
val type = this.types[variant] ?: throw IllegalArgumentException("Cannot resolve evolution requirement type for variant $variant")
|
||||
return context.deserialize(json, type.java)
|
||||
}
|
||||
|
||||
override fun serialize(requirement: Requirement, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
|
||||
val json = context.serialize(requirement, requirement::class.java).asJsonObject
|
||||
val variant = getVariant(requirement)
|
||||
override fun serialize(src: Requirement, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
|
||||
val json = context.serialize(src, src::class.java).asJsonObject
|
||||
val variant = this.types.inverse()[src::class] ?: throw IllegalArgumentException("Cannot resolve evolution requirement for type ${src::class.qualifiedName}")
|
||||
json.addProperty(VARIANT, variant)
|
||||
return json
|
||||
}
|
||||
|
||||
fun encode(requirement: Requirement, buffer: FriendlyByteBuf) {
|
||||
buffer.writeString(gson.toJson(requirement, Requirement::class.java))
|
||||
}
|
||||
|
||||
fun decode(buffer: FriendlyByteBuf): Requirement {
|
||||
return gson.fromJson(buffer.readString(), Requirement::class.java)
|
||||
}
|
||||
|
||||
private fun getVariant(requirement: Requirement): String {
|
||||
val variant = this.types.inverse()[requirement::class]
|
||||
if (variant == null) {
|
||||
throw IllegalArgumentException("Cannot resolve evolution requirement for type ${requirement::class.qualifiedName}")
|
||||
}
|
||||
|
||||
return variant
|
||||
}
|
||||
|
||||
private fun getRequirementType(variant: String): KClass<out Requirement> {
|
||||
val requirementType = this.types[variant]
|
||||
if (requirementType == null) {
|
||||
throw IllegalArgumentException("Cannot resolve evolution requirement type for variant $variant")
|
||||
}
|
||||
|
||||
return requirementType
|
||||
}
|
||||
}
|
||||
+4
-7
@@ -11,9 +11,9 @@ package com.cobblemon.mod.common.pokemon.requirements
|
||||
import com.cobblemon.mod.common.api.pokemon.requirement.OwnerQueryRequirement
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import kotlin.collections.iterator
|
||||
|
||||
/**
|
||||
* An [com.cobblemon.mod.common.api.pokemon.requirement.Requirement] that checks if the player has a certain [net.minecraft.advancements.Advancement]
|
||||
@@ -26,16 +26,13 @@ class AdvancementRequirement(val requiredAdvancement: ResourceLocation) : OwnerQ
|
||||
|
||||
override fun checkPlayer(
|
||||
pokemon: Pokemon,
|
||||
owner: Player
|
||||
owner: ServerPlayer
|
||||
): Boolean {
|
||||
val serverPlayer = owner as? ServerPlayer ?: return false
|
||||
|
||||
for (entry in serverPlayer.advancements.progress) {
|
||||
for (entry in owner.advancements.progress) {
|
||||
if (entry.key.id == requiredAdvancement && entry.value.isDone) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -12,9 +12,11 @@ import com.cobblemon.mod.common.api.pokemon.requirement.OwnerQueryRequirement
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.advancements.critereon.ItemPredicate
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import kotlin.collections.iterator
|
||||
|
||||
/**
|
||||
* An [OwnerQueryRequirement] that checks if the player/npc is holding a certain [ItemPredicate]
|
||||
@@ -28,7 +30,7 @@ class OwnerHoldsItemRequirement(val itemCondition: ItemPredicate)
|
||||
|
||||
override fun checkPlayer(
|
||||
pokemon: Pokemon,
|
||||
owner: Player
|
||||
owner: ServerPlayer
|
||||
): Boolean {
|
||||
return checkItem(owner)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.util
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Vector3f
|
||||
import kotlin.math.sqrt
|
||||
|
||||
/**
|
||||
* For conversion from Vec3dto BlockPos, loses accuracy
|
||||
@@ -22,9 +23,17 @@ fun Vec3.toBlockPos(): BlockPos {
|
||||
fun Vec3.toVec3f(): Vector3f = Vector3f(x.toFloat(), y.toFloat(), z.toFloat())
|
||||
fun Vector3f.toVec3d(): Vec3 =
|
||||
Vec3(x.toDouble(), y.toDouble(), z.toDouble())
|
||||
|
||||
fun Vector3f.set(vec3d: Vec3): Vector3f {
|
||||
x = vec3d.x.toFloat()
|
||||
y = vec3d.y.toFloat()
|
||||
z = vec3d.z.toFloat()
|
||||
return this
|
||||
}
|
||||
|
||||
fun Vector3f.distance(other: Vector3f): Float {
|
||||
val dx = other.x - x
|
||||
val dy = other.y - y
|
||||
val dz = other.z - z
|
||||
return sqrt(dx * dx + dy * dy + dz * dz)
|
||||
}
|
||||
+8
-12
@@ -8,22 +8,22 @@
|
||||
|
||||
package com.cobblemon.mod.common.util.adapters
|
||||
|
||||
import com.google.gson.*
|
||||
import com.google.gson.JsonDeserializationContext
|
||||
import com.google.gson.JsonDeserializer
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonSerializationContext
|
||||
import com.google.gson.JsonSerializer
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.JsonOps
|
||||
import java.lang.reflect.Type
|
||||
|
||||
class CodecBackedAdapter<T>(val codec: Codec<T>) : JsonDeserializer<T>, JsonSerializer<T> {
|
||||
|
||||
override fun deserialize(
|
||||
jElement: JsonElement,
|
||||
typeOfT: Type,
|
||||
context: JsonDeserializationContext
|
||||
): T {
|
||||
val ops = RegistryOpsProvider.getOpsWithDefaultFallback()
|
||||
val result = ops.withDecoder(codec).apply(jElement)
|
||||
return result.result().orElseThrow {
|
||||
IllegalStateException("Failed to deserialize $jElement: ${result.error().orElse(null)}")
|
||||
}.first
|
||||
return JsonOps.INSTANCE.withDecoder(codec).apply(jElement).result().get().first as T
|
||||
}
|
||||
|
||||
override fun serialize(
|
||||
@@ -31,10 +31,6 @@ class CodecBackedAdapter<T>(val codec: Codec<T>) : JsonDeserializer<T>, JsonSeri
|
||||
typeOfSrc: Type?,
|
||||
context: JsonSerializationContext?
|
||||
): JsonElement {
|
||||
val ops = RegistryOpsProvider.getOpsWithDefaultFallback()
|
||||
val result = ops.withEncoder(codec).apply(src)
|
||||
return result.result().orElseThrow {
|
||||
IllegalStateException("Failed to serialize $src: ${result.error().orElse(null)}")
|
||||
}
|
||||
return JsonOps.INSTANCE.withEncoder(codec).apply(src).result().get()
|
||||
}
|
||||
}
|
||||
@@ -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.util.adapters
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Environment
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import com.google.gson.JsonElement
|
||||
import com.mojang.serialization.DynamicOps
|
||||
import com.mojang.serialization.JsonOps
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.resources.RegistryOps
|
||||
|
||||
/**
|
||||
* Utility for obtaining RegistryOps with the correct client/server registry access.
|
||||
* Used when manually encoding/decoding registry-backed values (e.g., items, predicates).
|
||||
*/
|
||||
object RegistryOpsProvider {
|
||||
fun getOpsWithDefaultFallback(): DynamicOps<JsonElement> {
|
||||
if (Cobblemon.implementation.environment() == Environment.CLIENT) {
|
||||
val minecraft = Minecraft.getInstance()
|
||||
if (minecraft != null && minecraft.level != null)
|
||||
return RegistryOps.create(JsonOps.INSTANCE, minecraft.level!!.registryAccess())
|
||||
}
|
||||
|
||||
|
||||
if (Cobblemon.implementation.environment() == Environment.SERVER) {
|
||||
val server = server()
|
||||
if (server != null)
|
||||
return RegistryOps.create(JsonOps.INSTANCE, server.registryAccess())
|
||||
}
|
||||
|
||||
return JsonOps.INSTANCE
|
||||
}
|
||||
}
|
||||
@@ -820,14 +820,6 @@
|
||||
"cobblemon.cooking.cooking_quality.medium": "Medium",
|
||||
"cobblemon.cooking.cooking_quality.high": "High",
|
||||
|
||||
"effect.cobblemon.cleanse_all": "Effect Cleanse",
|
||||
"effect.cobblemon.cleanse_negative": "Negative Effect Cleanse",
|
||||
"effect.cobblemon.mental_restoration": "Mental Restoration",
|
||||
|
||||
"effect.cobblemon.cleanse_all": "Effect Cleanse",
|
||||
"effect.cobblemon.cleanse_negative": "Negative Effect Cleanse",
|
||||
"effect.cobblemon.mental_restoration": "Mental Restoration",
|
||||
|
||||
"cobblemon.fossil.armor": "Armor",
|
||||
"cobblemon.fossil.bird": "Bird",
|
||||
"cobblemon.fossil.claw": "Claw",
|
||||
@@ -3523,7 +3515,6 @@
|
||||
"tag.item.cobblemon.plants": "Plants",
|
||||
"tag.item.cobblemon.seeds": "Seeds",
|
||||
"tag.item.cobblemon.boats": "Boats",
|
||||
"tag.item.cobblemon.chest_boats": "Chest Boats",
|
||||
"tag.item.cobblemon.hanging_signs": "Hanging Signs",
|
||||
"tag.item.cobblemon.signs": "Signs",
|
||||
"tag.item.cobblemon.dawn_stone_ores": "Dawn Stone Ores",
|
||||
@@ -9454,14 +9445,5 @@
|
||||
"stat.cobblemon.traded": "Pokémon Traded",
|
||||
"stat.cobblemon.times_ridden": "Pokémon Ridden",
|
||||
"stat.cobblemon.rod_casts": "PokéRod Casts",
|
||||
"stat.cobblemon.reel_ins": "PokéRod Catches",
|
||||
"stat.cobblemon.riding_land": "Distance by Pokémon on Land",
|
||||
"stat.cobblemon.riding_air": "Distance by Pokémon in Air",
|
||||
"stat.cobblemon.riding_liquid": "Distance by Pokémon in Liquid",
|
||||
|
||||
"controlify.category.cobblemon.cobblemon": "Cobblemon",
|
||||
"controlify.bind.cobblemon.riding_up": "Look Up",
|
||||
"controlify.bind.cobblemon.riding_down": "Look Down",
|
||||
"controlify.bind.cobblemon.riding_left": "Look Left",
|
||||
"controlify.bind.cobblemon.riding_right": "Look Right"
|
||||
"stat.cobblemon.reel_ins": "PokéRod Catches"
|
||||
}
|
||||
|
||||
@@ -1517,139 +1517,76 @@
|
||||
{ "name": "cobblemon:animation/wings/steel_wing_flap_medium_8", "volume": 0.25 }
|
||||
]
|
||||
},
|
||||
"ride.loop.wind.mono": {
|
||||
"ride.loop.wind": {
|
||||
"sounds": [
|
||||
{
|
||||
"name": "cobblemon:ride/loop/wind_loop_mono",
|
||||
"name": "cobblemon:ride/loop/wind_loop",
|
||||
"stream": true,
|
||||
"attenuation_distance": 48.0,
|
||||
"volume": 0.15
|
||||
}
|
||||
]
|
||||
},
|
||||
"ride.loop.wind.stereo": {
|
||||
"ride.loop.leather": {
|
||||
"sounds": [
|
||||
{
|
||||
"name": "cobblemon:ride/loop/wind_loop_stereo",
|
||||
"stream": true,
|
||||
"volume": 0.04
|
||||
}
|
||||
]
|
||||
},
|
||||
"ride.loop.leather.mono": {
|
||||
"sounds": [
|
||||
{
|
||||
"name": "cobblemon:ride/loop/leather_flight_loop_mono",
|
||||
"name": "cobblemon:ride/loop/leather_flight_loop",
|
||||
"stream": true,
|
||||
"attenuation_distance": 48.0,
|
||||
"volume": 0.25
|
||||
}
|
||||
]
|
||||
},
|
||||
"ride.loop.leather.stereo": {
|
||||
"ride.loop.plumage": {
|
||||
"sounds": [
|
||||
{
|
||||
"name": "cobblemon:ride/loop/leather_flight_loop_stereo",
|
||||
"stream": true,
|
||||
"volume": 0.05
|
||||
}
|
||||
]
|
||||
},
|
||||
"ride.loop.plumage.mono": {
|
||||
"sounds": [
|
||||
{
|
||||
"name": "cobblemon:ride/loop/plumage_flight_loop_mono",
|
||||
"name": "cobblemon:ride/loop/plumage_flight_loop",
|
||||
"stream": true,
|
||||
"attenuation_distance": 48.0,
|
||||
"volume": 0.25
|
||||
}
|
||||
]
|
||||
},
|
||||
"ride.loop.plumage.stereo": {
|
||||
"ride.loop.saucer": {
|
||||
"sounds": [
|
||||
{
|
||||
"name": "cobblemon:ride/loop/plumage_flight_loop_stereo",
|
||||
"stream": true,
|
||||
"volume": 0.05
|
||||
}
|
||||
]
|
||||
},
|
||||
"ride.loop.saucer.mono": {
|
||||
"sounds": [
|
||||
{
|
||||
"name": "cobblemon:ride/loop/saucer_flight_loop_mono",
|
||||
"name": "cobblemon:ride/loop/saucer_flight_loop",
|
||||
"stream": true,
|
||||
"attenuation_distance": 48.0,
|
||||
"volume": 0.25
|
||||
}
|
||||
]
|
||||
},
|
||||
"ride.loop.saucer.stereo": {
|
||||
"ride.loop.rocket": {
|
||||
"sounds": [
|
||||
{
|
||||
"name": "cobblemon:ride/loop/saucer_flight_loop_stereo",
|
||||
"stream": true,
|
||||
"volume": 0.1
|
||||
}
|
||||
]
|
||||
},
|
||||
"ride.loop.rocket.mono": {
|
||||
"sounds": [
|
||||
{
|
||||
"name": "cobblemon:ride/loop/rocket_flight_loop_mono",
|
||||
"name": "cobblemon:ride/loop/rocket_flight_loop",
|
||||
"stream": true,
|
||||
"attenuation_distance": 48.0,
|
||||
"volume": 0.4
|
||||
}
|
||||
]
|
||||
},
|
||||
"ride.loop.rocket.stereo": {
|
||||
"ride.loop.water_surface": {
|
||||
"sounds": [
|
||||
{
|
||||
"name": "cobblemon:ride/loop/rocket_flight_loop_stereo",
|
||||
"stream": true,
|
||||
"volume": 0.3
|
||||
}
|
||||
]
|
||||
},
|
||||
"ride.loop.water_surface.mono": {
|
||||
"sounds": [
|
||||
{
|
||||
"name": "cobblemon:ride/loop/water_surface_loop_mono",
|
||||
"name": "cobblemon:ride/loop/water_surface_loop",
|
||||
"stream": true,
|
||||
"attenuation_distance": 32.0,
|
||||
"volume": 0.4
|
||||
}
|
||||
]
|
||||
},
|
||||
"ride.loop.water_surface.stereo": {
|
||||
"ride.loop.underwater": {
|
||||
"sounds": [
|
||||
{
|
||||
"name": "cobblemon:ride/loop/water_surface_loop_stereo",
|
||||
"stream": true,
|
||||
"volume": 0.13
|
||||
}
|
||||
]
|
||||
},
|
||||
"ride.loop.underwater.mono": {
|
||||
"sounds": [
|
||||
{
|
||||
"name": "cobblemon:ride/loop/underwater_loop_mono",
|
||||
"name": "cobblemon:ride/loop/underwater_loop",
|
||||
"stream": true,
|
||||
"attenuation_distance": 16.0,
|
||||
"volume": 0.4
|
||||
}
|
||||
]
|
||||
},
|
||||
"ride.loop.underwater.stereo": {
|
||||
"sounds": [
|
||||
{
|
||||
"name": "cobblemon:ride/loop/underwater_loop_stereo",
|
||||
"stream": true,
|
||||
"volume": 0.2
|
||||
}
|
||||
]
|
||||
},
|
||||
"pokemon.bulbasaur.ambient": {
|
||||
"sounds": [ "cobblemon:pokemon/bulbasaur/bulbasaur_ambient" ]
|
||||
},
|
||||
|
||||
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 599 B |
Binary file not shown.
|
Before Width: | Height: | Size: 606 B |
Binary file not shown.
|
Before Width: | Height: | Size: 566 B |
@@ -1,28 +0,0 @@
|
||||
{
|
||||
"defaults": {
|
||||
"cobblemon:riding_up": {
|
||||
"axis": "controlify:axis/right_stick_up"
|
||||
},
|
||||
"cobblemon:riding_down": {
|
||||
"axis": "controlify:axis/right_stick_down"
|
||||
},
|
||||
"cobblemon:riding_left": {
|
||||
"axis": "controlify:axis/right_stick_left"
|
||||
},
|
||||
"cobblemon:riding_right": {
|
||||
"axis": "controlify:axis/right_stick_right"
|
||||
},
|
||||
"cobblemon:interact_wheel_up": {
|
||||
"axis": "controlify:axis/right_stick_up"
|
||||
},
|
||||
"cobblemon:interact_wheel_down": {
|
||||
"axis": "controlify:axis/right_stick_down"
|
||||
},
|
||||
"cobblemon:interact_wheel_left": {
|
||||
"axis": "controlify:axis/right_stick_left"
|
||||
},
|
||||
"cobblemon:interact_wheel_right": {
|
||||
"axis": "controlify:axis/right_stick_right"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
"conditions": {
|
||||
"items": [
|
||||
{
|
||||
"items": "#cobblemon:mint_leaves"
|
||||
"items": "#cobblemon:mint_leaf"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
t.ticks_between_checks = 20 * 10;
|
||||
math.mod(q.player.world.game_time, t.ticks_between_checks) != 0 ? {
|
||||
return 0;
|
||||
};
|
||||
|
||||
t.steps_required = 10000;
|
||||
t.friendship_required = 200;
|
||||
|
||||
t.total_blocks =
|
||||
q.player.get_custom_stat('minecraft:walk_one_cm') +
|
||||
q.player.get_custom_stat('minecraft:crouch_one_cm') +
|
||||
q.player.get_custom_stat('minecraft:sprint_one_cm') +
|
||||
q.player.get_custom_stat('minecraft:walk_on_water_one_cm') +
|
||||
q.player.get_custom_stat('minecraft:fall_one_cm') +
|
||||
q.player.get_custom_stat('minecraft:climb_one_cm') +
|
||||
q.player.get_custom_stat('minecraft:fly_one_cm') +
|
||||
q.player.get_custom_stat('minecraft:walk_under_water_one_cm') +
|
||||
q.player.get_custom_stat('minecraft:minecart_one_cm') +
|
||||
q.player.get_custom_stat('minecraft:boat_one_cm') +
|
||||
q.player.get_custom_stat('minecraft:pig_one_cm') +
|
||||
q.player.get_custom_stat('minecraft:horse_one_cm') +
|
||||
q.player.get_custom_stat('minecraft:aviate_one_cm') +
|
||||
q.player.get_custom_stat('minecraft:swim_one_cm') +
|
||||
q.player.get_custom_stat('minecraft:strider_one_cm') +
|
||||
q.player.get_custom_stat('cobblemon:riding_land') +
|
||||
q.player.get_custom_stat('cobblemon:riding_air') +
|
||||
q.player.get_custom_stat('cobblemon:riding_liquid');
|
||||
|
||||
t.total_blocks = t.total_blocks / 100.0;
|
||||
t.player_data = q.player.data();
|
||||
|
||||
math.floor(t.total_blocks / t.steps_required) > math.floor(t.player_data.last_partner_mark_check / t.steps_required) ? {
|
||||
t.party = q.player.party;
|
||||
for_each(t.pokemon, t.party.pokemon, {
|
||||
t.pokemon.friendship >= t.friendship_required ? {
|
||||
t.pokemon.add_marks_with_chance('cobblemon:mark_partner');
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
t.player_data.last_partner_mark_check = t.total_blocks;
|
||||
@@ -4,6 +4,5 @@
|
||||
"titleColor": "40B282",
|
||||
"description": "cobblemon.mark.mark_partner.desc",
|
||||
"texture": "cobblemon:textures/gui/mark/mark_partner.png",
|
||||
"indexNumber": 104,
|
||||
"chance": 0.01
|
||||
"indexNumber": 104
|
||||
}
|
||||
@@ -26,7 +26,7 @@
|
||||
},
|
||||
{
|
||||
"content": 2,
|
||||
"tag": "#cobblemon:mint_leaves"
|
||||
"tag": "#cobblemon:mint_leaf"
|
||||
},
|
||||
{
|
||||
"content": 2,
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"ingredient": "cobblemon:mental_herb",
|
||||
"colour": "light_blue",
|
||||
"mobEffects": [
|
||||
{
|
||||
"effect": "cobblemon:mental_restoration",
|
||||
"duration": 200,
|
||||
"amplifier": 0,
|
||||
"ambient": false,
|
||||
"visible": true,
|
||||
"showIcon": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"ingredient": "minecraft:milk_bucket",
|
||||
"colour": "white",
|
||||
"mobEffects": [
|
||||
{
|
||||
"effect": "cobblemon:cleanse_all",
|
||||
"duration": 1,
|
||||
"amplifier": 0,
|
||||
"ambient": false,
|
||||
"visible": true,
|
||||
"showIcon": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"ingredient": "cobblemon:moomoo_milk",
|
||||
"colour": "white",
|
||||
"mobEffects": [
|
||||
{
|
||||
"effect": "cobblemon:cleanse_all",
|
||||
"duration": 1,
|
||||
"amplifier": 0,
|
||||
"ambient": false,
|
||||
"visible": true,
|
||||
"showIcon": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"ingredient": "cobblemon:white_herb",
|
||||
"colour": "white",
|
||||
"mobEffects": [
|
||||
{
|
||||
"effect": "cobblemon:cleanse_negative",
|
||||
"duration": 1,
|
||||
"amplifier": 0,
|
||||
"ambient": false,
|
||||
"visible": true,
|
||||
"showIcon": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -57,33 +57,15 @@
|
||||
{
|
||||
"muffleEnabled": true,
|
||||
"pitchExpr": "math.max(1.0 ,0.2 + math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2))",
|
||||
"playForPassengers": true,
|
||||
"playForNonPassengers": false,
|
||||
"soundLocation": "cobblemon:ride.loop.wind.stereo",
|
||||
"volumeExpr": "math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2)"
|
||||
},
|
||||
{
|
||||
"muffleEnabled": true,
|
||||
"pitchExpr": "math.max(1.0 ,0.2 + math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2))",
|
||||
"playForPassengers": false,
|
||||
"playForNonPassengers": true,
|
||||
"soundLocation": "cobblemon:ride.loop.wind.mono",
|
||||
"soundLocation": "cobblemon:ride.loop.wind",
|
||||
"volumeExpr": "math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2)"
|
||||
},
|
||||
{
|
||||
"muffleEnabled": true,
|
||||
"pitchExpr": "math.max(1.0 ,0.2 + math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2))",
|
||||
"playForPassengers": true,
|
||||
"playForNonPassengers": false,
|
||||
"soundLocation": "cobblemon:ride.loop.leather.stereo",
|
||||
"volumeExpr": "math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2)"
|
||||
},
|
||||
{
|
||||
"muffleEnabled": true,
|
||||
"pitchExpr": "math.max(1.0 ,0.2 + math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2))",
|
||||
"playForPassengers": false,
|
||||
"playForNonPassengers": true,
|
||||
"soundLocation": "cobblemon:ride.loop.leather.mono",
|
||||
"soundLocation": "cobblemon:ride.loop.leather",
|
||||
"volumeExpr": "math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2)"
|
||||
}
|
||||
],
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user