forked from mirrors/cobblemon
Compare commits
23
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2895c0a2ef | ||
|
|
acc87f9eae | ||
|
|
928dfcdadf | ||
|
|
21363405fc | ||
|
|
08c4f4a0ff | ||
|
|
c4a1704a8b | ||
|
|
837aa5acf5 | ||
|
|
969d6ac7fc | ||
|
|
46bb9e1aec | ||
|
|
9792ff3392 | ||
|
|
e863c6d094 | ||
|
|
a070dc56bd | ||
|
|
79f9e0f0f2 | ||
|
|
8500eb58ef | ||
|
|
e835b833b3 | ||
|
|
3b653b745e | ||
|
|
d03541ff6f | ||
|
|
0d7aff0349 | ||
|
|
c904888c6a | ||
|
|
c07d7d304e | ||
|
|
5f94999b4f | ||
|
|
6515bfa108 | ||
|
|
c502fec709 |
@@ -67,13 +67,24 @@ import com.cobblemon.mod.common.api.storage.player.factory.JsonPlayerDataStoreFa
|
||||
import com.cobblemon.mod.common.api.storage.player.factory.MongoPlayerDataStoreFactory
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonEntityTypeTags
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.battles.*
|
||||
import com.cobblemon.mod.common.battles.BagItems
|
||||
import com.cobblemon.mod.common.battles.BattleFormat
|
||||
import com.cobblemon.mod.common.battles.BattleRegistry
|
||||
import com.cobblemon.mod.common.battles.BattleSide
|
||||
import com.cobblemon.mod.common.battles.ShowdownThread
|
||||
import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.command.argument.*
|
||||
import com.cobblemon.mod.common.command.argument.DialogueArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.MoveArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PartySlotArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PokemonArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PokemonPropertiesArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PokemonStoreArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.SpawnBucketArgumentType
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import com.cobblemon.mod.common.config.LastChangedVersion
|
||||
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.AdvancementHandler
|
||||
import com.cobblemon.mod.common.events.ServerTickHandler
|
||||
@@ -94,7 +105,13 @@ import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
|
||||
import com.cobblemon.mod.common.sherds.CobblemonSherds
|
||||
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
|
||||
import com.cobblemon.mod.common.trade.TradeManager
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.ifDedicatedServer
|
||||
import com.cobblemon.mod.common.util.isLaterVersion
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import com.cobblemon.mod.common.util.removeAmountIf
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import com.cobblemon.mod.common.world.feature.CobblemonPlacedFeatures
|
||||
import com.cobblemon.mod.common.world.feature.ore.CobblemonOrePlacedFeatures
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
@@ -115,16 +132,13 @@ import org.apache.logging.log4j.Logger
|
||||
import java.io.File
|
||||
import java.io.FileReader
|
||||
import java.io.FileWriter
|
||||
import java.io.PrintWriter
|
||||
import java.util.*
|
||||
import kotlin.collections.filterIsInstance
|
||||
import kotlin.collections.forEach
|
||||
import kotlin.collections.listOf
|
||||
import kotlin.collections.set
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.properties.Delegates
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import kotlin.reflect.jvm.javaField
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
object Cobblemon {
|
||||
const val MODID = "cobblemon"
|
||||
@@ -152,6 +166,7 @@ object Cobblemon {
|
||||
var storage = PokemonStoreManager()
|
||||
var molangData = NbtMoLangDataStoreFactory
|
||||
lateinit var playerData: PlayerDataStoreManager
|
||||
lateinit var starterConfig: StarterConfig
|
||||
val dataProvider: DataProvider = CobblemonDataProvider
|
||||
var permissionValidator: PermissionValidator by Delegates.observable(LaxPermissionValidator().also { it.initialize() }) { _, _, newValue -> newValue.initialize() }
|
||||
var statProvider: StatProvider = CobblemonStatProvider
|
||||
@@ -462,6 +477,27 @@ object Cobblemon {
|
||||
this.saveConfig()
|
||||
|
||||
bestSpawner.loadConfig()
|
||||
PokemonSpecies.observable.subscribe { starterConfig = this.loadStarterConfig() }
|
||||
}
|
||||
|
||||
fun loadStarterConfig(): StarterConfig {
|
||||
if (config.exportStarterConfig) {
|
||||
val file = File("config/cobblemon/starters.json")
|
||||
file.parentFile.mkdirs()
|
||||
if (!file.exists()) {
|
||||
val config = StarterConfig()
|
||||
val pw = PrintWriter(file)
|
||||
StarterConfig.GSON.toJson(config, pw)
|
||||
pw.close()
|
||||
return config
|
||||
}
|
||||
val reader = FileReader(file)
|
||||
val config = StarterConfig.GSON.fromJson(reader, StarterConfig::class.java)
|
||||
reader.close()
|
||||
return config
|
||||
} else {
|
||||
return StarterConfig()
|
||||
}
|
||||
}
|
||||
|
||||
fun saveConfig() {
|
||||
|
||||
@@ -397,7 +397,7 @@ open class PokemonProperties {
|
||||
return false
|
||||
}
|
||||
}
|
||||
nickname?.takeIf { it.string != pokemon.nickname?.string }?.let { return false }
|
||||
nickname?.takeIf { it != pokemon.nickname }?.let { return false }
|
||||
form?.takeIf { !it.equals(pokemon.form.name, true) }?.let { return false }
|
||||
friendship?.takeIf { it != pokemon.friendship }?.let { return false }
|
||||
pokeball?.takeIf { it != pokemon.caughtBall.name.toString() }?.let { return false }
|
||||
@@ -437,7 +437,7 @@ open class PokemonProperties {
|
||||
}
|
||||
} catch (_: InvalidIdentifierException) {}
|
||||
}
|
||||
nickname?.takeIf { it.string != properties.nickname?.string }?.let { return false }
|
||||
nickname?.takeIf { it != properties.nickname }?.let { return false }
|
||||
form?.takeIf { !it.equals(properties.form, true) }?.let { return false }
|
||||
friendship?.takeIf { it != properties.friendship }?.let { return false }
|
||||
pokeball?.takeIf { it != properties.pokeball }?.let { return false }
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.starter
|
||||
|
||||
import com.cobblemon.mod.common.config.starter.StarterCategory
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
interface StarterHandler {
|
||||
fun getStarters(player: ServerPlayerEntity): Map<Identifier, StarterCategory>
|
||||
fun getStarterList(player: ServerPlayerEntity): List<StarterCategory>
|
||||
fun handleJoin(player: ServerPlayerEntity)
|
||||
fun requestStarterChoice(player: ServerPlayerEntity)
|
||||
fun chooseStarter(player: ServerPlayerEntity, categoryId: Identifier, index: Int)
|
||||
fun chooseStarter(player: ServerPlayerEntity, categoryName: String, index: Int)
|
||||
}
|
||||
@@ -1,69 +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.starter
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.data.DataRegistry
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
|
||||
import com.cobblemon.mod.common.util.adapters.PlainJsonTextAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.pokemonPropertiesShortAdapter
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.resource.ResourceType
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
/**
|
||||
* The registry for starter Pokémon.
|
||||
*
|
||||
* The data here is used by the [CobblemonStarterHandler].
|
||||
*
|
||||
* 3rd party is not enforced to respect this registry.
|
||||
*/
|
||||
object StarterRegistry : JsonDataRegistry<StarterCategory> {
|
||||
override val gson: Gson = GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.disableHtmlEscaping()
|
||||
.registerTypeAdapter(Text::class.java, PlainJsonTextAdapter)
|
||||
.registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter)
|
||||
.create()
|
||||
override val typeToken: TypeToken<StarterCategory> = TypeToken.get(StarterCategory::class.java)
|
||||
override val id: Identifier = cobblemonResource("starter")
|
||||
override val resourcePath: String = id.path
|
||||
override val type: ResourceType = ResourceType.SERVER_DATA
|
||||
override val observable: SimpleObservable<out DataRegistry> = SimpleObservable()
|
||||
private val categories = hashMapOf<Identifier, StarterCategory>()
|
||||
|
||||
// We let the default starter handler sync the client
|
||||
// This is to prevent unnecessary packets depending on impl
|
||||
override fun sync(player: ServerPlayerEntity) {}
|
||||
|
||||
override fun reload(data: Map<Identifier, StarterCategory>) {
|
||||
this.categories.clear()
|
||||
this.categories += data
|
||||
Cobblemon.LOGGER.info("Loaded {} starters ({} categories)", this.categories.values.sumOf { it.pokemon.size }, this.categories.size)
|
||||
}
|
||||
|
||||
fun all(): Map<Identifier, StarterCategory> = this.categories
|
||||
|
||||
fun keys(): Set<Identifier> = this.categories.keys
|
||||
|
||||
fun categories(): Collection<StarterCategory> = this.categories.values
|
||||
|
||||
fun categoryOf(key: Identifier): StarterCategory? = this.categories[key]
|
||||
|
||||
fun categoryOf(key: String): StarterCategory? = this.categories[key.asIdentifierDefaultingNamespace()]
|
||||
}
|
||||
@@ -37,7 +37,7 @@ data class PlayerData(
|
||||
fun defaultData(forPlayer: UUID) = PlayerData(
|
||||
uuid = forPlayer,
|
||||
starterPrompted = false,
|
||||
starterLocked = !Cobblemon.config.allowStarterOnJoin,
|
||||
starterLocked = !Cobblemon.starterConfig.allowStarterOnJoin,
|
||||
starterSelected = false,
|
||||
starterUUID = null,
|
||||
keyItems = mutableSetOf(),
|
||||
|
||||
@@ -9,23 +9,15 @@
|
||||
package com.cobblemon.mod.common.block
|
||||
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonBlockTags
|
||||
import com.cobblemon.mod.common.block.chest.GildedChestBlock
|
||||
import net.minecraft.block.*
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.fluid.FluidState
|
||||
import net.minecraft.fluid.Fluids
|
||||
import net.minecraft.item.ItemPlacementContext
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.server.world.ServerWorld
|
||||
import net.minecraft.state.StateManager
|
||||
import net.minecraft.state.property.BooleanProperty
|
||||
import net.minecraft.state.property.Properties
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.util.math.random.Random
|
||||
import net.minecraft.util.shape.VoxelShape
|
||||
import net.minecraft.world.BlockView
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.world.WorldAccess
|
||||
import net.minecraft.world.WorldView
|
||||
|
||||
@@ -36,18 +28,7 @@ class TumblestoneBlock(
|
||||
height: Int,
|
||||
xzOffset: Int,
|
||||
nextStage: Block?
|
||||
) : GrowableStoneBlock(settings, stage, height, xzOffset, nextStage), Waterloggable {
|
||||
|
||||
init {
|
||||
this.defaultState = this.stateManager.defaultState
|
||||
.with(FACING, Direction.DOWN)
|
||||
.with(WATERLOGGED, false)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val WATERLOGGED = BooleanProperty.of("waterlogged")
|
||||
}
|
||||
|
||||
) : GrowableStoneBlock(settings, stage, height, xzOffset, nextStage) {
|
||||
override fun canGrow(pos: BlockPos, world: BlockView): Boolean {
|
||||
if (stage == MAX_STAGE) return false
|
||||
val iterator: Iterator<BlockPos> =
|
||||
@@ -62,31 +43,4 @@ class TumblestoneBlock(
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getFluidState(state: BlockState): FluidState {
|
||||
return if (state.get(GildedChestBlock.WATERLOGGED)) {
|
||||
Fluids.WATER.getStill(false)
|
||||
} else super.getFluidState(state)
|
||||
}
|
||||
|
||||
override fun appendProperties(builder: StateManager.Builder<Block, BlockState>) {
|
||||
super.appendProperties(builder)
|
||||
builder.add(GildedChestBlock.WATERLOGGED)
|
||||
}
|
||||
|
||||
override fun getPlacementState(blockPlaceContext: ItemPlacementContext): BlockState? {
|
||||
return super.getPlacementState(blockPlaceContext)?.with(GildedChestBlock.WATERLOGGED, blockPlaceContext.world.getFluidState(blockPlaceContext.blockPos).fluid == Fluids.WATER)
|
||||
|
||||
}
|
||||
|
||||
override fun getStateForNeighborUpdate(
|
||||
state: BlockState,
|
||||
direction: Direction,
|
||||
neighborState: BlockState,
|
||||
world: WorldAccess,
|
||||
pos: BlockPos,
|
||||
neighborPos: BlockPos
|
||||
): BlockState? {
|
||||
if (state.get(GildedChestBlock.WATERLOGGED)) world.scheduleFluidTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world))
|
||||
return super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos)
|
||||
}
|
||||
}
|
||||
@@ -16,15 +16,20 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import com.cobblemon.mod.common.util.toVec3d
|
||||
import net.minecraft.block.*
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockRenderType
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.BlockWithEntity
|
||||
import net.minecraft.block.Blocks
|
||||
import net.minecraft.block.HorizontalFacingBlock
|
||||
import net.minecraft.block.ShapeContext
|
||||
import net.minecraft.block.Waterloggable
|
||||
import net.minecraft.entity.ai.pathing.NavigationType
|
||||
import net.minecraft.entity.mob.PiglinBrain
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.fluid.FluidState
|
||||
import net.minecraft.fluid.Fluids
|
||||
import net.minecraft.item.ItemPlacementContext
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.screen.ScreenHandler
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.sound.SoundCategory
|
||||
@@ -33,7 +38,12 @@ import net.minecraft.state.property.BooleanProperty
|
||||
import net.minecraft.state.property.Properties
|
||||
import net.minecraft.text.MutableText
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.*
|
||||
import net.minecraft.util.ActionResult
|
||||
import net.minecraft.util.BlockMirror
|
||||
import net.minecraft.util.BlockRotation
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.ItemScatterer
|
||||
import net.minecraft.util.hit.BlockHitResult
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
||||
@@ -96,7 +106,7 @@ class GildedChestBlock(settings: Settings, val type: Type = Type.RED) : BlockWit
|
||||
neighborPos: BlockPos
|
||||
): BlockState {
|
||||
if (state.get(WATERLOGGED)) world.scheduleFluidTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world))
|
||||
return super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos)
|
||||
return super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos)
|
||||
}
|
||||
|
||||
override fun getFluidState(state: BlockState): FluidState {
|
||||
@@ -248,17 +258,4 @@ class GildedChestBlock(settings: Settings, val type: Type = Type.RED) : BlockWit
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onPlaced(
|
||||
world: World,
|
||||
pos: BlockPos,
|
||||
state: BlockState,
|
||||
placer: LivingEntity?,
|
||||
itemStack: ItemStack
|
||||
) {
|
||||
val blockEntity = world.getBlockEntity(pos)
|
||||
if (itemStack.hasCustomName() && blockEntity is GildedChestBlockEntity) {
|
||||
blockEntity.customName = itemStack.name
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -140,7 +140,7 @@ class PokemonPastureBlockEntity(pos: BlockPos, val state: BlockState) : BlockEnt
|
||||
if (fixedPosition != null) {
|
||||
entity.setPosition(fixedPosition.toCenterPos().subtract(0.0, 0.5, 0.0))
|
||||
val pc = Cobblemon.storage.getPC(player.uuid)
|
||||
entity.beamMode = 2
|
||||
entity.beamMode = 1
|
||||
afterOnServer(seconds = SendOutPokemonHandler.SEND_OUT_DURATION) {
|
||||
entity.beamMode = 0
|
||||
}
|
||||
|
||||
+38
-62
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.entity
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.entity.PokemonSideDelegate
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.getQueryStruct
|
||||
@@ -21,6 +22,7 @@ import com.cobblemon.mod.common.api.scheduling.lerpOnClient
|
||||
import com.cobblemon.mod.common.client.particle.BedrockParticleEffectRepository
|
||||
import com.cobblemon.mod.common.client.particle.ParticleStorm
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper
|
||||
import com.cobblemon.mod.common.client.render.SnowstormParticle
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.PrimaryAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.StatefulAnimation
|
||||
@@ -32,8 +34,11 @@ import com.cobblemon.mod.common.util.MovingSoundInstance
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.client.util.math.MatrixStack
|
||||
import java.lang.Float.min
|
||||
import kotlin.math.abs
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.entity.data.TrackedData
|
||||
import net.minecraft.particle.ParticleTypes
|
||||
import net.minecraft.sound.SoundCategory
|
||||
import net.minecraft.sound.SoundEvent
|
||||
import net.minecraft.util.Hand
|
||||
@@ -100,8 +105,6 @@ class PokemonClientDelegate : PoseableEntityState<PokemonEntity>(), PokemonSideD
|
||||
this.addPrimaryAnimation(primaryAnimation)
|
||||
}
|
||||
} else if (data == PokemonEntity.BEAM_MODE) {
|
||||
// If you make adjustments to this code, make sure to Find Usages for both PokemonEntity.beamMode and PokemonEntity.BEAM_MODE
|
||||
// TODO: change beamMode to an enum, or a set of booleans (send-out vs recall, delay vs delay)
|
||||
val beamMode = currentEntity.beamMode
|
||||
when (beamMode) {
|
||||
0 -> { /* Do nothing */ }
|
||||
@@ -138,37 +141,39 @@ class PokemonClientDelegate : PoseableEntityState<PokemonEntity>(), PokemonSideD
|
||||
currentEntity.after(seconds = POKEBALL_AIR_TIME){
|
||||
beamStartTime = System.currentTimeMillis()
|
||||
ballDone = true
|
||||
if (client.soundManager.get(CobblemonSounds.POKE_BALL_SEND_OUT.id) != null && !playedSendOutSound) {
|
||||
client.world?.playSound(client.player, soundPos.x, soundPos.y, soundPos.z, SoundEvent.of(CobblemonSounds.POKE_BALL_SEND_OUT.id), SoundCategory.PLAYERS, 0.6f, 1f)
|
||||
playedSendOutSound = true
|
||||
}
|
||||
// Display ball-specific particles
|
||||
sendOutPosition?.let{
|
||||
val newPos = it.add(sendOutOffset)
|
||||
val ballType = currentEntity.pokemon.caughtBall.name.path.lowercase().replace("_","")
|
||||
val mode = if(currentEntity.isBattling) "battle" else "casual"
|
||||
val sendflash = BedrockParticleEffectRepository.getEffect(cobblemonResource("${ballType}/${mode}/sendflash"))
|
||||
sendflash?.let { effect ->
|
||||
val wrapper = MatrixWrapper()
|
||||
val matrix = MatrixStack()
|
||||
matrix.translate(newPos.x, newPos.y, newPos.z)
|
||||
wrapper.updateMatrix(matrix.peek().positionMatrix)
|
||||
val world = MinecraftClient.getInstance().world ?: return@let
|
||||
ParticleStorm(effect, wrapper, world).spawn()
|
||||
val ballsparks = BedrockParticleEffectRepository.getEffect(cobblemonResource("${ballType}/${mode}/ballsparks"))
|
||||
val ballsendsparkle = BedrockParticleEffectRepository.getEffect(cobblemonResource("${ballType}/${mode}/ballsendsparkle"))
|
||||
// using afterOnClient because it's such a small timeframe that it's unlikely the entity has been removed & we'd like the precision
|
||||
afterOnClient(seconds = 0.01667f) {
|
||||
ballsparks?.let { effect ->
|
||||
if (client.soundManager.get(CobblemonSounds.POKE_BALL_OPEN.id) != null && !playedSendOutSound) {
|
||||
currentEntity.owner?.let {
|
||||
client.world?.playSound(client.player, soundPos.x, soundPos.y, soundPos.z, SoundEvent.of(CobblemonSounds.POKE_BALL_SEND_OUT.id), SoundCategory.PLAYERS, 0.6f, 1f)
|
||||
playedSendOutSound = true
|
||||
/// create end rod particles in a 0.1 radius around the soundPos with a count of 50 and a random velocity of 0.1
|
||||
sendOutPosition?.let{
|
||||
val newPos = it.add(sendOutOffset)
|
||||
val ballType = currentEntity.pokemon.caughtBall.name.path.toLowerCase().replace("_","")
|
||||
val mode = if(currentEntity.isBattling) "battle" else "casual"
|
||||
val sendflash = BedrockParticleEffectRepository.getEffect(cobblemonResource("${ballType}/${mode}/sendflash"))
|
||||
sendflash?.let { effect ->
|
||||
val wrapper = MatrixWrapper()
|
||||
val matrix = MatrixStack()
|
||||
matrix.translate(newPos.x, newPos.y, newPos.z)
|
||||
wrapper.updateMatrix(matrix.peek().positionMatrix)
|
||||
val world = MinecraftClient.getInstance().world ?: return@let
|
||||
ParticleStorm(effect, wrapper, world).spawn()
|
||||
}
|
||||
ballsendsparkle?.let { effect ->
|
||||
ParticleStorm(effect, wrapper, world).spawn()
|
||||
}
|
||||
currentEntity.after(seconds = 0.4f) {
|
||||
val ballsparkle = BedrockParticleEffectRepository.getEffect(cobblemonResource("${ballType}/ballsparkle"))
|
||||
ballsparkle?.let { effect ->
|
||||
ParticleStorm(effect, wrapper, world).spawn()
|
||||
val ballsparks = BedrockParticleEffectRepository.getEffect(cobblemonResource("${ballType}/${mode}/ballsparks"))
|
||||
val ballsendsparkle = BedrockParticleEffectRepository.getEffect(cobblemonResource("${ballType}/${mode}/ballsendsparkle"))
|
||||
// using afterOnClient because it's such a small timeframe that it's unlikely the entity has been removed & we'd like the precision
|
||||
afterOnClient(seconds = 0.01667f) {
|
||||
ballsparks?.let { effect ->
|
||||
ParticleStorm(effect, wrapper, world).spawn()
|
||||
}
|
||||
ballsendsparkle?.let { effect ->
|
||||
ParticleStorm(effect, wrapper, world).spawn()
|
||||
}
|
||||
currentEntity.after(seconds = 0.4f) {
|
||||
val ballsparkle = BedrockParticleEffectRepository.getEffect(cobblemonResource("${ballType}/ballsparkle"))
|
||||
ballsparkle?.let { effect ->
|
||||
ParticleStorm(effect, wrapper, world).spawn()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -185,35 +190,7 @@ class PokemonClientDelegate : PoseableEntityState<PokemonEntity>(), PokemonSideD
|
||||
}
|
||||
}
|
||||
}
|
||||
2 -> {
|
||||
// Scaling up with no delay and no particles
|
||||
playedSendOutSound = false
|
||||
entityScaleModifier = 0F
|
||||
currentEntity.isInvisible = false
|
||||
val soundPos = currentEntity.pos
|
||||
val client = MinecraftClient.getInstance()
|
||||
|
||||
if (client.soundManager.get(CobblemonSounds.POKE_BALL_SEND_OUT.id) != null && !playedSendOutSound) {
|
||||
client.world?.playSound(
|
||||
client.player,
|
||||
soundPos.x,
|
||||
soundPos.y,
|
||||
soundPos.z,
|
||||
CobblemonSounds.POKE_BALL_SEND_OUT,
|
||||
SoundCategory.PLAYERS,
|
||||
0.6f,
|
||||
1f
|
||||
)
|
||||
playedSendOutSound = true
|
||||
}
|
||||
lerpOnClient(BEAM_SHRINK_TIME) { entityScaleModifier = it }
|
||||
currentEntity.after(seconds = BEAM_SHRINK_TIME * 2) {
|
||||
ballOffset = 0f
|
||||
ballRotOffset = 0f
|
||||
sendOutPosition = null
|
||||
}
|
||||
}
|
||||
3 -> {
|
||||
else -> {
|
||||
// Scaling down into pokeball
|
||||
entityScaleModifier = 1F
|
||||
beamStartTime = System.currentTimeMillis()
|
||||
@@ -226,7 +203,6 @@ class PokemonClientDelegate : PoseableEntityState<PokemonEntity>(), PokemonSideD
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> { /* Do nothing */ }
|
||||
}
|
||||
} else if (data == PokemonEntity.LABEL_LEVEL) {
|
||||
currentEntity.dataTracker.get(PokemonEntity.LABEL_LEVEL)
|
||||
|
||||
+17
-21
@@ -27,7 +27,7 @@ import com.cobblemon.mod.common.client.gui.summary.widgets.type.DualTypeWidget
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.type.SingleTypeWidget
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.type.TypeWidget
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.api.starter.RenderableStarterCategory
|
||||
import com.cobblemon.mod.common.config.starter.RenderableStarterCategory
|
||||
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
|
||||
import com.cobblemon.mod.common.pokemon.RenderablePokemon
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
@@ -40,7 +40,6 @@ import net.minecraft.client.gui.screen.Screen
|
||||
import net.minecraft.client.sound.PositionedSoundInstance
|
||||
import net.minecraft.client.toast.Toast
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
/**
|
||||
* Starterselection Screen Thingy
|
||||
@@ -48,7 +47,7 @@ import net.minecraft.util.Identifier
|
||||
* @author Qu
|
||||
* @since 2022-06-18
|
||||
*/
|
||||
class StarterSelectionScreen(categories: Map<Identifier, RenderableStarterCategory>): Screen("cobblemon.ui.starter.title".asTranslated()) {
|
||||
class StarterSelectionScreen(private val categories: List<RenderableStarterCategory>): Screen("cobblemon.ui.starter.title".asTranslated()) {
|
||||
|
||||
companion object {
|
||||
// Size of UI at scale 1
|
||||
@@ -65,9 +64,8 @@ class StarterSelectionScreen(categories: Map<Identifier, RenderableStarterCatego
|
||||
private val doubleTypeBackground = cobblemonResource("textures/gui/starterselection/starterselection_type_slot2.png")
|
||||
}
|
||||
|
||||
private val categories = categories.toSortedMap { a, b -> a.compareTo(b) }
|
||||
private var currentSelection = 0
|
||||
private lateinit var currentCategoryId: Identifier
|
||||
private lateinit var currentCategory: RenderableStarterCategory
|
||||
private lateinit var modelWidget: ModelWidget
|
||||
private lateinit var currentPokemon: RenderablePokemon
|
||||
private lateinit var typeWidget: TypeWidget
|
||||
@@ -97,7 +95,7 @@ class StarterSelectionScreen(categories: Map<Identifier, RenderableStarterCatego
|
||||
paneWidth = 71, paneHeight = BASE_HEIGHT - 11,
|
||||
topOffset = 6, bottomOffset = 5,
|
||||
entryHeight = 20, entryWidth = 57,
|
||||
categories = this.categories,
|
||||
categories = categories,
|
||||
x = x - 2, y = y + 8,
|
||||
starterSelectionScreen = this
|
||||
)
|
||||
@@ -122,8 +120,8 @@ class StarterSelectionScreen(categories: Map<Identifier, RenderableStarterCatego
|
||||
addDrawableChild(rightButton)
|
||||
addDrawableChild(leftButton)
|
||||
|
||||
currentCategoryId = categories.firstKey()
|
||||
currentPokemon = this.currentCategory().pokemon[currentSelection]
|
||||
currentCategory = categories.first()
|
||||
currentPokemon = currentCategory.pokemon[currentSelection]
|
||||
|
||||
with(currentPokemon) {
|
||||
modelWidget = ModelWidget(
|
||||
@@ -144,11 +142,11 @@ class StarterSelectionScreen(categories: Map<Identifier, RenderableStarterCatego
|
||||
) {
|
||||
CobblemonNetwork.sendPacketToServer(
|
||||
SelectStarterPacket(
|
||||
categoryId = currentCategoryId,
|
||||
categoryName = currentCategory.name,
|
||||
selected = currentSelection
|
||||
)
|
||||
)
|
||||
this.close()
|
||||
MinecraftClient.getInstance().setScreen(null)
|
||||
}
|
||||
|
||||
addDrawableChild(selectionButton)
|
||||
@@ -163,7 +161,7 @@ class StarterSelectionScreen(categories: Map<Identifier, RenderableStarterCatego
|
||||
starterRoundaboutLeft = StarterRoundabout(
|
||||
pX = x + 89, pY = height / 2 + 84,
|
||||
pWidth = StarterRoundabout.MODEL_WIDTH, pHeight = StarterRoundabout.MODEL_HEIGHT,
|
||||
pokemon = this.currentCategory().pokemon[leftOfCurrentSelection()],
|
||||
pokemon = currentCategory.pokemon[leftOfCurrentSelection()],
|
||||
clickAction = { _, _ -> this.left() },
|
||||
rotationVector = this.modelWidget.rotVec
|
||||
)
|
||||
@@ -171,7 +169,7 @@ class StarterSelectionScreen(categories: Map<Identifier, RenderableStarterCatego
|
||||
starterRoundaboutRight = StarterRoundabout(
|
||||
pX = x + 149, pY = height / 2 + 84,
|
||||
pWidth = StarterRoundabout.MODEL_WIDTH, pHeight = StarterRoundabout.MODEL_HEIGHT,
|
||||
pokemon = this.currentCategory().pokemon[rightOfCurrentSelection()],
|
||||
pokemon = currentCategory.pokemon[rightOfCurrentSelection()],
|
||||
clickAction = { _, _ -> this.right() },
|
||||
rotationVector = this.modelWidget.rotVec
|
||||
)
|
||||
@@ -278,8 +276,8 @@ class StarterSelectionScreen(categories: Map<Identifier, RenderableStarterCatego
|
||||
super.render(context, mouseX, mouseY, delta)
|
||||
}
|
||||
|
||||
fun changeCategory(id: Identifier) {
|
||||
currentCategoryId = id
|
||||
fun changeCategory(category: RenderableStarterCategory) {
|
||||
currentCategory = category
|
||||
currentSelection = 0
|
||||
updateSelection()
|
||||
}
|
||||
@@ -290,7 +288,7 @@ class StarterSelectionScreen(categories: Map<Identifier, RenderableStarterCatego
|
||||
updateSelection()
|
||||
}
|
||||
|
||||
private fun rightOfCurrentSelection() : Int = if (currentSelection + 1 <= this.currentCategory().pokemon.size - 1) currentSelection + 1 else 0
|
||||
private fun rightOfCurrentSelection() : Int = if (currentSelection + 1 <= currentCategory.pokemon.size - 1) currentSelection + 1 else 0
|
||||
|
||||
private fun left() {
|
||||
MinecraftClient.getInstance().soundManager.play(PositionedSoundInstance.master(CobblemonSounds.GUI_CLICK, 1.0F))
|
||||
@@ -298,16 +296,16 @@ class StarterSelectionScreen(categories: Map<Identifier, RenderableStarterCatego
|
||||
updateSelection()
|
||||
}
|
||||
|
||||
private fun leftOfCurrentSelection() : Int = if (currentSelection - 1 == -1) this.currentCategory().pokemon.size - 1 else currentSelection - 1
|
||||
private fun leftOfCurrentSelection() : Int = if (currentSelection - 1 == -1) currentCategory.pokemon.size - 1 else currentSelection - 1
|
||||
|
||||
private fun updateSelection() {
|
||||
currentPokemon = this.currentCategory().pokemon[currentSelection].also {
|
||||
currentPokemon = currentCategory.pokemon[currentSelection].also {
|
||||
modelWidget.pokemon = it
|
||||
typeWidget = typeWidget(it, (width - BASE_WIDTH) / 2, (height - BASE_HEIGHT) / 2)
|
||||
}
|
||||
starterRoundaboutLeft.pokemon = this.currentCategory().pokemon[leftOfCurrentSelection()]
|
||||
starterRoundaboutLeft.pokemon = currentCategory.pokemon[leftOfCurrentSelection()]
|
||||
starterRoundaboutCenter.pokemon = currentPokemon
|
||||
starterRoundaboutRight.pokemon = this.currentCategory().pokemon[rightOfCurrentSelection()]
|
||||
starterRoundaboutRight.pokemon = currentCategory.pokemon[rightOfCurrentSelection()]
|
||||
}
|
||||
|
||||
private fun typeWidget(pokemon: RenderablePokemon, x: Int, y: Int) : TypeWidget {
|
||||
@@ -326,7 +324,5 @@ class StarterSelectionScreen(categories: Map<Identifier, RenderableStarterCatego
|
||||
)
|
||||
}
|
||||
|
||||
private fun currentCategory(): RenderableStarterCategory = this.categories[this.currentCategoryId]!!
|
||||
|
||||
override fun shouldPause() = true
|
||||
}
|
||||
+19
-9
@@ -12,14 +12,14 @@ import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.startselection.StarterSelectionScreen
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.api.starter.RenderableStarterCategory
|
||||
import com.cobblemon.mod.common.config.starter.RenderableStarterCategory
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.client.gui.DrawContext
|
||||
import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget
|
||||
import net.minecraft.client.sound.PositionedSoundInstance
|
||||
import net.minecraft.client.util.math.MatrixStack
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
class CategoryList(
|
||||
private val paneWidth: Int,
|
||||
@@ -28,7 +28,7 @@ class CategoryList(
|
||||
bottomOffset: Int,
|
||||
private val entryWidth: Int,
|
||||
entryHeight: Int,
|
||||
private val categories: Map<Identifier, RenderableStarterCategory>,
|
||||
private val categories: List<RenderableStarterCategory>,
|
||||
val x: Int, val y: Int,
|
||||
private val minecraft: MinecraftClient = MinecraftClient.getInstance(),
|
||||
private val starterSelectionScreen: StarterSelectionScreen
|
||||
@@ -44,6 +44,7 @@ class CategoryList(
|
||||
companion object {
|
||||
private const val CATEGORY_BUTTON_WIDTH = 51.5f
|
||||
private const val CATEGORY_BUTTON_HEIGHT = 16f
|
||||
private const val ENTRY_X_OFFSET = 10f
|
||||
private val categoryResource = cobblemonResource("textures/gui/starterselection/starterselection_slot.png")
|
||||
}
|
||||
|
||||
@@ -52,12 +53,19 @@ class CategoryList(
|
||||
this.setRenderHorizontalShadows(false)
|
||||
this.setRenderBackground(false)
|
||||
this.setRenderSelection(false)
|
||||
this.categories.forEach { (id, category) ->
|
||||
this.addEntry(Category(id, category))
|
||||
}
|
||||
}
|
||||
|
||||
private var entriesCreated = false
|
||||
|
||||
private fun createEntries() = categories.map {
|
||||
Category(it)
|
||||
}
|
||||
|
||||
override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
if (!entriesCreated) {
|
||||
createEntries().forEach { addEntry(it) }
|
||||
entriesCreated = true
|
||||
}
|
||||
context.enableScissor(
|
||||
x,
|
||||
y,
|
||||
@@ -72,13 +80,15 @@ class CategoryList(
|
||||
this.updateSize(this.paneWidth, this.paneHeight, this.y, this.y + this.paneHeight)
|
||||
this.setLeftPos(this.x)
|
||||
}
|
||||
|
||||
private fun scale(n: Int): Int = (this.client.window.scaleFactor * n).toInt()
|
||||
override fun getRowWidth() = this.entryWidth
|
||||
override fun getScrollbarPositionX(): Int {
|
||||
return this.left + this.width - 5
|
||||
}
|
||||
|
||||
|
||||
inner class Category(private val id: Identifier, private val category: RenderableStarterCategory) : Entry<Category>() {
|
||||
inner class Category(private val category: RenderableStarterCategory) : Entry<Category>() {
|
||||
|
||||
override fun render(
|
||||
context: DrawContext,
|
||||
@@ -111,7 +121,7 @@ class CategoryList(
|
||||
)
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = category.displayName.copy(),
|
||||
text = category.displayNameText,
|
||||
x = x + 28,
|
||||
y = y + 4.5F,
|
||||
scale = 1F,
|
||||
@@ -122,7 +132,7 @@ class CategoryList(
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
starterSelectionScreen.changeCategory(this.id)
|
||||
starterSelectionScreen.changeCategory(category = category)
|
||||
minecraft.soundManager.play(PositionedSoundInstance.master(CobblemonSounds.GUI_CLICK, 1.0F))
|
||||
return true
|
||||
}
|
||||
|
||||
-5
@@ -67,11 +67,6 @@ abstract class PokeBallPoseableState : PoseableEntityState<EmptyPokeBallEntity>(
|
||||
setStatefulAnimations(currentModel!!.bedrockStateful(group, "critical"))
|
||||
}
|
||||
}
|
||||
EmptyPokeBallEntity.CaptureState.BROKEN_FREE -> {
|
||||
doLater {
|
||||
setStatefulAnimations(currentModel!!.bedrockStateful(group, "break"))
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -32,6 +32,7 @@ import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.util.math.DoubleRange
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import com.cobblemon.mod.common.util.math.remap
|
||||
import kotlin.math.*
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.client.font.TextRenderer
|
||||
import net.minecraft.client.render.*
|
||||
@@ -52,7 +53,6 @@ import org.joml.Math
|
||||
import org.joml.Quaternionf
|
||||
import org.joml.Vector3f
|
||||
import org.joml.Vector4f
|
||||
import kotlin.math.*
|
||||
|
||||
class PokemonRenderer(
|
||||
context: EntityRendererFactory.Context
|
||||
@@ -60,7 +60,7 @@ class PokemonRenderer(
|
||||
companion object {
|
||||
val recallBeamColour = Vector4f(1F, 0.1F, 0.1F, 1F)
|
||||
fun ease(x: Double): Double {
|
||||
return 1 - (1 - x).pow(3)
|
||||
return 1 - (1 - x).pow(3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ class PokemonRenderer(
|
||||
if (entity.beamMode != 0) {
|
||||
renderTransition(
|
||||
modelNow,
|
||||
entity.beamMode,
|
||||
entity.beamMode == 1,
|
||||
entity,
|
||||
partialTicks,
|
||||
poseMatrix,
|
||||
@@ -130,7 +130,7 @@ class PokemonRenderer(
|
||||
|
||||
fun renderTransition(
|
||||
modelNow: PoseableEntityModel<PokemonEntity>,
|
||||
beamMode: Int,
|
||||
sendingOut: Boolean,
|
||||
entity: PokemonEntity,
|
||||
partialTicks: Float,
|
||||
poseMatrix: MatrixStack,
|
||||
@@ -139,7 +139,7 @@ class PokemonRenderer(
|
||||
clientDelegate: PokemonClientDelegate
|
||||
) {
|
||||
val s = clientDelegate.secondsSinceBeamEffectStarted
|
||||
if (modelNow is PokemonPoseableModel && beamMode == 3) {
|
||||
if (modelNow is PokemonPoseableModel && !sendingOut) {
|
||||
if (s > BEAM_EXTEND_TIME) {
|
||||
val value = (s - BEAM_EXTEND_TIME) / BEAM_SHRINK_TIME
|
||||
val colourValue = 1F - min(0.6F, value)
|
||||
@@ -163,9 +163,9 @@ class PokemonRenderer(
|
||||
}
|
||||
}
|
||||
|
||||
if (clientDelegate.sendOutPosition == null && beamMode == 1) {
|
||||
if (clientDelegate.sendOutPosition == null && sendingOut) {
|
||||
clientDelegate.sendOutPosition = beamSourcePosition
|
||||
} else if (beamMode == 1) {
|
||||
} else if (sendingOut) {
|
||||
clientDelegate.sendOutPosition = clientDelegate.sendOutPosition!!.add(0.0, 0.04, 0.0)
|
||||
beamSourcePosition = clientDelegate.sendOutPosition!!
|
||||
}
|
||||
@@ -184,9 +184,9 @@ class PokemonRenderer(
|
||||
poseMatrix.multiply(RotationAxis.POSITIVE_Y.rotation(-angle.toFloat() + (180 * Math.PI / 180).toFloat()))
|
||||
|
||||
// TODO: if you want to remove the open ball, add `!clientDelegate.ballDone` to the if statement
|
||||
if (beamMode == 1 && !clientDelegate.ballDone){
|
||||
if (sendingOut && !clientDelegate.ballDone){
|
||||
if(entity.pokemon.caughtBall.name.toString().contains("beast")){
|
||||
// get rotation angle on x-axis for facingDir
|
||||
// get rotation angle on x acis for facingDir
|
||||
val xAngleFacingDir = MathHelper.atan2(facingDir.y, sqrt(facingDir.x * facingDir.x + facingDir.z * facingDir.z))
|
||||
poseMatrix.multiply(RotationAxis.POSITIVE_X.rotation(-xAngleFacingDir.toFloat()))
|
||||
}
|
||||
@@ -203,7 +203,7 @@ class PokemonRenderer(
|
||||
)
|
||||
}
|
||||
poseMatrix.pop()
|
||||
if (beamMode == 3) {
|
||||
if (!sendingOut) {
|
||||
renderBeam(poseMatrix, partialTicks, entity, phaseTarget, buffer, offsetDirection)
|
||||
}
|
||||
}
|
||||
|
||||
+16
-1
@@ -9,7 +9,11 @@
|
||||
package com.cobblemon.mod.common.command
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.permission.CobblemonPermissions
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.net.messages.client.starter.OpenStarterUIPacket
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.util.permission
|
||||
import com.mojang.brigadier.Command.SINGLE_SUCCESS
|
||||
import com.mojang.brigadier.CommandDispatcher
|
||||
@@ -34,7 +38,18 @@ object OpenStarterScreenCommand {
|
||||
|
||||
private fun execute(context: CommandContext<ServerCommandSource>) : Int {
|
||||
val player = EntityArgumentType.getPlayer(context, "player")
|
||||
Cobblemon.starterHandler.requestStarterChoice(player)
|
||||
val playerData = Cobblemon.playerData.get(player)
|
||||
if (playerData.starterSelected) {
|
||||
context.source.sendFeedback({ lang("ui.starter.hasalreadychosen", player.name).red() }, true)
|
||||
return 0
|
||||
}
|
||||
if (playerData.starterLocked) {
|
||||
playerData.starterLocked = false
|
||||
playerData.sendToPlayer(player)
|
||||
}
|
||||
playerData.starterPrompted = true
|
||||
Cobblemon.playerData.saveSingle(playerData)
|
||||
player.sendPacket(OpenStarterUIPacket(Cobblemon.starterHandler.getStarterList(player)))
|
||||
return SINGLE_SUCCESS
|
||||
}
|
||||
|
||||
|
||||
@@ -113,12 +113,6 @@ class CobblemonConfig {
|
||||
@NodeCategory(Category.Starter)
|
||||
var exportStarterConfig = false
|
||||
|
||||
@NodeCategory(Category.Starter)
|
||||
var allowStarterOnJoin = true
|
||||
|
||||
@NodeCategory(Category.Starter)
|
||||
var promptStarterOnceOnly = true
|
||||
|
||||
@NodeCategory(Category.Battles)
|
||||
var autoUpdateShowdown = true
|
||||
|
||||
|
||||
+11
-6
@@ -6,19 +6,24 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.starter
|
||||
package com.cobblemon.mod.common.config.starter
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.pokemon.RenderablePokemon
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import net.minecraft.text.Text
|
||||
|
||||
data class StarterCategory(
|
||||
val displayName: Text,
|
||||
val name: String,
|
||||
val displayName: String,
|
||||
val pokemon: List<PokemonProperties>
|
||||
)
|
||||
) {
|
||||
fun asRenderableStarterCategory() = RenderableStarterCategory(name, displayName, pokemon.map { it.asRenderablePokemon() })
|
||||
}
|
||||
|
||||
data class RenderableStarterCategory(
|
||||
val displayName: Text,
|
||||
val name: String,
|
||||
val displayName: String,
|
||||
val pokemon: List<RenderablePokemon>
|
||||
)
|
||||
) {
|
||||
val displayNameText = displayName.asTranslated()
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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.config.starter
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.config.Category
|
||||
import com.cobblemon.mod.common.config.LastChangedVersion
|
||||
import com.cobblemon.mod.common.config.NodeCategory
|
||||
import com.cobblemon.mod.common.util.adapters.pokemonPropertiesShortAdapter
|
||||
import com.google.gson.GsonBuilder
|
||||
|
||||
class StarterConfig {
|
||||
companion object {
|
||||
val GSON = GsonBuilder()
|
||||
.disableHtmlEscaping()
|
||||
.setPrettyPrinting()
|
||||
.registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter)
|
||||
.create()
|
||||
}
|
||||
|
||||
@NodeCategory(Category.Starter)
|
||||
var allowStarterOnJoin = true
|
||||
|
||||
@NodeCategory(Category.Starter)
|
||||
@LastChangedVersion("1.5.0")
|
||||
var promptStarterOnceOnly = true
|
||||
|
||||
@NodeCategory(Category.Starter)
|
||||
var starters = mutableListOf(
|
||||
StarterCategory(
|
||||
name = "Kanto",
|
||||
displayName = "cobblemon.starterselection.category.kanto",
|
||||
pokemon = mutableListOf(
|
||||
PokemonProperties.parse("Bulbasaur level=10"),
|
||||
PokemonProperties.parse("Charmander level=10"),
|
||||
PokemonProperties.parse("Squirtle level=10"),
|
||||
)
|
||||
),
|
||||
StarterCategory(
|
||||
name = "Johto",
|
||||
displayName = "cobblemon.starterselection.category.johto",
|
||||
pokemon = mutableListOf(
|
||||
PokemonProperties.parse("Chikorita level=10"),
|
||||
PokemonProperties.parse("Cyndaquil level=10"),
|
||||
PokemonProperties.parse("Totodile level=10"),
|
||||
)
|
||||
),
|
||||
StarterCategory(
|
||||
name = "Hoenn",
|
||||
displayName = "cobblemon.starterselection.category.hoenn",
|
||||
pokemon = mutableListOf(
|
||||
PokemonProperties.parse("Treecko level=10"),
|
||||
PokemonProperties.parse("Torchic level=10"),
|
||||
PokemonProperties.parse("Mudkip level=10"),
|
||||
)
|
||||
),
|
||||
StarterCategory(
|
||||
name = "Sinnoh",
|
||||
displayName = "cobblemon.starterselection.category.sinnoh",
|
||||
pokemon = mutableListOf(
|
||||
PokemonProperties.parse("Turtwig level=10"),
|
||||
PokemonProperties.parse("Chimchar level=10"),
|
||||
PokemonProperties.parse("Piplup level=10"),
|
||||
)
|
||||
),
|
||||
StarterCategory(
|
||||
name = "Unova",
|
||||
displayName = "cobblemon.starterselection.category.unova",
|
||||
pokemon = mutableListOf(
|
||||
PokemonProperties.parse("Snivy level=10"),
|
||||
PokemonProperties.parse("Tepig level=10"),
|
||||
PokemonProperties.parse("Oshawott level=10"),
|
||||
)
|
||||
),
|
||||
StarterCategory(
|
||||
name = "Kalos",
|
||||
displayName = "cobblemon.starterselection.category.kalos",
|
||||
pokemon = mutableListOf(
|
||||
PokemonProperties.parse("Chespin level=10"),
|
||||
PokemonProperties.parse("Fennekin level=10"),
|
||||
PokemonProperties.parse("Froakie level=10"),
|
||||
)
|
||||
),
|
||||
StarterCategory(
|
||||
name = "Alola",
|
||||
displayName = "cobblemon.starterselection.category.alola",
|
||||
pokemon = mutableListOf(
|
||||
PokemonProperties.parse("Rowlet level=10"),
|
||||
PokemonProperties.parse("Litten level=10"),
|
||||
PokemonProperties.parse("Popplio level=10"),
|
||||
)
|
||||
),
|
||||
StarterCategory(
|
||||
name = "Galar",
|
||||
displayName = "cobblemon.starterselection.category.galar",
|
||||
pokemon = mutableListOf(
|
||||
PokemonProperties.parse("Grookey level=10"),
|
||||
PokemonProperties.parse("Scorbunny level=10"),
|
||||
PokemonProperties.parse("Sobble level=10"),
|
||||
)
|
||||
),
|
||||
StarterCategory(
|
||||
name = "Paldea",
|
||||
displayName = "cobblemon.starterselection.category.paldea",
|
||||
pokemon = mutableListOf(
|
||||
PokemonProperties.parse("Sprigatito level=10"),
|
||||
PokemonProperties.parse("Fuecoco level=10"),
|
||||
PokemonProperties.parse("Quaxly level=10"),
|
||||
)
|
||||
)
|
||||
//,
|
||||
// StarterCategory(
|
||||
// name = "Johto",
|
||||
// displayName = lang("starterselection.category.johto"),
|
||||
// pokemon = mutableListOf(
|
||||
// PokemonProperties().also { it.level = 5 ; it.species = "Chikorita" },
|
||||
// PokemonProperties().also { it.level = 5 ; it.species = "Cyndaquil" },
|
||||
// PokemonProperties().also { it.level = 5 ; it.species = "Totodile" }
|
||||
// )
|
||||
// )
|
||||
)
|
||||
}
|
||||
@@ -29,7 +29,6 @@ import com.cobblemon.mod.common.api.pokemon.feature.SpeciesFeatures
|
||||
import com.cobblemon.mod.common.api.spawning.CobblemonSpawnPools
|
||||
import com.cobblemon.mod.common.api.spawning.CobblemonSpawnRules
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnDetailPresets
|
||||
import com.cobblemon.mod.common.api.starter.StarterRegistry
|
||||
import com.cobblemon.mod.common.battles.BagItems
|
||||
import com.cobblemon.mod.common.net.messages.client.data.UnlockReloadPacket
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
@@ -64,7 +63,6 @@ object CobblemonDataProvider : DataProvider {
|
||||
this.register(Abilities)
|
||||
this.register(PokemonSpecies)
|
||||
this.register(SpeciesAdditions)
|
||||
this.register(StarterRegistry)
|
||||
this.register(PokeBalls)
|
||||
this.register(PropertiesCompletionProvider)
|
||||
this.register(SpawnDetailPresets)
|
||||
|
||||
+15
-25
@@ -21,8 +21,9 @@ import com.cobblemon.mod.common.api.net.serializers.Vec3DataSerializer
|
||||
import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.api.pokeball.catching.CaptureContext
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.scheduling.Schedulable
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.scheduling.ScheduledTask
|
||||
import com.cobblemon.mod.common.api.scheduling.SchedulingTracker
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
@@ -36,12 +37,17 @@ import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.Poseable
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonServerDelegate
|
||||
import com.cobblemon.mod.common.net.messages.client.animation.PlayPoseableAnimationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleCaptureStartPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokeballPacket
|
||||
import com.cobblemon.mod.common.pokeball.PokeBall
|
||||
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.util.isServerSide
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.util.playSoundServer
|
||||
import com.cobblemon.mod.common.util.sendParticlesServer
|
||||
import com.cobblemon.mod.common.util.setPositionSafely
|
||||
import com.cobblemon.mod.common.util.update
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import net.minecraft.entity.EntityDimensions
|
||||
import net.minecraft.entity.EntityPose
|
||||
import net.minecraft.entity.EntityType
|
||||
@@ -64,7 +70,6 @@ import net.minecraft.util.math.MathHelper
|
||||
import net.minecraft.util.math.MathHelper.PI
|
||||
import net.minecraft.util.math.Vec3d
|
||||
import net.minecraft.world.World
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
class EmptyPokeBallEntity : ThrownItemEntity, Poseable, WaterDragModifier, Schedulable {
|
||||
enum class CaptureState {
|
||||
@@ -73,8 +78,7 @@ class EmptyPokeBallEntity : ThrownItemEntity, Poseable, WaterDragModifier, Sched
|
||||
FALL,
|
||||
SHAKE,
|
||||
CAPTURED,
|
||||
CAPTURED_CRITICAL,
|
||||
BROKEN_FREE
|
||||
CAPTURED_CRITICAL
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -131,7 +135,6 @@ class EmptyPokeBallEntity : ThrownItemEntity, Poseable, WaterDragModifier, Sched
|
||||
CaptureState.FALL -> setNoGravity(false)
|
||||
CaptureState.SHAKE -> setNoGravity(true)
|
||||
CaptureState.CAPTURED, CaptureState.CAPTURED_CRITICAL -> {}
|
||||
CaptureState.BROKEN_FREE -> {}
|
||||
}
|
||||
}
|
||||
dataTrackerEmitter.emit(data)
|
||||
@@ -345,27 +348,25 @@ class EmptyPokeBallEntity : ThrownItemEntity, Poseable, WaterDragModifier, Sched
|
||||
|
||||
world.playSoundServer(pos, CobblemonSounds.POKE_BALL_SHAKE, volume = 0.8F)
|
||||
// Emits a shake by changing the value to the opposite of what it currently is. Sends an update to the client basically.
|
||||
// We could replace this with a packet, but it feels awfully excessive when we already have 5 bajillion packets.
|
||||
// We could replace this with a packet but it feels awfully excessive when we already have 5 bajillion packets.
|
||||
dataTracker.update(SHAKE) { !it }
|
||||
}
|
||||
|
||||
private fun breakFree() {
|
||||
val pokemon = capturingPokemon ?: return
|
||||
pokemon.setPosition(pos)
|
||||
pokemon.beamMode = 2
|
||||
pokemon.beamMode = 1
|
||||
pokemon.isInvisible = false
|
||||
|
||||
if (pokemon.battleId == null) {
|
||||
pokemon.pokemon.status?.takeIf { it.status == Statuses.SLEEP }?.let { pokemon.pokemon.status = null }
|
||||
}
|
||||
|
||||
captureState = CaptureState.BROKEN_FREE
|
||||
world.playSoundServer(pos, CobblemonSounds.POKE_BALL_OPEN, volume = 0.8F)
|
||||
|
||||
after(seconds = 1F) {
|
||||
after(seconds = 0.25F) {
|
||||
pokemon.busyLocks.remove(this)
|
||||
captureFuture.complete(false)
|
||||
world.sendParticlesServer(ParticleTypes.CLOUD, pos, 20, Vec3d(0.0, 0.2, 0.0), 0.05)
|
||||
world.playSoundServer(pos, CobblemonSounds.POKE_BALL_OPEN, volume = 0.8F)
|
||||
discard()
|
||||
}
|
||||
}
|
||||
@@ -380,17 +381,6 @@ class EmptyPokeBallEntity : ThrownItemEntity, Poseable, WaterDragModifier, Sched
|
||||
captureState = CaptureState.HIT
|
||||
val mul = if (random.nextBoolean()) 1 else -1
|
||||
world.playSoundServer(pos, CobblemonSounds.POKE_BALL_HIT, volume = 0.4F)
|
||||
|
||||
// Hit Pokémon plays recoil animation
|
||||
val pkt = PlayPoseableAnimationPacket(pokemonEntity.id, setOf("recoil"), emptySet())
|
||||
pkt.sendToPlayersAround(
|
||||
x = pokemonEntity.x,
|
||||
y = pokemonEntity.y,
|
||||
z = pokemonEntity.z,
|
||||
worldKey = pokemonEntity.world.registryKey,
|
||||
distance = 50.0
|
||||
)
|
||||
|
||||
// Bounce backwards away from the hit Pokémon
|
||||
velocity = displace.multiply(-1.0, 0.0, -1.0).normalize().rotateY(mul * PI/3).multiply(0.1, 0.0, 0.1).add(0.0, 1.0 / 3, 0.0)
|
||||
pokemonEntity.phasingTargetId = this.id
|
||||
@@ -399,7 +389,7 @@ class EmptyPokeBallEntity : ThrownItemEntity, Poseable, WaterDragModifier, Sched
|
||||
velocity = Vec3d.ZERO
|
||||
setNoGravity(true)
|
||||
world.playSoundServer(pos, CobblemonSounds.POKE_BALL_CAPTURE_STARTED, volume = 0.6F)
|
||||
pokemonEntity.beamMode = 3
|
||||
pokemonEntity.beamMode = 2
|
||||
}
|
||||
|
||||
after(seconds = 2.2F) {
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.cobblemon.mod.common.api.scheduling.Schedulable
|
||||
import com.cobblemon.mod.common.api.scheduling.SchedulingTracker
|
||||
import com.cobblemon.mod.common.api.storage.InvalidSpeciesException
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes.FIRE
|
||||
import com.cobblemon.mod.common.battles.BagItems
|
||||
import com.cobblemon.mod.common.battles.BattleBuilder
|
||||
import com.cobblemon.mod.common.battles.BattleRegistry
|
||||
@@ -56,6 +57,10 @@ import com.cobblemon.mod.common.pokemon.evolution.variants.ItemInteractionEvolut
|
||||
import com.cobblemon.mod.common.pokemon.misc.GimmighoulStashHandler
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
import java.util.EnumSet
|
||||
import java.util.Optional
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import net.minecraft.entity.*
|
||||
import net.minecraft.entity.ai.control.MoveControl
|
||||
import net.minecraft.entity.ai.goal.EatGrassGoal
|
||||
@@ -102,8 +107,6 @@ import net.minecraft.util.math.Vec3d
|
||||
import net.minecraft.world.EntityView
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.world.event.GameEvent
|
||||
import java.util.*
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
@Suppress("unused")
|
||||
open class PokemonEntity(
|
||||
@@ -330,7 +333,7 @@ open class PokemonEntity(
|
||||
* Prevents fire type Pokémon from taking fire damage.
|
||||
*/
|
||||
override fun isFireImmune(): Boolean {
|
||||
return pokemon.isFireImmune()
|
||||
return FIRE in pokemon.types || !behaviour.moving.swim.hurtByLava
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -375,10 +378,10 @@ open class PokemonEntity(
|
||||
if (dataTracker.get(PHASING_TARGET_ID) == -1 && owner != null) {
|
||||
owner.getWorld().playSoundServer(pos, CobblemonSounds.POKE_BALL_RECALL, volume = 0.6F)
|
||||
dataTracker.set(PHASING_TARGET_ID, owner.id)
|
||||
dataTracker.set(BEAM_MODE, 3)
|
||||
dataTracker.set(BEAM_MODE, 2)
|
||||
val state = pokemon.state
|
||||
after(seconds = SEND_OUT_DURATION) {
|
||||
// only recall if the Pokémon hasn't been recalled yet for this state
|
||||
// only recall if the pokemon hasn't been recalled yet for this state
|
||||
if (state == pokemon.state) {
|
||||
pokemon.recall()
|
||||
}
|
||||
|
||||
+1
-1
@@ -205,7 +205,7 @@ class PokemonServerDelegate : PokemonSideDelegate {
|
||||
if (owner != null) {
|
||||
entity.world.playSoundServer(owner.pos, CobblemonSounds.POKE_BALL_RECALL, volume = 0.6F)
|
||||
entity.dataTracker.set(PokemonEntity.PHASING_TARGET_ID, owner.id)
|
||||
entity.dataTracker.set(PokemonEntity.BEAM_MODE, 3)
|
||||
entity.dataTracker.set(PokemonEntity.BEAM_MODE, 2)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-14
@@ -16,7 +16,6 @@ import com.cobblemon.mod.common.util.getWaterAndLavaIn
|
||||
import com.cobblemon.mod.common.util.math.geometry.toDegrees
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.sqrt
|
||||
import net.minecraft.entity.ai.control.MoveControl
|
||||
@@ -76,9 +75,9 @@ class PokemonMoveControl(val pokemonEntity: PokemonEntity) : MoveControl(pokemon
|
||||
entity.setSidewaysSpeed(sidewaysMovement)
|
||||
state = State.WAIT
|
||||
} else if (state == State.MOVE_TO) {
|
||||
var xDist = targetX - entity.x
|
||||
var zDist = targetZ - entity.z
|
||||
var yDist = targetY - entity.y
|
||||
val xDist = targetX - entity.x
|
||||
val zDist = targetZ - entity.z
|
||||
val yDist = targetY - entity.y
|
||||
|
||||
val horizontalDistanceFromTarget = xDist * xDist + zDist * zDist
|
||||
val closeHorizontally = horizontalDistanceFromTarget < VERY_CLOSE
|
||||
@@ -100,13 +99,12 @@ class PokemonMoveControl(val pokemonEntity: PokemonEntity) : MoveControl(pokemon
|
||||
verticalHandled = true
|
||||
entity.upwardSpeed = 0F
|
||||
entity.movementSpeed = 0F
|
||||
// Refinement is to prevent the entity from spinning around trying to get to a super precise location.
|
||||
val refine: (Double) -> Double = { if (abs(it) < 0.05) 0.0 else it }
|
||||
|
||||
val fullDistance = Vec3d(
|
||||
xDist,
|
||||
refine(yDist + 0.05), // + 0.05 for dealing with swimming out of water, they otherwise get stuck on the lip
|
||||
zDist
|
||||
refine(xDist),
|
||||
if (inFluid || pokemonEntity.getBehaviourFlag(PokemonBehaviourFlag.FLYING)) refine(yDist + 0.05) else 0.0,
|
||||
refine(zDist)
|
||||
)
|
||||
|
||||
val direction = fullDistance.normalize()
|
||||
@@ -114,13 +112,8 @@ class PokemonMoveControl(val pokemonEntity: PokemonEntity) : MoveControl(pokemon
|
||||
val scale = min(adjustedSpeed.toDouble(), fullDistance.length())
|
||||
|
||||
entity.velocity = direction.multiply(scale)
|
||||
|
||||
xDist = fullDistance.x
|
||||
zDist = fullDistance.z
|
||||
yDist = fullDistance.y
|
||||
} else {
|
||||
// division is to slow the speed down a bit so they don't overshoot when they get there.
|
||||
val forwardSpeed = min(adjustedSpeed, max(horizontalDistanceFromTarget.toFloat() / 2, 0.15F))
|
||||
val forwardSpeed = min(adjustedSpeed, sqrt(horizontalDistanceFromTarget).toFloat())
|
||||
entity.movementSpeed = forwardSpeed
|
||||
}
|
||||
|
||||
|
||||
@@ -12,14 +12,12 @@ import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
|
||||
import com.cobblemon.mod.common.pokeball.PokeBall
|
||||
import com.cobblemon.mod.common.util.isServerSide
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.TypedActionResult
|
||||
import net.minecraft.world.World
|
||||
import kotlin.math.cos
|
||||
|
||||
class PokeBallItem(
|
||||
val pokeBall : PokeBall
|
||||
@@ -38,12 +36,8 @@ class PokeBallItem(
|
||||
|
||||
private fun throwPokeBall(world: World, player: ServerPlayerEntity) {
|
||||
val pokeBallEntity = EmptyPokeBallEntity(pokeBall, player.world, player).apply {
|
||||
val overhandFactor: Float = if (player.pitch < 0) {
|
||||
5f * cos(player.pitch.toRadians())
|
||||
} else {
|
||||
5f
|
||||
}
|
||||
setVelocity(player, player.pitch - overhandFactor, player.yaw, 0.0f, pokeBall.throwPower, 1.0f)
|
||||
// setPos(player.x, player.y + player.standingEyeHeight - 0.2, player.z)
|
||||
setVelocity(player, player.pitch - 5, player.yaw, 0.0f, pokeBall.throwPower, 1.0f)
|
||||
setPosition(pos.add(velocity.normalize().multiply(1.0)))
|
||||
owner = player
|
||||
}
|
||||
|
||||
+28
-13
@@ -9,33 +9,48 @@
|
||||
package com.cobblemon.mod.common.net.messages.client.starter
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.starter.RenderableStarterCategory
|
||||
import com.cobblemon.mod.common.api.starter.StarterCategory
|
||||
import com.cobblemon.mod.common.config.starter.RenderableStarterCategory
|
||||
import com.cobblemon.mod.common.config.starter.StarterCategory
|
||||
import com.cobblemon.mod.common.pokemon.RenderablePokemon
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
class OpenStarterUIPacket(val categories: Map<Identifier, RenderableStarterCategory>) : NetworkPacket<OpenStarterUIPacket> {
|
||||
class OpenStarterUIPacket internal constructor(val categories: List<RenderableStarterCategory>) : NetworkPacket<OpenStarterUIPacket> {
|
||||
|
||||
override val id = ID
|
||||
|
||||
constructor(categories: Collection<StarterCategory>) : this(categories.map { it.asRenderableStarterCategory() })
|
||||
|
||||
override fun encode(buffer: PacketByteBuf) {
|
||||
buffer.writeMap(this.categories, PacketByteBuf::writeIdentifier) { categoryBuffer, category ->
|
||||
categoryBuffer.writeText(category.displayName)
|
||||
categoryBuffer.writeCollection(category.pokemon) { pokemonBuffer, renderable ->
|
||||
renderable.saveToBuffer(pokemonBuffer)
|
||||
}
|
||||
buffer.writeInt(categories.size)
|
||||
categories.forEach {
|
||||
buffer.writeString(it.name)
|
||||
buffer.writeString(it.displayName)
|
||||
buffer.writeInt(it.pokemon.size)
|
||||
it.pokemon.forEach { it.saveToBuffer(buffer) }
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("open_starter")
|
||||
fun decode(buffer: PacketByteBuf): OpenStarterUIPacket {
|
||||
val categories = buffer.readMap(PacketByteBuf::readIdentifier) { categoryBuffer ->
|
||||
val displayName = buffer.readText()
|
||||
val renderablePokemon = categoryBuffer.readList(RenderablePokemon::loadFromBuffer)
|
||||
return@readMap RenderableStarterCategory(displayName, renderablePokemon)
|
||||
val numCategories = buffer.readInt()
|
||||
val categories = arrayListOf<RenderableStarterCategory>()
|
||||
for (i in 0 until numCategories) {
|
||||
val name = buffer.readString()
|
||||
val displayName = buffer.readString()
|
||||
val numProperties = buffer.readInt()
|
||||
val renderablePokemon = mutableListOf<RenderablePokemon>()
|
||||
repeat(times = numProperties) {
|
||||
renderablePokemon.add(RenderablePokemon.loadFromBuffer(buffer))
|
||||
}
|
||||
categories.add(
|
||||
RenderableStarterCategory(
|
||||
name = name,
|
||||
displayName = displayName,
|
||||
pokemon = renderablePokemon
|
||||
)
|
||||
)
|
||||
}
|
||||
return OpenStarterUIPacket(categories)
|
||||
}
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ class SetClientPlayerDataPacket(val promptStarter: Boolean, val starterLocked: B
|
||||
playerData: PlayerData,
|
||||
resetStarterPrompt: Boolean? = null
|
||||
) : this(
|
||||
!playerData.starterPrompted || !Cobblemon.config.promptStarterOnceOnly,
|
||||
!playerData.starterPrompted || !Cobblemon.starterConfig.promptStarterOnceOnly,
|
||||
playerData.starterLocked,
|
||||
playerData.starterSelected,
|
||||
playerData.starterUUID,
|
||||
|
||||
+3
-4
@@ -11,17 +11,16 @@ package com.cobblemon.mod.common.net.messages.server
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
class SelectStarterPacket(val categoryId: Identifier, val selected: Int) : NetworkPacket<SelectStarterPacket> {
|
||||
class SelectStarterPacket(val categoryName: String, val selected: Int) : NetworkPacket<SelectStarterPacket> {
|
||||
override val id = ID
|
||||
override fun encode(buffer: PacketByteBuf) {
|
||||
buffer.writeIdentifier(this.categoryId)
|
||||
buffer.writeString(this.categoryName)
|
||||
buffer.writeInt(this.selected)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("select_starter")
|
||||
fun decode(buffer: PacketByteBuf): SelectStarterPacket = SelectStarterPacket(buffer.readIdentifier(), buffer.readInt())
|
||||
fun decode(buffer: PacketByteBuf): SelectStarterPacket = SelectStarterPacket(buffer.readString(), buffer.readInt())
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -16,6 +16,6 @@ import net.minecraft.server.network.ServerPlayerEntity
|
||||
|
||||
object SelectStarterPacketHandler : ServerNetworkPacketHandler<SelectStarterPacket> {
|
||||
override fun handle(packet: SelectStarterPacket, server: MinecraftServer, player: ServerPlayerEntity) {
|
||||
Cobblemon.starterHandler.chooseStarter(player, packet.categoryId, packet.selected)
|
||||
Cobblemon.starterHandler.chooseStarter(player, packet.categoryName, packet.selected)
|
||||
}
|
||||
}
|
||||
+7
-5
@@ -13,10 +13,11 @@ import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
|
||||
import com.cobblemon.mod.common.pokemon.activestate.ActivePokemonState
|
||||
import com.cobblemon.mod.common.pokemon.activestate.ShoulderedState
|
||||
import com.cobblemon.mod.common.util.raycastSafeSendout
|
||||
import com.cobblemon.mod.common.util.toVec3d
|
||||
import com.cobblemon.mod.common.util.traceBlockCollision
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.world.RaycastContext
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
object SendOutPokemonHandler : ServerNetworkPacketHandler<SendOutPokemonPacket> {
|
||||
|
||||
@@ -30,10 +31,11 @@ object SendOutPokemonHandler : ServerNetworkPacketHandler<SendOutPokemonPacket>
|
||||
return
|
||||
}
|
||||
val state = pokemon.state
|
||||
if (state is ShoulderedState || state !is ActivePokemonState) {
|
||||
val position = player.raycastSafeSendout(pokemon, 12.0, 5.0, RaycastContext.FluidHandling.ANY)
|
||||
|
||||
if (position != null) {
|
||||
if (state is ShoulderedState || state !is ActivePokemonState) {
|
||||
val trace = player.traceBlockCollision(maxDistance = 15F)
|
||||
if (trace != null && !player.world.getBlockState(trace.blockPos.up()).isSolid) {
|
||||
val position = Vec3d(trace.location.x, trace.blockPos.up().toVec3d().y, trace.location.z)
|
||||
pokemon.sendOutWithAnimation(player, player.serverWorld, position)
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -49,7 +49,6 @@ import com.cobblemon.mod.common.api.storage.StoreCoordinates
|
||||
import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore
|
||||
import com.cobblemon.mod.common.api.storage.pc.PCStore
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.api.types.tera.TeraType
|
||||
import com.cobblemon.mod.common.api.types.tera.TeraTypes
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
@@ -73,7 +72,6 @@ import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonPrimitive
|
||||
import com.mojang.serialization.Dynamic
|
||||
import com.mojang.serialization.JsonOps
|
||||
import net.minecraft.block.*
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.item.ItemStack
|
||||
@@ -82,7 +80,6 @@ import net.minecraft.nbt.NbtElement.COMPOUND_TYPE
|
||||
import net.minecraft.nbt.NbtList
|
||||
import net.minecraft.nbt.NbtOps
|
||||
import net.minecraft.nbt.NbtString
|
||||
import net.minecraft.registry.tag.FluidTags
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.server.world.ServerWorld
|
||||
import net.minecraft.text.MutableText
|
||||
@@ -91,11 +88,9 @@ import net.minecraft.text.TextContent
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.InvalidIdentifierException
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.MathHelper.ceil
|
||||
import net.minecraft.util.math.MathHelper.clamp
|
||||
import net.minecraft.util.math.Vec3d
|
||||
import net.minecraft.world.World
|
||||
import java.util.*
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import kotlin.math.absoluteValue
|
||||
@@ -539,7 +534,6 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
val rotatedOffset = Vec3d(shoulderHorizontalOffset, approxShoulderMonHight, 0.0).rotateY(-rotation * (Math.PI.toFloat() / 180f))
|
||||
val currentPosition = player.pos.add(rotatedOffset)
|
||||
|
||||
recall()
|
||||
sendOut(level, currentPosition) {
|
||||
// Play some sound indicating hopping off
|
||||
level.playSoundServer(currentPosition, CobblemonSounds.PC_DROP, volume = 0.6F)
|
||||
@@ -620,52 +614,6 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
}
|
||||
}
|
||||
|
||||
fun isFireImmune(): Boolean {
|
||||
return ElementalTypes.FIRE in types || !form.behaviour.moving.swim.hurtByLava
|
||||
}
|
||||
|
||||
fun isPositionSafe(world: World, pos: Vec3d): Boolean {
|
||||
return isPositionSafe(world, pos.toBlockPos())
|
||||
}
|
||||
|
||||
fun isPositionSafe(world: World, pos1: BlockPos): Boolean {
|
||||
// To make sure a location is safe, both the block the Pokemon is standing ON,
|
||||
// and the block it's standing IN need to be safe. pos2 represents the other position in that set.
|
||||
val pos2: BlockPos = if (world.getBlockState(pos1).isSolid) {
|
||||
pos1.up()
|
||||
} else {
|
||||
pos1.down()
|
||||
}
|
||||
|
||||
val positions = arrayOf(pos1, pos2)
|
||||
var isSafe = true
|
||||
|
||||
for (pos in positions) {
|
||||
if (isSafe) {
|
||||
val block = world.getBlockState(pos).block
|
||||
|
||||
if (block is SweetBerryBushBlock ||
|
||||
block is CactusBlock ||
|
||||
block is WitherRoseBlock
|
||||
) {
|
||||
isSafe = false
|
||||
}
|
||||
|
||||
if (!this.isFireImmune()) {
|
||||
if (block is FireBlock ||
|
||||
block is MagmaBlock ||
|
||||
block is CampfireBlock ||
|
||||
world.getBlockState(pos).fluidState.isIn(FluidTags.LAVA)
|
||||
) {
|
||||
isSafe = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return isSafe
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method that checks if this Pokémon species or form data contains the [CobblemonPokemonLabels.LEGENDARY] label.
|
||||
* This is used in Pokémon officially considered legendary.
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.starter
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.advancement.CobblemonCriteria
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.starter.StarterChosenEvent
|
||||
import com.cobblemon.mod.common.api.starter.StarterHandler
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.net.messages.client.starter.OpenStarterUIPacket
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
|
||||
open class CobblemonStarterHandler : StarterHandler {
|
||||
|
||||
override fun getStarterList(player: ServerPlayerEntity) = Cobblemon.starterConfig.starters
|
||||
|
||||
override fun handleJoin(player: ServerPlayerEntity) {}
|
||||
|
||||
override fun requestStarterChoice(player: ServerPlayerEntity) {
|
||||
val playerData = Cobblemon.playerData.get(player)
|
||||
if (playerData.starterSelected) {
|
||||
playerData.sendToPlayer(player)
|
||||
player.sendMessage(lang("ui.starter.alreadyselected").red(), true)
|
||||
} else if (playerData.starterLocked) {
|
||||
player.sendMessage(lang("ui.starter.cannotchoose").red(), true)
|
||||
} else {
|
||||
OpenStarterUIPacket(getStarterList(player)).sendToPlayer(player)
|
||||
playerData.starterPrompted = true
|
||||
Cobblemon.playerData.saveSingle(playerData)
|
||||
}
|
||||
}
|
||||
|
||||
override fun chooseStarter(player: ServerPlayerEntity, categoryName: String, index: Int) {
|
||||
val playerData = Cobblemon.playerData.get(player)
|
||||
if (playerData.starterSelected) {
|
||||
return player.sendMessage(lang("ui.starter.alreadyselected").red(), true)
|
||||
} else if (playerData.starterLocked) {
|
||||
return player.sendMessage(lang("ui.starter.cannotchoose").red(), true)
|
||||
}
|
||||
|
||||
val category = getStarterList(player).find { it.name == categoryName } ?: return
|
||||
|
||||
if (index > category.pokemon.size) {
|
||||
return
|
||||
}
|
||||
|
||||
val properties = category.pokemon[index]
|
||||
val pokemon = properties.create()
|
||||
|
||||
CobblemonEvents.STARTER_CHOSEN.postThen(StarterChosenEvent(player, properties, pokemon)) {
|
||||
Cobblemon.storage.getParty(player).add(
|
||||
it.pokemon.also {
|
||||
playerData.starterSelected = true
|
||||
playerData.starterUUID = it.uuid
|
||||
if (player.world.gameRules.getBoolean(CobblemonGameRules.SHINY_STARTERS)) { pokemon.shiny = true }
|
||||
}
|
||||
)
|
||||
CobblemonCriteria.PICK_STARTER.trigger(player, pokemon)
|
||||
Cobblemon.playerData.saveSingle(playerData)
|
||||
playerData.sendToPlayer(player)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.starter
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.advancement.CobblemonCriteria
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.starter.StarterChosenEvent
|
||||
import com.cobblemon.mod.common.api.starter.RenderableStarterCategory
|
||||
import com.cobblemon.mod.common.api.starter.StarterCategory
|
||||
import com.cobblemon.mod.common.api.starter.StarterHandler
|
||||
import com.cobblemon.mod.common.api.starter.StarterRegistry
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.net.messages.client.starter.OpenStarterUIPacket
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
open class CobblemonStarterHandler : StarterHandler {
|
||||
|
||||
override fun getStarters(player: ServerPlayerEntity): Map<Identifier, StarterCategory> = StarterRegistry.all()
|
||||
|
||||
// No OP the starters are sent out when the open UI packet is sent out instead
|
||||
override fun handleJoin(player: ServerPlayerEntity) {}
|
||||
|
||||
override fun requestStarterChoice(player: ServerPlayerEntity) {
|
||||
if (!this.isAbleToSelect(player)) {
|
||||
return
|
||||
}
|
||||
val playerData = Cobblemon.playerData.get(player)
|
||||
val renderable = this.getStarters(player).entries.associate { (id, category) ->
|
||||
val renderable = category.pokemon.map {
|
||||
// Let the actual Pokémon be created and apply the shiny accordingly
|
||||
// This won't be accurate with random but I mean what else do you want me to do
|
||||
val pokemon = it.create()
|
||||
// While they can still be shiny a random shiny from the #create doesn't mean the actual starter will be shiny
|
||||
// This tries to be realistic
|
||||
pokemon.shiny = player.world.gameRules.getBoolean(CobblemonGameRules.SHINY_STARTERS)
|
||||
pokemon.asRenderablePokemon()
|
||||
}
|
||||
id to RenderableStarterCategory(category.displayName, renderable)
|
||||
}
|
||||
OpenStarterUIPacket(renderable).sendToPlayer(player)
|
||||
playerData.starterPrompted = true
|
||||
Cobblemon.playerData.saveSingle(playerData)
|
||||
}
|
||||
|
||||
override fun chooseStarter(player: ServerPlayerEntity, categoryId: Identifier, index: Int) {
|
||||
if (!this.isAbleToSelect(player)) {
|
||||
return
|
||||
}
|
||||
val category = this.getStarters(player)[categoryId] ?: return
|
||||
val properties = category.pokemon.getOrNull(index) ?: return
|
||||
val pokemon = properties.create()
|
||||
val playerData = Cobblemon.playerData.get(player)
|
||||
CobblemonEvents.STARTER_CHOSEN.postThen(StarterChosenEvent(player, properties, pokemon)) { event ->
|
||||
Cobblemon.storage.getParty(player).add(
|
||||
event.pokemon.also {
|
||||
playerData.starterSelected = true
|
||||
playerData.starterUUID = it.uuid
|
||||
if (player.world.gameRules.getBoolean(CobblemonGameRules.SHINY_STARTERS)) { pokemon.shiny = true }
|
||||
}
|
||||
)
|
||||
CobblemonCriteria.PICK_STARTER.trigger(player, pokemon)
|
||||
Cobblemon.playerData.saveSingle(playerData)
|
||||
playerData.sendToPlayer(player)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the [player] can select a starter.
|
||||
* If not gives them an appropriate feedback message.
|
||||
*
|
||||
* @param player The [ServerPlayerEntity] being tested.
|
||||
* @return If the [player] can pick a starter.
|
||||
*/
|
||||
private fun isAbleToSelect(player: ServerPlayerEntity): Boolean {
|
||||
val playerData = Cobblemon.playerData.get(player)
|
||||
if (playerData.starterSelected) {
|
||||
player.sendMessage(lang("ui.starter.alreadyselected").red(), true)
|
||||
return false
|
||||
} else if (playerData.starterLocked) {
|
||||
player.sendMessage(lang("ui.starter.cannotchoose").red(), true)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,32 +13,11 @@ import net.minecraft.entity.data.DataTracker
|
||||
import net.minecraft.entity.data.TrackedData
|
||||
import net.minecraft.util.function.BooleanBiFunction
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Box
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.util.math.Vec3d
|
||||
import net.minecraft.util.shape.VoxelShapes
|
||||
|
||||
fun Entity.setPositionSafely(pos: Vec3d): Boolean {
|
||||
// TODO: Rework this function. Best way to do it would be to define a vertical and horizontal min/max shift based on the Pokemon's hitbox.
|
||||
// Then loop through horizontal/vertical shifts, and detect collisions in three categories: suffocation, damaging blocks, and general collision
|
||||
// The closest position with the least severe collision types will be selected to move the Pokemon to
|
||||
// The throw could be cancelled if there are no viable locations without severe problems
|
||||
|
||||
// Optional: use getBlockCollisions iterator and VoxelShapes.combineAndSimplify to create a single cube to represent collision area
|
||||
// Use that cube to "push" the Pokemon out of the wall at an angle
|
||||
// Note: may not work well with L shape wall collisions
|
||||
// val collisions = world.getBlockCollisions(this, box).iterator()
|
||||
// if (collisions.hasNext()) {
|
||||
// var collisionShape = collisions.next()
|
||||
// while (collisions.hasNext()) {
|
||||
// collisionShape = VoxelShapes.union(collisionShape, collisions.next())
|
||||
// println(collisionShape)
|
||||
// }
|
||||
// } else {
|
||||
// setPosition(pos)
|
||||
// return true
|
||||
// }
|
||||
|
||||
var result = pos
|
||||
val eyes = pos.withAxis(Direction.Axis.Y, pos.y + this.standingEyeHeight)
|
||||
|
||||
@@ -50,6 +29,27 @@ fun Entity.setPositionSafely(pos: Vec3d): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
val yChanges = listOf(1.0, -1.0, 2.0, -2.0)
|
||||
var previousChange = 0.0
|
||||
for (yChange in yChanges) {
|
||||
box = box.offset(0.0, yChange - previousChange, 0.0)
|
||||
val it = world.getBlockCollisions(this, box).iterator()
|
||||
previousChange = yChange
|
||||
if (it.hasNext()) {
|
||||
continue
|
||||
} else {
|
||||
val roundedY = (pos.y + yChange).toInt()
|
||||
box = box.offset(0.0, roundedY - pos.y, 0.0)
|
||||
// If the rounded position actually collides again, then don't round at all.
|
||||
if (world.getBlockCollisions(this, box).iterator().hasNext()) {
|
||||
setPosition(pos.add(0.0, yChange, 0.0))
|
||||
return true
|
||||
}
|
||||
setPosition(Vec3d(pos.x, roundedY.toDouble(), pos.z))
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
for (target in BlockPos.stream(box)) {
|
||||
val blockState = this.world.getBlockState(target)
|
||||
val collides = !blockState.isAir &&
|
||||
@@ -73,13 +73,13 @@ fun Entity.setPositionSafely(pos: Vec3d): Boolean {
|
||||
result = result.add(Vec3d(0.0, 0.0, 1 + (conflict.z - box.minZ + (1.0 / 8.0))))
|
||||
}
|
||||
Direction.SOUTH -> {
|
||||
result = result.add(Vec3d(0.0, 0.0, (conflict.z - box.maxZ) - (1.0 / 8.0)))
|
||||
result = result.add(Vec3d(0.0, 0.0, -1 * (1 - (conflict.z - box.minZ) + (1.0 / 8.0))))
|
||||
}
|
||||
Direction.WEST -> {
|
||||
result = result.add(Vec3d(1 + (conflict.x - box.minX + (1.0 / 8.0)), 0.0, 0.0))
|
||||
}
|
||||
Direction.EAST -> {
|
||||
result = result.add(Vec3d((conflict.x - box.maxX) - (1.0 / 8.0), 0.0, 0.0))
|
||||
result = result.add(Vec3d(-1 * (1 - (conflict.x - box.minX) + (1.0 / 8.0)), 0.0, 0.0))
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
@@ -89,90 +89,12 @@ fun Entity.setPositionSafely(pos: Vec3d): Boolean {
|
||||
}
|
||||
}
|
||||
|
||||
box = boundingBox.offset(result)
|
||||
if (!world.getBlockCollisions(this, box).iterator().hasNext()) {
|
||||
this.setPosition(result)
|
||||
return true
|
||||
} else {
|
||||
val yChanges = listOf(1.0, -1.0, 2.0, -2.0)
|
||||
var previousChange = 0.0
|
||||
|
||||
// If the Pokemon still collides with blocks after horizontal shifting, try vertical shifting from the shifted position
|
||||
for (yChange in yChanges) {
|
||||
box = box.offset(0.0, yChange - previousChange, 0.0)
|
||||
previousChange = yChange
|
||||
if (world.getBlockCollisions(this, box).iterator().hasNext()) {
|
||||
continue
|
||||
} else {
|
||||
val roundedY = (result.y + yChange).toInt()
|
||||
box = box.offset(0.0, roundedY - result.y, 0.0)
|
||||
// If the rounded position actually collides again, then don't round at all.
|
||||
if (world.getBlockCollisions(this, box).iterator().hasNext()) {
|
||||
result = result.add(0.0, yChange, 0.0)
|
||||
this.setPosition(result)
|
||||
return true
|
||||
} else {
|
||||
result = Vec3d(result.x, roundedY.toDouble(), result.z)
|
||||
this.setPosition(result)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If vertical shifting from the new position still collides, try vertical shifting from the original pos
|
||||
previousChange = 0.0
|
||||
box = boundingBox.offset(pos)
|
||||
for (yChange in yChanges) {
|
||||
box = box.offset(0.0, yChange - previousChange, 0.0)
|
||||
previousChange = yChange
|
||||
if (world.getBlockCollisions(this, box).iterator().hasNext()) {
|
||||
continue
|
||||
} else {
|
||||
val roundedY = (result.y + yChange).toInt()
|
||||
box = box.offset(0.0, roundedY - result.y, 0.0)
|
||||
// If the rounded position actually collides again, then don't round at all.
|
||||
if (world.getBlockCollisions(this, box).iterator().hasNext()) {
|
||||
result = result.add(0.0, yChange, 0.0)
|
||||
this.setPosition(result)
|
||||
return true
|
||||
} else {
|
||||
result = Vec3d(result.x, roundedY.toDouble(), result.z)
|
||||
this.setPosition(result)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (conflicts.size >= 3) {
|
||||
this.setPosition(pos)
|
||||
}
|
||||
|
||||
// This final check guarantees that the sendout will return to the original position if the Pokemon will suffocate in the new one
|
||||
// This will only happen if the horizontal shift moved the Pokemon into a suffocating position, and there was no valid vertical shift
|
||||
val resultEyes = result.withAxis(Direction.Axis.Y, result.y + this.standingEyeHeight)
|
||||
val resultEyeBox = Box.of(resultEyes, width.toDouble(), 1.0E-6, width.toDouble())
|
||||
var collides = false
|
||||
|
||||
for (target in BlockPos.stream(resultEyeBox)) {
|
||||
val blockState = this.world.getBlockState(target)
|
||||
collides = !blockState.isAir &&
|
||||
blockState.shouldSuffocate(this.world, target) &&
|
||||
VoxelShapes.matchesAnywhere(
|
||||
blockState.getCollisionShape(this.world, target)
|
||||
.offset(target.x.toDouble(), target.y.toDouble(), target.z.toDouble()),
|
||||
VoxelShapes.cuboid(box),
|
||||
BooleanBiFunction.AND
|
||||
)
|
||||
if (collides) break
|
||||
}
|
||||
if (collides) {
|
||||
this.setPosition(pos)
|
||||
return true
|
||||
} else {
|
||||
this.setPosition(result)
|
||||
return true
|
||||
}
|
||||
this.setPosition(result)
|
||||
return true
|
||||
}
|
||||
|
||||
fun Entity.distanceTo(pos: BlockPos): Double {
|
||||
|
||||
@@ -19,7 +19,7 @@ import com.cobblemon.mod.common.api.reactive.Observable.Companion.filter
|
||||
import com.cobblemon.mod.common.api.reactive.Observable.Companion.takeFirst
|
||||
import com.cobblemon.mod.common.battles.BattleRegistry
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import java.util.UUID
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
@@ -30,11 +30,10 @@ import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.sound.SoundCategory
|
||||
import net.minecraft.sound.SoundEvents
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.hit.BlockHitResult
|
||||
import net.minecraft.util.math.*
|
||||
import net.minecraft.world.RaycastContext
|
||||
import java.util.*
|
||||
import kotlin.math.min
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Box
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
// Stuff like getting their party
|
||||
fun ServerPlayerEntity.party() = Cobblemon.storage.getParty(this)
|
||||
@@ -252,91 +251,6 @@ fun findDirectionForIntercept(p0: Vec3d, p1: Vec3d, blockPos: BlockPos): Directi
|
||||
return minDirection
|
||||
}
|
||||
|
||||
fun ServerPlayerEntity.raycast(maxDistance: Float, fluidHandling: RaycastContext.FluidHandling?): BlockHitResult {
|
||||
val f = pitch
|
||||
val g = yaw
|
||||
val vec3d = eyePos
|
||||
val h = MathHelper.cos(-g * 0.017453292f - 3.1415927f)
|
||||
val i = MathHelper.sin(-g * 0.017453292f - 3.1415927f)
|
||||
val j = -MathHelper.cos(-f * 0.017453292f)
|
||||
val k = MathHelper.sin(-f * 0.017453292f)
|
||||
val l = i * j
|
||||
val n = h * j
|
||||
val vec3d2 = vec3d.add(l.toDouble() * maxDistance, k.toDouble() * maxDistance, n.toDouble() * maxDistance)
|
||||
return world.raycast(RaycastContext(vec3d, vec3d2, RaycastContext.ShapeType.OUTLINE, fluidHandling, this))
|
||||
}
|
||||
|
||||
fun ServerPlayerEntity.raycastSafeSendout(pokemon: Pokemon, maxDistance: Double, dropHeight: Double, fluidHandling: RaycastContext.FluidHandling?): Vec3d? {
|
||||
// Crazy math stuff, don't worry about it
|
||||
val f = pitch
|
||||
val g = yaw
|
||||
val vec3d = eyePos
|
||||
val h = MathHelper.cos(-g * 0.017453292f - 3.1415927f)
|
||||
val i = MathHelper.sin(-g * 0.017453292f - 3.1415927f)
|
||||
val j = -MathHelper.cos(-f * 0.017453292f)
|
||||
val k = MathHelper.sin(-f * 0.017453292f)
|
||||
val l = i * j
|
||||
val n = h * j
|
||||
val vec3d2 = vec3d.add(l.toDouble() * maxDistance, k.toDouble() * maxDistance, n.toDouble() * maxDistance)
|
||||
val result = world.raycast(RaycastContext(vec3d, vec3d2, RaycastContext.ShapeType.OUTLINE, fluidHandling, this))
|
||||
|
||||
|
||||
if (world.getBlockState(result.blockPos).isAir) {
|
||||
// If the trace returns air, the player isn't aiming at any blocks within range
|
||||
var traceDown: TraceResult?
|
||||
val minDrop = min(2.5, maxDistance)
|
||||
val stepDistance = 0.05
|
||||
var step = minDrop
|
||||
var stepDrop = minDrop
|
||||
var stepPos: Vec3d
|
||||
var traceHeight: Double
|
||||
var smallestHeight = dropHeight
|
||||
var fallLoc: TraceResult? = null
|
||||
|
||||
// Try to find a valid block below the player's aim instead
|
||||
while (step <= maxDistance) {
|
||||
stepPos = vec3d.add(l.toDouble() * step, k.toDouble() * step, n.toDouble() * step)
|
||||
if (minDrop != maxDistance) {
|
||||
stepDrop = ((step - minDrop) / (maxDistance - minDrop)) * dropHeight
|
||||
}
|
||||
traceDown = stepPos.traceDownwards(this.world, maxDistance = stepDrop.toFloat())
|
||||
if (traceDown != null && pokemon.isPositionSafe(world, traceDown.blockPos)) {
|
||||
traceHeight = (stepPos.y - traceDown.location.y)
|
||||
if (traceHeight < smallestHeight) {
|
||||
smallestHeight = traceHeight
|
||||
fallLoc = traceDown
|
||||
}
|
||||
}
|
||||
|
||||
step += stepDistance
|
||||
}
|
||||
|
||||
// If a valid block was found below the player's aim, return the location directly above it
|
||||
return fallLoc?.blockPos?.up()?.toCenterPos()
|
||||
} else if (result.side != Direction.UP) {
|
||||
// If the player targets the side or bottom of a block, try to find a valid spot in front of / below that block
|
||||
val offset: Double = if (result.side == Direction.DOWN) {
|
||||
0.125 + pokemon.form.hitbox.height*pokemon.form.baseScale*0.5
|
||||
} else {
|
||||
0.125 + pokemon.form.hitbox.width*pokemon.form.baseScale*0.5
|
||||
}
|
||||
|
||||
val posOffset = result.pos.offset(result.side, offset)
|
||||
|
||||
val traceDown = posOffset.traceDownwards(this.world, maxDistance = dropHeight.toFloat())
|
||||
|
||||
return if (traceDown == null || !pokemon.isPositionSafe(world, traceDown.blockPos)) {
|
||||
null
|
||||
} else {
|
||||
return Vec3d(traceDown.location.x, traceDown.blockPos.up().toVec3d().y, traceDown.location.z)
|
||||
}
|
||||
} else if (!this.world.getBlockState(result.blockPos.up()).isSolid && pokemon.isPositionSafe(world, result.blockPos)) {
|
||||
// If the player is targeting the top of a block, and the block above it isn't solid, it will spawn on that block
|
||||
return Vec3d(result.pos.x, result.blockPos.up().toVec3d().y, result.pos.z)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun PlayerInventory.usableItems() = offHand + main
|
||||
|
||||
/**
|
||||
|
||||
@@ -124,41 +124,3 @@ val World.itemRegistry: Registry<Item>
|
||||
get() = registryManager.get(RegistryKeys.ITEM)
|
||||
val World.biomeRegistry: Registry<Biome>
|
||||
get() = registryManager.get(RegistryKeys.BIOME)
|
||||
|
||||
|
||||
fun Vec3d.traceDownwards(
|
||||
world: World,
|
||||
maxDistance: Float = 10F,
|
||||
stepDistance: Float = 0.5F,
|
||||
): TraceResult? {
|
||||
var step = stepDistance
|
||||
val startPos = Vec3d(x, y, z)
|
||||
val direction = Vec3d(0.0, -1.0, 0.0)
|
||||
|
||||
var lastBlockPos = startPos.toBlockPos()
|
||||
|
||||
while (step <= maxDistance) {
|
||||
val location = startPos.add(direction.multiply(step.toDouble()))
|
||||
step += stepDistance
|
||||
|
||||
val blockPos = location.toBlockPos()
|
||||
|
||||
if (blockPos == lastBlockPos) {
|
||||
continue
|
||||
} else {
|
||||
lastBlockPos = blockPos
|
||||
}
|
||||
|
||||
val block = world.getBlockState(blockPos)
|
||||
if (!block.isAir) {
|
||||
val dir = findDirectionForIntercept(startPos, location, blockPos)
|
||||
return TraceResult(
|
||||
location = location,
|
||||
blockPos = blockPos,
|
||||
direction = dir
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.util.adapters
|
||||
|
||||
import com.google.gson.*
|
||||
import net.minecraft.text.Text
|
||||
import java.lang.reflect.Type
|
||||
|
||||
object PlainJsonTextAdapter : JsonDeserializer<Text>, JsonSerializer<Text> {
|
||||
override fun deserialize(jElement: JsonElement, type: Type, context: JsonDeserializationContext): Text {
|
||||
return Text.Serializer.fromJson(jElement) ?: throw IllegalArgumentException("Cannot resolve null text")
|
||||
}
|
||||
|
||||
override fun serialize(text: Text, type: Type, context: JsonSerializationContext): JsonElement = JsonPrimitive(Text.Serializer.toJson(text))
|
||||
}
|
||||
@@ -7,12 +7,6 @@
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"functions": [
|
||||
{
|
||||
"function": "minecraft:copy_name",
|
||||
"source": "block_entity"
|
||||
}
|
||||
],
|
||||
"name": "cobblemon:black_gilded_chest"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -7,12 +7,6 @@
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"functions": [
|
||||
{
|
||||
"function": "minecraft:copy_name",
|
||||
"source": "block_entity"
|
||||
}
|
||||
],
|
||||
"name": "cobblemon:blue_gilded_chest"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -7,12 +7,6 @@
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"functions": [
|
||||
{
|
||||
"function": "minecraft:copy_name",
|
||||
"source": "block_entity"
|
||||
}
|
||||
],
|
||||
"name": "cobblemon:gilded_chest"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -7,12 +7,6 @@
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"functions": [
|
||||
{
|
||||
"function": "minecraft:copy_name",
|
||||
"source": "block_entity"
|
||||
}
|
||||
],
|
||||
"name": "cobblemon:green_gilded_chest"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -7,12 +7,6 @@
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"functions": [
|
||||
{
|
||||
"function": "minecraft:copy_name",
|
||||
"source": "block_entity"
|
||||
}
|
||||
],
|
||||
"name": "cobblemon:pink_gilded_chest"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -7,12 +7,6 @@
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"functions": [
|
||||
{
|
||||
"function": "minecraft:copy_name",
|
||||
"source": "block_entity"
|
||||
}
|
||||
],
|
||||
"name": "cobblemon:white_gilded_chest"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -7,12 +7,6 @@
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"functions": [
|
||||
{
|
||||
"function": "minecraft:copy_name",
|
||||
"source": "block_entity"
|
||||
}
|
||||
],
|
||||
"name": "cobblemon:yellow_gilded_chest"
|
||||
}
|
||||
],
|
||||
|
||||
-5
@@ -29,11 +29,6 @@
|
||||
"name": "minecraft:coal",
|
||||
"weight": 6
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "minecraft:bone",
|
||||
"weight": 6
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:big_root",
|
||||
|
||||
+1
-1
@@ -58,5 +58,5 @@
|
||||
"rolls": 1.0
|
||||
}
|
||||
],
|
||||
"random_sequence": "cobblemon:fossils/uncommon/prehistoric_hydrothermal_vent"
|
||||
"random_sequence": "cobblemon:fossils/uncommon/prehistoric_hydrothermal_vents"
|
||||
}
|
||||
+1
-1
@@ -58,5 +58,5 @@
|
||||
"rolls": 1.0
|
||||
}
|
||||
],
|
||||
"random_sequence": "cobblemon:fossils/uncommon/prehistoric_vibrant_hydrothermal_vent"
|
||||
"random_sequence": "cobblemon:fossils/uncommon/prehistoric_vibrant_hydrothermal_vents"
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"type": "minecraft:archaeology",
|
||||
"pools": [
|
||||
{
|
||||
"bonus_rolls": 0.0,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "minecraft:copper_ingot",
|
||||
"weight": 10
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "minecraft:iron_ingot",
|
||||
"weight": 5
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "minecraft:gold_ingot",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:relic_coin",
|
||||
"weight": 25
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:dome_sherd",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:psychic_gem",
|
||||
"weight": 5
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:dark_gem",
|
||||
"weight": 5
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:rock_gem",
|
||||
"weight": 5
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
}
|
||||
],
|
||||
"random_sequence": "cobblemon:ruins/common/luna_henge_ruins"
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"type": "minecraft:archaeology",
|
||||
"pools": [
|
||||
{
|
||||
"bonus_rolls": 0.0,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "minecraft:copper_ingot",
|
||||
"weight": 10
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "minecraft:iron_ingot",
|
||||
"weight": 5
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "minecraft:gold_ingot",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:relic_coin",
|
||||
"weight": 25
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:helix_sherd",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:psychic_gem",
|
||||
"weight": 5
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:fire_gem",
|
||||
"weight": 5
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:rock_gem",
|
||||
"weight": 5
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
}
|
||||
],
|
||||
"random_sequence": "cobblemon:ruins/common/sol_henge_ruins"
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"type": "minecraft:archaeology",
|
||||
"pools": [
|
||||
{
|
||||
"bonus_rolls": 0.0,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "minecraft:copper_ingot",
|
||||
"weight": 10
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "minecraft:iron_ingot",
|
||||
"weight": 5
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "minecraft:gold_ingot",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:relic_coin",
|
||||
"weight": 25
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:nostalgic_sherd",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:rock_gem",
|
||||
"weight": 10
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
}
|
||||
],
|
||||
"random_sequence": "cobblemon:ruins/common/stonjourner_henge_ruins"
|
||||
}
|
||||
+12
-12
@@ -79,7 +79,7 @@
|
||||
{
|
||||
"rolls": {
|
||||
"type": "minecraft:uniform",
|
||||
"max": 3.0,
|
||||
"max": 1.0,
|
||||
"min": 0.0
|
||||
},
|
||||
"bonus_rolls": 0.0,
|
||||
@@ -93,7 +93,7 @@
|
||||
"function": "set_count",
|
||||
"count": {
|
||||
"min": 1,
|
||||
"max": 2
|
||||
"max": 3
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -103,8 +103,8 @@
|
||||
{
|
||||
"rolls": {
|
||||
"type": "minecraft:uniform",
|
||||
"max": 5.0,
|
||||
"min": 4.0
|
||||
"max": 3.0,
|
||||
"min": 2.0
|
||||
},
|
||||
"bonus_rolls": 0.0,
|
||||
"entries": [
|
||||
@@ -149,7 +149,7 @@
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:link_cable",
|
||||
"weight": 1
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
@@ -159,7 +159,7 @@
|
||||
"function": "enchant_randomly"
|
||||
}
|
||||
],
|
||||
"weight": 1
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
@@ -169,7 +169,7 @@
|
||||
"function": "enchant_randomly"
|
||||
}
|
||||
],
|
||||
"weight": 1
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
@@ -179,7 +179,7 @@
|
||||
"function": "enchant_randomly"
|
||||
}
|
||||
],
|
||||
"weight": 1
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
@@ -189,7 +189,7 @@
|
||||
"function": "enchant_randomly"
|
||||
}
|
||||
],
|
||||
"weight": 1
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
@@ -199,7 +199,7 @@
|
||||
"function": "enchant_randomly"
|
||||
}
|
||||
],
|
||||
"weight": 1
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
@@ -209,12 +209,12 @@
|
||||
"function": "enchant_randomly"
|
||||
}
|
||||
],
|
||||
"weight": 1
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:automaton_armor_trim_smithing_template",
|
||||
"weight": 2
|
||||
"weight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+6
-1
@@ -27,7 +27,12 @@
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:nostalgic_sherd",
|
||||
"weight": 30
|
||||
"weight": 15
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:bygone_sherd",
|
||||
"weight": 15
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
|
||||
+8
-3
@@ -7,12 +7,12 @@
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:kings_rock",
|
||||
"weight": 5
|
||||
"weight": 3
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:cracked_pot",
|
||||
"weight": 5
|
||||
"weight": 3
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
@@ -22,7 +22,12 @@
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:bygone_sherd",
|
||||
"weight": 20
|
||||
"weight": 10
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:dome_sherd",
|
||||
"weight": 10
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
|
||||
+6
-1
@@ -27,7 +27,12 @@
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:capture_sherd",
|
||||
"weight": 30
|
||||
"weight": 15
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:suspicious_sherd",
|
||||
"weight": 15
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
|
||||
+6
-1
@@ -27,7 +27,12 @@
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:capture_sherd",
|
||||
"weight": 30
|
||||
"weight": 15
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:dome_sherd",
|
||||
"weight": 15
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
|
||||
+6
-1
@@ -52,7 +52,12 @@
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:helix_sherd",
|
||||
"weight": 90
|
||||
"weight": 45
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:nostalgic_sherd",
|
||||
"weight": 45
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
|
||||
+6
-1
@@ -27,7 +27,12 @@
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:helix_sherd",
|
||||
"weight": 70
|
||||
"weight": 35
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:bygone_sherd",
|
||||
"weight": 35
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
|
||||
+6
-1
@@ -52,7 +52,12 @@
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:suspicious_sherd",
|
||||
"weight": 90
|
||||
"weight": 45
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:capture_sherd",
|
||||
"weight": 45
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"type": "minecraft:archaeology",
|
||||
"pools": [
|
||||
{
|
||||
"bonus_rolls": 0.0,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:covert_cloak",
|
||||
"weight": 5
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:spell_tag",
|
||||
"weight": 5
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:dome_sherd",
|
||||
"weight": 10
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:suspicious_sherd",
|
||||
"weight": 10
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
}
|
||||
],
|
||||
"random_sequence": "cobblemon:ruins/uncommon/luna_henge_ruins"
|
||||
}
|
||||
+6
-1
@@ -22,7 +22,12 @@
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:dome_sherd",
|
||||
"weight": 30
|
||||
"weight": 15
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:helix_sherd",
|
||||
"weight": 15
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
|
||||
+6
-1
@@ -27,7 +27,12 @@
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:nostalgic_sherd",
|
||||
"weight": 30
|
||||
"weight": 15
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:bygone_sherd",
|
||||
"weight": 15
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"type": "minecraft:archaeology",
|
||||
"pools": [
|
||||
{
|
||||
"bonus_rolls": 0.0,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:kings_rock",
|
||||
"weight": 5
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:cleanse_tag",
|
||||
"weight": 5
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:helix_sherd",
|
||||
"weight": 10
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:capture_sherd",
|
||||
"weight": 10
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
}
|
||||
],
|
||||
"random_sequence": "cobblemon:ruins/uncommon/luna_henge_ruins"
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"type": "minecraft:archaeology",
|
||||
"pools": [
|
||||
{
|
||||
"bonus_rolls": 0.0,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:covert_cloak",
|
||||
"weight": 5
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:shell_bell",
|
||||
"weight": 5
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:nostalgic_sherd",
|
||||
"weight": 10
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:bygone_sherd",
|
||||
"weight": 10
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
}
|
||||
],
|
||||
"random_sequence": "cobblemon:ruins/uncommon/stonjourner_henge_ruins"
|
||||
}
|
||||
+6
-1
@@ -32,7 +32,12 @@
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:helix_sherd",
|
||||
"weight": 40
|
||||
"weight": 20
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:dome_sherd",
|
||||
"weight": 20
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
|
||||
+6
-1
@@ -22,7 +22,12 @@
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:suspicious_sherd",
|
||||
"weight": 40
|
||||
"weight": 20
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:capture_sherd",
|
||||
"weight": 20
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:exp_candy_xs",
|
||||
"weight": 32,
|
||||
"weight": 24,
|
||||
"functions": [
|
||||
{
|
||||
"function": "set_count",
|
||||
@@ -26,7 +26,7 @@
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:exp_candy_s",
|
||||
"weight": 16,
|
||||
"weight": 15,
|
||||
"functions": [
|
||||
{
|
||||
"function": "set_count",
|
||||
@@ -40,20 +40,6 @@
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:exp_candy_m",
|
||||
"weight": 8,
|
||||
"functions": [
|
||||
{
|
||||
"function": "set_count",
|
||||
"count": {
|
||||
"min": 1,
|
||||
"max": 2
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:exp_candy_l",
|
||||
"weight": 1,
|
||||
"functions": [
|
||||
{
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"displayName": {
|
||||
"translate": "cobblemon.starterselection.category.kanto"
|
||||
},
|
||||
"pokemon": [
|
||||
"Bulbasaur level=10",
|
||||
"Charmander level=10",
|
||||
"Squirtle level=10"
|
||||
]
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"displayName": {
|
||||
"translate": "cobblemon.starterselection.category.johto"
|
||||
},
|
||||
"pokemon": [
|
||||
"Chikorita level=10",
|
||||
"Cyndaquil level=10",
|
||||
"Totodile level=10"
|
||||
]
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"displayName": {
|
||||
"translate": "cobblemon.starterselection.category.hoenn"
|
||||
},
|
||||
"pokemon": [
|
||||
"Treecko level=10",
|
||||
"Torchic level=10",
|
||||
"Mudkip level=10"
|
||||
]
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"displayName": {
|
||||
"translate": "cobblemon.starterselection.category.sinnoh"
|
||||
},
|
||||
"pokemon": [
|
||||
"Turtwig level=10",
|
||||
"Chimchar level=10",
|
||||
"Piplup level=10"
|
||||
]
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"displayName": {
|
||||
"translate": "cobblemon.starterselection.category.unova"
|
||||
},
|
||||
"pokemon": [
|
||||
"Snivy level=10",
|
||||
"Tepig level=10",
|
||||
"Oshawott level=10"
|
||||
]
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"displayName": {
|
||||
"translate": "cobblemon.starterselection.category.kalos"
|
||||
},
|
||||
"pokemon": [
|
||||
"Chespin level=10",
|
||||
"Fennekin level=10",
|
||||
"Froakie level=10"
|
||||
]
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"displayName": {
|
||||
"translate": "cobblemon.starterselection.category.alola"
|
||||
},
|
||||
"pokemon": [
|
||||
"Rowlet level=10",
|
||||
"Litten level=10",
|
||||
"Popplio level=10"
|
||||
]
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"displayName": {
|
||||
"translate": "cobblemon.starterselection.category.galar"
|
||||
},
|
||||
"pokemon": [
|
||||
"Grookey level=10",
|
||||
"Scorbunny level=10",
|
||||
"Sobble level=10"
|
||||
]
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"displayName": {
|
||||
"translate": "cobblemon.starterselection.category.paldea"
|
||||
},
|
||||
"pokemon": [
|
||||
"Sprigatito level=10",
|
||||
"Fuecoco level=10",
|
||||
"Quaxly level=10"
|
||||
]
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user