mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-25 00:26:26 -04:00
Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
380b6d6cee | ||
|
|
b4919d18d1 | ||
|
|
d9e8283743 | ||
|
|
b8d913bd2b | ||
|
|
9339d91cbb | ||
|
|
8b255c784a | ||
|
|
4cdea8d1fc | ||
|
|
1b6139b386 | ||
|
|
2bd1382b85 | ||
|
|
7791e72f72 |
@@ -6,6 +6,7 @@
|
||||
- Fixed a scenario where a Pokémon that rolled to spawn with a special Tera type sometimes has a Tera type that is already a part of their natural typing.
|
||||
- Fixed PokemonProperty argument suggestions for ``tera`` and ``tera_type`` not suggesting ``stellar``.
|
||||
- Fixed being able to stack Relic Coin Pouches on top of each other.
|
||||
- Fixed Model loader generating misleading crash-reports when client is crashing
|
||||
|
||||
### Additions
|
||||
- Added Pokémon (and item) fishing using modified fishing rods - Poké Rods! You'll need a Poké Rod smithing template, a fishing rod, and some type of Poké Ball. Each Poké Ball makes a differently themed rod. Why not?
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonBakingOverrides;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import net.minecraft.client.color.block.BlockColors;
|
||||
@@ -20,8 +19,6 @@ import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.client.resources.model.UnbakedModel;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
import org.slf4j.Logger;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -31,16 +28,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(ModelBakery.class)
|
||||
public abstract class ModelLoaderMixin {
|
||||
|
||||
@Shadow abstract UnbakedModel getModel(ResourceLocation resourceLocation);
|
||||
|
||||
@Shadow protected abstract void registerModel(ModelResourceLocation modelId, UnbakedModel unbakedModel);
|
||||
|
||||
@Final
|
||||
@Shadow
|
||||
private Map<ResourceLocation, UnbakedModel> unbakedCache;
|
||||
|
||||
@Final
|
||||
@Shadow
|
||||
private static Logger LOGGER;
|
||||
|
||||
@Inject(
|
||||
method = "<init>",
|
||||
at = @At("TAIL")
|
||||
@@ -51,19 +42,8 @@ public abstract class ModelLoaderMixin {
|
||||
Map<ResourceLocation, List<BlockStateModelLoader.LoadedJson>> blockStates,
|
||||
CallbackInfo ci) {
|
||||
CobblemonBakingOverrides.INSTANCE.getModels().forEach(bakingOverride -> {
|
||||
try {
|
||||
BlockModel unbakedModel = this.loadBlockModel(bakingOverride.getModelLocation());
|
||||
this.unbakedCache.put(bakingOverride.getModelIdentifier().id(), unbakedModel);
|
||||
this.registerModel(bakingOverride.getModelIdentifier(), unbakedModel);
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Error loading a Cobblemon BakedModel:", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
var unbakedModel = this.getModel(bakingOverride.getModelLocation());
|
||||
this.registerModel(bakingOverride.getModelIdentifier(), unbakedModel);
|
||||
});
|
||||
}
|
||||
|
||||
@Shadow
|
||||
private BlockModel loadBlockModel(ResourceLocation id) throws IOException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,9 @@ package com.cobblemon.mod.common.api.gui
|
||||
|
||||
import com.cobblemon.mod.common.api.text.font
|
||||
import com.cobblemon.mod.common.client.gui.battle.BattleOverlay.Companion.PORTRAIT_DIAMETER
|
||||
import com.cobblemon.mod.common.client.render.SpriteType
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
@@ -201,58 +203,71 @@ fun drawPosablePortrait(
|
||||
headYaw: Float = 0F,
|
||||
headPitch: Float = 0F
|
||||
) {
|
||||
val model = repository.getPoser(identifier, aspects)
|
||||
state.currentAspects = aspects
|
||||
state.currentModel = model
|
||||
val texture = repository.getTexture(identifier, aspects, state.animationSeconds)
|
||||
|
||||
val context = RenderContext()
|
||||
model.context = context
|
||||
repository.getTextureNoSubstitute(identifier, aspects, 0f).let { context.put(RenderContext.TEXTURE, it) }
|
||||
context.put(RenderContext.SCALE, contextScale)
|
||||
context.put(RenderContext.SPECIES, identifier)
|
||||
context.put(RenderContext.ASPECTS, aspects)
|
||||
context.put(RenderContext.POSABLE_STATE, state)
|
||||
|
||||
val renderType = RenderType.entityCutout(texture)
|
||||
|
||||
RenderSystem.applyModelViewMatrix()
|
||||
val quaternion1 = Axis.YP.rotationDegrees(-32F * if (reversed) -1F else 1F)
|
||||
val quaternion2 = Axis.XP.rotationDegrees(5F)
|
||||
|
||||
val originalPose = state.currentPose
|
||||
state.setPoseToFirstSuitable(PoseType.PORTRAIT)
|
||||
state.updatePartialTicks(partialTicks)
|
||||
model.applyAnimations(null, state, limbSwing, limbSwingAmount, ageInTicks, headYaw, headPitch)
|
||||
originalPose?.let { state.setPose(it) }
|
||||
|
||||
matrixStack.pushPose()
|
||||
matrixStack.translate(0.0, PORTRAIT_DIAMETER.toDouble() + 2.0, 0.0)
|
||||
matrixStack.scale(scale, scale, -scale)
|
||||
matrixStack.translate(0.0, -PORTRAIT_DIAMETER / 18.0, 0.0)
|
||||
matrixStack.translate(model.portraitTranslation.x * if (reversed) -1F else 1F, model.portraitTranslation.y, model.portraitTranslation.z - 4)
|
||||
matrixStack.scale(model.portraitScale, model.portraitScale, 1 / model.portraitScale)
|
||||
matrixStack.mulPose(quaternion1) // TODO (techdaan): correct?
|
||||
matrixStack.mulPose(quaternion2)
|
||||
|
||||
val light1 = Vector3f(0.2F, 1.0F, -1.0F)
|
||||
val light2 = Vector3f(0.1F, 0.0F, 8.0F)
|
||||
RenderSystem.setShaderLights(light1, light2)
|
||||
quaternion1.conjugate()
|
||||
val sprite = repository.getSprite(identifier, aspects, SpriteType.PORTRAIT);
|
||||
|
||||
val immediate = Minecraft.getInstance().renderBuffers().bufferSource()
|
||||
val buffer = immediate.getBuffer(renderType)
|
||||
val packedLight = LightTexture.pack(11, 7)
|
||||
if(sprite == null) {
|
||||
|
||||
model.withLayerContext(immediate, state, repository.getLayers(identifier, aspects)) {
|
||||
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
immediate.endBatch()
|
||||
val model = repository.getPoser(identifier, aspects)
|
||||
state.currentAspects = aspects
|
||||
state.currentModel = model
|
||||
val texture = repository.getTexture(identifier, aspects, state.animationSeconds)
|
||||
|
||||
val context = RenderContext()
|
||||
model.context = context
|
||||
repository.getTextureNoSubstitute(identifier, aspects, 0f).let { context.put(RenderContext.TEXTURE, it) }
|
||||
context.put(RenderContext.SCALE, contextScale)
|
||||
context.put(RenderContext.SPECIES, identifier)
|
||||
context.put(RenderContext.ASPECTS, aspects)
|
||||
context.put(RenderContext.POSABLE_STATE, state)
|
||||
|
||||
val renderType = RenderType.entityCutout(texture)
|
||||
|
||||
val quaternion1 = Axis.YP.rotationDegrees(-32F * if (reversed) -1F else 1F)
|
||||
val quaternion2 = Axis.XP.rotationDegrees(5F)
|
||||
|
||||
val originalPose = state.currentPose
|
||||
state.setPoseToFirstSuitable(PoseType.PORTRAIT)
|
||||
state.updatePartialTicks(partialTicks)
|
||||
model.applyAnimations(null, state, limbSwing, limbSwingAmount, ageInTicks, headYaw, headPitch)
|
||||
originalPose?.let { state.setPose(it) }
|
||||
|
||||
matrixStack.translate(
|
||||
model.portraitTranslation.x * if (reversed) -1F else 1F,
|
||||
model.portraitTranslation.y,
|
||||
model.portraitTranslation.z - 4
|
||||
)
|
||||
matrixStack.scale(model.portraitScale, model.portraitScale, 1 / model.portraitScale)
|
||||
matrixStack.mulPose(quaternion1) // TODO (techdaan): correct?
|
||||
matrixStack.mulPose(quaternion2)
|
||||
|
||||
val light1 = Vector3f(0.2F, 1.0F, -1.0F)
|
||||
val light2 = Vector3f(0.1F, 0.0F, 8.0F)
|
||||
RenderSystem.setShaderLights(light1, light2)
|
||||
quaternion1.conjugate()
|
||||
|
||||
val immediate = Minecraft.getInstance().renderBuffers().bufferSource()
|
||||
val buffer = immediate.getBuffer(renderType)
|
||||
val packedLight = LightTexture.pack(11, 7)
|
||||
|
||||
model.withLayerContext(immediate, state, repository.getLayers(identifier, aspects)) {
|
||||
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
immediate.endBatch()
|
||||
}
|
||||
|
||||
model.setDefault()
|
||||
|
||||
Lighting.setupFor3DItems()
|
||||
} else {
|
||||
renderSprite(matrixStack, sprite)
|
||||
}
|
||||
|
||||
matrixStack.popPose()
|
||||
model.setDefault()
|
||||
|
||||
Lighting.setupFor3DItems()
|
||||
}
|
||||
|
||||
fun drawProfile(
|
||||
@@ -264,50 +279,75 @@ fun drawProfile(
|
||||
partialTicks: Float,
|
||||
scale: Float = 20F
|
||||
) {
|
||||
val model = repository.getPoser(resourceIdentifier, aspects)
|
||||
val texture = repository.getTexture(resourceIdentifier, aspects, state.animationSeconds)
|
||||
|
||||
val context = RenderContext()
|
||||
model.context = context
|
||||
repository.getTextureNoSubstitute(resourceIdentifier, aspects, 0f).let { context.put(RenderContext.TEXTURE, it) }
|
||||
context.put(RenderContext.SCALE, 1F)
|
||||
context.put(RenderContext.SPECIES, resourceIdentifier)
|
||||
context.put(RenderContext.ASPECTS, aspects)
|
||||
context.put(RenderContext.POSABLE_STATE, state)
|
||||
state.currentAspects = aspects
|
||||
state.currentModel = model
|
||||
|
||||
val renderType = RenderType.entityCutout(texture)//model.getLayer(texture)
|
||||
|
||||
RenderSystem.applyModelViewMatrix()
|
||||
matrixStack.scale(scale, scale, -scale)
|
||||
|
||||
state.setPoseToFirstSuitable(PoseType.PORTRAIT)
|
||||
state.updatePartialTicks(partialTicks)
|
||||
model.applyAnimations(null, state, 0F, 0F, 0F, 0F, 0F)
|
||||
matrixStack.translate(model.profileTranslation.x, model.profileTranslation.y, model.profileTranslation.z - 4.0)
|
||||
matrixStack.scale(model.profileScale, model.profileScale, 1 / model.profileScale)
|
||||
val sprite = repository.getSprite(resourceIdentifier, aspects, SpriteType.PROFILE);
|
||||
|
||||
if(sprite == null) {
|
||||
|
||||
val model = repository.getPoser(resourceIdentifier, aspects)
|
||||
val texture = repository.getTexture(resourceIdentifier, aspects, state.animationSeconds)
|
||||
|
||||
val context = RenderContext()
|
||||
model.context = context
|
||||
repository.getTextureNoSubstitute(resourceIdentifier, aspects, 0f)
|
||||
.let { context.put(RenderContext.TEXTURE, it) }
|
||||
context.put(RenderContext.SCALE, 1F)
|
||||
context.put(RenderContext.SPECIES, resourceIdentifier)
|
||||
context.put(RenderContext.ASPECTS, aspects)
|
||||
context.put(RenderContext.POSABLE_STATE, state)
|
||||
state.currentAspects = aspects
|
||||
state.currentModel = model
|
||||
|
||||
val renderType = RenderType.entityCutout(texture)//model.getLayer(texture)
|
||||
|
||||
state.setPoseToFirstSuitable(PoseType.PORTRAIT)
|
||||
state.updatePartialTicks(partialTicks)
|
||||
model.applyAnimations(null, state, 0F, 0F, 0F, 0F, 0F)
|
||||
matrixStack.translate(model.profileTranslation.x, model.profileTranslation.y, model.profileTranslation.z - 4.0)
|
||||
matrixStack.scale(model.profileScale, model.profileScale, 1 / model.profileScale)
|
||||
// matrixStack.multiply(rotation)
|
||||
val quaternion1 = Axis.YP.rotationDegrees(-32F * if (false) -1F else 1F)
|
||||
val quaternion2 = Axis.XP.rotationDegrees(5F)
|
||||
matrixStack.mulPose(quaternion1)
|
||||
matrixStack.mulPose(quaternion2)
|
||||
Lighting.setupForEntityInInventory() // TODO (techdaan): Does this map correctly?
|
||||
val entityRenderDispatcher = Minecraft.getInstance().entityRenderDispatcher
|
||||
entityRenderDispatcher.setRenderShadow(true)
|
||||
val quaternion1 = Axis.YP.rotationDegrees(-32F * if (false) -1F else 1F)
|
||||
val quaternion2 = Axis.XP.rotationDegrees(5F)
|
||||
matrixStack.mulPose(quaternion1)
|
||||
matrixStack.mulPose(quaternion2)
|
||||
Lighting.setupForEntityInInventory() // TODO (techdaan): Does this map correctly?
|
||||
val entityRenderDispatcher = Minecraft.getInstance().entityRenderDispatcher
|
||||
entityRenderDispatcher.setRenderShadow(true)
|
||||
|
||||
val bufferSource = Minecraft.getInstance().renderBuffers().bufferSource()
|
||||
val buffer = bufferSource.getBuffer(renderType)
|
||||
val light1 = Vector3f(-1F, 1F, 1.0F)
|
||||
val light2 = Vector3f(1.3F, -1F, 1.0F)
|
||||
RenderSystem.setShaderLights(light1, light2)
|
||||
val packedLight = LightTexture.pack(11, 7)
|
||||
val bufferSource = Minecraft.getInstance().renderBuffers().bufferSource()
|
||||
val buffer = bufferSource.getBuffer(renderType)
|
||||
val light1 = Vector3f(-1F, 1F, 1.0F)
|
||||
val light2 = Vector3f(1.3F, -1F, 1.0F)
|
||||
RenderSystem.setShaderLights(light1, light2)
|
||||
val packedLight = LightTexture.pack(11, 7)
|
||||
|
||||
model.withLayerContext(bufferSource, state, repository.getLayers(resourceIdentifier, aspects)) {
|
||||
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
bufferSource.endBatch()
|
||||
model.withLayerContext(bufferSource, state, repository.getLayers(resourceIdentifier, aspects)) {
|
||||
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
bufferSource.endBatch()
|
||||
}
|
||||
model.setDefault()
|
||||
entityRenderDispatcher.setRenderShadow(true)
|
||||
Lighting.setupFor3DItems()
|
||||
} else {
|
||||
renderSprite(matrixStack, sprite)
|
||||
}
|
||||
model.setDefault()
|
||||
entityRenderDispatcher.setRenderShadow(true)
|
||||
Lighting.setupFor3DItems()
|
||||
}
|
||||
|
||||
fun renderSprite(matrixStack: PoseStack, sprite: ResourceLocation) {
|
||||
val matrix: PoseStack.Pose = matrixStack.last()
|
||||
matrix.pose().translate(-1f, 0f, 0f)
|
||||
|
||||
RenderSystem.setShaderTexture(0, sprite);
|
||||
RenderSystem.setShader(GameRenderer::getPositionTexShader)
|
||||
|
||||
var buffer = Tesselator.getInstance().begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX)
|
||||
|
||||
buffer.addVertex(matrix, 2f, 0f, 0.0f).setUv(1f, 0f)
|
||||
buffer.addVertex(matrix, 0f, 0f, 0.0f).setUv(0f, 0f)
|
||||
buffer.addVertex(matrix, 0f, 2f, 0.0f).setUv(0f, 1f)
|
||||
buffer.addVertex(matrix, 2f, 2f, 0.0f).setUv(1f, 1f)
|
||||
|
||||
BufferUploader.drawWithShader(buffer.buildOrThrow())
|
||||
}
|
||||
+1
-1
@@ -58,7 +58,7 @@ class FishingSpawnCause(
|
||||
entity.pokemon.forcedAspects += FISHED_ASPECT
|
||||
|
||||
bait?.effects?.forEach { it ->
|
||||
if (Math.random() < it.chance) return
|
||||
if (Math.random() > it.chance) return
|
||||
when (it.type) {
|
||||
FishingBait.Effects.SHINY_REROLL -> shinyReroll(entity, it)
|
||||
FishingBait.Effects.NATURE -> alterNatureAttempt(entity, it)
|
||||
|
||||
+13
-11
@@ -92,7 +92,7 @@ open class PlayerPartyStore(
|
||||
val random = Random.Default
|
||||
for (pokemon in this) {
|
||||
// Awake from fainted
|
||||
if (pokemon.isFainted()) {
|
||||
if (pokemon.isFainted() && Cobblemon.config.faintAwakenHealthPercent > 0 && Cobblemon.config.defaultFaintTimer > 0) {
|
||||
pokemon.faintedTimer -= 1
|
||||
if (pokemon.faintedTimer <= -1) {
|
||||
val php = ceil(pokemon.hp * Cobblemon.config.faintAwakenHealthPercent)
|
||||
@@ -101,24 +101,26 @@ open class PlayerPartyStore(
|
||||
}
|
||||
}
|
||||
// Passive healing while less than full health
|
||||
else if (pokemon.currentHealth < pokemon.hp) {
|
||||
else if (pokemon.currentHealth < pokemon.hp && Cobblemon.config.healTimer > 0 && Cobblemon.config.healPercent > 0) {
|
||||
pokemon.healTimer--
|
||||
if (pokemon.healTimer <= -1) {
|
||||
pokemon.healTimer = Cobblemon.config.healTimer
|
||||
val healAmount = 1.0.coerceAtLeast(pokemon.hp.toDouble() * Cobblemon.config.healPercent)
|
||||
pokemon.currentHealth = pokemon.currentHealth + round(healAmount).toInt()
|
||||
pokemon.currentHealth += round(healAmount).toInt()
|
||||
}
|
||||
}
|
||||
|
||||
// Statuses
|
||||
val status = pokemon.status
|
||||
if (status != null && !player.isSleeping) {
|
||||
if (status.isExpired()) {
|
||||
status.status.onStatusExpire(player, pokemon, random)
|
||||
pokemon.status = null
|
||||
} else {
|
||||
status.status.onSecondPassed(player, pokemon, random)
|
||||
status.tickTimer()
|
||||
if (Cobblemon.config.healPassiveStatuses) {
|
||||
val status = pokemon.status
|
||||
if (status != null && !player.isSleeping) {
|
||||
if (status.isExpired()) {
|
||||
status.status.onStatusExpire(player, pokemon, random)
|
||||
pokemon.status = null
|
||||
} else {
|
||||
status.status.onSecondPassed(player, pokemon, random)
|
||||
status.tickTimer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,9 +21,10 @@ import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.BaseEntityBlock
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock
|
||||
import net.minecraft.world.level.block.Rotation
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateDefinition
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties.HORIZONTAL_FACING
|
||||
import net.minecraft.world.level.block.state.properties.EnumProperty
|
||||
import net.minecraft.world.level.pathfinder.PathComputationType
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
@@ -33,7 +34,7 @@ import net.minecraft.world.phys.shapes.VoxelShape
|
||||
class MonitorBlock(settings: Properties) : MultiblockBlock(settings) {
|
||||
init {
|
||||
registerDefaultState(stateDefinition.any()
|
||||
.setValue(HorizontalDirectionalBlock.FACING, Direction.NORTH))
|
||||
.setValue(HORIZONTAL_FACING, Direction.NORTH))
|
||||
}
|
||||
|
||||
override fun createMultiBlockEntity(
|
||||
@@ -50,11 +51,11 @@ class MonitorBlock(settings: Properties) : MultiblockBlock(settings) {
|
||||
}
|
||||
|
||||
override fun getStateForPlacement(blockPlaceContext: BlockPlaceContext): BlockState {
|
||||
return defaultBlockState().setValue(HorizontalDirectionalBlock.FACING, blockPlaceContext.horizontalDirection)
|
||||
return defaultBlockState().setValue(HORIZONTAL_FACING, blockPlaceContext.horizontalDirection)
|
||||
}
|
||||
|
||||
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
builder.add(HorizontalDirectionalBlock.FACING)
|
||||
builder.add(HORIZONTAL_FACING)
|
||||
builder.add(SCREEN)
|
||||
}
|
||||
|
||||
@@ -80,6 +81,12 @@ class MonitorBlock(settings: Properties) : MultiblockBlock(settings) {
|
||||
): VoxelShape {
|
||||
return HITBOX
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun rotate(state: BlockState, rotation: Rotation): BlockState {
|
||||
return state.setValue(HORIZONTAL_FACING, rotation.rotate(state.getValue(HORIZONTAL_FACING)))
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun isPathfindable(state: BlockState, type: PathComputationType): Boolean {
|
||||
return false
|
||||
|
||||
@@ -38,6 +38,7 @@ import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateDefinition
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty
|
||||
import net.minecraft.world.level.block.state.properties.EnumProperty
|
||||
import net.minecraft.world.level.material.FluidState
|
||||
@@ -53,7 +54,6 @@ class PCBlock(properties: Properties): BaseEntityBlock(properties), SimpleWaterl
|
||||
val CODEC = simpleCodec(::PCBlock)
|
||||
val PART = EnumProperty.create("part", PCPart::class.java)
|
||||
val ON = BooleanProperty.create("on")
|
||||
val WATERLOGGED = BooleanProperty.create("waterlogged")
|
||||
|
||||
private val NORTH_AABB_TOP = Shapes.or(
|
||||
Shapes.box(0.1875, 0.0, 0.0, 0.8125, 0.875, 0.125),
|
||||
|
||||
@@ -53,6 +53,7 @@ import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
import java.util.*
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED
|
||||
|
||||
@Suppress("OVERRIDE_DEPRECATION", "DEPRECATION")
|
||||
class PastureBlock(settings: Properties): BaseEntityBlock(settings), SimpleWaterloggedBlock, PreEmptsExplosion {
|
||||
@@ -61,7 +62,6 @@ class PastureBlock(settings: Properties): BaseEntityBlock(settings), SimpleWater
|
||||
|
||||
val PART: EnumProperty<PasturePart> = EnumProperty.create("part", PasturePart::class.java)
|
||||
val ON: BooleanProperty = BooleanProperty.create("on")
|
||||
val WATERLOGGED: BooleanProperty = BooleanProperty.create("waterlogged")
|
||||
|
||||
private val SOUTH_AABB_TOP = buildCollider(top = true, Direction.NORTH)
|
||||
private val NORTH_AABB_TOP = buildCollider(top = true, Direction.SOUTH)
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.gui
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.renderSprite
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.client.render.SpriteType
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
@@ -51,52 +53,60 @@ fun drawProfilePokemon(
|
||||
partialTicks: Float,
|
||||
scale: Float = 20F
|
||||
) {
|
||||
val model = PokemonModelRepository.getPoser(species, aspects)
|
||||
val texture = PokemonModelRepository.getTexture(species, aspects, state.animationSeconds)
|
||||
|
||||
val context = RenderContext()
|
||||
model.context = context
|
||||
PokemonModelRepository.getTextureNoSubstitute(species, aspects, 0f).let { context.put(RenderContext.TEXTURE, it) }
|
||||
context.put(RenderContext.SCALE, PokemonSpecies.getByIdentifier(species)!!.getForm(aspects).baseScale)
|
||||
context.put(RenderContext.SPECIES, species)
|
||||
context.put(RenderContext.ASPECTS, aspects)
|
||||
context.put(RenderContext.RENDER_STATE, RenderContext.RenderState.PROFILE)
|
||||
context.put(RenderContext.POSABLE_STATE, state)
|
||||
|
||||
state.currentModel = model
|
||||
state.currentAspects = aspects
|
||||
|
||||
val renderType = RenderType.entityCutout(texture)
|
||||
|
||||
RenderSystem.applyModelViewMatrix()
|
||||
matrixStack.scale(scale, scale, -scale)
|
||||
|
||||
state.setPoseToFirstSuitable(PoseType.PROFILE)
|
||||
state.updatePartialTicks(partialTicks)
|
||||
model.applyAnimations(null, state, 0F, 0F, 0F, 0F, 0F)
|
||||
matrixStack.translate(model.profileTranslation.x, model.profileTranslation.y, model.profileTranslation.z - 4.0)
|
||||
matrixStack.scale(model.profileScale, model.profileScale, 1 / model.profileScale)
|
||||
val sprite = PokemonModelRepository.getSprite(species, aspects, SpriteType.PROFILE);
|
||||
|
||||
matrixStack.mulPose(rotation)
|
||||
Lighting.setupForEntityInInventory() // TODO (techdaan): Does this map correctly?
|
||||
val entityRenderDispatcher = Minecraft.getInstance().entityRenderDispatcher
|
||||
rotation.conjugate()
|
||||
entityRenderDispatcher.overrideCameraOrientation(rotation)
|
||||
entityRenderDispatcher.setRenderShadow(true)
|
||||
if(sprite == null) {
|
||||
|
||||
val bufferSource = Minecraft.getInstance().renderBuffers().bufferSource()
|
||||
val buffer = bufferSource.getBuffer(renderType)
|
||||
val light1 = Vector3f(-1F, 1F, 1.0F)
|
||||
val light2 = Vector3f(1.3F, -1F, 1.0F)
|
||||
RenderSystem.setShaderLights(light1, light2)
|
||||
val packedLight = LightTexture.pack(11, 7)
|
||||
val model = PokemonModelRepository.getPoser(species, aspects)
|
||||
val texture = PokemonModelRepository.getTexture(species, aspects, state.animationSeconds)
|
||||
|
||||
model.withLayerContext(bufferSource, state, PokemonModelRepository.getLayers(species, aspects)) {
|
||||
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
bufferSource.endBatch()
|
||||
val context = RenderContext()
|
||||
model.context = context
|
||||
PokemonModelRepository.getTextureNoSubstitute(species, aspects, 0f)
|
||||
.let { context.put(RenderContext.TEXTURE, it) }
|
||||
context.put(RenderContext.SCALE, PokemonSpecies.getByIdentifier(species)!!.getForm(aspects).baseScale)
|
||||
context.put(RenderContext.SPECIES, species)
|
||||
context.put(RenderContext.ASPECTS, aspects)
|
||||
context.put(RenderContext.RENDER_STATE, RenderContext.RenderState.PROFILE)
|
||||
context.put(RenderContext.POSABLE_STATE, state)
|
||||
|
||||
state.currentModel = model
|
||||
state.currentAspects = aspects
|
||||
|
||||
val renderType = RenderType.entityCutout(texture)
|
||||
|
||||
state.setPoseToFirstSuitable(PoseType.PROFILE)
|
||||
state.updatePartialTicks(partialTicks)
|
||||
model.applyAnimations(null, state, 0F, 0F, 0F, 0F, 0F)
|
||||
matrixStack.translate(model.profileTranslation.x, model.profileTranslation.y, model.profileTranslation.z - 4.0)
|
||||
matrixStack.scale(model.profileScale, model.profileScale, 1 / model.profileScale)
|
||||
|
||||
matrixStack.mulPose(rotation)
|
||||
Lighting.setupForEntityInInventory() // TODO (techdaan): Does this map correctly?
|
||||
val entityRenderDispatcher = Minecraft.getInstance().entityRenderDispatcher
|
||||
rotation.conjugate()
|
||||
entityRenderDispatcher.overrideCameraOrientation(rotation)
|
||||
entityRenderDispatcher.setRenderShadow(true)
|
||||
|
||||
val bufferSource = Minecraft.getInstance().renderBuffers().bufferSource()
|
||||
val buffer = bufferSource.getBuffer(renderType)
|
||||
val light1 = Vector3f(-1F, 1F, 1.0F)
|
||||
val light2 = Vector3f(1.3F, -1F, 1.0F)
|
||||
RenderSystem.setShaderLights(light1, light2)
|
||||
val packedLight = LightTexture.pack(11, 7)
|
||||
|
||||
model.withLayerContext(bufferSource, state, PokemonModelRepository.getLayers(species, aspects)) {
|
||||
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
bufferSource.endBatch()
|
||||
}
|
||||
model.setDefault()
|
||||
entityRenderDispatcher.setRenderShadow(true)
|
||||
Lighting.setupFor3DItems()
|
||||
} else {
|
||||
renderSprite(matrixStack, sprite)
|
||||
}
|
||||
model.setDefault()
|
||||
entityRenderDispatcher.setRenderShadow(true)
|
||||
Lighting.setupFor3DItems()
|
||||
}
|
||||
|
||||
|
||||
+13
-5
@@ -11,10 +11,7 @@ package com.cobblemon.mod.common.client.render
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Bone
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ModelTextureSupplierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.Vector3fAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.Vector4fAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.*
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.annotations.SerializedName
|
||||
@@ -52,6 +49,10 @@ class VaryingRenderableResolver<T : PosableModel>(
|
||||
?: throw IllegalStateException("Unable to find a texture for $name with aspects ${aspects.joinToString()}. This shouldn't be possible if you've defined the fallback variation.")
|
||||
}
|
||||
|
||||
fun getSprite(aspects: Set<String>, type: SpriteType): ResourceLocation? {
|
||||
return getVariationValue(aspects) { sprites }?.get(type)
|
||||
}
|
||||
|
||||
private fun <T> getVariationValue(aspects: Set<String>, selector: ModelAssetVariation.() -> T?): T? {
|
||||
return variations.lastOrNull { it.aspects.all { it in aspects } && selector(it) != null }?.let(selector)
|
||||
}
|
||||
@@ -86,6 +87,7 @@ class VaryingRenderableResolver<T : PosableModel>(
|
||||
.registerTypeAdapter(Vector3f::class.java, Vector3fAdapter)
|
||||
.registerTypeAdapter(Vector4f::class.java, Vector4fAdapter)
|
||||
.registerTypeAdapter(ModelTextureSupplier::class.java, ModelTextureSupplierAdapter)
|
||||
.registerTypeAdapter(SpriteType::class.java, SpriteTypeAdapter)
|
||||
.disableHtmlEscaping()
|
||||
.setLenient()
|
||||
.create()
|
||||
@@ -160,7 +162,8 @@ class ModelAssetVariation(
|
||||
val poser: ResourceLocation? = null,
|
||||
val model: ResourceLocation? = null,
|
||||
val texture: ModelTextureSupplier? = null,
|
||||
val layers: List<ModelLayer>? = null
|
||||
val layers: List<ModelLayer>? = null,
|
||||
val sprites: Map<SpriteType, ResourceLocation>? = null
|
||||
)
|
||||
|
||||
/**
|
||||
@@ -201,4 +204,9 @@ class ModelLayer {
|
||||
val texture: ModelTextureSupplier? = null
|
||||
val emissive: Boolean = false
|
||||
val translucent: Boolean = false
|
||||
}
|
||||
|
||||
enum class SpriteType {
|
||||
PORTRAIT,
|
||||
PROFILE
|
||||
}
|
||||
+1
-1
@@ -189,7 +189,7 @@ class PokeBobberEntityRenderer(context: EntityRendererProvider.Context?) : Entit
|
||||
val sinBodyYaw = Mth.sin(bodyYawRadians).toDouble()
|
||||
val cosBodyYaw = Mth.cos(bodyYawRadians).toDouble()
|
||||
val horizontalOffset = armOffset.toDouble() * 0.35
|
||||
if (!entityRenderDispatcher.options.cameraType.isFirstPerson || playerEntity !== Minecraft.getInstance().player) {
|
||||
if (!entityRenderDispatcher.options.cameraType.isFirstPerson || playerEntity != Minecraft.getInstance().player) {
|
||||
playerEyeYWorld = Mth.lerp(tickDelta.toDouble(), playerEntity.xo, playerEntity.x) - cosBodyYaw * horizontalOffset - sinBodyYaw * 0.8
|
||||
playerPosYWorld = playerEntity.yo + playerEntity.eyeHeight.toDouble() + (playerEntity.y - playerEntity.yo) * tickDelta.toDouble() - 0.45
|
||||
playerPosZWorld = Mth.lerp(tickDelta.toDouble(), playerEntity.zo, playerEntity.z) - sinBodyYaw * horizontalOffset + cosBodyYaw * 0.8
|
||||
|
||||
+8
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.client.render.ModelLayer
|
||||
import com.cobblemon.mod.common.client.render.ModelVariationSet
|
||||
import com.cobblemon.mod.common.client.render.SpriteType
|
||||
import com.cobblemon.mod.common.client.render.VaryingRenderableResolver
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.*
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.bedrock.animation.BedrockAnimationRepository
|
||||
@@ -232,6 +233,13 @@ abstract class VaryingModelRepository<T : PosableModel> {
|
||||
return this.variations[fallback]!!.getLayers(aspects)
|
||||
}
|
||||
|
||||
fun getSprite(name: ResourceLocation, aspects: Set<String>, type: SpriteType): ResourceLocation? {
|
||||
try {
|
||||
return this.variations[name]?.getSprite(aspects, type)
|
||||
} catch (_: IllegalStateException) {}
|
||||
return null
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun registerFactory(id: String, factory: BiFunction<ResourceLocation, Resource, Pair<ResourceLocation, Function<Boolean, Bone>>>) {
|
||||
MODEL_FACTORIES[id] = factory
|
||||
|
||||
@@ -147,6 +147,9 @@ class CobblemonConfig {
|
||||
Statuses.BURN.configEntry()
|
||||
)
|
||||
|
||||
@NodeCategory(Category.PassiveStatus)
|
||||
var healPassiveStatuses = true
|
||||
|
||||
@NodeCategory(Category.Healing)
|
||||
var infiniteHealerCharge = false
|
||||
|
||||
|
||||
@@ -281,7 +281,7 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
var friendship = this.form.baseFriendship
|
||||
private set(value) {
|
||||
// Don't check on client, that way we don't need to actually sync the config value it doesn't affect anything
|
||||
if (!this.isClient || !this.isPossibleFriendship(value)) {
|
||||
if (!this.isPossibleFriendship(value)) {
|
||||
return
|
||||
}
|
||||
FRIENDSHIP_UPDATED.post(FriendshipUpdatedEvent(this, value)) {
|
||||
@@ -996,7 +996,7 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
*/
|
||||
fun setFriendship(value: Int, coerceSafe: Boolean = true): Boolean {
|
||||
val sanitizedAmount = if (coerceSafe) value.absoluteValue.coerceAtMost(Cobblemon.config.maxPokemonFriendship) else value.absoluteValue
|
||||
if (!this.isClient || !this.isPossibleFriendship(sanitizedAmount)) {
|
||||
if (!this.isPossibleFriendship(sanitizedAmount)) {
|
||||
return false
|
||||
}
|
||||
this.friendship = sanitizedAmount
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.util.adapters
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.egg.EggGroup
|
||||
import com.cobblemon.mod.common.client.render.SpriteType
|
||||
import com.google.gson.*
|
||||
import java.lang.reflect.Type
|
||||
|
||||
object SpriteTypeAdapter : JsonDeserializer<SpriteType>, JsonSerializer<SpriteType> {
|
||||
|
||||
// Safe to just cache
|
||||
private val spriteTypes = SpriteType.values()
|
||||
override fun deserialize(json: JsonElement, typeOfT: Type?, context: JsonDeserializationContext?): SpriteType {
|
||||
val rawID = json.asString
|
||||
return this.spriteTypes.firstOrNull { spriteType -> spriteType.name.equals(rawID, true) }
|
||||
?: throw IllegalStateException("Failed to resolve sprite type from: $rawID")
|
||||
}
|
||||
|
||||
override fun serialize(src: SpriteType, typeOfSrc: Type, context: JsonSerializationContext): JsonElement = JsonPrimitive(src.name.lowercase())
|
||||
}
|
||||
Reference in New Issue
Block a user