mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-27 20:46:27 -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 |
@@ -54,6 +54,8 @@ dependencies {
|
|||||||
// Flywheel has no common dep so just pick one and don't use any platform specific code in common
|
// Flywheel has no common dep so just pick one and don't use any platform specific code in common
|
||||||
// modCompileOnly(libs.flywheelFabric)
|
// 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
|
// Showdown
|
||||||
modCompileOnly(libs.graal)
|
modCompileOnly(libs.graal)
|
||||||
|
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ import com.cobblemon.mod.common.api.scheduling.ServerRealTimeTaskTracker
|
|||||||
import com.cobblemon.mod.common.api.scheduling.ServerTaskTracker
|
import com.cobblemon.mod.common.api.scheduling.ServerTaskTracker
|
||||||
import com.cobblemon.mod.common.api.spawning.BestSpawner
|
import com.cobblemon.mod.common.api.spawning.BestSpawner
|
||||||
import com.cobblemon.mod.common.api.spawning.CobblemonSpawningZoneGenerator
|
import com.cobblemon.mod.common.api.spawning.CobblemonSpawningZoneGenerator
|
||||||
import com.cobblemon.mod.common.api.spawning.position.AreaSpawnablePositionResolver
|
|
||||||
import com.cobblemon.mod.common.api.spawning.SpawningZoneGenerator
|
import com.cobblemon.mod.common.api.spawning.SpawningZoneGenerator
|
||||||
|
import com.cobblemon.mod.common.api.spawning.position.AreaSpawnablePositionResolver
|
||||||
import com.cobblemon.mod.common.api.starter.StarterHandler
|
import com.cobblemon.mod.common.api.starter.StarterHandler
|
||||||
import com.cobblemon.mod.common.api.stats.CobblemonStats
|
import com.cobblemon.mod.common.api.stats.CobblemonStats
|
||||||
import com.cobblemon.mod.common.api.storage.PokemonStoreManager
|
import com.cobblemon.mod.common.api.storage.PokemonStoreManager
|
||||||
@@ -76,12 +76,8 @@ import com.cobblemon.mod.common.config.LastChangedVersion
|
|||||||
import com.cobblemon.mod.common.config.constraint.IntConstraint
|
import com.cobblemon.mod.common.config.constraint.IntConstraint
|
||||||
import com.cobblemon.mod.common.config.starter.StarterConfig
|
import com.cobblemon.mod.common.config.starter.StarterConfig
|
||||||
import com.cobblemon.mod.common.data.CobblemonDataProvider
|
import com.cobblemon.mod.common.data.CobblemonDataProvider
|
||||||
import com.cobblemon.mod.common.events.AdvancementHandler
|
import com.cobblemon.mod.common.events.*
|
||||||
import com.cobblemon.mod.common.events.EntityCallbackHandler
|
import com.cobblemon.mod.common.integration.vivecraft.CobblemonVR
|
||||||
import com.cobblemon.mod.common.events.CallbackHandler
|
|
||||||
import com.cobblemon.mod.common.events.PokedexHandler
|
|
||||||
import com.cobblemon.mod.common.events.ServerTickHandler
|
|
||||||
import com.cobblemon.mod.common.events.StatHandler
|
|
||||||
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
|
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
|
||||||
import com.cobblemon.mod.common.permission.LaxPermissionValidator
|
import com.cobblemon.mod.common.permission.LaxPermissionValidator
|
||||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||||
@@ -135,10 +131,12 @@ object Cobblemon {
|
|||||||
const val MODID = CobblemonBuildDetails.MOD_ID
|
const val MODID = CobblemonBuildDetails.MOD_ID
|
||||||
const val VERSION = CobblemonBuildDetails.VERSION
|
const val VERSION = CobblemonBuildDetails.VERSION
|
||||||
const val CONFIG_PATH = "config/$MODID/main.json"
|
const val CONFIG_PATH = "config/$MODID/main.json"
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val LOGGER: Logger = LogManager.getLogger()
|
val LOGGER: Logger = LogManager.getLogger()
|
||||||
|
|
||||||
lateinit var implementation: CobblemonImplementation
|
lateinit var implementation: CobblemonImplementation
|
||||||
|
|
||||||
@Deprecated("This field is now a config value", ReplaceWith("Cobblemon.config.captureCalculator"))
|
@Deprecated("This field is now a config value", ReplaceWith("Cobblemon.config.captureCalculator"))
|
||||||
var captureCalculator: CaptureCalculator
|
var captureCalculator: CaptureCalculator
|
||||||
get() = this.config.captureCalculator
|
get() = this.config.captureCalculator
|
||||||
@@ -168,21 +166,49 @@ object Cobblemon {
|
|||||||
val serverPlayerStructs = mutableMapOf<UUID, ObjectValue<Player>>()
|
val serverPlayerStructs = mutableMapOf<UUID, ObjectValue<Player>>()
|
||||||
|
|
||||||
val statistics: CobblemonStats = CobblemonStats
|
val statistics: CobblemonStats = CobblemonStats
|
||||||
|
var cobblemonVR: CobblemonVR? = null
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
val builtinPacks = listOf<CobblemonPack>(
|
val builtinPacks = listOf<CobblemonPack>(
|
||||||
CobblemonPack(id = "adorncompatibility", name = "Adorn Compatibility", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.ALWAYS_ENABLED, neededMods = setOf("adorn")),
|
CobblemonPack(
|
||||||
CobblemonPack(id = "gyaradosjump", name = "Gyarados Jump Patterns", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED),
|
id = "adorncompatibility",
|
||||||
CobblemonPack(id = "regionbiasforms", name = "Region Bias Forms", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED),
|
name = "Adorn Compatibility",
|
||||||
CobblemonPack(id = "uniqueshinyforms", name = "Shinies for Magikarp Jump", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.NORMAL),
|
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) {
|
fun preInitialize(implementation: CobblemonImplementation) {
|
||||||
this.implementation = implementation
|
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) {
|
if (CobblemonBuildDetails.SNAPSHOT) {
|
||||||
this.LOGGER.info(" - Git Commit: ${smallCommitHash()} (https://gitlab.com/cable-mc/cobblemon/-/commit/${CobblemonBuildDetails.GIT_COMMIT})")
|
this.LOGGER.info(" - Git Commit: ${smallCommitHash()} (https://gitlab.com/cable-mc/cobblemon/-/commit/${CobblemonBuildDetails.GIT_COMMIT})")
|
||||||
this.LOGGER.info(" - Branch: ${CobblemonBuildDetails.BRANCH}")
|
this.LOGGER.info(" - Branch: ${CobblemonBuildDetails.BRANCH}")
|
||||||
@@ -246,7 +272,10 @@ object Cobblemon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PlatformEvents.RIGHT_CLICK_ENTITY.subscribe { event ->
|
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()
|
event.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -257,7 +286,10 @@ object Cobblemon {
|
|||||||
pokemon.lockedEvolutions
|
pokemon.lockedEvolutions
|
||||||
.filterIsInstance<BlockClickEvolution>()
|
.filterIsInstance<BlockClickEvolution>()
|
||||||
.forEach { evolution ->
|
.forEach { evolution ->
|
||||||
evolution.attemptEvolution(pokemon, BlockClickEvolution.BlockInteractionContext(block, player.level()))
|
evolution.attemptEvolution(
|
||||||
|
pokemon,
|
||||||
|
BlockClickEvolution.BlockInteractionContext(block, player.level())
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -317,6 +349,11 @@ object Cobblemon {
|
|||||||
SlowpokeTailRegrowthSpeciesFeatureProvider
|
SlowpokeTailRegrowthSpeciesFeatureProvider
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (implementation.isModInstalled("vivecraft")) { // VR integration
|
||||||
|
cobblemonVR = CobblemonVR()
|
||||||
|
cobblemonVR?.init()
|
||||||
|
}
|
||||||
|
|
||||||
CustomPokemonProperty.register(UncatchableProperty)
|
CustomPokemonProperty.register(UncatchableProperty)
|
||||||
CustomPokemonProperty.register(BattleCloneProperty)
|
CustomPokemonProperty.register(BattleCloneProperty)
|
||||||
CustomPokemonProperty.register(PokemonFlagProperty)
|
CustomPokemonProperty.register(PokemonFlagProperty)
|
||||||
@@ -336,7 +373,7 @@ object Cobblemon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PlatformEvents.SERVER_TICK_POST.subscribe {
|
PlatformEvents.SERVER_TICK_POST.subscribe {
|
||||||
ServerTaskTracker.update(1/20F)
|
ServerTaskTracker.update(1 / 20F)
|
||||||
ServerRealTimeTaskTracker.update()
|
ServerRealTimeTaskTracker.update()
|
||||||
}
|
}
|
||||||
PlatformEvents.SERVER_TICK_PRE.subscribe {
|
PlatformEvents.SERVER_TICK_PRE.subscribe {
|
||||||
@@ -380,10 +417,22 @@ object Cobblemon {
|
|||||||
.applyConnectionString(ConnectionString(config.mongoDBConnectionString))
|
.applyConnectionString(ConnectionString(config.mongoDBConnectionString))
|
||||||
.build()
|
.build()
|
||||||
mongoClient = MongoClients.create(mongoClientSettings)
|
mongoClient = MongoClients.create(mongoClientSettings)
|
||||||
val generalMongoFactory = CachedPlayerDataStoreFactory(PlayerDataMongoBackend(mongoClient, config.mongoDBDatabaseName, "PlayerDataCollection"))
|
val generalMongoFactory = CachedPlayerDataStoreFactory(
|
||||||
|
PlayerDataMongoBackend(
|
||||||
|
mongoClient,
|
||||||
|
config.mongoDBDatabaseName,
|
||||||
|
"PlayerDataCollection"
|
||||||
|
)
|
||||||
|
)
|
||||||
generalMongoFactory.setup(server)
|
generalMongoFactory.setup(server)
|
||||||
|
|
||||||
val pokedexMongoFactory = CachedPlayerDataStoreFactory(DexDataMongoBackend(mongoClient, config.mongoDBDatabaseName, "PokeDexCollection"))
|
val pokedexMongoFactory = CachedPlayerDataStoreFactory(
|
||||||
|
DexDataMongoBackend(
|
||||||
|
mongoClient,
|
||||||
|
config.mongoDBDatabaseName,
|
||||||
|
"PokeDexCollection"
|
||||||
|
)
|
||||||
|
)
|
||||||
pokedexMongoFactory.setup(server)
|
pokedexMongoFactory.setup(server)
|
||||||
|
|
||||||
playerDataManager.setFactory(generalMongoFactory, PlayerInstancedDataStoreTypes.GENERAL)
|
playerDataManager.setFactory(generalMongoFactory, PlayerInstancedDataStoreTypes.GENERAL)
|
||||||
@@ -505,6 +554,7 @@ object Cobblemon {
|
|||||||
field.set(config, field.get(defaultConfig))
|
field.set(config, field.get(defaultConfig))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is IntConstraint -> {
|
is IntConstraint -> {
|
||||||
var value = field.get(config)
|
var value = field.get(config)
|
||||||
if (value is Int) {
|
if (value is Int) {
|
||||||
@@ -557,20 +607,76 @@ object Cobblemon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun registerArgumentTypes() {
|
private fun registerArgumentTypes() {
|
||||||
this.implementation.registerCommandArgument(cobblemonResource("pokemon"), SpeciesArgumentType::class, SingletonArgumentInfo.contextFree(SpeciesArgumentType::species))
|
this.implementation.registerCommandArgument(
|
||||||
this.implementation.registerCommandArgument(cobblemonResource("pokemon_properties"), PokemonPropertiesArgumentType::class, SingletonArgumentInfo.contextFree(PokemonPropertiesArgumentType::properties))
|
cobblemonResource("pokemon"),
|
||||||
this.implementation.registerCommandArgument(cobblemonResource("spawn_bucket"), SpawnBucketArgumentType::class, SingletonArgumentInfo.contextFree(SpawnBucketArgumentType::spawnBucket))
|
SpeciesArgumentType::class,
|
||||||
this.implementation.registerCommandArgument(cobblemonResource("move"), MoveArgumentType::class, SingletonArgumentInfo.contextFree(MoveArgumentType::move))
|
SingletonArgumentInfo.contextFree(SpeciesArgumentType::species)
|
||||||
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(
|
||||||
this.implementation.registerCommandArgument(cobblemonResource("dialogue"), DialogueArgumentType::class, SingletonArgumentInfo.contextFree(DialogueArgumentType::dialogue))
|
cobblemonResource("pokemon_properties"),
|
||||||
this.implementation.registerCommandArgument(cobblemonResource("form"), FormArgumentType::class, SingletonArgumentInfo.contextFree(FormArgumentType::form))
|
PokemonPropertiesArgumentType::class,
|
||||||
this.implementation.registerCommandArgument(cobblemonResource("dex"), DexArgumentType::class, SingletonArgumentInfo.contextFree (DexArgumentType::dex))
|
SingletonArgumentInfo.contextFree(PokemonPropertiesArgumentType::properties)
|
||||||
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(
|
||||||
this.implementation.registerCommandArgument(cobblemonResource("mark"), MarkArgumentType::class, SingletonArgumentInfo.contextFree(MarkArgumentType::mark))
|
cobblemonResource("spawn_bucket"),
|
||||||
this.implementation.registerCommandArgument(cobblemonResource("transform_type"), TransformTypeArgumentType::class, SingletonArgumentInfo.contextFree(TransformTypeArgumentType::transformType))
|
SpawnBucketArgumentType::class,
|
||||||
this.implementation.registerCommandArgument(cobblemonResource("model_part"), ModelPartArgumentType::class, SingletonArgumentInfo.contextFree(ModelPartArgumentType::modelPart))
|
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)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,9 @@
|
|||||||
|
|
||||||
package com.cobblemon.mod.common.client
|
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.LOGGER
|
||||||
|
import com.cobblemon.mod.common.Cobblemon.cobblemonVR
|
||||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||||
import com.cobblemon.mod.common.CobblemonBlocks
|
import com.cobblemon.mod.common.CobblemonBlocks
|
||||||
import com.cobblemon.mod.common.CobblemonClientImplementation
|
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.RideControlsOverlay
|
||||||
import com.cobblemon.mod.common.client.gui.battle.BattleOverlay
|
import com.cobblemon.mod.common.client.gui.battle.BattleOverlay
|
||||||
import com.cobblemon.mod.common.client.gui.cookingpot.CookingPotScreen
|
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.particle.BedrockParticleOptionsRepository
|
||||||
import com.cobblemon.mod.common.client.render.ClientPlayerIcon
|
import com.cobblemon.mod.common.client.render.ClientPlayerIcon
|
||||||
import com.cobblemon.mod.common.client.render.DeferredRenderer
|
import com.cobblemon.mod.common.client.render.DeferredRenderer
|
||||||
@@ -72,6 +75,7 @@ import com.cobblemon.mod.common.client.tooltips.TooltipManager
|
|||||||
import com.cobblemon.mod.common.client.trade.ClientTrade
|
import com.cobblemon.mod.common.client.trade.ClientTrade
|
||||||
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
|
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
|
||||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
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.platform.events.PlatformEvents
|
||||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext
|
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext
|
||||||
import com.cobblemon.mod.common.util.isLookingAt
|
import com.cobblemon.mod.common.util.isLookingAt
|
||||||
@@ -152,6 +156,10 @@ object CobblemonClient {
|
|||||||
this.registerTooltipManagers()
|
this.registerTooltipManagers()
|
||||||
this.registerMenuScreens()
|
this.registerMenuScreens()
|
||||||
|
|
||||||
|
if (Cobblemon.implementation.isModInstalled("vivecraft")) { // VR integration
|
||||||
|
CobblemonVRClient.init()
|
||||||
|
}
|
||||||
|
|
||||||
LOGGER.info("Registering custom BuiltinItemRenderers")
|
LOGGER.info("Registering custom BuiltinItemRenderers")
|
||||||
CobblemonBuiltinItemRendererRegistry.register(CobblemonItems.POKEMON_MODEL, PokemonItemRenderer())
|
CobblemonBuiltinItemRendererRegistry.register(CobblemonItems.POKEMON_MODEL, PokemonItemRenderer())
|
||||||
|
|
||||||
@@ -187,7 +195,9 @@ object CobblemonClient {
|
|||||||
|
|
||||||
nearbyPokemon?.forEach { entity ->
|
nearbyPokemon?.forEach { entity ->
|
||||||
if (entity is PokemonEntity && !entity.isSilent && !entity.passengers.contains(player)) {
|
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()
|
entity.delegate.spawnAspectParticle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -369,7 +379,10 @@ object CobblemonClient {
|
|||||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.DISPLAY_CASE, ::DisplayCaseRenderer)
|
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.DISPLAY_CASE, ::DisplayCaseRenderer)
|
||||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.LECTERN, ::LecternBlockEntityRenderer)
|
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.LECTERN, ::LecternBlockEntityRenderer)
|
||||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.CAMPFIRE, ::CampfireBlockEntityRenderer)
|
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.CAMPFIRE, ::CampfireBlockEntityRenderer)
|
||||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.POKE_SNACK, ::PokeSnackBlockEntityRenderer)
|
this.implementation.registerBlockEntityRenderer(
|
||||||
|
CobblemonBlockEntities.POKE_SNACK,
|
||||||
|
::PokeSnackBlockEntityRenderer
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerEntityRenderers() {
|
private fun registerEntityRenderers() {
|
||||||
@@ -398,7 +411,11 @@ object CobblemonClient {
|
|||||||
|
|
||||||
private fun registerItemColors() {
|
private fun registerItemColors() {
|
||||||
implementation.registerItemColors(AprijuiceItemColorProvider, *CobblemonItems.aprijuices.toTypedArray())
|
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(PokeBaitItemColorProvider, CobblemonItems.POKE_BAIT)
|
||||||
implementation.registerItemColors(PonigiriItemColorProvider, CobblemonItems.PONIGIRI)
|
implementation.registerItemColors(PonigiriItemColorProvider, CobblemonItems.PONIGIRI)
|
||||||
implementation.registerItemColors(SinisterTeaItemColorProvider, CobblemonItems.SINISTER_TEA)
|
implementation.registerItemColors(SinisterTeaItemColorProvider, CobblemonItems.SINISTER_TEA)
|
||||||
|
|||||||
+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
|
||||||
|
)
|
||||||
@@ -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
|
import kotlin.math.cos
|
||||||
|
|
||||||
class PokeBallItem(
|
class PokeBallItem(
|
||||||
val pokeBall: PokeBall
|
val pokeBall: PokeBall
|
||||||
) : CobblemonItem(Properties().apply {
|
) : CobblemonItem(Properties().apply {
|
||||||
when (pokeBall.name) {
|
when (pokeBall.name) {
|
||||||
// Master balls are a netherite product and should be fire immune
|
// Master balls are a netherite product and should be fire immune
|
||||||
@@ -43,7 +43,7 @@ class PokeBallItem(
|
|||||||
return InteractionResultHolder.sidedSuccess(itemStack, world.isClientSide)
|
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 pokeBallEntity = EmptyPokeBallEntity(pokeBall, player.level(), player).apply {
|
||||||
val overhandFactor: Float = if (player.xRot < 0) {
|
val overhandFactor: Float = if (player.xRot < 0) {
|
||||||
5f * cos(player.xRot.toRadians())
|
5f * cos(player.xRot.toRadians())
|
||||||
@@ -57,4 +57,5 @@ class PokeBallItem(
|
|||||||
}
|
}
|
||||||
world.addFreshEntity(pokeBallEntity)
|
world.addFreshEntity(pokeBallEntity)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,8 @@ class PokerodItem(val pokeRodId: ResourceLocation, settings: Properties) : Fishi
|
|||||||
|
|
||||||
if (baitCount > 1) {
|
if (baitCount > 1) {
|
||||||
baitStack.count = 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> {
|
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
|
||||||
|
|
||||||
val itemStack = user.getItemInHand(hand)
|
val itemStack = user.getItemInHand(hand)
|
||||||
val offHandItem = user.getItemInHand(InteractionHand.OFF_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
|
attemptApplyOffhandBait(world, user, itemStack, offHandItem)?.let { return it }
|
||||||
if (!world.isClientSide && user.fishing == null && SpawnBaitEffects.isFishingBait(offHandItem)) {
|
|
||||||
CobblemonEvents.BAIT_SET_PRE.postThen(BaitSetEvent(itemStack, offHandItem), { event ->
|
|
||||||
return InteractionResultHolder.fail(itemStack)
|
|
||||||
}, {
|
|
||||||
playAttachSound(user)
|
|
||||||
|
|
||||||
// if there is bait on the rod already then drop it on the ground before applying offhand bait
|
if (user.fishing != null) {
|
||||||
val baitStack = getBaitStackOnRod(itemStack)
|
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) {
|
return InteractionResultHolder.sidedSuccess(itemStack, world.isClientSide)
|
||||||
user.drop(baitStack, true) // Drop the full stack
|
}
|
||||||
|
|
||||||
// apply single bait item from offhand
|
fun applyBait(
|
||||||
val singleBait = offHandItem.copy()
|
rodStack: ItemStack,
|
||||||
singleBait.count = 1
|
baitSource: ItemStack,
|
||||||
setBait(itemStack, singleBait)
|
player: Player?
|
||||||
offHandItem.shrink(1)
|
): 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
|
return null
|
||||||
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)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
world.playSound(null as Player?, user.x, user.y, user.z, CobblemonSounds.FISHING_ROD_REEL_IN, SoundSource.PLAYERS, 1.0f, 1.0f)
|
fun attemptReel(
|
||||||
user.gameEvent(GameEvent.ITEM_INTERACT_FINISH)
|
world: Level,
|
||||||
} else { // if the bobber is not out yet
|
user: Player,
|
||||||
|
hand: InteractionHand,
|
||||||
|
itemStack: ItemStack
|
||||||
|
): InteractionResultHolder<ItemStack>? {
|
||||||
|
if (user.fishing == null) return null
|
||||||
|
|
||||||
if (!world.isClientSide) {
|
if (!world.isClientSide) {
|
||||||
val lureLevel = world.enchantmentRegistry.getHolder(Enchantments.LURE).map { EnchantmentHelper.getItemEnchantmentLevel(it, itemStack) }.orElse(0)
|
CobblemonEvents.POKEROD_REEL.postThen(
|
||||||
val luckLevel = world.enchantmentRegistry.getHolder(Enchantments.LUCK_OF_THE_SEA).map { EnchantmentHelper.getItemEnchantmentLevel(it, itemStack) }.orElse(0)
|
PokerodReelEvent(user, itemStack),
|
||||||
|
{ event -> return InteractionResultHolder.fail(itemStack) },
|
||||||
val bobberEntity = PokeRodFishingBobberEntity(
|
{ event ->
|
||||||
user,
|
val i = user.fishing!!.retrieve(itemStack)
|
||||||
pokeRodId,
|
itemStack.hurtAndBreak(i, user, hand.toEquipmentSlot())
|
||||||
getBaitStackOnRod(itemStack),
|
world.playSoundServer(
|
||||||
world,
|
Vec3(user.x, user.y, user.z),
|
||||||
luckLevel,
|
CobblemonSounds.FISHING_ROD_REEL_IN,
|
||||||
lureLevel,
|
SoundSource.PLAYERS,
|
||||||
itemStack
|
1.0f,
|
||||||
)
|
1.0f / (world.getRandom().nextFloat() * 0.4f + 0.8f)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
return InteractionResultHolder.sidedSuccess(itemStack, world.isClientSide)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+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. */
|
/** Represents when a layer is rendered by [LevelRenderer.renderLevel]. Ordinal corresponds with its render order. */
|
||||||
enum class Stage {
|
enum class Stage {
|
||||||
|
AFTER_ENTITIES,
|
||||||
TRANSLUCENT
|
TRANSLUCENT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.util
|
|||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.world.phys.Vec3
|
import net.minecraft.world.phys.Vec3
|
||||||
import org.joml.Vector3f
|
import org.joml.Vector3f
|
||||||
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For conversion from Vec3dto BlockPos, loses accuracy
|
* 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 Vec3.toVec3f(): Vector3f = Vector3f(x.toFloat(), y.toFloat(), z.toFloat())
|
||||||
fun Vector3f.toVec3d(): Vec3 =
|
fun Vector3f.toVec3d(): Vec3 =
|
||||||
Vec3(x.toDouble(), y.toDouble(), z.toDouble())
|
Vec3(x.toDouble(), y.toDouble(), z.toDouble())
|
||||||
|
|
||||||
fun Vector3f.set(vec3d: Vec3): Vector3f {
|
fun Vector3f.set(vec3d: Vec3): Vector3f {
|
||||||
x = vec3d.x.toFloat()
|
x = vec3d.x.toFloat()
|
||||||
y = vec3d.y.toFloat()
|
y = vec3d.y.toFloat()
|
||||||
z = vec3d.z.toFloat()
|
z = vec3d.z.toFloat()
|
||||||
return this
|
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)
|
||||||
}
|
}
|
||||||
Binary file not shown.
@@ -51,6 +51,16 @@ dependencies {
|
|||||||
modImplementation(libs.fabric.loader)
|
modImplementation(libs.fabric.loader)
|
||||||
modApi(libs.fabric.api)
|
modApi(libs.fabric.api)
|
||||||
modApi(libs.bundles.fabric)
|
modApi(libs.bundles.fabric)
|
||||||
|
|
||||||
|
// VR Support
|
||||||
|
modRuntimeOnly(files("temp/vivecraft-1.21.1-1.3.4-fabric.jar"))
|
||||||
|
runtimeOnly("com.illposed.osc:javaosc-core:0.9")
|
||||||
|
runtimeOnly("com.electronwill.night-config:toml:3.6.6")
|
||||||
|
runtimeOnly("com.electronwill.night-config:core:3.6.6")
|
||||||
|
runtimeOnly("org.lwjgl:lwjgl-openvr:3.3.3")
|
||||||
|
runtimeOnly("org.lwjgl:lwjgl-openvr:3.3.3:natives-linux")
|
||||||
|
runtimeOnly("org.lwjgl:lwjgl-openvr:3.3.3:natives-macos")
|
||||||
|
runtimeOnly("org.lwjgl:lwjgl-openvr:3.3.3:natives-windows")
|
||||||
|
|
||||||
modCompileOnly(libs.bundles.common.integrations.compileOnly) {
|
modCompileOnly(libs.bundles.common.integrations.compileOnly) {
|
||||||
isTransitive = false
|
isTransitive = false
|
||||||
|
|||||||
@@ -170,6 +170,18 @@ class CobblemonFabricClient: ClientModInitializer, CobblemonClientImplementation
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
WorldRenderEvents.AFTER_ENTITIES.register { context -> PlatformEvents.RENDER.post(
|
||||||
|
RenderEvent(
|
||||||
|
stage = RenderEvent.Stage.AFTER_ENTITIES,
|
||||||
|
levelRenderer = context.worldRenderer(),
|
||||||
|
poseStack = context.matrixStack() ?: PoseStack(),
|
||||||
|
modelViewMatrix = context.positionMatrix(),
|
||||||
|
projectionMatrix = context.projectionMatrix(),
|
||||||
|
tickCounter = context.tickCounter(),
|
||||||
|
camera = context.camera()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
CobblemonModelPredicateRegistry.registerPredicates()
|
CobblemonModelPredicateRegistry.registerPredicates()
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -39,6 +39,14 @@ dependencies {
|
|||||||
//include(libs.flywheelForge)
|
//include(libs.flywheelForge)
|
||||||
modLocalRuntime(libs.neoforge.debugutils)
|
modLocalRuntime(libs.neoforge.debugutils)
|
||||||
modRuntimeOnly(libs.bundles.neoforge.integrations.runtimeOnly)
|
modRuntimeOnly(libs.bundles.neoforge.integrations.runtimeOnly)
|
||||||
|
|
||||||
|
// VR Support
|
||||||
|
modRuntimeOnly(files("temp/vivecraft-1.21.1-1.3.4-neoforge.jar"))
|
||||||
|
runtimeOnly("com.illposed.osc:javaosc-core:0.9")
|
||||||
|
runtimeOnly("org.lwjgl:lwjgl-openvr:3.3.3")
|
||||||
|
runtimeOnly("org.lwjgl:lwjgl-openvr:3.3.3:natives-linux")
|
||||||
|
runtimeOnly("org.lwjgl:lwjgl-openvr:3.3.3:natives-macos")
|
||||||
|
runtimeOnly("org.lwjgl:lwjgl-openvr:3.3.3:natives-windows")
|
||||||
|
|
||||||
implementation(libs.neo.kotlin.forge)
|
implementation(libs.neo.kotlin.forge)
|
||||||
|
|
||||||
|
|||||||
+1
@@ -74,6 +74,7 @@ object NeoForgeClientPlatformEventHandler {
|
|||||||
fun onRenderLevelStageEvent(event: RenderLevelStageEvent) {
|
fun onRenderLevelStageEvent(event: RenderLevelStageEvent) {
|
||||||
val stage = when (event.stage) {
|
val stage = when (event.stage) {
|
||||||
RenderLevelStageEvent.Stage.AFTER_PARTICLES -> RenderEvent.Stage.TRANSLUCENT
|
RenderLevelStageEvent.Stage.AFTER_PARTICLES -> RenderEvent.Stage.TRANSLUCENT
|
||||||
|
RenderLevelStageEvent.Stage.AFTER_ENTITIES -> RenderEvent.Stage.AFTER_ENTITIES
|
||||||
else -> return
|
else -> return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user