mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-11-11 18:58:53 -05:00
add player edible cake
This commit is contained in:
1 parent
5190bbe723
commit
c86103fd31
11 files changed
+481
-225
No files matched your search
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.block.entity.PokeCakeBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.BerryBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.HealingMachineBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.PCBlockEntity
|
||||
@@ -105,8 +106,13 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
|
||||
|
||||
@JvmField
|
||||
val LURE_CAKE: BlockEntityType<LureCakeBlockEntity> = this.create(
|
||||
"lure_cake",
|
||||
BlockEntityType.Builder.of(::LureCakeBlockEntity, CobblemonBlocks.LURE_CAKE).build(null)
|
||||
"lure_cake",
|
||||
BlockEntityType.Builder.of(::LureCakeBlockEntity, CobblemonBlocks.LURE_CAKE).build(null)
|
||||
)
|
||||
@JvmField
|
||||
val POKE_CAKE: BlockEntityType<PokeCakeBlockEntity> = this.create(
|
||||
"poke_cake",
|
||||
BlockEntityType.Builder.of(::PokeCakeBlockEntity, CobblemonBlocks.POKE_CAKE).build(null)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.api.apricorn.Apricorn
|
||||
import com.cobblemon.mod.common.block.*
|
||||
import com.cobblemon.mod.common.block.LecternBlock
|
||||
import com.cobblemon.mod.common.block.CampfireBlock
|
||||
import com.cobblemon.mod.common.block.LecternBlock
|
||||
import com.cobblemon.mod.common.block.MintBlock.MintType
|
||||
import com.cobblemon.mod.common.block.chest.GildedChestBlock
|
||||
import com.cobblemon.mod.common.block.sign.CobblemonHangingSignBlock
|
||||
@@ -232,6 +232,8 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
|
||||
@JvmField
|
||||
val LURE_CAKE = this.create("lure_cake", LureCakeBlock(BlockBehaviour.Properties.of().randomTicks().sound(SoundType.SPONGE).mapColor(MapColor.COLOR_LIGHT_GRAY).noOcclusion()))
|
||||
@JvmField
|
||||
val POKE_CAKE = this.create("poke_cake", PokeCakeBlock(BlockBehaviour.Properties.of().randomTicks().sound(SoundType.SPONGE).mapColor(MapColor.COLOR_LIGHT_GRAY).noOcclusion()))
|
||||
|
||||
@JvmField
|
||||
val TUMBLESTONE_CLUSTER = tumblestoneBlock("tumblestone_cluster", GrowableStoneBlock.STAGE_3, 7, 3, null)
|
||||
|
||||
@@ -333,6 +333,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
|
||||
@JvmField
|
||||
val LURE_CAKE = blockItem("lure_cake", CobblemonBlocks.LURE_CAKE)
|
||||
@JvmField
|
||||
val POKE_CAKE = blockItem("poke_cake", CobblemonBlocks.POKE_CAKE)
|
||||
|
||||
val aprijuices = mutableListOf<AprijuiceItem>()
|
||||
@JvmField
|
||||
@@ -511,8 +513,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
|
||||
// todo THE MOCHIS (are they all with their own item classes? Or bundled into one itemclass like some of the berries?
|
||||
|
||||
//todo PokeCake the player cake that is not a lure
|
||||
|
||||
// todo potato mochi
|
||||
|
||||
// todo fried rice
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
package com.cobblemon.mod.common.block
|
||||
|
||||
import com.cobblemon.mod.common.block.entity.PokeCakeBlockEntity
|
||||
import com.mojang.serialization.MapCodec
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.InteractionHand.MAIN_HAND
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.LevelAccessor
|
||||
import net.minecraft.world.level.LevelReader
|
||||
import net.minecraft.world.level.block.BaseEntityBlock
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.gameevent.GameEvent
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
|
||||
class PokeCakeBlock(settings: Properties): BaseEntityBlock(settings) {
|
||||
|
||||
companion object {
|
||||
val SHAPE_BY_BITE = arrayOf(
|
||||
box(1.0, 0.0, 1.0, 15.0, 9.0, 15.0),
|
||||
box(3.0, 0.0, 1.0, 15.0, 9.0, 15.0),
|
||||
box(5.0, 0.0, 1.0, 15.0, 9.0, 15.0),
|
||||
box(7.0, 0.0, 1.0, 15.0, 9.0, 15.0),
|
||||
box(9.0, 0.0, 1.0, 15.0, 9.0, 15.0),
|
||||
box(11.0, 0.0, 1.0, 15.0, 9.0, 15.0),
|
||||
box(13.0, 0.0, 1.0, 15.0, 9.0, 15.0)
|
||||
)
|
||||
}
|
||||
|
||||
override fun codec(): MapCodec<out BaseEntityBlock?>? {
|
||||
return simpleCodec(::PokeCakeBlock)
|
||||
}
|
||||
|
||||
override fun newBlockEntity(pos: BlockPos, state: BlockState): BlockEntity? {
|
||||
return PokeCakeBlockEntity(pos, state)
|
||||
}
|
||||
|
||||
override fun setPlacedBy(
|
||||
level: Level,
|
||||
pos: BlockPos,
|
||||
state: BlockState,
|
||||
placer: LivingEntity?,
|
||||
stack: ItemStack
|
||||
) {
|
||||
super.setPlacedBy(level, pos, state, placer, stack)
|
||||
|
||||
val blockEntity = level.getBlockEntity(pos) as? PokeCakeBlockEntity
|
||||
blockEntity?.initializeFromItemStack(stack)
|
||||
}
|
||||
|
||||
override fun useWithoutItem(
|
||||
state: BlockState,
|
||||
level: Level,
|
||||
pos: BlockPos,
|
||||
player: Player,
|
||||
hitResult: BlockHitResult
|
||||
): InteractionResult? {
|
||||
if (level.isClientSide) {
|
||||
if (eat(level, pos, player).consumesAction()) {
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
if (player.getItemInHand(MAIN_HAND).isEmpty) {
|
||||
return InteractionResult.CONSUME;
|
||||
}
|
||||
}
|
||||
|
||||
return eat(level, pos, player);
|
||||
}
|
||||
|
||||
fun eat(level: LevelAccessor, pos: BlockPos, player: Player): InteractionResult {
|
||||
if (!player.canEat(false)) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
player.getFoodData().eat(2, 0.1F);
|
||||
level.gameEvent(player, GameEvent.EAT, pos);
|
||||
|
||||
var bites = getBites(level, pos)
|
||||
if (bites < 6) {
|
||||
setBites(level, pos, bites + 1)
|
||||
} else {
|
||||
level.removeBlock(pos, false);
|
||||
level.gameEvent(player, GameEvent.BLOCK_DESTROY, pos);
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
override fun getShape(
|
||||
state: BlockState,
|
||||
level: BlockGetter,
|
||||
pos: BlockPos,
|
||||
context: CollisionContext
|
||||
): VoxelShape? {
|
||||
return SHAPE_BY_BITE[getBites(level, pos)]
|
||||
}
|
||||
|
||||
override fun getCloneItemStack(
|
||||
level: LevelReader,
|
||||
pos: BlockPos,
|
||||
state: BlockState
|
||||
): ItemStack? {
|
||||
val blockEntity = level.getBlockEntity(pos) as? PokeCakeBlockEntity ?: return ItemStack.EMPTY
|
||||
return blockEntity.toItemStack()
|
||||
}
|
||||
|
||||
fun getBites(level: BlockGetter, pos: BlockPos): Int = (level.getBlockEntity(pos) as? PokeCakeBlockEntity)?.bites ?: 0
|
||||
fun setBites(level: BlockGetter, pos: BlockPos, bites: Int) = (level.getBlockEntity(pos) as? PokeCakeBlockEntity)?.bites = bites
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.cobblemon.mod.common.block.entity
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||
import com.cobblemon.mod.common.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.item.components.CookingComponent
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.NbtOps
|
||||
import net.minecraft.network.protocol.Packet
|
||||
import net.minecraft.network.protocol.game.ClientGamePacketListener
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
|
||||
class PokeCakeBlockEntity(
|
||||
pos: BlockPos,
|
||||
state: BlockState
|
||||
) : BlockEntity(CobblemonBlockEntities.POKE_CAKE, pos, state) {
|
||||
var cookingComponent: CookingComponent? = null
|
||||
var bites: Int = 0
|
||||
|
||||
fun initializeFromItemStack(itemStack: ItemStack) {
|
||||
cookingComponent = itemStack.get(CobblemonItemComponents.COOKING_COMPONENT)
|
||||
}
|
||||
|
||||
override fun saveAdditional(
|
||||
tag: CompoundTag,
|
||||
registries: HolderLookup.Provider
|
||||
) {
|
||||
super.saveAdditional(tag, registries)
|
||||
|
||||
tag.putInt("Bites", bites)
|
||||
cookingComponent?.let { component ->
|
||||
CobblemonItemComponents.COOKING_COMPONENT.codec()
|
||||
?.encodeStart(NbtOps.INSTANCE, component)
|
||||
?.result()
|
||||
?.ifPresent { encodedTag ->
|
||||
tag.put("CookingComponent", encodedTag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun loadAdditional(
|
||||
tag: CompoundTag,
|
||||
registries: HolderLookup.Provider
|
||||
) {
|
||||
super.loadAdditional(tag, registries)
|
||||
|
||||
bites = tag.getInt("Bites")
|
||||
if (tag.contains("CookingComponent")) {
|
||||
CobblemonItemComponents.COOKING_COMPONENT.codec()
|
||||
?.parse(NbtOps.INSTANCE, tag.getCompound("CookingComponent"))
|
||||
?.result()
|
||||
?.ifPresent { component ->
|
||||
cookingComponent = component
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getUpdatePacket(): Packet<ClientGamePacketListener?>? {
|
||||
return ClientboundBlockEntityDataPacket.create(this)
|
||||
}
|
||||
|
||||
override fun getUpdateTag(registries: HolderLookup.Provider): CompoundTag? {
|
||||
val tag = CompoundTag()
|
||||
saveAdditional(tag, registries)
|
||||
return tag
|
||||
}
|
||||
|
||||
fun toItemStack(): ItemStack {
|
||||
val stack = ItemStack(this.blockState.block)
|
||||
cookingComponent?.let { component ->
|
||||
stack.getComponents().apply {
|
||||
stack.set(CobblemonItemComponents.COOKING_COMPONENT, component)
|
||||
}
|
||||
}
|
||||
return stack
|
||||
}
|
||||
}
|
||||
@@ -267,6 +267,7 @@ object CobblemonClient {
|
||||
CobblemonBlocks.SACCHARINE_WALL_HANGING_SIGN,
|
||||
CobblemonBlocks.SACCHARINE_SAPLING,
|
||||
CobblemonBlocks.LURE_CAKE,
|
||||
CobblemonBlocks.POKE_CAKE,
|
||||
CobblemonBlocks.LECTERN,
|
||||
CobblemonBlocks.CAMPFIRE
|
||||
)
|
||||
@@ -304,6 +305,7 @@ object CobblemonClient {
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.LECTERN, ::LecternBlockEntityRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.CAMPFIRE, ::CampfireBlockEntityRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.LURE_CAKE, ::LureCakeBlockEntityRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.POKE_CAKE, ::PokeCakeBlockEntityRenderer)
|
||||
}
|
||||
|
||||
private fun registerEntityRenderers() {
|
||||
|
||||
+226
@@ -0,0 +1,226 @@
|
||||
package com.cobblemon.mod.common.client.render.block
|
||||
|
||||
import com.cobblemon.mod.common.api.cooking.getColor
|
||||
import com.cobblemon.mod.common.block.entity.LureCakeBlockEntity
|
||||
import com.cobblemon.mod.common.item.components.CookingComponent
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer
|
||||
import com.mojang.math.Axis
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.inventory.InventoryMenu.BLOCK_ATLAS
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import org.joml.Vector3d
|
||||
|
||||
const val PIXEL_SHIFT = 1.0 / 16.0
|
||||
const val WHITE_OPAQUE_COLOR = 0xFFFFFFFF.toInt()
|
||||
|
||||
const val ATLAS_START = 0.0f
|
||||
const val ATLAS_END = 1.0f
|
||||
const val HEIGHT = 0.5f
|
||||
const val TOP_LAYER_HEIGHT = 0.5625f
|
||||
const val BOTTOM_LAYER_HEIGHT = 0.0f
|
||||
|
||||
val TOP_LAYER: TextureAtlasSprite = loadTexture("block/poke_snack_top_layer2")
|
||||
val CHERRY_LAYER: TextureAtlasSprite = loadTexture("block/poke_snack_top_layer3")
|
||||
val SIDE_LAYER_BOTTOM: TextureAtlasSprite = loadTexture("block/poke_snack_side_layer1")
|
||||
val SIDE_LAYER_TOP: TextureAtlasSprite = loadTexture("block/poke_snack_side_layer2")
|
||||
val SIDE_LAYER_MIDDLE: TextureAtlasSprite = loadTexture("block/poke_snack_side_layer3")
|
||||
val BOTTOM_LAYER: TextureAtlasSprite = loadTexture("block/poke_snack_bottom_layer1")
|
||||
val FIRST_INNER_LAYER: TextureAtlasSprite = loadTexture("block/poke_snack_inner_layer1")
|
||||
val SECOND_INNER_LAYER: TextureAtlasSprite = loadTexture("block/poke_snack_inner_layer2")
|
||||
val THIRD_INNER_LAYER: TextureAtlasSprite = loadTexture("block/poke_snack_inner_layer3")
|
||||
|
||||
fun loadTexture(textureName: String): TextureAtlasSprite {
|
||||
return Minecraft.getInstance().getTextureAtlas(BLOCK_ATLAS).apply(ResourceLocation("cobblemon", textureName))
|
||||
}
|
||||
|
||||
fun renderCake(
|
||||
cookingComponent: CookingComponent?,
|
||||
poseStack: PoseStack,
|
||||
multiBufferSource: MultiBufferSource,
|
||||
light: Int,
|
||||
bites: Int,
|
||||
) {
|
||||
val maxBites = 7f
|
||||
val cakeIsFull = bites.toFloat() == 0f
|
||||
val percentageToRender = if (cakeIsFull) 1.0f else PIXEL_SHIFT.toFloat() + (PIXEL_SHIFT.toFloat() * 2f * (maxBites - bites).toFloat())
|
||||
val clippedWidth = (ATLAS_END - ATLAS_START) * percentageToRender
|
||||
val uClipped = TOP_LAYER.u0 + (TOP_LAYER.u1 - TOP_LAYER.u0) * percentageToRender
|
||||
|
||||
val vertexConsumer = multiBufferSource.getBuffer(RenderType.cutout())
|
||||
val primaryColor = cookingComponent?.seasoning1?.color?.let { getColor(it) } ?: WHITE_OPAQUE_COLOR
|
||||
val secondaryColor = cookingComponent?.seasoning2?.color?.let { getColor(it) } ?: WHITE_OPAQUE_COLOR
|
||||
val tertiaryColor = cookingComponent?.seasoning3?.color?.let { getColor(it) } ?: WHITE_OPAQUE_COLOR
|
||||
|
||||
poseStack.pushPose()
|
||||
poseStack.translate(0.5, 0.5, 0.5)
|
||||
poseStack.mulPose(Axis.YP.rotationDegrees(180f))
|
||||
poseStack.translate(-0.5, -0.5, -0.5)
|
||||
|
||||
poseStack.pushPose()
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, TOP_LAYER_HEIGHT, ATLAS_START, clippedWidth, TOP_LAYER_HEIGHT, ATLAS_END,
|
||||
TOP_LAYER.u0, TOP_LAYER.v0, uClipped, TOP_LAYER.v1,
|
||||
light, secondaryColor
|
||||
)
|
||||
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, TOP_LAYER_HEIGHT, ATLAS_START, clippedWidth, TOP_LAYER_HEIGHT, ATLAS_END,
|
||||
CHERRY_LAYER.u0, CHERRY_LAYER.v0, uClipped, CHERRY_LAYER.v1,
|
||||
light, primaryColor
|
||||
)
|
||||
poseStack.popPose()
|
||||
|
||||
val translations = arrayOf(
|
||||
Vector3d(-1.0, 1.0, 0.5 - PIXEL_SHIFT),
|
||||
Vector3d(0.0, 1.0, 0.5 - PIXEL_SHIFT),
|
||||
Vector3d(0.0, 1.0, -0.5 - PIXEL_SHIFT),
|
||||
Vector3d(-1.0, 1.0, -0.5 - PIXEL_SHIFT),
|
||||
)
|
||||
|
||||
val rotationsY = arrayOf(
|
||||
Axis.YP.rotationDegrees(90f),
|
||||
Axis.YP.rotationDegrees(0f),
|
||||
Axis.YP.rotationDegrees(-90f),
|
||||
Axis.YP.rotationDegrees(-180f)
|
||||
)
|
||||
|
||||
for (i in translations.indices) {
|
||||
poseStack.pushPose()
|
||||
poseStack.mulPose(rotationsY[i])
|
||||
poseStack.translate(translations[i].x, translations[i].y, translations[i].z)
|
||||
poseStack.mulPose(Axis.XP.rotationDegrees(90f))
|
||||
|
||||
if (i == 0 && !cakeIsFull) {
|
||||
poseStack.translate(0.0, -bites * PIXEL_SHIFT * 2, 0.0)
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, HEIGHT, ATLAS_START, ATLAS_END, HEIGHT, ATLAS_END,
|
||||
FIRST_INNER_LAYER.u0, FIRST_INNER_LAYER.v0, FIRST_INNER_LAYER.u1, FIRST_INNER_LAYER.v1,
|
||||
light, tertiaryColor
|
||||
)
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, HEIGHT, ATLAS_START, ATLAS_END, HEIGHT, ATLAS_END,
|
||||
SECOND_INNER_LAYER.u0, SECOND_INNER_LAYER.v0, SECOND_INNER_LAYER.u1, SECOND_INNER_LAYER.v1,
|
||||
light, secondaryColor
|
||||
)
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, HEIGHT, ATLAS_START, ATLAS_END, HEIGHT, ATLAS_END,
|
||||
THIRD_INNER_LAYER.u0, THIRD_INNER_LAYER.v0, THIRD_INNER_LAYER.u1, THIRD_INNER_LAYER.v1,
|
||||
light, primaryColor
|
||||
)
|
||||
} else if (i == 0 || i == 1) {
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, HEIGHT, ATLAS_START, clippedWidth, HEIGHT, ATLAS_END,
|
||||
SIDE_LAYER_BOTTOM.u0, SIDE_LAYER_BOTTOM.v0, uClipped, SIDE_LAYER_BOTTOM.v1,
|
||||
light, tertiaryColor
|
||||
)
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, HEIGHT, ATLAS_START, clippedWidth, HEIGHT, ATLAS_END,
|
||||
SIDE_LAYER_TOP.u0, SIDE_LAYER_TOP.v0, uClipped, SIDE_LAYER_TOP.v1,
|
||||
light, secondaryColor
|
||||
)
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, HEIGHT, ATLAS_START, clippedWidth, HEIGHT, ATLAS_END,
|
||||
SIDE_LAYER_MIDDLE.u0, SIDE_LAYER_MIDDLE.v0, uClipped, SIDE_LAYER_MIDDLE.v1,
|
||||
light, primaryColor
|
||||
)
|
||||
} else if (i == 2) {
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, HEIGHT, ATLAS_START, ATLAS_END, HEIGHT, ATLAS_END,
|
||||
SIDE_LAYER_BOTTOM.u0, SIDE_LAYER_BOTTOM.v0, SIDE_LAYER_BOTTOM.u1, SIDE_LAYER_BOTTOM.v1,
|
||||
light, tertiaryColor
|
||||
)
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, HEIGHT, ATLAS_START, ATLAS_END, HEIGHT, ATLAS_END,
|
||||
SIDE_LAYER_TOP.u0, SIDE_LAYER_TOP.v0, SIDE_LAYER_TOP.u1, SIDE_LAYER_TOP.v1,
|
||||
light, secondaryColor
|
||||
)
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, HEIGHT, ATLAS_START, ATLAS_END, HEIGHT, ATLAS_END,
|
||||
SIDE_LAYER_TOP.u0, SIDE_LAYER_MIDDLE.v0, SIDE_LAYER_MIDDLE.u1, SIDE_LAYER_MIDDLE.v1,
|
||||
light, primaryColor
|
||||
)
|
||||
} else if (i == 3) {
|
||||
val clippedStartX = ATLAS_START + (ATLAS_END - ATLAS_START) * (1 - percentageToRender)
|
||||
val clippedUStart = SIDE_LAYER_BOTTOM.u0 + (SIDE_LAYER_BOTTOM.u1 - SIDE_LAYER_BOTTOM.u0) * (1 - percentageToRender)
|
||||
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
clippedStartX, HEIGHT, ATLAS_START, ATLAS_END, HEIGHT, ATLAS_END,
|
||||
clippedUStart, SIDE_LAYER_BOTTOM.v0, SIDE_LAYER_BOTTOM.u1, SIDE_LAYER_BOTTOM.v1,
|
||||
light, tertiaryColor
|
||||
)
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
clippedStartX, HEIGHT, ATLAS_START, ATLAS_END, HEIGHT, ATLAS_END,
|
||||
clippedUStart, SIDE_LAYER_TOP.v0, SIDE_LAYER_TOP.u1, SIDE_LAYER_TOP.v1,
|
||||
light, secondaryColor
|
||||
)
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
clippedStartX, HEIGHT, ATLAS_START, ATLAS_END, HEIGHT, ATLAS_END,
|
||||
clippedUStart, SIDE_LAYER_MIDDLE.v0, SIDE_LAYER_MIDDLE.u1, SIDE_LAYER_MIDDLE.v1,
|
||||
light, primaryColor
|
||||
)
|
||||
}
|
||||
|
||||
poseStack.popPose()
|
||||
}
|
||||
|
||||
poseStack.pushPose()
|
||||
poseStack.translate(0.5, 0.0, 0.5)
|
||||
poseStack.mulPose(Axis.XP.rotationDegrees(180f))
|
||||
poseStack.translate(-0.5, 0.0, -0.5)
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, BOTTOM_LAYER_HEIGHT, ATLAS_START, clippedWidth, BOTTOM_LAYER_HEIGHT, ATLAS_END,
|
||||
BOTTOM_LAYER.u0, BOTTOM_LAYER.v0, uClipped, BOTTOM_LAYER.v1,
|
||||
light, tertiaryColor
|
||||
)
|
||||
poseStack.popPose()
|
||||
|
||||
poseStack.popPose()
|
||||
}
|
||||
|
||||
private fun drawQuad(
|
||||
builder: VertexConsumer,
|
||||
poseStack: PoseStack,
|
||||
x0: Float, y0: Float, z0: Float,
|
||||
x1: Float, y1: Float, z1: Float,
|
||||
u0: Float, v0: Float, u1: Float, v1: Float,
|
||||
packedLight: Int, color: Int,
|
||||
) {
|
||||
drawVertex(builder, poseStack, x0, y0, z0, u0, v0, packedLight, color)
|
||||
drawVertex(builder, poseStack, x0, y1, z1, u0, v1, packedLight, color)
|
||||
drawVertex(builder, poseStack, x1, y1, z1, u1, v1, packedLight, color)
|
||||
drawVertex(builder, poseStack, x1, y0, z0, u1, v0, packedLight, color)
|
||||
}
|
||||
|
||||
private fun drawVertex(
|
||||
builder: VertexConsumer,
|
||||
poseStack: PoseStack,
|
||||
x: Float, y: Float, z: Float,
|
||||
u: Float, v: Float,
|
||||
packedLight: Int, color: Int
|
||||
) {
|
||||
builder.addVertex(poseStack.last().pose(), x, y, z)
|
||||
.setColor(color)
|
||||
.setUv(u, v)
|
||||
.setLight(packedLight)
|
||||
.setNormal(0f, 1f, 0f)
|
||||
}
|
||||
+1
-220
@@ -8,50 +8,15 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.block
|
||||
|
||||
import com.cobblemon.mod.common.api.cooking.getColor
|
||||
import com.cobblemon.mod.common.block.LureCakeBlock.Companion.BITES
|
||||
import com.cobblemon.mod.common.block.entity.LureCakeBlockEntity
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer
|
||||
import com.mojang.math.Axis
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.inventory.InventoryMenu.BLOCK_ATLAS
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import org.joml.Vector3d
|
||||
|
||||
class LureCakeBlockEntityRenderer(ctx: BlockEntityRendererProvider.Context) : BlockEntityRenderer<LureCakeBlockEntity> {
|
||||
|
||||
companion object {
|
||||
const val PIXEL_SHIFT = 1.0 / 16.0
|
||||
const val WHITE_OPAQUE_COLOR = 0xFFFFFFFF.toInt()
|
||||
|
||||
const val ATLAS_START = 0.0f
|
||||
const val ATLAS_END = 1.0f
|
||||
const val HEIGHT = 0.5f
|
||||
const val TOP_LAYER_HEIGHT = 0.5625f
|
||||
const val BOTTOM_LAYER_HEIGHT = 0.0f
|
||||
|
||||
val TOP_LAYER: TextureAtlasSprite = loadTexture("block/poke_snack_top_layer2")
|
||||
val CHERRY_LAYER: TextureAtlasSprite = loadTexture("block/poke_snack_top_layer3")
|
||||
val SIDE_LAYER_BOTTOM: TextureAtlasSprite = loadTexture("block/poke_snack_side_layer1")
|
||||
val SIDE_LAYER_TOP: TextureAtlasSprite = loadTexture("block/poke_snack_side_layer2")
|
||||
val SIDE_LAYER_MIDDLE: TextureAtlasSprite = loadTexture("block/poke_snack_side_layer3")
|
||||
val BOTTOM_LAYER: TextureAtlasSprite = loadTexture("block/poke_snack_bottom_layer1")
|
||||
val FIRST_INNER_LAYER: TextureAtlasSprite = loadTexture("block/poke_snack_inner_layer1")
|
||||
val SECOND_INNER_LAYER: TextureAtlasSprite = loadTexture("block/poke_snack_inner_layer2")
|
||||
val THIRD_INNER_LAYER: TextureAtlasSprite = loadTexture("block/poke_snack_inner_layer3")
|
||||
|
||||
fun loadTexture(textureName: String): TextureAtlasSprite {
|
||||
return Minecraft.getInstance().getTextureAtlas(BLOCK_ATLAS).apply(ResourceLocation("cobblemon", textureName))
|
||||
}
|
||||
}
|
||||
|
||||
override fun render(
|
||||
blockEntity: LureCakeBlockEntity,
|
||||
tickDelta: Float,
|
||||
@@ -60,190 +25,6 @@ class LureCakeBlockEntityRenderer(ctx: BlockEntityRendererProvider.Context) : Bl
|
||||
light: Int,
|
||||
overlay: Int
|
||||
) {
|
||||
val blockState: BlockState = blockEntity.blockState
|
||||
if (blockState.isAir) {
|
||||
return
|
||||
}
|
||||
|
||||
val bites = blockState.getValue(BITES).toFloat()
|
||||
val maxBites = 7f
|
||||
val cakeIsFull = bites == 0f
|
||||
val percentageToRender = if (cakeIsFull) 1.0f else PIXEL_SHIFT.toFloat() + (PIXEL_SHIFT.toFloat() * 2f * (maxBites - bites).toFloat())
|
||||
val clippedWidth = (ATLAS_END - ATLAS_START) * percentageToRender
|
||||
val uClipped = TOP_LAYER.u0 + (TOP_LAYER.u1 - TOP_LAYER.u0) * percentageToRender
|
||||
|
||||
val vertexConsumer = multiBufferSource.getBuffer(RenderType.cutout())
|
||||
val cookingComponent = blockEntity.cookingComponent
|
||||
val primaryColor = cookingComponent?.seasoning1?.color?.let { getColor(it) } ?: WHITE_OPAQUE_COLOR
|
||||
val secondaryColor = cookingComponent?.seasoning2?.color?.let { getColor(it) } ?: WHITE_OPAQUE_COLOR
|
||||
val tertiaryColor = cookingComponent?.seasoning3?.color?.let { getColor(it) } ?: WHITE_OPAQUE_COLOR
|
||||
|
||||
poseStack.pushPose()
|
||||
poseStack.translate(0.5, 0.5, 0.5)
|
||||
poseStack.mulPose(Axis.YP.rotationDegrees(180f))
|
||||
poseStack.translate(-0.5, -0.5, -0.5)
|
||||
|
||||
poseStack.pushPose()
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, TOP_LAYER_HEIGHT, ATLAS_START, clippedWidth, TOP_LAYER_HEIGHT, ATLAS_END,
|
||||
TOP_LAYER.u0, TOP_LAYER.v0, uClipped, TOP_LAYER.v1,
|
||||
light, secondaryColor
|
||||
)
|
||||
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, TOP_LAYER_HEIGHT, ATLAS_START, clippedWidth, TOP_LAYER_HEIGHT, ATLAS_END,
|
||||
CHERRY_LAYER.u0, CHERRY_LAYER.v0, uClipped, CHERRY_LAYER.v1,
|
||||
light, primaryColor
|
||||
)
|
||||
poseStack.popPose()
|
||||
|
||||
val translations = arrayOf(
|
||||
Vector3d(-1.0, 1.0, 0.5 - PIXEL_SHIFT),
|
||||
Vector3d(0.0, 1.0, 0.5 - PIXEL_SHIFT),
|
||||
Vector3d(0.0, 1.0, -0.5 - PIXEL_SHIFT),
|
||||
Vector3d(-1.0, 1.0, -0.5 - PIXEL_SHIFT),
|
||||
)
|
||||
|
||||
val rotationsY = arrayOf(
|
||||
Axis.YP.rotationDegrees(90f),
|
||||
Axis.YP.rotationDegrees(0f),
|
||||
Axis.YP.rotationDegrees(-90f),
|
||||
Axis.YP.rotationDegrees(-180f)
|
||||
)
|
||||
|
||||
for (i in translations.indices) {
|
||||
poseStack.pushPose()
|
||||
poseStack.mulPose(rotationsY[i])
|
||||
poseStack.translate(translations[i].x, translations[i].y, translations[i].z)
|
||||
poseStack.mulPose(Axis.XP.rotationDegrees(90f))
|
||||
|
||||
if (i == 0 && !cakeIsFull) {
|
||||
poseStack.translate(0.0, -bites * PIXEL_SHIFT * 2, 0.0)
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, HEIGHT, ATLAS_START, ATLAS_END, HEIGHT, ATLAS_END,
|
||||
FIRST_INNER_LAYER.u0, FIRST_INNER_LAYER.v0, FIRST_INNER_LAYER.u1, FIRST_INNER_LAYER.v1,
|
||||
light, tertiaryColor
|
||||
)
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, HEIGHT, ATLAS_START, ATLAS_END, HEIGHT, ATLAS_END,
|
||||
SECOND_INNER_LAYER.u0, SECOND_INNER_LAYER.v0, SECOND_INNER_LAYER.u1, SECOND_INNER_LAYER.v1,
|
||||
light, secondaryColor
|
||||
)
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, HEIGHT, ATLAS_START, ATLAS_END, HEIGHT, ATLAS_END,
|
||||
THIRD_INNER_LAYER.u0, THIRD_INNER_LAYER.v0, THIRD_INNER_LAYER.u1, THIRD_INNER_LAYER.v1,
|
||||
light, primaryColor
|
||||
)
|
||||
} else if (i == 0 || i == 1) {
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, HEIGHT, ATLAS_START, clippedWidth, HEIGHT, ATLAS_END,
|
||||
SIDE_LAYER_BOTTOM.u0, SIDE_LAYER_BOTTOM.v0, uClipped, SIDE_LAYER_BOTTOM.v1,
|
||||
light, tertiaryColor
|
||||
)
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, HEIGHT, ATLAS_START, clippedWidth, HEIGHT, ATLAS_END,
|
||||
SIDE_LAYER_TOP.u0, SIDE_LAYER_TOP.v0, uClipped, SIDE_LAYER_TOP.v1,
|
||||
light, secondaryColor
|
||||
)
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, HEIGHT, ATLAS_START, clippedWidth, HEIGHT, ATLAS_END,
|
||||
SIDE_LAYER_MIDDLE.u0, SIDE_LAYER_MIDDLE.v0, uClipped, SIDE_LAYER_MIDDLE.v1,
|
||||
light, primaryColor
|
||||
)
|
||||
} else if (i == 2) {
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, HEIGHT, ATLAS_START, ATLAS_END, HEIGHT, ATLAS_END,
|
||||
SIDE_LAYER_BOTTOM.u0, SIDE_LAYER_BOTTOM.v0, SIDE_LAYER_BOTTOM.u1, SIDE_LAYER_BOTTOM.v1,
|
||||
light, tertiaryColor
|
||||
)
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, HEIGHT, ATLAS_START, ATLAS_END, HEIGHT, ATLAS_END,
|
||||
SIDE_LAYER_TOP.u0, SIDE_LAYER_TOP.v0, SIDE_LAYER_TOP.u1, SIDE_LAYER_TOP.v1,
|
||||
light, secondaryColor
|
||||
)
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, HEIGHT, ATLAS_START, ATLAS_END, HEIGHT, ATLAS_END,
|
||||
SIDE_LAYER_TOP.u0, SIDE_LAYER_MIDDLE.v0, SIDE_LAYER_MIDDLE.u1, SIDE_LAYER_MIDDLE.v1,
|
||||
light, primaryColor
|
||||
)
|
||||
} else if (i == 3) {
|
||||
val clippedStartX = ATLAS_START + (ATLAS_END - ATLAS_START) * (1 - percentageToRender)
|
||||
val clippedUStart = SIDE_LAYER_BOTTOM.u0 + (SIDE_LAYER_BOTTOM.u1 - SIDE_LAYER_BOTTOM.u0) * (1 - percentageToRender)
|
||||
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
clippedStartX, HEIGHT, ATLAS_START, ATLAS_END, HEIGHT, ATLAS_END,
|
||||
clippedUStart, SIDE_LAYER_BOTTOM.v0, SIDE_LAYER_BOTTOM.u1, SIDE_LAYER_BOTTOM.v1,
|
||||
light, tertiaryColor
|
||||
)
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
clippedStartX, HEIGHT, ATLAS_START, ATLAS_END, HEIGHT, ATLAS_END,
|
||||
clippedUStart, SIDE_LAYER_TOP.v0, SIDE_LAYER_TOP.u1, SIDE_LAYER_TOP.v1,
|
||||
light, secondaryColor
|
||||
)
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
clippedStartX, HEIGHT, ATLAS_START, ATLAS_END, HEIGHT, ATLAS_END,
|
||||
clippedUStart, SIDE_LAYER_MIDDLE.v0, SIDE_LAYER_MIDDLE.u1, SIDE_LAYER_MIDDLE.v1,
|
||||
light, primaryColor
|
||||
)
|
||||
}
|
||||
|
||||
poseStack.popPose()
|
||||
}
|
||||
|
||||
poseStack.pushPose()
|
||||
poseStack.translate(0.5, 0.0, 0.5)
|
||||
poseStack.mulPose(Axis.XP.rotationDegrees(180f))
|
||||
poseStack.translate(-0.5, 0.0, -0.5)
|
||||
drawQuad(
|
||||
vertexConsumer, poseStack,
|
||||
ATLAS_START, BOTTOM_LAYER_HEIGHT, ATLAS_START, clippedWidth, BOTTOM_LAYER_HEIGHT, ATLAS_END,
|
||||
BOTTOM_LAYER.u0, BOTTOM_LAYER.v0, uClipped, BOTTOM_LAYER.v1,
|
||||
light, tertiaryColor
|
||||
)
|
||||
poseStack.popPose()
|
||||
|
||||
poseStack.popPose()
|
||||
}
|
||||
|
||||
private fun drawQuad(
|
||||
builder: VertexConsumer,
|
||||
poseStack: PoseStack,
|
||||
x0: Float, y0: Float, z0: Float,
|
||||
x1: Float, y1: Float, z1: Float,
|
||||
u0: Float, v0: Float, u1: Float, v1: Float,
|
||||
packedLight: Int, color: Int,
|
||||
) {
|
||||
drawVertex(builder, poseStack, x0, y0, z0, u0, v0, packedLight, color)
|
||||
drawVertex(builder, poseStack, x0, y1, z1, u0, v1, packedLight, color)
|
||||
drawVertex(builder, poseStack, x1, y1, z1, u1, v1, packedLight, color)
|
||||
drawVertex(builder, poseStack, x1, y0, z0, u1, v0, packedLight, color)
|
||||
}
|
||||
|
||||
private fun drawVertex(
|
||||
builder: VertexConsumer,
|
||||
poseStack: PoseStack,
|
||||
x: Float, y: Float, z: Float,
|
||||
u: Float, v: Float,
|
||||
packedLight: Int, color: Int
|
||||
) {
|
||||
builder.addVertex(poseStack.last().pose(), x, y, z)
|
||||
.setColor(color)
|
||||
.setUv(u, v)
|
||||
.setLight(packedLight)
|
||||
.setNormal(0f, 1f, 0f)
|
||||
renderCake(blockEntity.cookingComponent, poseStack, multiBufferSource, light, blockEntity.blockState.getValue(BITES))
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.cobblemon.mod.common.client.render.block
|
||||
|
||||
import com.cobblemon.mod.common.block.entity.PokeCakeBlockEntity
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
|
||||
|
||||
class PokeCakeBlockEntityRenderer(ctx: BlockEntityRendererProvider.Context) : BlockEntityRenderer<PokeCakeBlockEntity> {
|
||||
|
||||
override fun render(
|
||||
blockEntity: PokeCakeBlockEntity,
|
||||
partialTick: Float,
|
||||
poseStack: PoseStack,
|
||||
bufferSource: MultiBufferSource,
|
||||
packedLight: Int,
|
||||
packedOverlay: Int
|
||||
) {
|
||||
val cookingComponent = blockEntity.cookingComponent
|
||||
renderCake(cookingComponent, poseStack, bufferSource, packedLight, blockEntity.bites)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "builtin/entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"type": "cobblemon:cooking_pot_shapeless",
|
||||
"category": "foods",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "minecraft:cake"
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"id": "cobblemon:poke_cake"
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user