mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-21 06:36:25 -04:00
Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
415042815d | ||
|
|
d6e0f332f2 | ||
|
|
c77963dec0 | ||
|
|
515986e7bd | ||
|
|
245f569c8a | ||
|
|
b7d8d85b1c | ||
|
|
66ffb21bbd |
@@ -10,13 +10,18 @@ package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.ModAPI;
|
||||
import com.cobblemon.mod.common.client.render.modification.ModificationVariantModels;
|
||||
import com.cobblemon.mod.common.item.PokeBallItem;
|
||||
import com.cobblemon.mod.common.item.PokedexItem;
|
||||
import com.cobblemon.mod.common.item.WearableItem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.ItemModelShaper;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.Sheets;
|
||||
import net.minecraft.client.renderer.entity.ItemRenderer;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
@@ -48,12 +53,19 @@ public abstract class ItemRendererMixin {
|
||||
|
||||
@Shadow public abstract void render(ItemStack stack, ItemDisplayContext renderMode, boolean leftHanded, PoseStack matrices, MultiBufferSource vertexConsumers, int light, int overlay, BakedModel model);
|
||||
|
||||
@Shadow protected abstract void renderModelLists(BakedModel model, ItemStack stack, int light, int overlay, PoseStack matrices, VertexConsumer consumer);
|
||||
|
||||
@Inject(
|
||||
method = "render(Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemDisplayContext;ZLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;IILnet/minecraft/client/resources/model/BakedModel;)V",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true
|
||||
)
|
||||
private void cobblemon$overrideItemModel(ItemStack stack, ItemDisplayContext renderMode, boolean leftHanded, PoseStack matrices, MultiBufferSource multiBufferSource, int light, int overlay, BakedModel model, CallbackInfo ci) {
|
||||
if (!model.isCustomRenderer() && ModificationVariantModels.isTranslucentVariant(stack)) {
|
||||
cobblemon$renderTranslucentVariant(stack, renderMode, leftHanded, matrices, multiBufferSource, light, overlay, model);
|
||||
ci.cancel();
|
||||
return;
|
||||
}
|
||||
boolean shouldBe2d = renderMode == ItemDisplayContext.GUI || renderMode == ItemDisplayContext.FIXED;
|
||||
ResourceLocation resourceLocation = null;
|
||||
if (shouldBe2d) {
|
||||
@@ -73,6 +85,11 @@ public abstract class ItemRendererMixin {
|
||||
|
||||
@Inject(method = "getModel", at = @At("HEAD"), cancellable = true)
|
||||
private void cobblemon$getItemModel(ItemStack stack, Level world, LivingEntity entity, int seed, CallbackInfoReturnable<BakedModel> cir) {
|
||||
BakedModel variantModel = ModificationVariantModels.itemModel(stack);
|
||||
if (variantModel != null) {
|
||||
cir.setReturnValue(variantModel);
|
||||
return;
|
||||
}
|
||||
ResourceLocation resourceLocation = null;
|
||||
if (stack.getItem() instanceof PokeBallItem pokeBallItem) resourceLocation = pokeBallItem.getPokeBall().getModel3d();
|
||||
else if (stack.getItem() instanceof PokedexItem pokedexItem) {
|
||||
@@ -90,6 +107,20 @@ public abstract class ItemRendererMixin {
|
||||
}
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void cobblemon$renderTranslucentVariant(ItemStack stack, ItemDisplayContext renderMode, boolean leftHanded, PoseStack matrices, MultiBufferSource multiBufferSource, int light, int overlay, BakedModel model) {
|
||||
boolean isDirect = renderMode == ItemDisplayContext.GUI || renderMode.firstPerson();
|
||||
RenderType renderType = isDirect && Minecraft.useShaderTransparency() ? Sheets.translucentItemSheet() : Sheets.translucentCullBlockSheet();
|
||||
VertexConsumer consumer = isDirect
|
||||
? ItemRenderer.getFoilBufferDirect(multiBufferSource, renderType, true, stack.hasFoil())
|
||||
: ItemRenderer.getFoilBuffer(multiBufferSource, renderType, true, stack.hasFoil());
|
||||
matrices.pushPose();
|
||||
model.getTransforms().getTransform(renderMode).apply(leftHanded, matrices);
|
||||
matrices.translate(-0.5F, -0.5F, -0.5F);
|
||||
this.renderModelLists(model, stack, light, overlay, matrices, consumer);
|
||||
matrices.popPose();
|
||||
}
|
||||
|
||||
// this method aims to cover an issue with modernfixes and it's "dynamic resource" causing the usual .equals check to always fail, resulting in a StackOverflow
|
||||
// this falls back to comparing the model contents (e.g. location of the texture, width and height)
|
||||
@Unique
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.client.CobblemonBakingOverrides;
|
||||
import com.cobblemon.mod.common.client.render.modification.ModificationVariantModels;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import net.minecraft.client.color.block.BlockColors;
|
||||
@@ -45,5 +47,16 @@ public abstract class ModelLoaderMixin {
|
||||
var unbakedModel = this.getModel(bakingOverride.getModelLocation());
|
||||
this.registerModel(bakingOverride.getModelIdentifier(), unbakedModel);
|
||||
});
|
||||
ModificationVariantModels.clearCache();
|
||||
List<ResourceLocation> variantModelLocations = jsonUnbakedModels.keySet().stream()
|
||||
.map(ModelBakery.MODEL_LISTER::fileToId)
|
||||
.filter(ModificationVariantModels::isVariantModel)
|
||||
.toList();
|
||||
variantModelLocations.forEach(modelLocation -> {
|
||||
UnbakedModel unbakedModel = this.getModel(modelLocation);
|
||||
unbakedModel.resolveParents(this::getModel);
|
||||
this.registerModel(ModificationVariantModels.bakedIdentifier(modelLocation), unbakedModel);
|
||||
});
|
||||
Cobblemon.LOGGER.info("Registered {} modification variant models", variantModelLocations.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,12 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
|
||||
@JvmField
|
||||
val PC: BlockEntityType<PCBlockEntity> = this.create("pc", BlockEntityType.Builder.of(::PCBlockEntity, CobblemonBlocks.PC).build(null))
|
||||
|
||||
@JvmField
|
||||
val MOD_VARIANT: BlockEntityType<ModVariantBlockEntity> = this.create(
|
||||
"mod_variant",
|
||||
BlockEntityType.Builder.of(::ModVariantBlockEntity, CobblemonBlocks.MOD_VARIANT).build(null)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val LECTERN: BlockEntityType<LecternBlockEntity> = this.create("lectern", BlockEntityType.Builder.of(::LecternBlockEntity, CobblemonBlocks.LECTERN).build(null))
|
||||
|
||||
|
||||
@@ -22,6 +22,9 @@ import com.cobblemon.mod.common.block.sign.CobblemonHangingSignBlock
|
||||
import com.cobblemon.mod.common.block.sign.CobblemonSignBlock
|
||||
import com.cobblemon.mod.common.block.sign.CobblemonWallHangingSignBlock
|
||||
import com.cobblemon.mod.common.block.sign.CobblemonWallSignBlock
|
||||
import com.cobblemon.mod.common.block.modification.ModVariantBlock
|
||||
import com.cobblemon.mod.common.block.modification.ModFillerBlock
|
||||
import com.cobblemon.mod.common.block.modification.ModificationVariantBlock
|
||||
import com.cobblemon.mod.common.block.tmmachine.TMMachineBlock
|
||||
import com.cobblemon.mod.common.block.general.HorizontalRotationCarpetBlock
|
||||
import com.cobblemon.mod.common.block.general.HorizontalRotationalBlock
|
||||
@@ -664,7 +667,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
val HEALING_MACHINE = create("healing_machine", HealingMachineBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F).noOcclusion().lightLevel { if (it.getValue(HealingMachineBlock.CHARGE_LEVEL) >= HealingMachineBlock.MAX_CHARGE_LEVEL) 12 else 5 }))
|
||||
|
||||
@JvmField
|
||||
val PC = create("pc", PCBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F).noOcclusion().lightLevel { if ((it.getValue(PCBlock.ON) as Boolean) && (it.getValue(PCBlock.PART) == PCBlock.PCPart.TOP)) 13 else 0 }))
|
||||
val PC = create("pc", PCBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F).noOcclusion().dynamicShape().lightLevel { if (it.getValue(PCBlock.ON) && (it.getValue(PCBlock.PART) == PCBlock.PCPart.TOP || it.getValue(ModificationVariantBlock.MODIFIED))) 13 else 0 }))
|
||||
|
||||
val TM_MACHINE = create(
|
||||
"tm_machine",
|
||||
@@ -678,6 +681,47 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val MODIFICATION_STATION = create(
|
||||
"modification_station",
|
||||
ModificationStationBlock(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.STONE)
|
||||
.sound(SoundType.STONE)
|
||||
.strength(3.5F)
|
||||
.noOcclusion()
|
||||
.requiresCorrectToolForDrops()
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val MOD_FILLER = create(
|
||||
"mod_filler",
|
||||
ModFillerBlock(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.NONE)
|
||||
.pushReaction(PushReaction.BLOCK)
|
||||
.strength(2F)
|
||||
.noOcclusion()
|
||||
.dynamicShape()
|
||||
.noLootTable()
|
||||
.lightLevel { if (it.getValue(BlockStateProperties.LIT)) 13 else 0 }
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val MOD_VARIANT = create(
|
||||
"mod_variant",
|
||||
ModVariantBlock(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.STONE)
|
||||
.sound(SoundType.STONE)
|
||||
.pushReaction(PushReaction.BLOCK)
|
||||
.strength(0.8F)
|
||||
.noOcclusion()
|
||||
.dynamicShape()
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val LECTERN = create("lectern", LecternBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).sound(SoundType.WOOD).strength(2.5F).ignitedByLava().lightLevel { if (it.getValue(LecternBlock.EMIT_LIGHT) as Boolean) 13 else 0 }))
|
||||
@@ -686,7 +730,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
val TM_SHELF = create("tm_shelf", TMShelfBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).sound(SoundType.METAL).strength(2.5F)))
|
||||
|
||||
@JvmField
|
||||
val DISPLAY_CASE = create("display_case", DisplayCaseBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.DISPLAY_CASE_SOUNDS).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.STONE).strength(0.3F).requiresCorrectToolForDrops()))
|
||||
val DISPLAY_CASE = create("display_case", DisplayCaseBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.DISPLAY_CASE_SOUNDS).noOcclusion().dynamicShape().pushReaction(PushReaction.BLOCK).mapColor(MapColor.STONE).strength(0.3F).requiresCorrectToolForDrops()))
|
||||
|
||||
// TODO after 1.7
|
||||
// @JvmField
|
||||
|
||||
@@ -99,6 +99,12 @@ object CobblemonItemComponents : PlatformRegistry<Registry<DataComponentType<*>>
|
||||
.networkSynchronized(ByteBufCodecs.BOOL)
|
||||
.build())
|
||||
|
||||
@JvmField
|
||||
val MODIFICATION_VARIANT: DataComponentType<ModificationVariantComponent> = create("modification_variant", DataComponentType.builder<ModificationVariantComponent>()
|
||||
.persistent(ModificationVariantComponent.CODEC)
|
||||
.networkSynchronized(ModificationVariantComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
fun register() {
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:pokemon_item"), POKEMON_ITEM)
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:bait"), BAIT)
|
||||
@@ -112,6 +118,7 @@ object CobblemonItemComponents : PlatformRegistry<Registry<DataComponentType<*>>
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:food"), FOOD)
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:mob_effects"), MOB_EFFECTS)
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:held_item_effect"), HELD_ITEM_EFFECT)
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:modification_variant"), MODIFICATION_VARIANT)
|
||||
}
|
||||
|
||||
override val registry = BuiltInRegistries.DATA_COMPONENT_TYPE
|
||||
|
||||
@@ -459,6 +459,10 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val TM_MACHINE = blockItem("tm_machine", CobblemonBlocks.TM_MACHINE)
|
||||
@JvmField
|
||||
val MODIFICATION_STATION = blockItem("modification_station", CobblemonBlocks.MODIFICATION_STATION)
|
||||
@JvmField
|
||||
val MOD_VARIANT = blockItem("mod_variant", CobblemonBlocks.MOD_VARIANT)
|
||||
@JvmField
|
||||
val TM_SHELF = blockItem("tm_shelf", CobblemonBlocks.TM_SHELF)
|
||||
@JvmField
|
||||
val PASTURE = blockItem("pasture", CobblemonBlocks.PASTURE)
|
||||
|
||||
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common
|
||||
|
||||
|
||||
import com.cobblemon.mod.common.block.campfirepot.CookingPotMenu
|
||||
import com.cobblemon.mod.common.block.modificationstation.ModificationStationMenu
|
||||
import com.cobblemon.mod.common.block.tmmachine.TMMachineMenu
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import net.minecraft.core.Registry
|
||||
@@ -22,6 +23,7 @@ object CobblemonMenuType : PlatformRegistry<Registry<MenuType<*>>, ResourceKey<R
|
||||
|
||||
val COOKING_POT = MenuType.register("cooking_pot_menu", ::CookingPotMenu)
|
||||
val TM_MACHINE = MenuType.register("tm_machine_menu", ::TMMachineMenu)
|
||||
val MODIFICATION_STATION = MenuType.register("modification_station_menu", ::ModificationStationMenu)
|
||||
|
||||
override val registry: Registry<MenuType<*>>
|
||||
get() = BuiltInRegistries.MENU
|
||||
|
||||
@@ -416,6 +416,7 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(DexEntrySyncPacket.ID, DexEntrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(SpawnBaitRegistrySyncPacket.ID, SpawnBaitRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(SeasoningRegistrySyncPacket.ID, SeasoningRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(ModificationVariantRegistrySyncPacket.ID, ModificationVariantRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(CallbackRegistrySyncPacket.ID, CallbackRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(CosmeticItemAssignmentSyncPacket.ID, CosmeticItemAssignmentSyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(BehaviourSyncPacket.ID, BehaviourSyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
@@ -626,4 +627,4 @@ object CobblemonNetwork {
|
||||
fun sendPacketToPlayer(player: ServerPlayer, packet: NetworkPacket<*>) {
|
||||
Cobblemon.implementation.networkManager.sendPacketToPlayer(player, packet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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.modification
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.item.components.ModificationVariantComponent
|
||||
import com.cobblemon.mod.common.util.rotateShape
|
||||
import java.util.EnumMap
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.core.Vec3i
|
||||
import net.minecraft.core.component.DataComponents
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.phys.AABB
|
||||
import net.minecraft.world.phys.shapes.BooleanOp
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
|
||||
class ModificationVariant(
|
||||
val identifier: ResourceLocation,
|
||||
val parent: ResourceLocation,
|
||||
val block: ResourceLocation,
|
||||
val model: ResourceLocation,
|
||||
val blockstateModels: List<ModificationVariantBlockstateModel>,
|
||||
val cells: List<Vec3i>,
|
||||
val hitbox: List<AABB>,
|
||||
val order: Int,
|
||||
val isTranslucent: Boolean
|
||||
) {
|
||||
private val hitboxesByFacing = EnumMap<Direction, VoxelShape>(Direction::class.java)
|
||||
private val cellHitboxes = hashMapOf<Pair<Direction, Vec3i>, VoxelShape>()
|
||||
|
||||
fun targetBlock(): Block? = BuiltInRegistries.BLOCK.getOptional(block).orElse(null)
|
||||
|
||||
fun parentItem(): Item? = BuiltInRegistries.ITEM.getOptional(parent).orElse(null)
|
||||
|
||||
fun displayName(): MutableComponent = Component.translatable("modification_variant.${identifier.namespace}.${identifier.path}")
|
||||
|
||||
fun modelFor(state: BlockState): ResourceLocation = blockstateModels.firstOrNull { it.matches(state) }?.model ?: model
|
||||
|
||||
fun allModels(): List<ResourceLocation> = listOf(model) + blockstateModels.map { it.model }
|
||||
|
||||
fun createStack(): ItemStack {
|
||||
val item = targetBlock()?.asItem() ?: return ItemStack.EMPTY
|
||||
if (item == Items.AIR) {
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
return ItemStack(item).apply {
|
||||
set(CobblemonItemComponents.MODIFICATION_VARIANT, ModificationVariantComponent(identifier))
|
||||
set(DataComponents.ITEM_NAME, displayName())
|
||||
}
|
||||
}
|
||||
|
||||
fun rotatedCells(facing: Direction): List<Vec3i> = cells.map { rotateCell(it, facing) }
|
||||
|
||||
fun fillerCells(facing: Direction): List<Vec3i> = rotatedCells(facing).filter { it != Vec3i.ZERO }
|
||||
|
||||
fun cellsMin(): Vec3i = Vec3i(cells.minOf { it.x }, cells.minOf { it.y }, cells.minOf { it.z })
|
||||
|
||||
fun cellsMax(): Vec3i = Vec3i(cells.maxOf { it.x }, cells.maxOf { it.y }, cells.maxOf { it.z })
|
||||
|
||||
fun hitbox(facing: Direction): VoxelShape = hitboxesByFacing.getOrPut(facing) { rotateShape(Direction.SOUTH, facing, unrotatedHitbox()) }
|
||||
|
||||
fun cellHitbox(facing: Direction, cell: Vec3i): VoxelShape = cellHitboxes.getOrPut(facing to cell) {
|
||||
val shifted = hitbox(facing).move(-cell.x.toDouble(), -cell.y.toDouble(), -cell.z.toDouble())
|
||||
Shapes.join(shifted, Shapes.block(), BooleanOp.AND)
|
||||
}
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(identifier)
|
||||
buffer.writeResourceLocation(parent)
|
||||
buffer.writeResourceLocation(block)
|
||||
buffer.writeResourceLocation(model)
|
||||
buffer.writeCollection(blockstateModels) { buf, blockstateModel -> blockstateModel.encode(buf) }
|
||||
buffer.writeCollection(cells) { buf, cell ->
|
||||
buf.writeVarInt(cell.x)
|
||||
buf.writeVarInt(cell.y)
|
||||
buf.writeVarInt(cell.z)
|
||||
}
|
||||
buffer.writeCollection(hitbox) { buf, box ->
|
||||
buf.writeDouble(box.minX)
|
||||
buf.writeDouble(box.minY)
|
||||
buf.writeDouble(box.minZ)
|
||||
buf.writeDouble(box.maxX)
|
||||
buf.writeDouble(box.maxY)
|
||||
buf.writeDouble(box.maxZ)
|
||||
}
|
||||
buffer.writeVarInt(order)
|
||||
buffer.writeBoolean(isTranslucent)
|
||||
}
|
||||
|
||||
private fun unrotatedHitbox(): VoxelShape {
|
||||
val boxes = hitbox.ifEmpty { cells.map(::cellBox) }
|
||||
return boxes.fold(Shapes.empty()) { combined, box ->
|
||||
Shapes.or(combined, Shapes.box(box.minX / 16.0, box.minY / 16.0, box.minZ / 16.0, box.maxX / 16.0, box.maxY / 16.0, box.maxZ / 16.0))
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val MAX_HEIGHT = 5
|
||||
const val MAX_DEPTH = 3
|
||||
const val MAX_HITBOX_BOXES = 64
|
||||
val MIN_CELL_OFFSET = Vec3i(-2, 0, -2)
|
||||
val MAX_CELL_OFFSET = Vec3i(2, 4, 2)
|
||||
|
||||
fun rotateCell(cell: Vec3i, facing: Direction): Vec3i {
|
||||
var rotated = cell
|
||||
repeat(facing.get2DDataValue()) {
|
||||
rotated = Vec3i(-rotated.z, rotated.y, rotated.x)
|
||||
}
|
||||
return rotated
|
||||
}
|
||||
|
||||
fun cellBox(cell: Vec3i): AABB = AABB(
|
||||
cell.x * 16.0,
|
||||
cell.y * 16.0,
|
||||
cell.z * 16.0,
|
||||
(cell.x + 1) * 16.0,
|
||||
(cell.y + 1) * 16.0,
|
||||
(cell.z + 1) * 16.0
|
||||
)
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): ModificationVariant = ModificationVariant(
|
||||
identifier = buffer.readResourceLocation(),
|
||||
parent = buffer.readResourceLocation(),
|
||||
block = buffer.readResourceLocation(),
|
||||
model = buffer.readResourceLocation(),
|
||||
blockstateModels = buffer.readList { buf -> ModificationVariantBlockstateModel.decode(buf) },
|
||||
cells = buffer.readList { buf -> Vec3i(buf.readVarInt(), buf.readVarInt(), buf.readVarInt()) },
|
||||
hitbox = buffer.readList { buf ->
|
||||
AABB(buf.readDouble(), buf.readDouble(), buf.readDouble(), buf.readDouble(), buf.readDouble(), buf.readDouble())
|
||||
},
|
||||
order = buffer.readVarInt(),
|
||||
isTranslucent = buffer.readBoolean()
|
||||
)
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.modification
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.properties.Property
|
||||
|
||||
class ModificationVariantBlockstateModel(val conditions: Map<String, String>, val model: ResourceLocation) {
|
||||
fun matches(state: BlockState): Boolean = conditions.all { (propertyName, expectedValue) ->
|
||||
val property = state.block.stateDefinition.getProperty(propertyName) ?: return@all false
|
||||
propertyValueName(state, property) == expectedValue
|
||||
}
|
||||
|
||||
fun encode(buffer: FriendlyByteBuf) {
|
||||
buffer.writeMap(conditions, { buf, key -> buf.writeUtf(key) }, { buf, value -> buf.writeUtf(value) })
|
||||
buffer.writeResourceLocation(model)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val CONDITION_SEPARATOR = ","
|
||||
private const val VALUE_SEPARATOR = "="
|
||||
|
||||
fun parseConditions(raw: String): Map<String, String>? {
|
||||
val conditions = linkedMapOf<String, String>()
|
||||
raw.split(CONDITION_SEPARATOR).forEach { condition ->
|
||||
val parts = condition.split(VALUE_SEPARATOR)
|
||||
if (parts.size != 2 || parts[0].isBlank() || parts[1].isBlank()) {
|
||||
return null
|
||||
}
|
||||
conditions[parts[0].trim()] = parts[1].trim()
|
||||
}
|
||||
return conditions
|
||||
}
|
||||
|
||||
fun decode(buffer: FriendlyByteBuf): ModificationVariantBlockstateModel {
|
||||
val conditions = buffer.readMap({ buf -> buf.readUtf() }, { buf -> buf.readUtf() })
|
||||
return ModificationVariantBlockstateModel(conditions, buffer.readResourceLocation())
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun propertyValueName(state: BlockState, property: Property<*>): String {
|
||||
return valueName(state, property as Property<Comparable<Any>>)
|
||||
}
|
||||
|
||||
private fun <T : Comparable<T>> valueName(state: BlockState, property: Property<T>): String = property.getName(state.getValue(property))
|
||||
}
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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.modification
|
||||
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParseException
|
||||
import net.minecraft.core.Vec3i
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.GsonHelper
|
||||
import net.minecraft.world.phys.AABB
|
||||
|
||||
object ModificationVariantParser {
|
||||
private const val MIN_HITBOX_HORIZONTAL_PIXEL = -32.0
|
||||
private const val MAX_HITBOX_HORIZONTAL_PIXEL = 48.0
|
||||
private const val MIN_HITBOX_VERTICAL_PIXEL = 0.0
|
||||
private const val MAX_HITBOX_VERTICAL_PIXEL = 80.0
|
||||
|
||||
fun parse(identifier: ResourceLocation, json: JsonObject): ModificationVariant {
|
||||
val parent = parseResourceLocation(json, "parent")
|
||||
val block = if (json.has("block")) parseResourceLocation(json, "block") else parent
|
||||
return ModificationVariant(
|
||||
identifier = identifier,
|
||||
parent = parent,
|
||||
block = block,
|
||||
model = parseResourceLocation(json, "model"),
|
||||
blockstateModels = parseBlockstateModels(json),
|
||||
cells = parseSize(json),
|
||||
hitbox = parseHitbox(json),
|
||||
order = GsonHelper.getAsInt(json, "order", 0),
|
||||
isTranslucent = GsonHelper.getAsBoolean(json, "translucent", false)
|
||||
)
|
||||
}
|
||||
|
||||
private fun parseResourceLocation(json: JsonObject, key: String): ResourceLocation {
|
||||
val raw = GsonHelper.getAsString(json, key)
|
||||
return ResourceLocation.tryParse(raw) ?: throw JsonParseException("Invalid resource location '$raw' for '$key'")
|
||||
}
|
||||
|
||||
private fun parseBlockstateModels(json: JsonObject): List<ModificationVariantBlockstateModel> {
|
||||
if (!json.has("blockstates")) {
|
||||
return emptyList()
|
||||
}
|
||||
return GsonHelper.getAsJsonObject(json, "blockstates").entrySet().map { (rawConditions, element) ->
|
||||
val conditions = ModificationVariantBlockstateModel.parseConditions(rawConditions)
|
||||
?: throw JsonParseException("Blockstate condition '$rawConditions' must look like 'property=value' with commas between properties")
|
||||
val raw = GsonHelper.convertToString(element, "blockstate model")
|
||||
val model = ResourceLocation.tryParse(raw) ?: throw JsonParseException("Invalid resource location '$raw' for blockstate '$rawConditions'")
|
||||
ModificationVariantBlockstateModel(conditions, model)
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseSize(json: JsonObject): List<Vec3i> {
|
||||
if (!json.has("size")) {
|
||||
return listOf(Vec3i.ZERO)
|
||||
}
|
||||
val size = GsonHelper.getAsJsonObject(json, "size")
|
||||
val height = GsonHelper.getAsInt(size, "height", 1)
|
||||
val depth = GsonHelper.getAsInt(size, "depth", 1)
|
||||
if (height !in 1..ModificationVariant.MAX_HEIGHT) {
|
||||
throw JsonParseException("Size height must be between 1 and ${ModificationVariant.MAX_HEIGHT}, found $height")
|
||||
}
|
||||
if (depth !in 1..ModificationVariant.MAX_DEPTH) {
|
||||
throw JsonParseException("Size depth must be between 1 and ${ModificationVariant.MAX_DEPTH}, found $depth")
|
||||
}
|
||||
return (0 until depth).flatMap { z -> (0 until height).map { y -> Vec3i(0, y, z) } }
|
||||
}
|
||||
|
||||
private fun parseHitbox(json: JsonObject): List<AABB> {
|
||||
if (!json.has("hitbox")) {
|
||||
return emptyList()
|
||||
}
|
||||
val boxes = GsonHelper.getAsJsonArray(json, "hitbox").map { element ->
|
||||
parseBox(GsonHelper.convertToJsonArray(element, "hitbox box"))
|
||||
}
|
||||
if (boxes.size > ModificationVariant.MAX_HITBOX_BOXES) {
|
||||
throw JsonParseException("Hitbox has ${boxes.size} boxes, the limit is ${ModificationVariant.MAX_HITBOX_BOXES}")
|
||||
}
|
||||
return boxes
|
||||
}
|
||||
|
||||
private fun parseBox(coordinates: JsonArray): AABB {
|
||||
if (coordinates.size() != 6) {
|
||||
throw JsonParseException("Hitbox boxes need exactly 6 coordinates, found ${coordinates.size()}")
|
||||
}
|
||||
val values = coordinates.map { it.asDouble }
|
||||
if (values.any { !it.isFinite() }) {
|
||||
throw JsonParseException("Hitbox box $values contains a non finite coordinate")
|
||||
}
|
||||
val box = AABB(values[0], values[1], values[2], values[3], values[4], values[5])
|
||||
if (box.minX >= box.maxX || box.minY >= box.maxY || box.minZ >= box.maxZ) {
|
||||
throw JsonParseException("Hitbox box $values has a minimum that is not below its maximum")
|
||||
}
|
||||
val isHorizontalInRange = listOf(box.minX, box.maxX, box.minZ, box.maxZ).all { it in MIN_HITBOX_HORIZONTAL_PIXEL..MAX_HITBOX_HORIZONTAL_PIXEL }
|
||||
val isVerticalInRange = listOf(box.minY, box.maxY).all { it in MIN_HITBOX_VERTICAL_PIXEL..MAX_HITBOX_VERTICAL_PIXEL }
|
||||
if (!isHorizontalInRange || !isVerticalInRange) {
|
||||
throw JsonParseException("Hitbox box $values is outside the allowed pixel range")
|
||||
}
|
||||
return box
|
||||
}
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.modification
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.block.modification.ModificationVariantBlock
|
||||
import com.cobblemon.mod.common.net.messages.client.data.ModificationVariantRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.endsWith
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.JsonParser
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import java.io.File
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.server.packs.resources.ResourceManager
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
object ModificationVariants : JsonDataRegistry<ModificationVariant> {
|
||||
override val id: ResourceLocation = cobblemonResource("modification_variants")
|
||||
override val type: PackType = PackType.SERVER_DATA
|
||||
override val observable = SimpleObservable<ModificationVariants>()
|
||||
override val typeToken: TypeToken<ModificationVariant> = TypeToken.get(ModificationVariant::class.java)
|
||||
override val resourcePath = "modification_variants"
|
||||
override val gson: Gson = GsonBuilder().disableHtmlEscaping().create()
|
||||
|
||||
private val variantsByIdentifier = linkedMapOf<ResourceLocation, ModificationVariant>()
|
||||
private val variantsByParent = hashMapOf<ResourceLocation, List<ModificationVariant>>()
|
||||
private val variantOrder = compareBy<ModificationVariant> { it.identifier.namespace != Cobblemon.MODID }
|
||||
.thenBy { it.identifier.namespace }
|
||||
.thenBy { it.order }
|
||||
.thenBy { it.identifier.toString() }
|
||||
|
||||
override fun reload(manager: ResourceManager) {
|
||||
val parsed = hashMapOf<ResourceLocation, ModificationVariant>()
|
||||
manager.listResources(resourcePath) { path -> path.endsWith(JsonDataRegistry.JSON_EXTENSION) }.forEach { (location, resource) ->
|
||||
val identifier = ResourceLocation.fromNamespaceAndPath(location.namespace, File(location.path).nameWithoutExtension)
|
||||
try {
|
||||
resource.openAsReader().use { reader ->
|
||||
parsed[identifier] = ModificationVariantParser.parse(identifier, JsonParser.parseReader(reader).asJsonObject)
|
||||
}
|
||||
} catch (exception: Exception) {
|
||||
Cobblemon.LOGGER.error("Skipping modification variant {} from {}: {}", identifier, location, exception.message)
|
||||
}
|
||||
}
|
||||
reload(parsed)
|
||||
}
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, ModificationVariant>) {
|
||||
replaceEntries(data.values.filter(::isRegistered))
|
||||
}
|
||||
|
||||
fun replaceEntries(entries: Collection<ModificationVariant>) {
|
||||
variantsByIdentifier.clear()
|
||||
variantsByParent.clear()
|
||||
entries.sortedWith(variantOrder).forEach { variant -> variantsByIdentifier[variant.identifier] = variant }
|
||||
variantsByParent.putAll(variantsByIdentifier.values.groupBy { it.parent })
|
||||
Cobblemon.LOGGER.info("Loaded {} modification variants", variantsByIdentifier.size)
|
||||
observable.emit(this)
|
||||
}
|
||||
|
||||
override fun sync(player: ServerPlayer) {
|
||||
ModificationVariantRegistrySyncPacket(all()).sendToPlayer(player)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun all(): List<ModificationVariant> = variantsByIdentifier.values.toList()
|
||||
|
||||
@JvmStatic
|
||||
fun forParent(parent: ResourceLocation): List<ModificationVariant> = variantsByParent[parent] ?: emptyList()
|
||||
|
||||
@JvmStatic
|
||||
fun getByIdentifier(identifier: ResourceLocation): ModificationVariant? = variantsByIdentifier[identifier]
|
||||
|
||||
@JvmStatic
|
||||
fun fromStack(stack: ItemStack): ModificationVariant? = stack.get(CobblemonItemComponents.MODIFICATION_VARIANT)?.variant?.let(::getByIdentifier)
|
||||
|
||||
@JvmStatic
|
||||
fun parentOf(stack: ItemStack): ResourceLocation = fromStack(stack)?.parent ?: BuiltInRegistries.ITEM.getKey(stack.item)
|
||||
|
||||
@JvmStatic
|
||||
fun hasVariantsFor(stack: ItemStack): Boolean = !stack.isEmpty && forParent(parentOf(stack)).isNotEmpty()
|
||||
|
||||
private fun isRegistered(variant: ModificationVariant): Boolean {
|
||||
val hasParent = BuiltInRegistries.BLOCK.containsKey(variant.parent) || BuiltInRegistries.ITEM.containsKey(variant.parent)
|
||||
if (!hasParent) {
|
||||
Cobblemon.LOGGER.warn("Skipping modification variant {} because parent {} is not a registered block or item", variant.identifier, variant.parent)
|
||||
return false
|
||||
}
|
||||
if (variant.targetBlock() !is ModificationVariantBlock) {
|
||||
Cobblemon.LOGGER.warn("Skipping modification variant {} because block {} cannot hold modification variants", variant.identifier, variant.block)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,10 @@
|
||||
|
||||
package com.cobblemon.mod.common.block
|
||||
|
||||
import com.cobblemon.mod.common.api.modification.ModificationVariant
|
||||
import com.cobblemon.mod.common.block.entity.DisplayCaseBlockEntity
|
||||
import com.cobblemon.mod.common.block.modification.ModificationVariantBlock
|
||||
import com.cobblemon.mod.common.block.modification.ModificationVariantStructures
|
||||
import com.cobblemon.mod.common.item.PokeBallItem
|
||||
import com.mojang.serialization.MapCodec
|
||||
import net.minecraft.core.BlockPos
|
||||
@@ -32,26 +35,28 @@ import net.minecraft.world.level.block.state.StateDefinition
|
||||
import net.minecraft.world.level.block.state.properties.DirectionProperty
|
||||
import net.minecraft.world.level.pathfinder.PathComputationType
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
|
||||
@Suppress("OVERRIDE_DEPRECATION")
|
||||
class DisplayCaseBlock(settings: Properties) : BaseEntityBlock(settings) {
|
||||
class DisplayCaseBlock(settings: Properties) : ModificationVariantBlock(settings) {
|
||||
init {
|
||||
registerDefaultState(stateDefinition.any()
|
||||
registerDefaultState(unmodifiedState()
|
||||
.setValue(FACING, Direction.NORTH)
|
||||
.setValue(ITEM_DIRECTION, Direction.NORTH))
|
||||
}
|
||||
|
||||
override fun getStateForPlacement(ctx: BlockPlaceContext): BlockState? {
|
||||
var blockState = defaultBlockState()
|
||||
val worldView = ctx.level
|
||||
val blockPos = ctx.clickedPos
|
||||
ctx.nearestLookingDirections.forEach { direction ->
|
||||
override fun stockPlacementState(context: BlockPlaceContext, variant: ModificationVariant?): BlockState? {
|
||||
val worldView = context.level
|
||||
val blockPos = context.clickedPos
|
||||
context.nearestLookingDirections.forEach { direction ->
|
||||
if (direction.axis.isHorizontal) {
|
||||
blockState = blockState
|
||||
val blockState = defaultBlockState()
|
||||
.setValue(FACING, direction)
|
||||
.setValue(ITEM_DIRECTION, direction)
|
||||
as BlockState
|
||||
if (blockState.canSurvive(worldView, blockPos)) {
|
||||
val hasRoom = variant == null || ModificationVariantStructures.canPlace(context, variant, direction)
|
||||
if (hasRoom && blockState.canSurvive(worldView, blockPos)) {
|
||||
return blockState
|
||||
}
|
||||
}
|
||||
@@ -59,7 +64,7 @@ class DisplayCaseBlock(settings: Properties) : BaseEntityBlock(settings) {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
override fun addStockProperties(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
builder.add(FACING)
|
||||
builder.add(ITEM_DIRECTION)
|
||||
}
|
||||
@@ -124,6 +129,8 @@ class DisplayCaseBlock(settings: Properties) : BaseEntityBlock(settings) {
|
||||
|
||||
override fun hasAnalogOutputSignal(state: BlockState): Boolean = true
|
||||
|
||||
override fun stockShape(state: BlockState, level: BlockGetter, pos: BlockPos, context: CollisionContext): VoxelShape = Shapes.block()
|
||||
|
||||
override fun codec(): MapCodec<out BaseEntityBlock> {
|
||||
return CODEC
|
||||
}
|
||||
@@ -135,4 +142,4 @@ class DisplayCaseBlock(settings: Properties) : BaseEntityBlock(settings) {
|
||||
val ITEM_DIRECTION = DirectionProperty.create("item_facing")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.block
|
||||
|
||||
import com.cobblemon.mod.common.block.modificationstation.ModificationStationMenu
|
||||
import com.mojang.serialization.MapCodec
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.stats.Stats
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.MenuProvider
|
||||
import net.minecraft.world.SimpleMenuProvider
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.ContainerLevelAccess
|
||||
import net.minecraft.world.item.context.BlockPlaceContext
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock
|
||||
import net.minecraft.world.level.block.Mirror
|
||||
import net.minecraft.world.level.block.RenderShape
|
||||
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.DirectionProperty
|
||||
import net.minecraft.world.level.pathfinder.PathComputationType
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
|
||||
class ModificationStationBlock(properties: Properties) : Block(properties) {
|
||||
override fun codec(): MapCodec<ModificationStationBlock> = CODEC
|
||||
|
||||
init {
|
||||
registerDefaultState(stateDefinition.any().setValue(FACING, Direction.NORTH))
|
||||
}
|
||||
|
||||
override fun getStateForPlacement(context: BlockPlaceContext): BlockState {
|
||||
return defaultBlockState().setValue(FACING, context.horizontalDirection)
|
||||
}
|
||||
|
||||
override fun useWithoutItem(state: BlockState, level: Level, pos: BlockPos, player: Player, hit: BlockHitResult): InteractionResult {
|
||||
if (level.isClientSide) {
|
||||
return InteractionResult.SUCCESS
|
||||
}
|
||||
|
||||
player.openMenu(state.getMenuProvider(level, pos))
|
||||
player.awardStat(Stats.INTERACT_WITH_STONECUTTER)
|
||||
return InteractionResult.CONSUME
|
||||
}
|
||||
|
||||
override fun getMenuProvider(state: BlockState, level: Level, pos: BlockPos): MenuProvider {
|
||||
return SimpleMenuProvider(
|
||||
{ syncId, inventory, _ -> ModificationStationMenu(syncId, inventory, ContainerLevelAccess.create(level, pos)) },
|
||||
CONTAINER_TITLE
|
||||
)
|
||||
}
|
||||
|
||||
override fun getRenderShape(state: BlockState): RenderShape = RenderShape.MODEL
|
||||
|
||||
override fun rotate(state: BlockState, rotation: Rotation): BlockState {
|
||||
return state.setValue(FACING, rotation.rotate(state.getValue(FACING)))
|
||||
}
|
||||
|
||||
override fun mirror(state: BlockState, mirror: Mirror): BlockState {
|
||||
return state.rotate(mirror.getRotation(state.getValue(FACING)))
|
||||
}
|
||||
|
||||
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
builder.add(FACING)
|
||||
}
|
||||
|
||||
override fun isPathfindable(state: BlockState, type: PathComputationType): Boolean = false
|
||||
|
||||
companion object {
|
||||
val CODEC: MapCodec<ModificationStationBlock> = simpleCodec(::ModificationStationBlock)
|
||||
val CONTAINER_TITLE: Component = Component.translatable("container.cobblemon.modification_station")
|
||||
val FACING: DirectionProperty = HorizontalDirectionalBlock.FACING
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,13 @@ package com.cobblemon.mod.common.block
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.modification.ModificationVariant
|
||||
import com.cobblemon.mod.common.api.storage.pc.link.PCLinkManager
|
||||
import com.cobblemon.mod.common.api.storage.pc.link.ProximityPCLink
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.block.entity.PCBlockEntity
|
||||
import com.cobblemon.mod.common.block.modification.ModificationVariantBlock
|
||||
import com.cobblemon.mod.common.block.modification.ModificationVariantStructures
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.OpenPCPacket
|
||||
import com.cobblemon.mod.common.util.isInBattle
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
@@ -50,7 +53,7 @@ import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
|
||||
class PCBlock(properties: Properties): BaseEntityBlock(properties), SimpleWaterloggedBlock {
|
||||
class PCBlock(properties: Properties): ModificationVariantBlock(properties), SimpleWaterloggedBlock {
|
||||
companion object {
|
||||
val CODEC = simpleCodec(::PCBlock)
|
||||
val PART = EnumProperty.create("part", PCPart::class.java)
|
||||
@@ -129,7 +132,7 @@ class PCBlock(properties: Properties): BaseEntityBlock(properties), SimpleWaterl
|
||||
}
|
||||
|
||||
init {
|
||||
registerDefaultState(stateDefinition.any()
|
||||
registerDefaultState(unmodifiedState()
|
||||
.setValue(HorizontalDirectionalBlock.FACING, Direction.NORTH)
|
||||
.setValue(PART, PCPart.BOTTOM)
|
||||
.setValue(ON, false)
|
||||
@@ -140,7 +143,7 @@ class PCBlock(properties: Properties): BaseEntityBlock(properties), SimpleWaterl
|
||||
|
||||
override fun newBlockEntity(blockPos: BlockPos, blockState: BlockState) = if (blockState.getValue(PART) == PCPart.BOTTOM) PCBlockEntity(blockPos, blockState) else null
|
||||
|
||||
override fun getShape(
|
||||
override fun stockShape(
|
||||
blockState: BlockState,
|
||||
blockGetter: BlockGetter,
|
||||
blockPos: BlockPos,
|
||||
@@ -181,7 +184,7 @@ class PCBlock(properties: Properties): BaseEntityBlock(properties), SimpleWaterl
|
||||
|
||||
private fun isBase(state: BlockState): Boolean = state.getValue(PART) == PCPart.BOTTOM
|
||||
|
||||
override fun setPlacedBy(
|
||||
override fun onStockPlaced(
|
||||
world: Level,
|
||||
pos: BlockPos,
|
||||
state: BlockState,
|
||||
@@ -197,10 +200,11 @@ class PCBlock(properties: Properties): BaseEntityBlock(properties), SimpleWaterl
|
||||
state.updateNeighbourShapes(world, pos, 3)
|
||||
}
|
||||
|
||||
override fun getStateForPlacement(blockPlaceContext: BlockPlaceContext): BlockState? {
|
||||
override fun stockPlacementState(blockPlaceContext: BlockPlaceContext, variant: ModificationVariant?): BlockState? {
|
||||
val abovePosition = blockPlaceContext.clickedPos.above()
|
||||
val world = blockPlaceContext.level
|
||||
if (world.getBlockState(abovePosition).canBeReplaced(blockPlaceContext) && !world.isOutsideBuildHeight(abovePosition)) {
|
||||
val hasRoom = variant != null || (world.getBlockState(abovePosition).canBeReplaced(blockPlaceContext) && !world.isOutsideBuildHeight(abovePosition))
|
||||
if (hasRoom) {
|
||||
return defaultBlockState()
|
||||
.setValue(HorizontalDirectionalBlock.FACING, blockPlaceContext.horizontalDirection)
|
||||
.setValue(PART, PCPart.BOTTOM)
|
||||
@@ -210,6 +214,8 @@ class PCBlock(properties: Properties): BaseEntityBlock(properties), SimpleWaterl
|
||||
return null
|
||||
}
|
||||
|
||||
override fun anchorPosition(state: BlockState, pos: BlockPos): BlockPos = getBasePosition(state, pos)
|
||||
|
||||
override fun canSurvive(state: BlockState, world: LevelReader, pos: BlockPos): Boolean {
|
||||
val blockPos = pos.below()
|
||||
val blockState = world.getBlockState(blockPos)
|
||||
@@ -238,7 +244,7 @@ class PCBlock(properties: Properties): BaseEntityBlock(properties), SimpleWaterl
|
||||
pathComputationType: PathComputationType
|
||||
): Boolean = false
|
||||
|
||||
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
override fun addStockProperties(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
builder.add(HorizontalDirectionalBlock.FACING, NATURAL)
|
||||
builder.add(PART)
|
||||
builder.add(ON)
|
||||
@@ -256,10 +262,6 @@ class PCBlock(properties: Properties): BaseEntityBlock(properties), SimpleWaterl
|
||||
return blockState.rotate(mirror.getRotation(blockState.getValue(HorizontalDirectionalBlock.FACING)))
|
||||
}
|
||||
|
||||
override fun onRemove(state: BlockState, world: Level, pos: BlockPos, newState: BlockState, moved: Boolean) {
|
||||
if (!state.`is`(newState.block)) super.onRemove(state, world, pos, newState, moved)
|
||||
}
|
||||
|
||||
override fun useWithoutItem(
|
||||
blockState: BlockState,
|
||||
world: Level,
|
||||
@@ -271,8 +273,10 @@ class PCBlock(properties: Properties): BaseEntityBlock(properties), SimpleWaterl
|
||||
|
||||
val basePos = getBasePosition(blockState, blockPos)
|
||||
|
||||
// Remove any duplicate block entities that may exist
|
||||
world.getBlockEntity(basePos.above())?.setRemoved()
|
||||
if (!ModificationVariantStructures.isModified(blockState)) {
|
||||
// Remove any duplicate block entities that may exist
|
||||
world.getBlockEntity(basePos.above())?.setRemoved()
|
||||
}
|
||||
|
||||
val baseEntity = world.getBlockEntity(basePos)
|
||||
if (baseEntity !is PCBlockEntity) return InteractionResult.SUCCESS
|
||||
@@ -320,6 +324,9 @@ class PCBlock(properties: Properties): BaseEntityBlock(properties), SimpleWaterl
|
||||
if (state.getValue(WATERLOGGED)) {
|
||||
world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world))
|
||||
}
|
||||
if (ModificationVariantStructures.isModified(state)) {
|
||||
return state
|
||||
}
|
||||
|
||||
val isPC = neighborState.`is`(this)
|
||||
val part = state.getValue(PART)
|
||||
@@ -331,4 +338,4 @@ class PCBlock(properties: Properties): BaseEntityBlock(properties), SimpleWaterl
|
||||
|
||||
return state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-14
@@ -16,9 +16,6 @@ import net.minecraft.core.Direction
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.core.NonNullList
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.protocol.Packet
|
||||
import net.minecraft.network.protocol.game.ClientGamePacketListener
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.ContainerHelper
|
||||
import net.minecraft.world.InteractionHand
|
||||
@@ -29,10 +26,9 @@ import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
|
||||
class DisplayCaseBlockEntity(pos: BlockPos, state: BlockState) : BlockEntity(CobblemonBlockEntities.DISPLAY_CASE, pos, state),
|
||||
class DisplayCaseBlockEntity(pos: BlockPos, state: BlockState) : ModificationVariantBlockEntity(CobblemonBlockEntities.DISPLAY_CASE, pos, state),
|
||||
WorldlyContainer {
|
||||
|
||||
val inv: NonNullList<ItemStack> = NonNullList.withSize(1, ItemStack.EMPTY)
|
||||
@@ -109,14 +105,6 @@ class DisplayCaseBlockEntity(pos: BlockPos, state: BlockState) : BlockEntity(Cob
|
||||
ContainerHelper.loadAllItems(nbt, inv, registryLookup)
|
||||
}
|
||||
|
||||
override fun getUpdatePacket(): Packet<ClientGamePacketListener>? {
|
||||
return ClientboundBlockEntityDataPacket.create(this)
|
||||
}
|
||||
|
||||
override fun getUpdateTag(registryLookup: HolderLookup.Provider): CompoundTag {
|
||||
return this.saveWithoutMetadata(registryLookup)
|
||||
}
|
||||
|
||||
private fun onItemUpdated(world: Level, oldState: BlockState, newState: BlockState) {
|
||||
world.sendBlockUpdated(blockPos, oldState, newState, Block.UPDATE_CLIENTS)
|
||||
world.updateNeighbourForOutputSignal(blockPos, world.getBlockState(blockPos).block)
|
||||
@@ -176,4 +164,4 @@ class DisplayCaseBlockEntity(pos: BlockPos, state: BlockState) : BlockEntity(Cob
|
||||
|
||||
override fun canPlaceItemThroughFace(slot: Int, stack: ItemStack, dir: Direction?): Boolean = (getStack().isEmpty)
|
||||
override fun canTakeItemThroughFace(slot: Int, stack: ItemStack, direction: Direction): Boolean = (direction == Direction.DOWN)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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.block.entity
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
|
||||
class ModVariantBlockEntity(pos: BlockPos, state: BlockState) : ModificationVariantBlockEntity(CobblemonBlockEntities.MOD_VARIANT, pos, state)
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.block.entity
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.api.modification.ModificationVariant
|
||||
import com.cobblemon.mod.common.api.modification.ModificationVariants
|
||||
import com.cobblemon.mod.common.item.components.ModificationVariantComponent
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.core.component.DataComponentMap
|
||||
import net.minecraft.core.component.DataComponents
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.protocol.Packet
|
||||
import net.minecraft.network.protocol.game.ClientGamePacketListener
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
|
||||
abstract class ModificationVariantBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state: BlockState) : BlockEntity(type, pos, state) {
|
||||
var variantIdentifier: ResourceLocation? = null
|
||||
|
||||
fun variant(): ModificationVariant? = variantIdentifier?.let(ModificationVariants::getByIdentifier)
|
||||
|
||||
override fun saveAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
|
||||
super.saveAdditional(tag, registries)
|
||||
variantIdentifier?.let { tag.putString(VARIANT_TAG, it.toString()) }
|
||||
}
|
||||
|
||||
override fun loadAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
|
||||
super.loadAdditional(tag, registries)
|
||||
variantIdentifier = if (tag.contains(VARIANT_TAG)) ResourceLocation.tryParse(tag.getString(VARIANT_TAG)) else null
|
||||
}
|
||||
|
||||
override fun getUpdatePacket(): Packet<ClientGamePacketListener> = ClientboundBlockEntityDataPacket.create(this)
|
||||
|
||||
override fun getUpdateTag(registries: HolderLookup.Provider): CompoundTag = saveWithoutMetadata(registries)
|
||||
|
||||
override fun applyImplicitComponents(componentInput: DataComponentInput) {
|
||||
super.applyImplicitComponents(componentInput)
|
||||
variantIdentifier = componentInput.get(CobblemonItemComponents.MODIFICATION_VARIANT)?.variant
|
||||
}
|
||||
|
||||
override fun collectImplicitComponents(builder: DataComponentMap.Builder) {
|
||||
super.collectImplicitComponents(builder)
|
||||
val identifier = variantIdentifier ?: return
|
||||
builder.set(CobblemonItemComponents.MODIFICATION_VARIANT, ModificationVariantComponent(identifier))
|
||||
ModificationVariants.getByIdentifier(identifier)?.let { builder.set(DataComponents.ITEM_NAME, it.displayName()) }
|
||||
}
|
||||
|
||||
override fun removeComponentsFromTag(tag: CompoundTag) {
|
||||
super.removeComponentsFromTag(tag)
|
||||
tag.remove(VARIANT_TAG)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val VARIANT_TAG = "ModificationVariant"
|
||||
}
|
||||
}
|
||||
@@ -13,13 +13,13 @@ import com.cobblemon.mod.common.CobblemonBlocks
|
||||
import com.cobblemon.mod.common.api.storage.pc.link.PCLinkManager
|
||||
import com.cobblemon.mod.common.api.storage.pc.link.ProximityPCLink
|
||||
import com.cobblemon.mod.common.block.PCBlock
|
||||
import com.cobblemon.mod.common.block.modification.ModificationVariantStructures
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.entity.item.ItemEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Blocks
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.entity.BlockEntityTicker
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.entity.EntityTypeTest
|
||||
@@ -28,7 +28,7 @@ import net.minecraft.world.phys.AABB
|
||||
class PCBlockEntity(
|
||||
blockPos: BlockPos,
|
||||
blockState: BlockState
|
||||
) : BlockEntity(CobblemonBlockEntities.PC, blockPos, blockState) {
|
||||
) : ModificationVariantBlockEntity(CobblemonBlockEntities.PC, blockPos, blockState) {
|
||||
|
||||
companion object {
|
||||
internal val TICKER = BlockEntityTicker<PCBlockEntity> { world, _, _, blockEntity ->
|
||||
@@ -43,6 +43,10 @@ class PCBlockEntity(
|
||||
|
||||
val world = level
|
||||
if (world != null && !world.isClientSide) {
|
||||
if (ModificationVariantStructures.isModified(blockState)) {
|
||||
toggleModifiedPCOn(world, on)
|
||||
return
|
||||
}
|
||||
val posBottom = pcBlock.getBasePosition(blockState, blockPos)
|
||||
val stateBottom = world.getBlockState(posBottom)
|
||||
|
||||
@@ -69,6 +73,14 @@ class PCBlockEntity(
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleModifiedPCOn(world: Level, on: Boolean) {
|
||||
val state = world.getBlockState(blockPos)
|
||||
if (state.hasProperty(PCBlock.ON) && state.getValue(PCBlock.ON) != on) {
|
||||
world.setBlockAndUpdate(blockPos, state.setValue(PCBlock.ON, on))
|
||||
}
|
||||
ModificationVariantStructures.setFillersLit(world, blockPos, on)
|
||||
}
|
||||
|
||||
private fun isPlayerViewing(player: Player): Boolean {
|
||||
val pcLink = PCLinkManager.getLink(player.uuid)
|
||||
return pcLink != null
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* 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.block.modification
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBlocks
|
||||
import com.mojang.serialization.MapCodec
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.core.Vec3i
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.ItemInteractionResult
|
||||
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.Block
|
||||
import net.minecraft.world.level.block.RenderShape
|
||||
import net.minecraft.world.level.block.SimpleWaterloggedBlock
|
||||
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
|
||||
import net.minecraft.world.level.block.state.properties.IntegerProperty
|
||||
import net.minecraft.world.level.material.FluidState
|
||||
import net.minecraft.world.level.material.Fluids
|
||||
import net.minecraft.world.level.pathfinder.PathComputationType
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
|
||||
class ModFillerBlock(properties: Properties) : Block(properties), SimpleWaterloggedBlock {
|
||||
init {
|
||||
registerDefaultState(stateDefinition.any()
|
||||
.setValue(OFFSET_X, HORIZONTAL_OFFSET_SHIFT)
|
||||
.setValue(OFFSET_Y, 0)
|
||||
.setValue(OFFSET_Z, HORIZONTAL_OFFSET_SHIFT)
|
||||
.setValue(BlockStateProperties.LIT, false)
|
||||
.setValue(BlockStateProperties.WATERLOGGED, false))
|
||||
}
|
||||
|
||||
override fun codec(): MapCodec<ModFillerBlock> = CODEC
|
||||
|
||||
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
builder.add(OFFSET_X, OFFSET_Y, OFFSET_Z, BlockStateProperties.LIT, BlockStateProperties.WATERLOGGED)
|
||||
}
|
||||
|
||||
override fun getRenderShape(state: BlockState): RenderShape = RenderShape.INVISIBLE
|
||||
|
||||
override fun getShape(state: BlockState, level: BlockGetter, pos: BlockPos, context: CollisionContext): VoxelShape {
|
||||
val anchorPos = anchorPosition(state, pos)
|
||||
val anchorState = level.getBlockState(anchorPos)
|
||||
if (anchorState.block !is ModificationVariantBlock) {
|
||||
return Shapes.empty()
|
||||
}
|
||||
val variant = ModificationVariantStructures.variantAt(level, anchorPos) ?: return Shapes.block()
|
||||
return variant.cellHitbox(ModificationVariantStructures.facingOf(anchorState), cellOffset(state))
|
||||
}
|
||||
|
||||
override fun getCollisionShape(state: BlockState, level: BlockGetter, pos: BlockPos, context: CollisionContext): VoxelShape {
|
||||
return getShape(state, level, pos, context)
|
||||
}
|
||||
|
||||
override fun useWithoutItem(state: BlockState, level: Level, pos: BlockPos, player: Player, hit: BlockHitResult): InteractionResult {
|
||||
val anchorPos = anchorPosition(state, pos)
|
||||
val anchorState = level.getBlockState(anchorPos)
|
||||
if (anchorState.block !is ModificationVariantBlock) {
|
||||
return InteractionResult.PASS
|
||||
}
|
||||
return anchorState.useWithoutItem(level, player, hit.withPosition(anchorPos))
|
||||
}
|
||||
|
||||
override fun useItemOn(
|
||||
stack: ItemStack,
|
||||
state: BlockState,
|
||||
level: Level,
|
||||
pos: BlockPos,
|
||||
player: Player,
|
||||
hand: InteractionHand,
|
||||
hit: BlockHitResult
|
||||
): ItemInteractionResult {
|
||||
val anchorPos = anchorPosition(state, pos)
|
||||
val anchorState = level.getBlockState(anchorPos)
|
||||
if (anchorState.block !is ModificationVariantBlock) {
|
||||
return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION
|
||||
}
|
||||
return anchorState.useItemOn(stack, level, player, hand, hit.withPosition(anchorPos))
|
||||
}
|
||||
|
||||
override fun getCloneItemStack(level: LevelReader, pos: BlockPos, state: BlockState): ItemStack {
|
||||
val anchorPos = anchorPosition(state, pos)
|
||||
val anchorState = level.getBlockState(anchorPos)
|
||||
return if (anchorState.block is ModificationVariantBlock) anchorState.block.getCloneItemStack(level, anchorPos, anchorState) else ItemStack.EMPTY
|
||||
}
|
||||
|
||||
override fun playerWillDestroy(level: Level, pos: BlockPos, state: BlockState, player: Player): BlockState {
|
||||
val anchorPos = anchorPosition(state, pos)
|
||||
val anchorState = level.getBlockState(anchorPos)
|
||||
if (!level.isClientSide && anchorState.block is ModificationVariantBlock) {
|
||||
val shouldDrop = !player.isCreative && player.hasCorrectToolForDrops(anchorState)
|
||||
level.destroyBlock(anchorPos, shouldDrop, player)
|
||||
}
|
||||
return super.playerWillDestroy(level, pos, state, player)
|
||||
}
|
||||
|
||||
override fun onRemove(state: BlockState, level: Level, pos: BlockPos, newState: BlockState, isMoved: Boolean) {
|
||||
if (!newState.`is`(this)) {
|
||||
val anchorPos = anchorPosition(state, pos)
|
||||
if (level.getBlockState(anchorPos).block is ModificationVariantBlock) {
|
||||
level.destroyBlock(anchorPos, true)
|
||||
}
|
||||
}
|
||||
super.onRemove(state, level, pos, newState, isMoved)
|
||||
}
|
||||
|
||||
override fun canSurvive(state: BlockState, level: LevelReader, pos: BlockPos): Boolean {
|
||||
return level.getBlockState(anchorPosition(state, pos)).block is ModificationVariantBlock
|
||||
}
|
||||
|
||||
override fun updateShape(
|
||||
state: BlockState,
|
||||
direction: Direction,
|
||||
neighborState: BlockState,
|
||||
level: LevelAccessor,
|
||||
pos: BlockPos,
|
||||
neighborPos: BlockPos
|
||||
): BlockState {
|
||||
if (state.getValue(BlockStateProperties.WATERLOGGED)) {
|
||||
level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level))
|
||||
}
|
||||
return if (canSurvive(state, level, pos)) state else ModificationVariantStructures.replacementFor(state)
|
||||
}
|
||||
|
||||
override fun getFluidState(state: BlockState): FluidState {
|
||||
return if (state.getValue(BlockStateProperties.WATERLOGGED)) Fluids.WATER.getSource(false) else super.getFluidState(state)
|
||||
}
|
||||
|
||||
override fun isPathfindable(state: BlockState, type: PathComputationType): Boolean = false
|
||||
|
||||
companion object {
|
||||
val CODEC: MapCodec<ModFillerBlock> = simpleCodec(::ModFillerBlock)
|
||||
private const val HORIZONTAL_OFFSET_SHIFT = 2
|
||||
val OFFSET_X: IntegerProperty = IntegerProperty.create("offset_x", 0, 4)
|
||||
val OFFSET_Y: IntegerProperty = IntegerProperty.create("offset_y", 0, 4)
|
||||
val OFFSET_Z: IntegerProperty = IntegerProperty.create("offset_z", 0, 4)
|
||||
|
||||
fun stateFor(cell: Vec3i, isLit: Boolean, isWaterlogged: Boolean): BlockState {
|
||||
return CobblemonBlocks.MOD_FILLER.defaultBlockState()
|
||||
.setValue(OFFSET_X, cell.x + HORIZONTAL_OFFSET_SHIFT)
|
||||
.setValue(OFFSET_Y, cell.y)
|
||||
.setValue(OFFSET_Z, cell.z + HORIZONTAL_OFFSET_SHIFT)
|
||||
.setValue(BlockStateProperties.LIT, isLit)
|
||||
.setValue(BlockStateProperties.WATERLOGGED, isWaterlogged)
|
||||
}
|
||||
|
||||
fun cellOffset(state: BlockState): Vec3i = Vec3i(
|
||||
state.getValue(OFFSET_X) - HORIZONTAL_OFFSET_SHIFT,
|
||||
state.getValue(OFFSET_Y),
|
||||
state.getValue(OFFSET_Z) - HORIZONTAL_OFFSET_SHIFT
|
||||
)
|
||||
|
||||
fun anchorPosition(state: BlockState, pos: BlockPos): BlockPos = pos.subtract(cellOffset(state))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.block.modification
|
||||
|
||||
import com.cobblemon.mod.common.api.modification.ModificationVariant
|
||||
import com.cobblemon.mod.common.block.entity.ModVariantBlockEntity
|
||||
import com.mojang.serialization.MapCodec
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.world.item.context.BlockPlaceContext
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.Mirror
|
||||
import net.minecraft.world.level.block.RenderShape
|
||||
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.pathfinder.PathComputationType
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
|
||||
class ModVariantBlock(properties: Properties) : ModificationVariantBlock(properties) {
|
||||
init {
|
||||
registerDefaultState(unmodifiedState().setValue(FACING, Direction.SOUTH))
|
||||
}
|
||||
|
||||
override fun codec(): MapCodec<ModVariantBlock> = CODEC
|
||||
|
||||
override fun addStockProperties(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
builder.add(FACING)
|
||||
}
|
||||
|
||||
override fun stockPlacementState(context: BlockPlaceContext, variant: ModificationVariant?): BlockState? {
|
||||
if (variant == null) {
|
||||
return null
|
||||
}
|
||||
return defaultBlockState().setValue(FACING, context.horizontalDirection)
|
||||
}
|
||||
|
||||
override fun stockShape(state: BlockState, level: BlockGetter, pos: BlockPos, context: CollisionContext): VoxelShape = Shapes.block()
|
||||
|
||||
override fun newBlockEntity(pos: BlockPos, state: BlockState) = ModVariantBlockEntity(pos, state)
|
||||
|
||||
override fun getRenderShape(state: BlockState): RenderShape = RenderShape.INVISIBLE
|
||||
|
||||
override fun rotate(state: BlockState, rotation: Rotation): BlockState = state.setValue(FACING, rotation.rotate(state.getValue(FACING)))
|
||||
|
||||
override fun mirror(state: BlockState, mirror: Mirror): BlockState = state.rotate(mirror.getRotation(state.getValue(FACING)))
|
||||
|
||||
override fun isPathfindable(state: BlockState, type: PathComputationType): Boolean = false
|
||||
|
||||
companion object {
|
||||
val CODEC: MapCodec<ModVariantBlock> = simpleCodec(::ModVariantBlock)
|
||||
}
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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.block.modification
|
||||
|
||||
import com.cobblemon.mod.common.api.modification.ModificationVariant
|
||||
import com.cobblemon.mod.common.api.modification.ModificationVariants
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.context.BlockPlaceContext
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.LevelReader
|
||||
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.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateDefinition
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty
|
||||
import net.minecraft.world.level.block.state.properties.DirectionProperty
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
|
||||
abstract class ModificationVariantBlock(properties: Properties) : BaseEntityBlock(properties) {
|
||||
protected abstract fun stockShape(state: BlockState, level: BlockGetter, pos: BlockPos, context: CollisionContext): VoxelShape
|
||||
|
||||
protected abstract fun stockPlacementState(context: BlockPlaceContext, variant: ModificationVariant?): BlockState?
|
||||
|
||||
protected abstract fun addStockProperties(builder: StateDefinition.Builder<Block, BlockState>)
|
||||
|
||||
protected open fun onStockPlaced(level: Level, pos: BlockPos, state: BlockState, placer: LivingEntity?, stack: ItemStack) {}
|
||||
|
||||
protected open fun anchorPosition(state: BlockState, pos: BlockPos): BlockPos = pos
|
||||
|
||||
protected fun unmodifiedState(): BlockState = stateDefinition.any().setValue(MODIFIED, false)
|
||||
|
||||
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
builder.add(MODIFIED)
|
||||
addStockProperties(builder)
|
||||
}
|
||||
|
||||
override fun getStateForPlacement(context: BlockPlaceContext): BlockState? {
|
||||
val variant = ModificationVariants.fromStack(context.itemInHand)
|
||||
val stockState = stockPlacementState(context, variant) ?: return null
|
||||
if (variant != null && !ModificationVariantStructures.canPlace(context, variant, ModificationVariantStructures.facingOf(stockState))) {
|
||||
return null
|
||||
}
|
||||
return stockState.setValue(MODIFIED, variant != null)
|
||||
}
|
||||
|
||||
override fun setPlacedBy(level: Level, pos: BlockPos, state: BlockState, placer: LivingEntity?, stack: ItemStack) {
|
||||
super.setPlacedBy(level, pos, state, placer, stack)
|
||||
val variant = ModificationVariants.fromStack(stack)
|
||||
if (variant != null && ModificationVariantStructures.isModified(state)) {
|
||||
ModificationVariantStructures.placeFillers(level, pos, variant, ModificationVariantStructures.facingOf(state), isLit = false)
|
||||
return
|
||||
}
|
||||
onStockPlaced(level, pos, state, placer, stack)
|
||||
}
|
||||
|
||||
override fun getShape(state: BlockState, level: BlockGetter, pos: BlockPos, context: CollisionContext): VoxelShape {
|
||||
return ModificationVariantStructures.anchorShape(level, pos, state, stockShape(state, level, pos, context))
|
||||
}
|
||||
|
||||
override fun getCloneItemStack(level: LevelReader, pos: BlockPos, state: BlockState): ItemStack {
|
||||
return ModificationVariantStructures.withVariantComponents(level, anchorPosition(state, pos), super.getCloneItemStack(level, pos, state))
|
||||
}
|
||||
|
||||
override fun onRemove(state: BlockState, level: Level, pos: BlockPos, newState: BlockState, moved: Boolean) {
|
||||
if (!state.`is`(newState.block) && ModificationVariantStructures.isModified(state)) {
|
||||
ModificationVariantStructures.removeFillers(level, pos)
|
||||
}
|
||||
super.onRemove(state, level, pos, newState, moved)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val MODIFIED: BooleanProperty = BooleanProperty.create("modified")
|
||||
val FACING: DirectionProperty = HorizontalDirectionalBlock.FACING
|
||||
}
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.block.modification
|
||||
|
||||
import com.cobblemon.mod.common.api.modification.ModificationVariant
|
||||
import com.cobblemon.mod.common.block.entity.ModificationVariantBlockEntity
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.core.Vec3i
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.context.BlockPlaceContext
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.LevelAccessor
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.Blocks
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties
|
||||
import net.minecraft.world.level.material.Fluids
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
|
||||
object ModificationVariantStructures {
|
||||
fun variantAt(level: BlockGetter, pos: BlockPos): ModificationVariant? = (level.getBlockEntity(pos) as? ModificationVariantBlockEntity)?.variant()
|
||||
|
||||
fun isModified(state: BlockState): Boolean = state.hasProperty(ModificationVariantBlock.MODIFIED) && state.getValue(ModificationVariantBlock.MODIFIED)
|
||||
|
||||
fun facingOf(state: BlockState): Direction = if (state.hasProperty(ModificationVariantBlock.FACING)) state.getValue(ModificationVariantBlock.FACING) else Direction.SOUTH
|
||||
|
||||
fun canPlace(context: BlockPlaceContext, variant: ModificationVariant, facing: Direction): Boolean {
|
||||
val level = context.level
|
||||
return variant.fillerCells(facing).all { cell ->
|
||||
val cellPos = context.clickedPos.offset(cell)
|
||||
!level.isOutsideBuildHeight(cellPos) && level.getBlockState(cellPos).canBeReplaced(context)
|
||||
}
|
||||
}
|
||||
|
||||
fun placeFillers(level: LevelAccessor, anchorPos: BlockPos, variant: ModificationVariant, facing: Direction, isLit: Boolean) {
|
||||
variant.fillerCells(facing).forEach { cell ->
|
||||
val cellPos = anchorPos.offset(cell)
|
||||
val isWaterlogged = level.getFluidState(cellPos).type == Fluids.WATER
|
||||
level.setBlock(cellPos, ModFillerBlock.stateFor(cell, isLit, isWaterlogged), Block.UPDATE_ALL)
|
||||
}
|
||||
}
|
||||
|
||||
fun removeFillers(level: LevelAccessor, anchorPos: BlockPos) {
|
||||
forEachFiller(level, anchorPos) { fillerPos, fillerState ->
|
||||
level.setBlock(fillerPos, replacementFor(fillerState), Block.UPDATE_ALL or Block.UPDATE_SUPPRESS_DROPS)
|
||||
}
|
||||
}
|
||||
|
||||
fun setFillersLit(level: LevelAccessor, anchorPos: BlockPos, isLit: Boolean) {
|
||||
forEachFiller(level, anchorPos) { fillerPos, fillerState ->
|
||||
if (fillerState.getValue(BlockStateProperties.LIT) != isLit) {
|
||||
level.setBlock(fillerPos, fillerState.setValue(BlockStateProperties.LIT, isLit), Block.UPDATE_ALL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun anchorShape(level: BlockGetter, pos: BlockPos, state: BlockState, fallback: VoxelShape): VoxelShape {
|
||||
if (!isModified(state)) {
|
||||
return fallback
|
||||
}
|
||||
val variant = variantAt(level, pos) ?: return fallback
|
||||
return variant.cellHitbox(facingOf(state), Vec3i.ZERO)
|
||||
}
|
||||
|
||||
fun withVariantComponents(level: BlockGetter, pos: BlockPos, stack: ItemStack): ItemStack {
|
||||
val blockEntity = level.getBlockEntity(pos) ?: return stack
|
||||
stack.applyComponents(blockEntity.collectComponents())
|
||||
return stack
|
||||
}
|
||||
|
||||
fun replacementFor(state: BlockState): BlockState {
|
||||
val isWaterlogged = state.hasProperty(BlockStateProperties.WATERLOGGED) && state.getValue(BlockStateProperties.WATERLOGGED)
|
||||
return if (isWaterlogged) Blocks.WATER.defaultBlockState() else Blocks.AIR.defaultBlockState()
|
||||
}
|
||||
|
||||
private fun forEachFiller(level: LevelAccessor, anchorPos: BlockPos, action: (BlockPos, BlockState) -> Unit) {
|
||||
val searchMin = anchorPos.offset(ModificationVariant.MIN_CELL_OFFSET)
|
||||
val searchMax = anchorPos.offset(ModificationVariant.MAX_CELL_OFFSET)
|
||||
BlockPos.betweenClosed(searchMin, searchMax).forEach { searchPos ->
|
||||
val state = level.getBlockState(searchPos)
|
||||
if (state.block is ModFillerBlock && ModFillerBlock.anchorPosition(state, searchPos) == anchorPos) {
|
||||
action(searchPos.immutable(), state)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+209
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* 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.block.modificationstation
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBlocks
|
||||
import com.cobblemon.mod.common.CobblemonMenuType
|
||||
import com.cobblemon.mod.common.api.modification.ModificationVariants
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.Container
|
||||
import net.minecraft.world.SimpleContainer
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.inventory.ContainerLevelAccess
|
||||
import net.minecraft.world.inventory.DataSlot
|
||||
import net.minecraft.world.inventory.ResultContainer
|
||||
import net.minecraft.world.inventory.Slot
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
class ModificationStationMenu(
|
||||
containerId: Int,
|
||||
playerInventory: Inventory,
|
||||
private val access: ContainerLevelAccess
|
||||
) : AbstractContainerMenu(CobblemonMenuType.MODIFICATION_STATION, containerId) {
|
||||
|
||||
private val selectedOutputIndex = DataSlot.standalone()
|
||||
private var outputs: List<ItemStack> = emptyList()
|
||||
private var lastInput: ItemStack = ItemStack.EMPTY
|
||||
private var lastSoundTime: Long = 0L
|
||||
private var slotUpdateListener: Runnable = Runnable {}
|
||||
|
||||
val container: Container = object : SimpleContainer(1) {
|
||||
override fun setChanged() {
|
||||
super.setChanged()
|
||||
this@ModificationStationMenu.slotsChanged(this)
|
||||
slotUpdateListener.run()
|
||||
}
|
||||
}
|
||||
|
||||
private val resultContainer = ResultContainer()
|
||||
val inputSlot: Slot
|
||||
val resultSlot: Slot
|
||||
|
||||
init {
|
||||
inputSlot = addSlot(object : Slot(container, INPUT_SLOT, 20, 33) {
|
||||
override fun mayPlace(stack: ItemStack): Boolean = ModificationVariants.hasVariantsFor(stack)
|
||||
})
|
||||
|
||||
resultSlot = addSlot(object : Slot(resultContainer, RESULT_SLOT, 143, 33) {
|
||||
override fun mayPlace(stack: ItemStack): Boolean = false
|
||||
|
||||
override fun onTake(player: Player, stack: ItemStack) {
|
||||
stack.onCraftedBy(player.level(), player, stack.count)
|
||||
inputSlot.remove(1)
|
||||
|
||||
if (inputSlot.hasItem()) {
|
||||
setupResultSlot()
|
||||
} else {
|
||||
selectedOutputIndex.set(-1)
|
||||
this.set(ItemStack.EMPTY)
|
||||
}
|
||||
|
||||
access.execute { level, pos ->
|
||||
val gameTime = level.gameTime
|
||||
if (lastSoundTime != gameTime) {
|
||||
level.playSound(null, pos, SoundEvents.UI_STONECUTTER_TAKE_RESULT, SoundSource.BLOCKS, 1.0F, 1.0F)
|
||||
lastSoundTime = gameTime
|
||||
}
|
||||
}
|
||||
|
||||
super.onTake(player, stack)
|
||||
}
|
||||
})
|
||||
|
||||
for (row in 0 until 3) {
|
||||
for (column in 0 until 9) {
|
||||
addSlot(Slot(playerInventory, column + row * 9 + 9, 8 + column * 18, 84 + row * 18))
|
||||
}
|
||||
}
|
||||
|
||||
for (hotbarSlot in 0 until 9) {
|
||||
addSlot(Slot(playerInventory, hotbarSlot, 8 + hotbarSlot * 18, 142))
|
||||
}
|
||||
|
||||
addDataSlot(selectedOutputIndex)
|
||||
}
|
||||
|
||||
constructor(containerId: Int, playerInventory: Inventory) : this(containerId, playerInventory, ContainerLevelAccess.NULL)
|
||||
|
||||
fun getSelectedOutputIndex(): Int = selectedOutputIndex.get()
|
||||
|
||||
fun getOutputs(): List<ItemStack> = outputs
|
||||
|
||||
fun hasInputItem(): Boolean = inputSlot.hasItem() && outputs.isNotEmpty()
|
||||
|
||||
fun registerUpdateListener(listener: Runnable) {
|
||||
slotUpdateListener = listener
|
||||
}
|
||||
|
||||
override fun stillValid(player: Player): Boolean = stillValid(access, player, CobblemonBlocks.MODIFICATION_STATION)
|
||||
|
||||
override fun clickMenuButton(player: Player, id: Int): Boolean {
|
||||
if (isValidOutputIndex(id)) {
|
||||
selectedOutputIndex.set(id)
|
||||
setupResultSlot()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun slotsChanged(container: Container) {
|
||||
val inputStack = inputSlot.item
|
||||
if (!ItemStack.isSameItemSameComponents(inputStack, lastInput)) {
|
||||
lastInput = inputStack.copy()
|
||||
setupOutputs(inputStack)
|
||||
}
|
||||
}
|
||||
|
||||
override fun canTakeItemForPickAll(stack: ItemStack, slot: Slot): Boolean {
|
||||
return slot.container !== resultContainer && super.canTakeItemForPickAll(stack, slot)
|
||||
}
|
||||
|
||||
override fun quickMoveStack(player: Player, index: Int): ItemStack {
|
||||
val slot = slots[index]
|
||||
if (!slot.hasItem()) {
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
val movedStack = slot.item
|
||||
val copiedStack = movedStack.copy()
|
||||
|
||||
val wasMoved = when {
|
||||
index == RESULT_SLOT -> {
|
||||
movedStack.item.onCraftedBy(movedStack, player.level(), player)
|
||||
moveItemStackTo(movedStack, INV_SLOT_START, USE_ROW_SLOT_END, true).also { if (it) slot.onQuickCraft(movedStack, copiedStack) }
|
||||
}
|
||||
index == INPUT_SLOT -> moveItemStackTo(movedStack, INV_SLOT_START, USE_ROW_SLOT_END, false)
|
||||
ModificationVariants.hasVariantsFor(movedStack) -> moveItemStackTo(movedStack, INPUT_SLOT, RESULT_SLOT, false)
|
||||
index in INV_SLOT_START until INV_SLOT_END -> moveItemStackTo(movedStack, USE_ROW_SLOT_START, USE_ROW_SLOT_END, false)
|
||||
index in USE_ROW_SLOT_START until USE_ROW_SLOT_END -> moveItemStackTo(movedStack, INV_SLOT_START, INV_SLOT_END, false)
|
||||
else -> false
|
||||
}
|
||||
if (!wasMoved) {
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
|
||||
if (movedStack.isEmpty) {
|
||||
slot.setByPlayer(ItemStack.EMPTY)
|
||||
} else {
|
||||
slot.setChanged()
|
||||
}
|
||||
if (movedStack.count == copiedStack.count) {
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
|
||||
slot.onTake(player, movedStack)
|
||||
broadcastChanges()
|
||||
return copiedStack
|
||||
}
|
||||
|
||||
override fun removed(player: Player) {
|
||||
super.removed(player)
|
||||
resultContainer.removeItemNoUpdate(1)
|
||||
access.execute { _, _ -> clearContainer(player, container) }
|
||||
}
|
||||
|
||||
private fun isValidOutputIndex(index: Int): Boolean = index in outputs.indices
|
||||
|
||||
private fun setupOutputs(inputStack: ItemStack) {
|
||||
outputs = emptyList()
|
||||
selectedOutputIndex.set(-1)
|
||||
resultSlot.set(ItemStack.EMPTY)
|
||||
if (inputStack.isEmpty) {
|
||||
return
|
||||
}
|
||||
|
||||
val parent = ModificationVariants.parentOf(inputStack)
|
||||
val variantOutputs = ModificationVariants.forParent(parent).map { it.createStack() }.filterNot { it.isEmpty }
|
||||
if (variantOutputs.isEmpty()) {
|
||||
return
|
||||
}
|
||||
outputs = (listOfNotNull(stockOutputFor(parent)) + variantOutputs)
|
||||
.filterNot { ItemStack.isSameItemSameComponents(it, inputStack) }
|
||||
}
|
||||
|
||||
private fun stockOutputFor(parent: ResourceLocation): ItemStack? = BuiltInRegistries.ITEM.getOptional(parent).map(::ItemStack).orElse(null)
|
||||
|
||||
private fun setupResultSlot() {
|
||||
val selectedIndex = selectedOutputIndex.get()
|
||||
resultSlot.set(if (isValidOutputIndex(selectedIndex)) outputs[selectedIndex].copy() else ItemStack.EMPTY)
|
||||
broadcastChanges()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val INPUT_SLOT = 0
|
||||
const val RESULT_SLOT = 1
|
||||
private const val INV_SLOT_START = 2
|
||||
private const val INV_SLOT_END = 29
|
||||
private const val USE_ROW_SLOT_START = 29
|
||||
private const val USE_ROW_SLOT_END = 38
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,8 @@ import com.cobblemon.mod.common.api.storage.player.client.ClientGeneralPlayerDat
|
||||
import com.cobblemon.mod.common.api.storage.player.client.ClientPokedexManager
|
||||
import com.cobblemon.mod.common.api.storage.player.client.ClientTMMoveManager
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.block.entity.ModVariantBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.PCBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.TintBlockEntity
|
||||
import com.cobblemon.mod.common.client.battle.ClientBattle
|
||||
import com.cobblemon.mod.common.client.gui.PartyOverlay
|
||||
@@ -28,6 +30,7 @@ import com.cobblemon.mod.common.client.gui.PartyOverlayDataControl
|
||||
import com.cobblemon.mod.common.client.gui.RideControlsOverlay
|
||||
import com.cobblemon.mod.common.client.gui.battle.BattleOverlay
|
||||
import com.cobblemon.mod.common.client.gui.cookingpot.CookingPotScreen
|
||||
import com.cobblemon.mod.common.client.gui.modificationstation.ModificationStationScreen
|
||||
import com.cobblemon.mod.common.client.gui.tmmachine.TMMachineScreen
|
||||
import com.cobblemon.mod.common.client.gui.party.PartyTutorialToasts
|
||||
import com.cobblemon.mod.common.client.particle.BedrockParticleOptionsRepository
|
||||
@@ -39,6 +42,7 @@ import com.cobblemon.mod.common.client.render.block.DisplayCaseRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.FossilAnalyzerRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.GildedChestBlockRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.HealingMachineRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.ModificationVariantRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.LecternBlockEntityRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.PokeSnackBlockEntityRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.RestorationTankRenderer
|
||||
@@ -252,6 +256,7 @@ object CobblemonClient {
|
||||
RenderType.cutout(),
|
||||
CobblemonBlocks.GILDED_CHEST,
|
||||
CobblemonBlocks.FOSSIL_ANALYZER,
|
||||
CobblemonBlocks.MODIFICATION_STATION,
|
||||
CobblemonBlocks.APRICORN_DOOR,
|
||||
CobblemonBlocks.APRICORN_TRAPDOOR,
|
||||
CobblemonBlocks.APRICORN_SIGN,
|
||||
@@ -421,6 +426,7 @@ object CobblemonClient {
|
||||
private fun registerMenuScreens() {
|
||||
MenuScreens.register(CobblemonMenuType.COOKING_POT, ::CookingPotScreen)
|
||||
MenuScreens.register(CobblemonMenuType.TM_MACHINE, ::TMMachineScreen)
|
||||
MenuScreens.register(CobblemonMenuType.MODIFICATION_STATION, ::ModificationStationScreen)
|
||||
}
|
||||
|
||||
private fun registerBlockEntityRenderers() {
|
||||
@@ -441,6 +447,8 @@ object CobblemonClient {
|
||||
)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.GILDED_CHEST, ::GildedChestBlockRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.DISPLAY_CASE, ::DisplayCaseRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.PC) { ModificationVariantRenderer<PCBlockEntity>(it) }
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.MOD_VARIANT) { ModificationVariantRenderer<ModVariantBlockEntity>(it) }
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.LECTERN, ::LecternBlockEntityRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.CAMPFIRE, ::CampfireBlockEntityRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.POKE_SNACK, ::PokeSnackBlockEntityRenderer)
|
||||
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.modificationstation
|
||||
|
||||
import com.cobblemon.mod.common.block.modificationstation.ModificationStationMenu
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
|
||||
class ModificationStationScreen(
|
||||
menu: ModificationStationMenu,
|
||||
playerInventory: Inventory,
|
||||
title: Component
|
||||
) : AbstractContainerScreen<ModificationStationMenu>(menu, playerInventory, title) {
|
||||
|
||||
private var scrollOffset = 0.0F
|
||||
private var isScrolling = false
|
||||
private var startIndex = 0
|
||||
private var hasOutputs = false
|
||||
|
||||
init {
|
||||
menu.registerUpdateListener { onOutputsChanged() }
|
||||
titleLabelY -= 1
|
||||
}
|
||||
|
||||
override fun render(graphics: GuiGraphics, mouseX: Int, mouseY: Int, partialTick: Float) {
|
||||
super.render(graphics, mouseX, mouseY, partialTick)
|
||||
renderTooltip(graphics, mouseX, mouseY)
|
||||
}
|
||||
|
||||
override fun renderBg(graphics: GuiGraphics, partialTick: Float, mouseX: Int, mouseY: Int) {
|
||||
graphics.blit(BACKGROUND, leftPos, topPos, 0, 0, imageWidth, imageHeight)
|
||||
|
||||
val scrollerY = (SCROLLER_TRAVEL * scrollOffset).toInt()
|
||||
val scrollerSprite = if (isScrollBarActive()) SCROLLER_SPRITE else SCROLLER_DISABLED_SPRITE
|
||||
graphics.blitSprite(scrollerSprite, leftPos + SCROLLER_X, topPos + SCROLLER_Y + scrollerY, SCROLLER_WIDTH, SCROLLER_HEIGHT)
|
||||
|
||||
renderOutputButtons(graphics, mouseX, mouseY)
|
||||
renderOutputItems(graphics)
|
||||
}
|
||||
|
||||
override fun renderTooltip(graphics: GuiGraphics, x: Int, y: Int) {
|
||||
super.renderTooltip(graphics, x, y)
|
||||
if (!hasOutputs) {
|
||||
return
|
||||
}
|
||||
val hoveredIndex = outputIndexAt(x.toDouble(), y.toDouble()) ?: return
|
||||
graphics.renderTooltip(font, menu.getOutputs()[hoveredIndex], x, y)
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
isScrolling = false
|
||||
val client = minecraft ?: return super.mouseClicked(mouseX, mouseY, button)
|
||||
if (!hasOutputs) {
|
||||
return super.mouseClicked(mouseX, mouseY, button)
|
||||
}
|
||||
|
||||
val clickedIndex = outputIndexAt(mouseX, mouseY)
|
||||
val player = client.player
|
||||
if (clickedIndex != null && player != null && menu.clickMenuButton(player, clickedIndex)) {
|
||||
client.soundManager.play(SimpleSoundInstance.forUI(SoundEvents.UI_STONECUTTER_SELECT_RECIPE, 1.0F))
|
||||
client.gameMode?.handleInventoryButtonClick(menu.containerId, clickedIndex)
|
||||
return true
|
||||
}
|
||||
|
||||
val scrollerLeft = leftPos + SCROLLER_X
|
||||
val scrollerTop = topPos + SCROLLER_TRACK_Y
|
||||
if (mouseX >= scrollerLeft && mouseX < scrollerLeft + SCROLLER_WIDTH && mouseY >= scrollerTop && mouseY < scrollerTop + SCROLLER_TRACK_HEIGHT) {
|
||||
isScrolling = true
|
||||
}
|
||||
return super.mouseClicked(mouseX, mouseY, button)
|
||||
}
|
||||
|
||||
override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, dragX: Double, dragY: Double): Boolean {
|
||||
if (isScrolling && isScrollBarActive()) {
|
||||
val trackTop = topPos + SCROLLER_TRACK_Y
|
||||
scrollOffset = Mth.clamp((mouseY.toFloat() - trackTop - SCROLLER_HEIGHT / 2F) / (SCROLLER_TRACK_HEIGHT - SCROLLER_HEIGHT), 0.0F, 1.0F)
|
||||
startIndex = (scrollOffset * offscreenRows() + 0.5F).toInt() * GRID_COLUMNS
|
||||
return true
|
||||
}
|
||||
return super.mouseDragged(mouseX, mouseY, button, dragX, dragY)
|
||||
}
|
||||
|
||||
override fun mouseScrolled(mouseX: Double, mouseY: Double, scrollX: Double, scrollY: Double): Boolean {
|
||||
if (isScrollBarActive()) {
|
||||
val rows = offscreenRows()
|
||||
scrollOffset = Mth.clamp(scrollOffset - scrollY.toFloat() / rows, 0.0F, 1.0F)
|
||||
startIndex = (scrollOffset * rows + 0.5F).toInt() * GRID_COLUMNS
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun renderOutputButtons(graphics: GuiGraphics, mouseX: Int, mouseY: Int) {
|
||||
visibleOutputIndices().forEach { index ->
|
||||
val cellX = cellX(index)
|
||||
val cellY = cellY(index)
|
||||
val isHovered = mouseX in cellX until cellX + CELL_WIDTH && mouseY in cellY until cellY + CELL_HEIGHT
|
||||
val sprite = when {
|
||||
index == menu.getSelectedOutputIndex() -> SELECTED_CELL_SPRITE
|
||||
isHovered -> HIGHLIGHTED_CELL_SPRITE
|
||||
else -> CELL_SPRITE
|
||||
}
|
||||
graphics.blitSprite(sprite, cellX, cellY - 1, CELL_WIDTH, CELL_HEIGHT)
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderOutputItems(graphics: GuiGraphics) {
|
||||
val outputs = menu.getOutputs()
|
||||
visibleOutputIndices().forEach { index -> graphics.renderItem(outputs[index], cellX(index), cellY(index)) }
|
||||
}
|
||||
|
||||
private fun visibleOutputIndices(): IntRange {
|
||||
val lastVisible = minOf(startIndex + GRID_COLUMNS * GRID_ROWS, menu.getOutputs().size)
|
||||
return startIndex until lastVisible
|
||||
}
|
||||
|
||||
private fun outputIndexAt(mouseX: Double, mouseY: Double): Int? {
|
||||
return visibleOutputIndices().firstOrNull { index ->
|
||||
val cellX = cellX(index)
|
||||
val cellY = cellY(index)
|
||||
mouseX >= cellX && mouseX < cellX + CELL_WIDTH && mouseY >= cellY && mouseY < cellY + CELL_HEIGHT
|
||||
}
|
||||
}
|
||||
|
||||
private fun cellX(index: Int): Int = leftPos + GRID_X + (index - startIndex) % GRID_COLUMNS * CELL_WIDTH
|
||||
|
||||
private fun cellY(index: Int): Int = topPos + GRID_Y + (index - startIndex) / GRID_COLUMNS * CELL_HEIGHT + 2
|
||||
|
||||
private fun isScrollBarActive(): Boolean = hasOutputs && menu.getOutputs().size > GRID_COLUMNS * GRID_ROWS
|
||||
|
||||
private fun offscreenRows(): Int = (menu.getOutputs().size + GRID_COLUMNS - 1) / GRID_COLUMNS - GRID_ROWS
|
||||
|
||||
private fun onOutputsChanged() {
|
||||
hasOutputs = menu.hasInputItem()
|
||||
if (!hasOutputs) {
|
||||
scrollOffset = 0.0F
|
||||
startIndex = 0
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val SCROLLER_SPRITE = ResourceLocation.withDefaultNamespace("container/stonecutter/scroller")
|
||||
private val SCROLLER_DISABLED_SPRITE = ResourceLocation.withDefaultNamespace("container/stonecutter/scroller_disabled")
|
||||
private val SELECTED_CELL_SPRITE = ResourceLocation.withDefaultNamespace("container/stonecutter/recipe_selected")
|
||||
private val HIGHLIGHTED_CELL_SPRITE = ResourceLocation.withDefaultNamespace("container/stonecutter/recipe_highlighted")
|
||||
private val CELL_SPRITE = ResourceLocation.withDefaultNamespace("container/stonecutter/recipe")
|
||||
private val BACKGROUND = ResourceLocation.withDefaultNamespace("textures/gui/container/stonecutter.png")
|
||||
|
||||
private const val GRID_COLUMNS = 4
|
||||
private const val GRID_ROWS = 3
|
||||
private const val CELL_WIDTH = 16
|
||||
private const val CELL_HEIGHT = 18
|
||||
private const val GRID_X = 52
|
||||
private const val GRID_Y = 14
|
||||
private const val SCROLLER_X = 119
|
||||
private const val SCROLLER_Y = 15
|
||||
private const val SCROLLER_WIDTH = 12
|
||||
private const val SCROLLER_HEIGHT = 15
|
||||
private const val SCROLLER_TRAVEL = 41.0F
|
||||
private const val SCROLLER_TRACK_Y = 9
|
||||
private const val SCROLLER_TRACK_HEIGHT = 54
|
||||
}
|
||||
}
|
||||
+8
-2
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.block.DisplayCaseBlock
|
||||
import com.cobblemon.mod.common.block.entity.DisplayCaseBlockEntity
|
||||
import com.cobblemon.mod.common.client.render.modification.ModificationVariantModels
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.item.PokedexItem
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
@@ -34,6 +35,7 @@ class DisplayCaseRenderer(ctx: BlockEntityRendererProvider.Context) : BlockEntit
|
||||
val coinPouchStack: ItemStack by lazy { ItemStack(
|
||||
CobblemonItems.RELIC_COIN_POUCH
|
||||
).also { it.set(DataComponents.CUSTOM_MODEL_DATA, CustomModelData(1)) } }
|
||||
|
||||
override fun render(
|
||||
entity: DisplayCaseBlockEntity,
|
||||
tickDelta: Float,
|
||||
@@ -42,11 +44,13 @@ class DisplayCaseRenderer(ctx: BlockEntityRendererProvider.Context) : BlockEntit
|
||||
light: Int,
|
||||
overlay: Int
|
||||
) {
|
||||
ModificationVariantModels.renderBlock(entity, matrices, vertexConsumers, light, overlay)
|
||||
val stack: ItemStack = if (entity.getStack().`is`(CobblemonItems.RELIC_COIN_POUCH)) {
|
||||
coinPouchStack
|
||||
} else {
|
||||
entity.getStack()
|
||||
}
|
||||
|
||||
val world = entity.level ?: return
|
||||
val posType = getPositioningType(stack, world)
|
||||
val blockState = if (entity.level != null) entity.blockState
|
||||
@@ -167,6 +171,7 @@ class DisplayCaseRenderer(ctx: BlockEntityRendererProvider.Context) : BlockEntit
|
||||
//stack.item == CobblemonItems.POKEMON_MODEL -> PositioningType.ITEM_MODEL
|
||||
stack.item == Items.SHIELD -> PositioningType.SHIELD
|
||||
stack.item == Items.DECORATED_POT -> PositioningType.MOB_HEAD
|
||||
stack.item == CobblemonItems.DOME_FOSSIL -> PositioningType.DOME_FOSSIL
|
||||
Minecraft.getInstance().itemRenderer.getModel(stack, world, null, 0).isGui3d -> PositioningType.BLOCK_MODEL
|
||||
else -> PositioningType.ITEM_MODEL
|
||||
}
|
||||
@@ -186,6 +191,7 @@ class DisplayCaseRenderer(ctx: BlockEntityRendererProvider.Context) : BlockEntit
|
||||
MOB_HEAD(1f, 1f, 1f, 0f, -0.025f, 0f, 180f),
|
||||
SHIELD(1f, 1f, 1f, 0f, -0.045f, 0f, 180f),
|
||||
PASTURE(1f, 1f, 1f, 0f, 0.0375f, 0f),
|
||||
COIN_POUCH(1f, 1f, 1f, 0f, 0.415f, 0f)
|
||||
COIN_POUCH(1f, 1f, 1f, 0f, 0.415f, 0f),
|
||||
DOME_FOSSIL(1f, 1f, 1f, 0f, -0.15f, 0f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.block
|
||||
|
||||
import com.cobblemon.mod.common.block.entity.ModificationVariantBlockEntity
|
||||
import com.cobblemon.mod.common.client.render.modification.ModificationVariantModels
|
||||
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 ModificationVariantRenderer<T : ModificationVariantBlockEntity>(context: BlockEntityRendererProvider.Context) : BlockEntityRenderer<T> {
|
||||
override fun render(entity: T, partialTick: Float, poseStack: PoseStack, buffers: MultiBufferSource, light: Int, overlay: Int) {
|
||||
ModificationVariantModels.renderBlock(entity, poseStack, buffers, light, overlay)
|
||||
}
|
||||
|
||||
override fun shouldRenderOffScreen(entity: T): Boolean = true
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.modification
|
||||
|
||||
import com.cobblemon.mod.common.api.modification.ModificationVariant
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad
|
||||
import net.minecraft.client.renderer.block.model.ItemOverrides
|
||||
import net.minecraft.client.renderer.block.model.ItemTransform
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite
|
||||
import net.minecraft.client.resources.model.BakedModel
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.world.item.ItemDisplayContext
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import org.joml.Vector3f
|
||||
|
||||
class ModificationVariantItemModel(private val delegate: BakedModel, variant: ModificationVariant) : BakedModel {
|
||||
private val cellExtent = cellExtent(variant)
|
||||
private val scale = 1F / cellExtent
|
||||
private val center: Vector3f
|
||||
private val quadsBySide = hashMapOf<Direction?, MutableList<BakedQuad>>()
|
||||
|
||||
init {
|
||||
val min = variant.cellsMin()
|
||||
val max = variant.cellsMax()
|
||||
center = Vector3f((min.x + max.x + 1) / 2F, (min.y + max.y + 1) / 2F, (min.z + max.z + 1) / 2F)
|
||||
}
|
||||
|
||||
override fun getQuads(state: BlockState?, side: Direction?, random: RandomSource): MutableList<BakedQuad> {
|
||||
if (cellExtent <= 1) {
|
||||
return delegate.getQuads(state, side, random)
|
||||
}
|
||||
return quadsBySide.getOrPut(side) { delegate.getQuads(state, side, random).map(::scaleQuad).toMutableList() }
|
||||
}
|
||||
|
||||
override fun useAmbientOcclusion(): Boolean = delegate.useAmbientOcclusion()
|
||||
|
||||
override fun isGui3d(): Boolean = true
|
||||
|
||||
override fun usesBlockLight(): Boolean = true
|
||||
|
||||
override fun isCustomRenderer(): Boolean = delegate.isCustomRenderer
|
||||
|
||||
override fun getParticleIcon(): TextureAtlasSprite = delegate.particleIcon
|
||||
|
||||
override fun getTransforms(): ItemTransforms {
|
||||
return if (delegate.transforms.hasTransform(ItemDisplayContext.GUI)) delegate.transforms else BLOCK_TRANSFORMS
|
||||
}
|
||||
|
||||
override fun getOverrides(): ItemOverrides = delegate.overrides
|
||||
|
||||
private fun scaleQuad(quad: BakedQuad): BakedQuad {
|
||||
val vertices = quad.vertices.copyOf()
|
||||
for (vertex in 0 until VERTICES_PER_QUAD) {
|
||||
val positionIndex = vertex * VERTEX_STRIDE
|
||||
vertices[positionIndex] = scaleCoordinate(vertices[positionIndex], center.x)
|
||||
vertices[positionIndex + 1] = scaleCoordinate(vertices[positionIndex + 1], center.y)
|
||||
vertices[positionIndex + 2] = scaleCoordinate(vertices[positionIndex + 2], center.z)
|
||||
}
|
||||
return BakedQuad(vertices, quad.tintIndex, quad.direction, quad.sprite, quad.isShade)
|
||||
}
|
||||
|
||||
private fun scaleCoordinate(packed: Int, centerCoordinate: Float): Int {
|
||||
val coordinate = Float.fromBits(packed)
|
||||
return (0.5F + (coordinate - centerCoordinate) * scale).toBits()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val VERTICES_PER_QUAD = 4
|
||||
private val VERTEX_STRIDE = DefaultVertexFormat.BLOCK.vertexSize / Int.SIZE_BYTES
|
||||
private val BLOCK_TRANSFORMS = ItemTransforms(
|
||||
blockTransform(75F, 45F, 0F, 0F, 2.5F, 0F, 0.375F),
|
||||
blockTransform(75F, 45F, 0F, 0F, 2.5F, 0F, 0.375F),
|
||||
blockTransform(0F, 225F, 0F, 0F, 0F, 0F, 0.4F),
|
||||
blockTransform(0F, 45F, 0F, 0F, 0F, 0F, 0.4F),
|
||||
ItemTransform.NO_TRANSFORM,
|
||||
blockTransform(30F, 225F, 0F, 0F, 0F, 0F, 0.625F),
|
||||
blockTransform(0F, 0F, 0F, 0F, 3F, 0F, 0.25F),
|
||||
blockTransform(0F, 0F, 0F, 0F, 0F, 0F, 0.5F)
|
||||
)
|
||||
|
||||
fun cellExtent(variant: ModificationVariant): Int {
|
||||
val size = variant.cellsMax().subtract(variant.cellsMin())
|
||||
return maxOf(size.x, size.y, size.z) + 1
|
||||
}
|
||||
|
||||
private fun blockTransform(
|
||||
rotationX: Float,
|
||||
rotationY: Float,
|
||||
rotationZ: Float,
|
||||
translationX: Float,
|
||||
translationY: Float,
|
||||
translationZ: Float,
|
||||
scale: Float
|
||||
): ItemTransform = ItemTransform(
|
||||
Vector3f(rotationX, rotationY, rotationZ),
|
||||
Vector3f(translationX / 16F, translationY / 16F, translationZ / 16F),
|
||||
Vector3f(scale, scale, scale)
|
||||
)
|
||||
}
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.modification
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.modification.ModificationVariant
|
||||
import com.cobblemon.mod.common.block.entity.ModificationVariantBlockEntity
|
||||
import com.cobblemon.mod.common.api.modification.ModificationVariants
|
||||
import com.cobblemon.mod.common.block.modification.ModificationVariantBlock
|
||||
import com.cobblemon.mod.common.block.modification.ModificationVariantStructures
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.math.Axis
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.Sheets
|
||||
import net.minecraft.client.resources.model.BakedModel
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
|
||||
object ModificationVariantModels {
|
||||
private const val VARIANT_MODEL_FOLDER = "mod_station/"
|
||||
private const val STANDALONE_VARIANT = "standalone"
|
||||
private val itemModels = hashMapOf<ResourceLocation, BakedModel>()
|
||||
private val missingModelLocations = hashSetOf<ResourceLocation>()
|
||||
|
||||
@JvmStatic
|
||||
fun isVariantModel(location: ResourceLocation): Boolean {
|
||||
return location.path.startsWith("block/$VARIANT_MODEL_FOLDER") || location.path.startsWith("item/$VARIANT_MODEL_FOLDER")
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun bakedIdentifier(location: ResourceLocation): ModelResourceLocation = ModelResourceLocation(location, STANDALONE_VARIANT)
|
||||
|
||||
@JvmStatic
|
||||
fun clearCache() {
|
||||
itemModels.clear()
|
||||
missingModelLocations.clear()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun isTranslucentVariant(stack: ItemStack): Boolean = ModificationVariants.fromStack(stack)?.isTranslucent == true
|
||||
|
||||
@JvmStatic
|
||||
fun itemModel(stack: ItemStack): BakedModel? {
|
||||
val variant = ModificationVariants.fromStack(stack) ?: return null
|
||||
val model = bakedModel(variant, variant.model) ?: return null
|
||||
return itemModels.getOrPut(variant.model) { ModificationVariantItemModel(model, variant) }
|
||||
}
|
||||
|
||||
fun bakedModel(variant: ModificationVariant, modelLocation: ResourceLocation): BakedModel? {
|
||||
val modelManager = Minecraft.getInstance().modelManager
|
||||
val model = modelManager.getModel(bakedIdentifier(modelLocation))
|
||||
if (model !== modelManager.missingModel) {
|
||||
return model
|
||||
}
|
||||
if (missingModelLocations.add(modelLocation)) {
|
||||
Cobblemon.LOGGER.warn("Modification variant {} references model {} which is not under a mod_station model folder or does not exist", variant.identifier, modelLocation)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun renderBlock(entity: ModificationVariantBlockEntity, poseStack: PoseStack, buffers: MultiBufferSource, light: Int, overlay: Int) {
|
||||
val state = entity.blockState
|
||||
if (!ModificationVariantStructures.isModified(state)) {
|
||||
return
|
||||
}
|
||||
if (state.block !is ModificationVariantBlock) {
|
||||
return
|
||||
}
|
||||
val variant = entity.variant()
|
||||
val variantModel = variant?.let { bakedModel(it, it.modelFor(state)) }
|
||||
if (variantModel != null) {
|
||||
renderRotatedModel(variantModel, state, variant.isTranslucent, poseStack, buffers, light, overlay)
|
||||
return
|
||||
}
|
||||
val stockState = state.setValue(ModificationVariantBlock.MODIFIED, false)
|
||||
val stockModel = Minecraft.getInstance().blockRenderer.getBlockModel(stockState)
|
||||
val renderType = Sheets.cutoutBlockSheet()
|
||||
Minecraft.getInstance().blockRenderer.modelRenderer.renderModel(poseStack.last(), buffers.getBuffer(renderType), stockState, stockModel, 1F, 1F, 1F, light, overlay)
|
||||
}
|
||||
|
||||
private fun renderRotatedModel(
|
||||
model: BakedModel,
|
||||
state: BlockState,
|
||||
isTranslucent: Boolean,
|
||||
poseStack: PoseStack,
|
||||
buffers: MultiBufferSource,
|
||||
light: Int,
|
||||
overlay: Int
|
||||
) {
|
||||
val renderType = if (isTranslucent) Sheets.translucentCullBlockSheet() else Sheets.cutoutBlockSheet()
|
||||
poseStack.pushPose()
|
||||
poseStack.translate(0.5, 0.0, 0.5)
|
||||
poseStack.mulPose(Axis.YP.rotationDegrees(-ModificationVariantStructures.facingOf(state).toYRot()))
|
||||
poseStack.translate(-0.5, 0.0, -0.5)
|
||||
Minecraft.getInstance().blockRenderer.modelRenderer.renderModel(poseStack.last(), buffers.getBuffer(renderType), state, model, 1F, 1F, 1F, light, overlay)
|
||||
poseStack.popPose()
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,7 @@ import com.cobblemon.mod.common.api.fossil.NaturalMaterials
|
||||
import com.cobblemon.mod.common.api.interaction.PokemonInteractions
|
||||
import com.cobblemon.mod.common.api.item.HeldItems
|
||||
import com.cobblemon.mod.common.api.mark.Marks
|
||||
import com.cobblemon.mod.common.api.modification.ModificationVariants
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffects
|
||||
import com.cobblemon.mod.common.api.npc.NPCClasses
|
||||
@@ -119,6 +120,7 @@ object CobblemonDataProvider : DataProvider {
|
||||
this.register(SpawnBaitEffects, reloadable = false)
|
||||
this.register(CobblemonRideSettings, reloadable = true)
|
||||
this.register(TechnicalMachines, reloadable = false)
|
||||
this.register(ModificationVariants, reloadable = true)
|
||||
SpawnBait.Effects.setupEffects()
|
||||
|
||||
PlatformEvents.SERVER_PLAYER_LOGOUT.subscribe {
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.item.components
|
||||
|
||||
import com.mojang.serialization.Codec
|
||||
import io.netty.buffer.ByteBuf
|
||||
import net.minecraft.network.codec.ByteBufCodecs
|
||||
import net.minecraft.network.codec.StreamCodec
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
data class ModificationVariantComponent(val variant: ResourceLocation) {
|
||||
companion object {
|
||||
val CODEC: Codec<ModificationVariantComponent> = ResourceLocation.CODEC.xmap(
|
||||
::ModificationVariantComponent,
|
||||
ModificationVariantComponent::variant
|
||||
)
|
||||
|
||||
val PACKET_CODEC: StreamCodec<ByteBuf, ModificationVariantComponent> = ByteBufCodecs.fromCodec(CODEC)
|
||||
}
|
||||
}
|
||||
@@ -251,6 +251,7 @@ object CobblemonItemGroups {
|
||||
entries.accept(CobblemonItems.HEALING_MACHINE)
|
||||
entries.accept(CobblemonItems.PASTURE)
|
||||
entries.accept(CobblemonItems.TM_MACHINE)
|
||||
entries.accept(CobblemonItems.MODIFICATION_STATION)
|
||||
|
||||
entries.accept(CobblemonItems.GILDED_CHEST)
|
||||
entries.accept(CobblemonItems.YELLOW_GILDED_CHEST)
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.net.messages.client.data
|
||||
|
||||
import com.cobblemon.mod.common.api.modification.ModificationVariant
|
||||
import com.cobblemon.mod.common.api.modification.ModificationVariants
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class ModificationVariantRegistrySyncPacket(variants: Collection<ModificationVariant>) :
|
||||
DataRegistrySyncPacket<ModificationVariant, ModificationVariantRegistrySyncPacket>(variants) {
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("modification_variant_registry_sync")
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): ModificationVariantRegistrySyncPacket {
|
||||
return ModificationVariantRegistrySyncPacket(emptyList()).apply { decodeBuffer(buffer) }
|
||||
}
|
||||
}
|
||||
|
||||
override val id = ID
|
||||
|
||||
override fun encodeEntry(buffer: RegistryFriendlyByteBuf, entry: ModificationVariant) = entry.encode(buffer)
|
||||
|
||||
override fun decodeEntry(buffer: RegistryFriendlyByteBuf): ModificationVariant = ModificationVariant.decode(buffer)
|
||||
|
||||
override fun synchronizeDecoded(entries: Collection<ModificationVariant>) {
|
||||
ModificationVariants.replaceEntries(entries)
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,20 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=south": {
|
||||
"model": "cobblemon:block/display_case"
|
||||
"multipart": [
|
||||
{
|
||||
"when": { "modified": "false", "facing": "south" },
|
||||
"apply": { "model": "cobblemon:block/display_case" }
|
||||
},
|
||||
"facing=west": {
|
||||
"model": "cobblemon:block/display_case",
|
||||
"y": 90
|
||||
{
|
||||
"when": { "modified": "false", "facing": "west" },
|
||||
"apply": { "model": "cobblemon:block/display_case", "y": 90 }
|
||||
},
|
||||
"facing=north": {
|
||||
"model": "cobblemon:block/display_case",
|
||||
"y": 180
|
||||
{
|
||||
"when": { "modified": "false", "facing": "north" },
|
||||
"apply": { "model": "cobblemon:block/display_case", "y": 180 }
|
||||
},
|
||||
"facing=east": {
|
||||
"model": "cobblemon:block/display_case",
|
||||
"y": 270
|
||||
{
|
||||
"when": { "modified": "false", "facing": "east" },
|
||||
"apply": { "model": "cobblemon:block/display_case", "y": 270 }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "cobblemon:block/mod_empty"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "cobblemon:block/mod_empty"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=south": {
|
||||
"model": "cobblemon:block/modification_station"
|
||||
},
|
||||
"facing=west": {
|
||||
"model": "cobblemon:block/modification_station",
|
||||
"y": 90
|
||||
},
|
||||
"facing=north": {
|
||||
"model": "cobblemon:block/modification_station",
|
||||
"y": 180
|
||||
},
|
||||
"facing=east": {
|
||||
"model": "cobblemon:block/modification_station",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,64 +1,68 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=south,part=top,on=false": {
|
||||
"model": "cobblemon:block/pc_top"
|
||||
"multipart": [
|
||||
{
|
||||
"when": { "modified": "false", "part": "top", "on": "false", "facing": "south" },
|
||||
"apply": { "model": "cobblemon:block/pc_top" }
|
||||
},
|
||||
"facing=west,part=top,on=false": {
|
||||
"model": "cobblemon:block/pc_top",
|
||||
"y": 90
|
||||
{
|
||||
"when": { "modified": "false", "part": "top", "on": "false", "facing": "west" },
|
||||
"apply": { "model": "cobblemon:block/pc_top", "y": 90 }
|
||||
},
|
||||
"facing=north,part=top,on=false": {
|
||||
"model": "cobblemon:block/pc_top",
|
||||
"y": 180
|
||||
{
|
||||
"when": { "modified": "false", "part": "top", "on": "false", "facing": "north" },
|
||||
"apply": { "model": "cobblemon:block/pc_top", "y": 180 }
|
||||
},
|
||||
"facing=east,part=top,on=false": {
|
||||
"model": "cobblemon:block/pc_top",
|
||||
"y": 270
|
||||
{
|
||||
"when": { "modified": "false", "part": "top", "on": "false", "facing": "east" },
|
||||
"apply": { "model": "cobblemon:block/pc_top", "y": 270 }
|
||||
},
|
||||
"facing=south,part=top,on=true": {
|
||||
"model": "cobblemon:block/pc_top_on"
|
||||
{
|
||||
"when": { "modified": "false", "part": "top", "on": "true", "facing": "south" },
|
||||
"apply": { "model": "cobblemon:block/pc_top_on" }
|
||||
},
|
||||
"facing=west,part=top,on=true": {
|
||||
"model": "cobblemon:block/pc_top_on",
|
||||
"y": 90
|
||||
{
|
||||
"when": { "modified": "false", "part": "top", "on": "true", "facing": "west" },
|
||||
"apply": { "model": "cobblemon:block/pc_top_on", "y": 90 }
|
||||
},
|
||||
"facing=north,part=top,on=true": {
|
||||
"model": "cobblemon:block/pc_top_on",
|
||||
"y": 180
|
||||
{
|
||||
"when": { "modified": "false", "part": "top", "on": "true", "facing": "north" },
|
||||
"apply": { "model": "cobblemon:block/pc_top_on", "y": 180 }
|
||||
},
|
||||
"facing=east,part=top,on=true": {
|
||||
"model": "cobblemon:block/pc_top_on",
|
||||
"y": 270
|
||||
{
|
||||
"when": { "modified": "false", "part": "top", "on": "true", "facing": "east" },
|
||||
"apply": { "model": "cobblemon:block/pc_top_on", "y": 270 }
|
||||
},
|
||||
"facing=south,part=bottom,on=false": {
|
||||
"model": "cobblemon:block/pc_bottom"
|
||||
{
|
||||
"when": { "modified": "false", "part": "bottom", "on": "false", "facing": "south" },
|
||||
"apply": { "model": "cobblemon:block/pc_bottom" }
|
||||
},
|
||||
"facing=west,part=bottom,on=false": {
|
||||
"model": "cobblemon:block/pc_bottom",
|
||||
"y": 90
|
||||
{
|
||||
"when": { "modified": "false", "part": "bottom", "on": "false", "facing": "west" },
|
||||
"apply": { "model": "cobblemon:block/pc_bottom", "y": 90 }
|
||||
},
|
||||
"facing=north,part=bottom,on=false": {
|
||||
"model": "cobblemon:block/pc_bottom",
|
||||
"y": 180
|
||||
{
|
||||
"when": { "modified": "false", "part": "bottom", "on": "false", "facing": "north" },
|
||||
"apply": { "model": "cobblemon:block/pc_bottom", "y": 180 }
|
||||
},
|
||||
"facing=east,part=bottom,on=false": {
|
||||
"model": "cobblemon:block/pc_bottom",
|
||||
"y": 270
|
||||
{
|
||||
"when": { "modified": "false", "part": "bottom", "on": "false", "facing": "east" },
|
||||
"apply": { "model": "cobblemon:block/pc_bottom", "y": 270 }
|
||||
},
|
||||
"facing=south,part=bottom,on=true": {
|
||||
"model": "cobblemon:block/pc_bottom"
|
||||
{
|
||||
"when": { "modified": "false", "part": "bottom", "on": "true", "facing": "south" },
|
||||
"apply": { "model": "cobblemon:block/pc_bottom" }
|
||||
},
|
||||
"facing=west,part=bottom,on=true": {
|
||||
"model": "cobblemon:block/pc_bottom",
|
||||
"y": 90
|
||||
{
|
||||
"when": { "modified": "false", "part": "bottom", "on": "true", "facing": "west" },
|
||||
"apply": { "model": "cobblemon:block/pc_bottom", "y": 90 }
|
||||
},
|
||||
"facing=north,part=bottom,on=true": {
|
||||
"model": "cobblemon:block/pc_bottom",
|
||||
"y": 180
|
||||
{
|
||||
"when": { "modified": "false", "part": "bottom", "on": "true", "facing": "north" },
|
||||
"apply": { "model": "cobblemon:block/pc_bottom", "y": 180 }
|
||||
},
|
||||
"facing=east,part=bottom,on=true": {
|
||||
"model": "cobblemon:block/pc_bottom",
|
||||
"y": 270
|
||||
{
|
||||
"when": { "modified": "false", "part": "bottom", "on": "true", "facing": "east" },
|
||||
"apply": { "model": "cobblemon:block/pc_bottom", "y": 270 }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -989,6 +989,7 @@
|
||||
"block.cobblemon.campfire_pot_white": "White Campfire Pot",
|
||||
"block.cobblemon.campfire_pot_yellow": "Yellow Campfire Pot",
|
||||
"block.cobblemon.tm_machine": "TM Machine",
|
||||
"block.cobblemon.modification_station": "Modification Station",
|
||||
"block.cobblemon.hearty_grain_bale": "Hearty Grain Bale",
|
||||
"block.cobblemon.tatami_block": "Tatami",
|
||||
"block.cobblemon.tatami_mat": "Tatami Mat",
|
||||
@@ -1184,6 +1185,7 @@
|
||||
"cobblemon.container.campfire_pot": "Campfire Pot",
|
||||
"cobblemon.container.campfire_pot.recipe_book.toggle_recipes": "Showing Cookable",
|
||||
"cobblemon.container.tm_machine": "TM Machine",
|
||||
"container.cobblemon.modification_station": "Modification Station",
|
||||
|
||||
"cobblemon.ui.pokenav.title": "PokéNav",
|
||||
"cobblemon.ui.pokenav.narrator.backbutton": "Poke Nav button pressed",
|
||||
@@ -9573,5 +9575,64 @@
|
||||
"stat.cobblemon.reel_ins": "PokéRod Catches",
|
||||
"stat.cobblemon.riding_land": "Distance by Pokémon on Land",
|
||||
"stat.cobblemon.riding_air": "Distance by Pokémon in Air",
|
||||
"stat.cobblemon.riding_liquid": "Distance by Pokémon in Liquid"
|
||||
"stat.cobblemon.riding_liquid": "Distance by Pokémon in Liquid",
|
||||
"block.cobblemon.mod_variant": "Variant",
|
||||
"block.cobblemon.mod_filler": "Variant Part",
|
||||
"modification_variant.cobblemon.pc_hgss": "HeartGold & SoulSilver PC",
|
||||
"modification_variant.cobblemon.pc_sm": "Sun & Moon PC",
|
||||
"modification_variant.cobblemon.pc_xd": "XD PC",
|
||||
"modification_variant.cobblemon.pc_bw": "Black & White PC",
|
||||
"modification_variant.cobblemon.pc_dppt": "Diamond, Pearl & Platinum PC",
|
||||
"modification_variant.cobblemon.pc_oras": "Omega Ruby & Alpha Sapphire PC",
|
||||
"modification_variant.cobblemon.pc_swsh": "Sword & Shield PC",
|
||||
"modification_variant.cobblemon.dome_fossil_block_1": "Dome Fossil Display",
|
||||
"modification_variant.cobblemon.dome_fossil_block_2": "Dome Fossil Slab",
|
||||
"modification_variant.cobblemon.display_case_stone_glass_color_1": "Glass Display Case 1",
|
||||
"modification_variant.cobblemon.display_case_stone_no_glass_color_1": "Open Display Case 1",
|
||||
"modification_variant.cobblemon.display_case_stone_tinted_glass_color_1": "Tinted Glass Display Case 1",
|
||||
"modification_variant.cobblemon.display_case_stone_glass_color_2": "Glass Display Case 2",
|
||||
"modification_variant.cobblemon.display_case_stone_no_glass_color_2": "Open Display Case 2",
|
||||
"modification_variant.cobblemon.display_case_stone_tinted_glass_color_2": "Tinted Glass Display Case 2",
|
||||
"modification_variant.cobblemon.display_case_stone_glass_color_3": "Glass Display Case 3",
|
||||
"modification_variant.cobblemon.display_case_stone_no_glass_color_3": "Open Display Case 3",
|
||||
"modification_variant.cobblemon.display_case_stone_tinted_glass_color_3": "Tinted Glass Display Case 3",
|
||||
"modification_variant.cobblemon.display_case_stone_glass_color_4": "Glass Display Case 4",
|
||||
"modification_variant.cobblemon.display_case_stone_no_glass_color_4": "Open Display Case 4",
|
||||
"modification_variant.cobblemon.display_case_stone_tinted_glass_color_4": "Tinted Glass Display Case 4",
|
||||
"modification_variant.cobblemon.display_case_stone_glass_color_5": "Glass Display Case 5",
|
||||
"modification_variant.cobblemon.display_case_stone_no_glass_color_5": "Open Display Case 5",
|
||||
"modification_variant.cobblemon.display_case_stone_tinted_glass_color_5": "Tinted Glass Display Case 5",
|
||||
"modification_variant.cobblemon.display_case_stone_glass_color_6": "Glass Display Case 6",
|
||||
"modification_variant.cobblemon.display_case_stone_no_glass_color_6": "Open Display Case 6",
|
||||
"modification_variant.cobblemon.display_case_stone_tinted_glass_color_6": "Tinted Glass Display Case 6",
|
||||
"modification_variant.cobblemon.display_case_stone_glass_color_7": "Glass Display Case 7",
|
||||
"modification_variant.cobblemon.display_case_stone_no_glass_color_7": "Open Display Case 7",
|
||||
"modification_variant.cobblemon.display_case_stone_tinted_glass_color_7": "Tinted Glass Display Case 7",
|
||||
"modification_variant.cobblemon.display_case_stone_glass_color_8": "Glass Display Case 8",
|
||||
"modification_variant.cobblemon.display_case_stone_no_glass_color_8": "Open Display Case 8",
|
||||
"modification_variant.cobblemon.display_case_stone_tinted_glass_color_8": "Tinted Glass Display Case 8",
|
||||
"modification_variant.cobblemon.display_case_stone_glass_color_9": "Glass Display Case 9",
|
||||
"modification_variant.cobblemon.display_case_stone_no_glass_color_9": "Open Display Case 9",
|
||||
"modification_variant.cobblemon.display_case_stone_tinted_glass_color_9": "Tinted Glass Display Case 9",
|
||||
"modification_variant.cobblemon.display_case_stone_glass_color_10": "Glass Display Case 10",
|
||||
"modification_variant.cobblemon.display_case_stone_no_glass_color_10": "Open Display Case 10",
|
||||
"modification_variant.cobblemon.display_case_stone_tinted_glass_color_10": "Tinted Glass Display Case 10",
|
||||
"modification_variant.cobblemon.display_case_stone_glass_color_11": "Glass Display Case 11",
|
||||
"modification_variant.cobblemon.display_case_stone_no_glass_color_11": "Open Display Case 11",
|
||||
"modification_variant.cobblemon.display_case_stone_tinted_glass_color_11": "Tinted Glass Display Case 11",
|
||||
"modification_variant.cobblemon.display_case_stone_glass_color_12": "Glass Display Case 12",
|
||||
"modification_variant.cobblemon.display_case_stone_no_glass_color_12": "Open Display Case 12",
|
||||
"modification_variant.cobblemon.display_case_stone_tinted_glass_color_12": "Tinted Glass Display Case 12",
|
||||
"modification_variant.cobblemon.display_case_stone_glass_color_13": "Glass Display Case 13",
|
||||
"modification_variant.cobblemon.display_case_stone_no_glass_color_13": "Open Display Case 13",
|
||||
"modification_variant.cobblemon.display_case_stone_tinted_glass_color_13": "Tinted Glass Display Case 13",
|
||||
"modification_variant.cobblemon.display_case_stone_glass_color_14": "Glass Display Case 14",
|
||||
"modification_variant.cobblemon.display_case_stone_no_glass_color_14": "Open Display Case 14",
|
||||
"modification_variant.cobblemon.display_case_stone_tinted_glass_color_14": "Tinted Glass Display Case 14",
|
||||
"modification_variant.cobblemon.display_case_stone_glass_color_15": "Glass Display Case 15",
|
||||
"modification_variant.cobblemon.display_case_stone_no_glass_color_15": "Open Display Case 15",
|
||||
"modification_variant.cobblemon.display_case_stone_tinted_glass_color_15": "Tinted Glass Display Case 15",
|
||||
"modification_variant.cobblemon.display_case_stone_glass_color_16": "Glass Display Case 16",
|
||||
"modification_variant.cobblemon.display_case_stone_no_glass_color_16": "Open Display Case 16",
|
||||
"modification_variant.cobblemon.display_case_stone_tinted_glass_color_16": "Tinted Glass Display Case 16"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"textures": {
|
||||
"particle": "minecraft:block/stone"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_1"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_10"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_11"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_12"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_13"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_14"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_15"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_16"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_2"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_3"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_4"
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"format_version": "1.9.0",
|
||||
"credit": "Made with Blockbench",
|
||||
"textures": {
|
||||
"0": "cobblemon:block/functional/display_case_bottom",
|
||||
"1": "cobblemon:block/functional/display_case_side",
|
||||
"2": "cobblemon:block/functional/display_case_top",
|
||||
"3": "cobblemon:block/functional/display_case_internal",
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_5",
|
||||
"particle": "cobblemon:block/functional/display_case_bottom"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"name": "cushion",
|
||||
"from": [2, 4, 2],
|
||||
"to": [14, 5, 14],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 4, 2]},
|
||||
"faces": {
|
||||
"north": {"uv": [1, 13, 13, 14], "texture": "#8"},
|
||||
"east": {"uv": [0, 1, 1, 13], "rotation": 270, "texture": "#8"},
|
||||
"south": {"uv": [1, 0, 13, 1], "rotation": 180, "texture": "#8"},
|
||||
"west": {"uv": [13, 1, 14, 13], "rotation": 90, "texture": "#8"},
|
||||
"up": {"uv": [13, 13, 1, 1], "texture": "#8"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "base",
|
||||
"from": [0, 0, 0],
|
||||
"to": [16, 4, 16],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 12, 16, 16], "texture": "#1", "cullface": "north"},
|
||||
"east": {"uv": [0, 12, 16, 16], "texture": "#1", "cullface": "north"},
|
||||
"south": {"uv": [0, 12, 16, 16], "texture": "#1", "cullface": "north"},
|
||||
"west": {"uv": [0, 12, 16, 16], "texture": "#1", "cullface": "north"},
|
||||
"up": {"uv": [0, 0, 16, 16], "texture": "#3"},
|
||||
"down": {"uv": [0, 0, 16, 16], "texture": "#0", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "glass",
|
||||
"from": [0, 4, 0],
|
||||
"to": [16, 16, 16],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 16, 12], "texture": "#1", "cullface": "north"},
|
||||
"east": {"uv": [0, 0, 16, 12], "texture": "#1", "cullface": "east"},
|
||||
"south": {"uv": [0, 0, 16, 12], "texture": "#1", "cullface": "south"},
|
||||
"west": {"uv": [0, 0, 16, 12], "texture": "#1", "cullface": "west"},
|
||||
"up": {"uv": [0, 0, 16, 16], "texture": "#2", "cullface": "up"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "glass_int",
|
||||
"from": [15.975, 15.975, 15.975],
|
||||
"to": [0.025, 4, 0.025],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 12, 16, 0], "texture": "#1", "cullface": "south"},
|
||||
"east": {"uv": [0, 12, 16, 0], "texture": "#1", "cullface": "west"},
|
||||
"south": {"uv": [0, 12, 16, 0], "texture": "#1", "cullface": "north"},
|
||||
"west": {"uv": [0, 12, 16, 0], "texture": "#1", "cullface": "east"},
|
||||
"down": {"uv": [16, 0, 0, 16], "texture": "#1", "cullface": "up"}
|
||||
}
|
||||
}
|
||||
],
|
||||
"display": {
|
||||
"thirdperson_righthand": {
|
||||
"rotation": [75, 135, 0],
|
||||
"translation": [0, 2.5, 0],
|
||||
"scale": [0.375, 0.375, 0.375]
|
||||
},
|
||||
"firstperson_righthand": {
|
||||
"rotation": [0, 135, 0],
|
||||
"scale": [0.4, 0.4, 0.4]
|
||||
},
|
||||
"firstperson_lefthand": {
|
||||
"rotation": [0, 135, 0],
|
||||
"scale": [0.4, 0.4, 0.4]
|
||||
},
|
||||
"ground": {
|
||||
"translation": [0, 3, 0],
|
||||
"scale": [0.25, 0.25, 0.25]
|
||||
},
|
||||
"gui": {
|
||||
"rotation": [30, -135, 0],
|
||||
"scale": [0.625, 0.625, 0.625]
|
||||
},
|
||||
"fixed": {
|
||||
"scale": [0.5, 0.5, 0.5]
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_6"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_7"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_8"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_9"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_no_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_1"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_no_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_10"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_no_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_11"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_no_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_12"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_no_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_13"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_no_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_14"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_no_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_15"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_no_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_16"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_no_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_2"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_no_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_3"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_no_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_4"
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"format_version": "1.9.0",
|
||||
"credit": "Made with Blockbench",
|
||||
"textures": {
|
||||
"0": "cobblemon:block/functional/display_case_bottom",
|
||||
"1": "cobblemon:block/functional/display_case_side",
|
||||
"3": "cobblemon:block/functional/display_case_internal",
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_5",
|
||||
"particle": "cobblemon:block/functional/display_case_bottom"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"name": "cushion",
|
||||
"from": [2, 4, 2],
|
||||
"to": [14, 5, 14],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 4, 2]},
|
||||
"faces": {
|
||||
"north": {"uv": [1, 13, 13, 14], "texture": "#8"},
|
||||
"east": {"uv": [0, 1, 1, 13], "rotation": 270, "texture": "#8"},
|
||||
"south": {"uv": [1, 0, 13, 1], "rotation": 180, "texture": "#8"},
|
||||
"west": {"uv": [13, 1, 14, 13], "rotation": 90, "texture": "#8"},
|
||||
"up": {"uv": [13, 13, 1, 1], "texture": "#8"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "base",
|
||||
"from": [0, 0, 0],
|
||||
"to": [16, 4, 16],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 12, 16, 16], "texture": "#1", "cullface": "north"},
|
||||
"east": {"uv": [0, 12, 16, 16], "texture": "#1", "cullface": "north"},
|
||||
"south": {"uv": [0, 12, 16, 16], "texture": "#1", "cullface": "north"},
|
||||
"west": {"uv": [0, 12, 16, 16], "texture": "#1", "cullface": "north"},
|
||||
"up": {"uv": [0, 0, 16, 16], "texture": "#3"},
|
||||
"down": {"uv": [0, 0, 16, 16], "texture": "#0", "cullface": "down"}
|
||||
}
|
||||
}
|
||||
],
|
||||
"display": {
|
||||
"thirdperson_righthand": {
|
||||
"rotation": [75, 135, 0],
|
||||
"translation": [0, 2.5, 0],
|
||||
"scale": [0.375, 0.375, 0.375]
|
||||
},
|
||||
"firstperson_righthand": {
|
||||
"rotation": [0, 135, 0],
|
||||
"scale": [0.4, 0.4, 0.4]
|
||||
},
|
||||
"firstperson_lefthand": {
|
||||
"rotation": [0, 135, 0],
|
||||
"scale": [0.4, 0.4, 0.4]
|
||||
},
|
||||
"ground": {
|
||||
"translation": [0, 3, 0],
|
||||
"scale": [0.25, 0.25, 0.25]
|
||||
},
|
||||
"gui": {
|
||||
"rotation": [30, -135, 0],
|
||||
"scale": [0.625, 0.625, 0.625]
|
||||
},
|
||||
"fixed": {
|
||||
"scale": [0.5, 0.5, 0.5]
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_no_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_6"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_no_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_7"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_no_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_8"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_no_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_9"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_tinted_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_1"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_tinted_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_10"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_tinted_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_11"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_tinted_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_12"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_tinted_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_13"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_tinted_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_14"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_tinted_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_15"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_tinted_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_16"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_tinted_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_2"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_tinted_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_3"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_tinted_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_4"
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"format_version": "1.9.0",
|
||||
"credit": "Made with Blockbench",
|
||||
"textures": {
|
||||
"0": "cobblemon:block/functional/display_case_bottom",
|
||||
"1": "cobblemon:block/mod_station/display_case/display_case_side_tinted_glass",
|
||||
"2": "cobblemon:block/mod_station/display_case/display_case_top_tinted_glass",
|
||||
"3": "cobblemon:block/functional/display_case_internal",
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_5",
|
||||
"particle": "cobblemon:block/functional/display_case_bottom"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"name": "cushion",
|
||||
"from": [2, 4, 2],
|
||||
"to": [14, 5, 14],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 4, 2]},
|
||||
"faces": {
|
||||
"north": {"uv": [1, 13, 13, 14], "texture": "#8"},
|
||||
"east": {"uv": [0, 1, 1, 13], "rotation": 270, "texture": "#8"},
|
||||
"south": {"uv": [1, 0, 13, 1], "rotation": 180, "texture": "#8"},
|
||||
"west": {"uv": [13, 1, 14, 13], "rotation": 90, "texture": "#8"},
|
||||
"up": {"uv": [13, 13, 1, 1], "texture": "#8"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "base",
|
||||
"from": [0, 0, 0],
|
||||
"to": [16, 4, 16],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 12, 16, 16], "texture": "#1", "cullface": "north"},
|
||||
"east": {"uv": [0, 12, 16, 16], "texture": "#1", "cullface": "north"},
|
||||
"south": {"uv": [0, 12, 16, 16], "texture": "#1", "cullface": "north"},
|
||||
"west": {"uv": [0, 12, 16, 16], "texture": "#1", "cullface": "north"},
|
||||
"up": {"uv": [0, 0, 16, 16], "texture": "#3"},
|
||||
"down": {"uv": [0, 0, 16, 16], "texture": "#0", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "glass",
|
||||
"from": [0, 4, 0],
|
||||
"to": [16, 16, 16],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 16, 12], "texture": "#1", "cullface": "north"},
|
||||
"east": {"uv": [0, 0, 16, 12], "texture": "#1", "cullface": "east"},
|
||||
"south": {"uv": [0, 0, 16, 12], "texture": "#1", "cullface": "south"},
|
||||
"west": {"uv": [0, 0, 16, 12], "texture": "#1", "cullface": "west"},
|
||||
"up": {"uv": [0, 0, 16, 16], "texture": "#2", "cullface": "up"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "glass_int",
|
||||
"from": [15.975, 15.975, 15.975],
|
||||
"to": [0.025, 4, 0.025],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 12, 16, 0], "texture": "#1", "cullface": "south"},
|
||||
"east": {"uv": [0, 12, 16, 0], "texture": "#1", "cullface": "west"},
|
||||
"south": {"uv": [0, 12, 16, 0], "texture": "#1", "cullface": "north"},
|
||||
"west": {"uv": [0, 12, 16, 0], "texture": "#1", "cullface": "east"},
|
||||
"down": {"uv": [16, 0, 0, 16], "texture": "#1", "cullface": "up"}
|
||||
}
|
||||
}
|
||||
],
|
||||
"display": {
|
||||
"thirdperson_righthand": {
|
||||
"rotation": [75, 135, 0],
|
||||
"translation": [0, 2.5, 0],
|
||||
"scale": [0.375, 0.375, 0.375]
|
||||
},
|
||||
"firstperson_righthand": {
|
||||
"rotation": [0, 135, 0],
|
||||
"scale": [0.4, 0.4, 0.4]
|
||||
},
|
||||
"firstperson_lefthand": {
|
||||
"rotation": [0, 135, 0],
|
||||
"scale": [0.4, 0.4, 0.4]
|
||||
},
|
||||
"ground": {
|
||||
"translation": [0, 3, 0],
|
||||
"scale": [0.25, 0.25, 0.25]
|
||||
},
|
||||
"gui": {
|
||||
"rotation": [30, -135, 0],
|
||||
"scale": [0.625, 0.625, 0.625]
|
||||
},
|
||||
"fixed": {
|
||||
"scale": [0.5, 0.5, 0.5]
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_tinted_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_6"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_tinted_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_7"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_tinted_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_8"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "cobblemon:block/mod_station/display_case/display_case_stone_tinted_glass_color_5",
|
||||
"textures": {
|
||||
"8": "cobblemon:block/mod_station/display_case/display_case_pillow_9"
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"textures": {
|
||||
"0": "cobblemon:block/mod_station/dome_fossil/dome_fossil_block_1",
|
||||
"particle": "cobblemon:block/mod_station/dome_fossil/dome_fossil_block_1"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [4, -0.25, 3],
|
||||
"to": [12, 1.75, 13],
|
||||
"rotation": {
|
||||
"angle": 0,
|
||||
"axis": "y",
|
||||
"origin": [8, -0.75, 8.5]
|
||||
},
|
||||
"faces": {
|
||||
"north": {"uv": [2.5, 12.5, 4.5, 13], "texture": "#0"},
|
||||
"east": {"uv": [0, 12.5, 2.5, 13], "texture": "#0"},
|
||||
"south": {"uv": [7, 12.5, 9, 13], "texture": "#0"},
|
||||
"west": {"uv": [4.5, 12.5, 7, 13], "texture": "#0"},
|
||||
"up": {"uv": [4.5, 12.5, 2.5, 10], "texture": "#0"},
|
||||
"down": {"uv": [6.5, 10, 4.5, 12.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [4.5, -0.25, 4],
|
||||
"to": [11.5, 2.75, 12],
|
||||
"rotation": {
|
||||
"angle": 0,
|
||||
"axis": "y",
|
||||
"origin": [8, -0.75, 8.5]
|
||||
},
|
||||
"faces": {
|
||||
"north": {"uv": [2, 4.75, 3.75, 5.5], "texture": "#0"},
|
||||
"east": {"uv": [0, 4.75, 2, 5.5], "texture": "#0"},
|
||||
"south": {"uv": [5.75, 4.75, 7.5, 5.5], "texture": "#0"},
|
||||
"west": {"uv": [3.75, 4.75, 5.75, 5.5], "texture": "#0"},
|
||||
"up": {"uv": [3.75, 4.75, 2, 2.75], "texture": "#0"},
|
||||
"down": {"uv": [5.5, 2.75, 3.75, 4.75], "texture": "#0"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
{
|
||||
"textures": {
|
||||
"0": "cobblemon:block/mod_station/dome_fossil/dome_fossil_block_1",
|
||||
"particle": "cobblemon:block/mod_station/dome_fossil/dome_fossil_block_1"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [4, 2.75, 3],
|
||||
"to": [12, 4.75, 13],
|
||||
"rotation": {
|
||||
"angle": 0,
|
||||
"axis": "y",
|
||||
"origin": [8, 2.25, 8.5]
|
||||
},
|
||||
"faces": {
|
||||
"north": {"uv": [2.5, 12.5, 4.5, 13], "texture": "#0"},
|
||||
"east": {"uv": [0, 12.5, 2.5, 13], "texture": "#0"},
|
||||
"south": {"uv": [7, 12.5, 9, 13], "texture": "#0"},
|
||||
"west": {"uv": [4.5, 12.5, 7, 13], "texture": "#0"},
|
||||
"up": {"uv": [4.5, 12.5, 2.5, 10], "texture": "#0"},
|
||||
"down": {"uv": [6.5, 10, 4.5, 12.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [4.5, 2.75, 4],
|
||||
"to": [11.5, 5.75, 12],
|
||||
"rotation": {
|
||||
"angle": 0,
|
||||
"axis": "y",
|
||||
"origin": [8, 2.25, 8.5]
|
||||
},
|
||||
"faces": {
|
||||
"north": {"uv": [2, 4.75, 3.75, 5.5], "texture": "#0"},
|
||||
"east": {"uv": [0, 4.75, 2, 5.5], "texture": "#0"},
|
||||
"south": {"uv": [5.75, 4.75, 7.5, 5.5], "texture": "#0"},
|
||||
"west": {"uv": [3.75, 4.75, 5.75, 5.5], "texture": "#0"},
|
||||
"up": {"uv": [3.75, 4.75, 2, 2.75], "texture": "#0"},
|
||||
"down": {"uv": [5.5, 2.75, 3.75, 4.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [2, 0, 0],
|
||||
"to": [13, 4, 14],
|
||||
"rotation": {
|
||||
"angle": 0,
|
||||
"axis": "y",
|
||||
"origin": [8, 0, 8]
|
||||
},
|
||||
"faces": {
|
||||
"north": {"uv": [7.5, 2.75, 10.25, 3.75], "texture": "#0"},
|
||||
"east": {"uv": [5.5, 5.5, 9, 6.5], "texture": "#0"},
|
||||
"south": {"uv": [7.5, 3.75, 10.25, 4.75], "texture": "#0"},
|
||||
"west": {"uv": [5.5, 6.5, 9, 7.5], "texture": "#0"},
|
||||
"up": {"uv": [2.75, 9, 0, 5.5], "texture": "#0"},
|
||||
"down": {"uv": [5.5, 5.5, 2.75, 9], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [4, 0, 14],
|
||||
"to": [13, 4, 16],
|
||||
"rotation": {
|
||||
"angle": 0,
|
||||
"axis": "y",
|
||||
"origin": [8, 0, 8]
|
||||
},
|
||||
"faces": {
|
||||
"north": {"uv": [5.5, 7.5, 7.75, 8.5], "texture": "#0"},
|
||||
"east": {"uv": [2.5, 9, 3, 10], "texture": "#0"},
|
||||
"south": {"uv": [7.75, 7.5, 10, 8.5], "texture": "#0"},
|
||||
"west": {"uv": [3, 9, 3.5, 10], "texture": "#0"},
|
||||
"up": {"uv": [9.75, 5.25, 7.5, 4.75], "texture": "#0"},
|
||||
"down": {"uv": [10.75, 0, 8.5, 0.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [13, 0, 3],
|
||||
"to": [16, 3, 9],
|
||||
"rotation": {
|
||||
"angle": 0,
|
||||
"axis": "y",
|
||||
"origin": [8, 0, 8]
|
||||
},
|
||||
"faces": {
|
||||
"north": {"uv": [1, 9, 1.75, 9.75], "texture": "#0"},
|
||||
"east": {"uv": [8.5, 0.5, 10, 1.25], "texture": "#0"},
|
||||
"south": {"uv": [1.75, 9, 2.5, 9.75], "texture": "#0"},
|
||||
"west": {"uv": [8.5, 1.25, 10, 2], "texture": "#0"},
|
||||
"up": {"uv": [6.25, 10, 5.5, 8.5], "texture": "#0"},
|
||||
"down": {"uv": [7, 8.5, 6.25, 10], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [0, 0, 1],
|
||||
"to": [2, 2, 10],
|
||||
"rotation": {
|
||||
"angle": 0,
|
||||
"axis": "y",
|
||||
"origin": [8, 0, 8]
|
||||
},
|
||||
"faces": {
|
||||
"north": {"uv": [3.5, 9, 4, 9.5], "texture": "#0"},
|
||||
"east": {"uv": [8.5, 2, 10.75, 2.5], "texture": "#0"},
|
||||
"south": {"uv": [4, 9, 4.5, 9.5], "texture": "#0"},
|
||||
"west": {"uv": [7, 8.5, 9.25, 9], "texture": "#0"},
|
||||
"up": {"uv": [0.5, 11.25, 0, 9], "texture": "#0"},
|
||||
"down": {"uv": [1, 9, 0.5, 11.25], "texture": "#0"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
{
|
||||
"format_version": "1.21.11",
|
||||
"credit": "Made with Blockbench",
|
||||
"texture_size": [64, 64],
|
||||
"textures": {
|
||||
"2": "cobblemon:block/mod_station/pc/pc_bw",
|
||||
"particle": "cobblemon:block/mod_station/pc/pc_bw"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"name": "main",
|
||||
"from": [2, 15, 7],
|
||||
"to": [14, 31, 15],
|
||||
"faces": {
|
||||
"north": {"uv": [3, 8.25, 6, 12.25], "texture": "#2"},
|
||||
"east": {"uv": [0.25, 8.25, 2.25, 12.25], "texture": "#2"},
|
||||
"south": {"uv": [9.5, 8.25, 12.5, 12.25], "texture": "#2"},
|
||||
"west": {"uv": [6.75, 8.25, 8.75, 12.25], "texture": "#2"},
|
||||
"up": {"uv": [6, 7.25, 3, 5.25], "texture": "#2"},
|
||||
"down": {"uv": [12.5, 5.25, 9.5, 8], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "extrusion",
|
||||
"from": [0, 17.9, 10],
|
||||
"to": [2, 25.9, 12],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 0.4, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [6, 9.5, 6.5, 11.5], "texture": "#2"},
|
||||
"east": {"uv": [1, 9.5, 1.5, 11.5], "texture": "#2"},
|
||||
"south": {"uv": [9, 9.5, 9.5, 11.5], "texture": "#2"},
|
||||
"west": {"uv": [7.5, 9.5, 8, 11.5], "texture": "#2"},
|
||||
"up": {"uv": [6.5, 6.5, 6, 6], "texture": "#2"},
|
||||
"down": {"uv": [13, 6, 12.5, 6.5], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "extrusion",
|
||||
"from": [14, 17.9, 10],
|
||||
"to": [16, 25.9, 12],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 0.4, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [2.5, 9.5, 3, 11.5], "texture": "#2"},
|
||||
"east": {"uv": [1, 9.5, 1.5, 11.5], "texture": "#2"},
|
||||
"south": {"uv": [12.5, 9.5, 13, 11.5], "texture": "#2"},
|
||||
"west": {"uv": [7.5, 9.5, 8, 11.5], "texture": "#2"},
|
||||
"up": {"uv": [3, 6.5, 2.5, 6], "texture": "#2"},
|
||||
"down": {"uv": [9.5, 6, 9, 6.5], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "main",
|
||||
"from": [1.99, 8.99, 3.99],
|
||||
"to": [14.01, 15.01, 15.01],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 0, -1]},
|
||||
"faces": {
|
||||
"north": {"uv": [3, 12.25, 6, 13.75], "texture": "#2"},
|
||||
"east": {"uv": [0.25, 12.25, 3, 13.75], "texture": "#2"},
|
||||
"south": {"uv": [9.5, 12.25, 12.5, 13.75], "texture": "#2"},
|
||||
"west": {"uv": [6, 12.25, 8.75, 13.75], "texture": "#2"},
|
||||
"up": {"uv": [6, 8, 3, 5.25], "texture": "#2"},
|
||||
"down": {"uv": [12.5, 5.25, 9.5, 8], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "base",
|
||||
"from": [4, 0, 7],
|
||||
"to": [12, 2, 13],
|
||||
"faces": {
|
||||
"north": {"uv": [3.5, 15.5, 5.5, 16], "texture": "#2"},
|
||||
"east": {"uv": [0.75, 15.5, 2.25, 16], "texture": "#2"},
|
||||
"south": {"uv": [10, 15.5, 12, 16], "texture": "#2"},
|
||||
"west": {"uv": [6.75, 15.5, 8.25, 16], "texture": "#2"},
|
||||
"up": {"uv": [8.75, 6.75, 6.75, 5.25], "texture": "#2"},
|
||||
"down": {"uv": [8.75, 6.75, 6.75, 8.25], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "pole",
|
||||
"from": [6, 2, 9],
|
||||
"to": [10, 9, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [4, 13.75, 5, 15.5], "texture": "#2"},
|
||||
"east": {"uv": [1.25, 13.75, 1.75, 15.5], "texture": "#2"},
|
||||
"south": {"uv": [10.5, 13.75, 11.5, 15.5], "texture": "#2"},
|
||||
"west": {"uv": [7.25, 13.75, 7.75, 15.5], "texture": "#2"},
|
||||
"up": {"uv": [5.75, 11.375, 5.25, 11.125], "texture": "#2"},
|
||||
"down": {"uv": [5.75, 11.125, 5.25, 11.375], "texture": "#2"}
|
||||
}
|
||||
}
|
||||
],
|
||||
"groups": [
|
||||
{
|
||||
"name": "PC_BW",
|
||||
"origin": [0, 0, 0],
|
||||
"scope": 0,
|
||||
"color": 0,
|
||||
"children": [
|
||||
{
|
||||
"name": "top_half",
|
||||
"origin": [0, 0, 0],
|
||||
"scope": 0,
|
||||
"color": 0,
|
||||
"children": [0, 1, 2]
|
||||
},
|
||||
{
|
||||
"name": "bottom_half",
|
||||
"origin": [0, 0, 0],
|
||||
"scope": 0,
|
||||
"color": 0,
|
||||
"children": [3]
|
||||
},
|
||||
{
|
||||
"name": "stand",
|
||||
"origin": [0, 0, 0],
|
||||
"scope": 0,
|
||||
"color": 0,
|
||||
"children": [4, 5]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
{
|
||||
"format_version": "1.21.11",
|
||||
"credit": "Made with Blockbench",
|
||||
"texture_size": [64, 64],
|
||||
"textures": {
|
||||
"2": "cobblemon:block/mod_station/pc/pc_bw",
|
||||
"particle": "cobblemon:block/mod_station/pc/pc_bw"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"name": "main",
|
||||
"from": [2, 15, 7],
|
||||
"to": [14, 31, 15],
|
||||
"faces": {
|
||||
"north": {"uv": [3, 1, 6, 5], "texture": "#2"},
|
||||
"east": {"uv": [0.25, 8.25, 2.25, 12.25], "texture": "#2"},
|
||||
"south": {"uv": [9.5, 8.25, 12.5, 12.25], "texture": "#2"},
|
||||
"west": {"uv": [6.75, 8.25, 8.75, 12.25], "texture": "#2"},
|
||||
"up": {"uv": [6, 7.25, 3, 5.25], "texture": "#2"},
|
||||
"down": {"uv": [12.5, 5.25, 9.5, 8], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "extrusion",
|
||||
"from": [0, 17.9, 10],
|
||||
"to": [2, 25.9, 12],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 0.4, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [6, 9.5, 6.5, 11.5], "texture": "#2"},
|
||||
"east": {"uv": [1, 9.5, 1.5, 11.5], "texture": "#2"},
|
||||
"south": {"uv": [9, 9.5, 9.5, 11.5], "texture": "#2"},
|
||||
"west": {"uv": [7.5, 9.5, 8, 11.5], "texture": "#2"},
|
||||
"up": {"uv": [6.5, 6.5, 6, 6], "texture": "#2"},
|
||||
"down": {"uv": [13, 6, 12.5, 6.5], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "extrusion",
|
||||
"from": [14, 17.9, 10],
|
||||
"to": [16, 25.9, 12],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 0.4, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [2.5, 9.5, 3, 11.5], "texture": "#2"},
|
||||
"east": {"uv": [1, 9.5, 1.5, 11.5], "texture": "#2"},
|
||||
"south": {"uv": [12.5, 9.5, 13, 11.5], "texture": "#2"},
|
||||
"west": {"uv": [7.5, 9.5, 8, 11.5], "texture": "#2"},
|
||||
"up": {"uv": [3, 6.5, 2.5, 6], "texture": "#2"},
|
||||
"down": {"uv": [9.5, 6, 9, 6.5], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "main",
|
||||
"from": [1.99, 8.99, 3.99],
|
||||
"to": [14.01, 15.01, 15.01],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 0, -1]},
|
||||
"faces": {
|
||||
"north": {"uv": [3, 12.25, 6, 13.75], "texture": "#2"},
|
||||
"east": {"uv": [0.25, 12.25, 3, 13.75], "texture": "#2"},
|
||||
"south": {"uv": [9.5, 12.25, 12.5, 13.75], "texture": "#2"},
|
||||
"west": {"uv": [6, 12.25, 8.75, 13.75], "texture": "#2"},
|
||||
"up": {"uv": [6, 8, 3, 5.25], "texture": "#2"},
|
||||
"down": {"uv": [12.5, 5.25, 9.5, 8], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "base",
|
||||
"from": [4, 0, 7],
|
||||
"to": [12, 2, 13],
|
||||
"faces": {
|
||||
"north": {"uv": [3.5, 15.5, 5.5, 16], "texture": "#2"},
|
||||
"east": {"uv": [0.75, 15.5, 2.25, 16], "texture": "#2"},
|
||||
"south": {"uv": [10, 15.5, 12, 16], "texture": "#2"},
|
||||
"west": {"uv": [6.75, 15.5, 8.25, 16], "texture": "#2"},
|
||||
"up": {"uv": [8.75, 6.75, 6.75, 5.25], "texture": "#2"},
|
||||
"down": {"uv": [8.75, 6.75, 6.75, 8.25], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "pole",
|
||||
"from": [6, 2, 9],
|
||||
"to": [10, 9, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [4, 13.75, 5, 15.5], "texture": "#2"},
|
||||
"east": {"uv": [1.25, 13.75, 1.75, 15.5], "texture": "#2"},
|
||||
"south": {"uv": [10.5, 13.75, 11.5, 15.5], "texture": "#2"},
|
||||
"west": {"uv": [7.25, 13.75, 7.75, 15.5], "texture": "#2"},
|
||||
"up": {"uv": [5.75, 11.375, 5.25, 11.125], "texture": "#2"},
|
||||
"down": {"uv": [5.75, 11.125, 5.25, 11.375], "texture": "#2"}
|
||||
}
|
||||
}
|
||||
],
|
||||
"groups": [
|
||||
{
|
||||
"name": "PC_BW",
|
||||
"origin": [0, 0, 0],
|
||||
"scope": 0,
|
||||
"color": 0,
|
||||
"children": [
|
||||
{
|
||||
"name": "top_half",
|
||||
"origin": [0, 0, 0],
|
||||
"scope": 0,
|
||||
"color": 0,
|
||||
"children": [0, 1, 2]
|
||||
},
|
||||
{
|
||||
"name": "bottom_half",
|
||||
"origin": [0, 0, 0],
|
||||
"scope": 0,
|
||||
"color": 0,
|
||||
"children": [3]
|
||||
},
|
||||
{
|
||||
"name": "stand",
|
||||
"origin": [0, 0, 0],
|
||||
"scope": 0,
|
||||
"color": 0,
|
||||
"children": [4, 5]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
{
|
||||
"format_version": "1.21.11",
|
||||
"credit": "Made with Blockbench",
|
||||
"texture_size": [64, 64],
|
||||
"textures": {
|
||||
"0": "cobblemon:block/mod_station/pc/pc_dppt",
|
||||
"particle": "cobblemon:block/mod_station/pc/pc_dppt"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [2.5, 5, 2.5],
|
||||
"to": [13.5, 16, 13.5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [3.5, 11, 10.5]},
|
||||
"faces": {
|
||||
"north": {"uv": [4.5, 12, 7.25, 14.75], "texture": "#0"},
|
||||
"east": {"uv": [8.75, 12, 11.5, 14.75], "texture": "#0"},
|
||||
"south": {"uv": [12.5, 12, 15.25, 14.75], "texture": "#0"},
|
||||
"west": {"uv": [0.5, 12, 3.25, 14.75], "texture": "#0"},
|
||||
"up": {"uv": [7.25, 3.5, 4.5, 0.75], "texture": "#0"},
|
||||
"down": {"uv": [15.25, 0.75, 12.5, 3.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [3, 0, 3],
|
||||
"to": [13, 5, 13],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [3, 6, 9]},
|
||||
"faces": {
|
||||
"north": {"uv": [4.75, 14.75, 7.25, 16], "texture": "#0"},
|
||||
"east": {"uv": [8.75, 14.75, 11.25, 16], "texture": "#0"},
|
||||
"south": {"uv": [12.75, 14.75, 15.25, 16], "texture": "#0"},
|
||||
"west": {"uv": [0.75, 14.75, 3.25, 16], "texture": "#0"},
|
||||
"up": {"uv": [11.25, 3.25, 8.75, 0.75], "texture": "#0"},
|
||||
"down": {"uv": [11.25, 0.75, 8.75, 3.25], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [3.5, 16, 3.5],
|
||||
"to": [12.5, 17, 6.5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [4.5, 16, 10.5]},
|
||||
"faces": {
|
||||
"north": {"uv": [12.75, 6.25, 15, 6.5], "texture": "#0"},
|
||||
"east": {"uv": [10.5, 11.75, 11.25, 12], "texture": "#0"},
|
||||
"south": {"uv": [12.75, 5.25, 15, 5.5], "texture": "#0"},
|
||||
"west": {"uv": [0.75, 11.75, 1.5, 12], "texture": "#0"},
|
||||
"up": {"uv": [15, 6.25, 12.75, 5.5], "texture": "#0"},
|
||||
"down": {"uv": [15, 5.5, 12.75, 6.25], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6.5, 16, 9.5],
|
||||
"to": [9.5, 20, 12.5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [3.5, 16, 10.5]},
|
||||
"faces": {
|
||||
"north": {"uv": [5.5, 11, 6.25, 12], "texture": "#0"},
|
||||
"east": {"uv": [9, 11, 9.75, 12], "texture": "#0"},
|
||||
"south": {"uv": [13.5, 11, 14.25, 12], "texture": "#0"},
|
||||
"west": {"uv": [2.25, 11, 3, 12], "texture": "#0"},
|
||||
"up": {"uv": [10.5, 2, 9.5, 1], "texture": "#0"},
|
||||
"down": {"uv": [10.5, 1, 9.5, 2], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [0, 20, 9.5],
|
||||
"to": [16, 31, 13.5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [4, 21, 11.5]},
|
||||
"faces": {
|
||||
"north": {"uv": [4, 8.25, 8, 11], "texture": "#0"},
|
||||
"east": {"uv": [8.75, 8.25, 9.75, 11], "texture": "#0"},
|
||||
"south": {"uv": [12, 8.25, 16, 11], "texture": "#0"},
|
||||
"west": {"uv": [2.25, 8.25, 3.25, 11], "texture": "#0"},
|
||||
"up": {"uv": [8, 5.75, 4, 4.75], "texture": "#0"},
|
||||
"down": {"uv": [8, 4.75, 12, 5.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [1, 30, 8.5],
|
||||
"to": [15, 31, 9.5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [4, 21, 7.5]},
|
||||
"faces": {
|
||||
"north": {"uv": [4.25, 8.25, 7.75, 8.5], "texture": "#0"},
|
||||
"east": {"uv": [9.75, 8.25, 10, 8.5], "texture": "#0"},
|
||||
"south": {"uv": [12.25, 8.25, 15.75, 8.5], "texture": "#0"},
|
||||
"west": {"uv": [2, 8.25, 2.25, 8.5], "texture": "#0"},
|
||||
"up": {"uv": [7.75, 6, 4.25, 5.75], "texture": "#0"},
|
||||
"down": {"uv": [3.75, 4.5, 0.25, 4.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [1, 20, 8.5],
|
||||
"to": [15, 21, 9.5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [4, 11, 7.5]},
|
||||
"faces": {
|
||||
"north": {"uv": [4.25, 10.75, 7.75, 11], "texture": "#0"},
|
||||
"east": {"uv": [9.75, 10.75, 10, 11], "texture": "#0"},
|
||||
"south": {"uv": [12.25, 10.75, 15.75, 11], "texture": "#0"},
|
||||
"west": {"uv": [2, 10.75, 2.25, 11], "texture": "#0"},
|
||||
"up": {"uv": [3.75, 7.25, 0.25, 7], "texture": "#0"},
|
||||
"down": {"uv": [11.75, 5.75, 8.25, 6], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [15, 20, 8.5],
|
||||
"to": [16, 31, 9.5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [5, 13, 7.5]},
|
||||
"faces": {
|
||||
"north": {"uv": [4, 8.25, 4.25, 11], "texture": "#0"},
|
||||
"east": {"uv": [9.75, 8.25, 10, 11], "texture": "#0"},
|
||||
"south": {"uv": [15.75, 8.25, 16, 11], "texture": "#0"},
|
||||
"west": {"uv": [0, 4.5, 0.25, 7.25], "texture": "#0"},
|
||||
"up": {"uv": [4.25, 6, 4, 5.75], "texture": "#0"},
|
||||
"down": {"uv": [12, 5.75, 11.75, 6], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [0, 20, 8.5],
|
||||
"to": [1, 31, 9.5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [-10, 13, 7.5]},
|
||||
"faces": {
|
||||
"north": {"uv": [7.75, 8.25, 8, 11], "texture": "#0"},
|
||||
"east": {"uv": [3.75, 4.5, 4, 7.25], "texture": "#0"},
|
||||
"south": {"uv": [12, 8.25, 12.25, 11], "texture": "#0"},
|
||||
"west": {"uv": [2, 8.25, 2.25, 11], "texture": "#0"},
|
||||
"up": {"uv": [8, 6, 7.75, 5.75], "texture": "#0"},
|
||||
"down": {"uv": [8.25, 5.75, 8, 6], "texture": "#0"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
{
|
||||
"format_version": "1.21.11",
|
||||
"credit": "Made with Blockbench",
|
||||
"texture_size": [64, 64],
|
||||
"textures": {
|
||||
"0": "cobblemon:block/mod_station/pc/pc_dppt",
|
||||
"particle": "cobblemon:block/mod_station/pc/pc_dppt"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [2.5, 5, 2.5],
|
||||
"to": [13.5, 16, 13.5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [3.5, 11, 10.5]},
|
||||
"faces": {
|
||||
"north": {"uv": [4.5, 12, 7.25, 14.75], "texture": "#0"},
|
||||
"east": {"uv": [8.75, 12, 11.5, 14.75], "texture": "#0"},
|
||||
"south": {"uv": [12.5, 12, 15.25, 14.75], "texture": "#0"},
|
||||
"west": {"uv": [0.5, 12, 3.25, 14.75], "texture": "#0"},
|
||||
"up": {"uv": [7.25, 3.5, 4.5, 0.75], "texture": "#0"},
|
||||
"down": {"uv": [15.25, 0.75, 12.5, 3.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [3, 0, 3],
|
||||
"to": [13, 5, 13],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [3, 6, 9]},
|
||||
"faces": {
|
||||
"north": {"uv": [4.75, 14.75, 7.25, 16], "texture": "#0"},
|
||||
"east": {"uv": [8.75, 14.75, 11.25, 16], "texture": "#0"},
|
||||
"south": {"uv": [12.75, 14.75, 15.25, 16], "texture": "#0"},
|
||||
"west": {"uv": [0.75, 14.75, 3.25, 16], "texture": "#0"},
|
||||
"up": {"uv": [11.25, 3.25, 8.75, 0.75], "texture": "#0"},
|
||||
"down": {"uv": [11.25, 0.75, 8.75, 3.25], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [3.5, 16, 3.5],
|
||||
"to": [12.5, 17, 6.5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [4.5, 16, 10.5]},
|
||||
"faces": {
|
||||
"north": {"uv": [12.75, 6.25, 15, 6.5], "texture": "#0"},
|
||||
"east": {"uv": [10.5, 11.75, 11.25, 12], "texture": "#0"},
|
||||
"south": {"uv": [12.75, 5.25, 15, 5.5], "texture": "#0"},
|
||||
"west": {"uv": [0.75, 11.75, 1.5, 12], "texture": "#0"},
|
||||
"up": {"uv": [15, 6.25, 12.75, 5.5], "texture": "#0"},
|
||||
"down": {"uv": [15, 5.5, 12.75, 6.25], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6.5, 16, 9.5],
|
||||
"to": [9.5, 20, 12.5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [3.5, 16, 10.5]},
|
||||
"faces": {
|
||||
"north": {"uv": [5.5, 11, 6.25, 12], "texture": "#0"},
|
||||
"east": {"uv": [9, 11, 9.75, 12], "texture": "#0"},
|
||||
"south": {"uv": [13.5, 11, 14.25, 12], "texture": "#0"},
|
||||
"west": {"uv": [2.25, 11, 3, 12], "texture": "#0"},
|
||||
"up": {"uv": [10.5, 2, 9.5, 1], "texture": "#0"},
|
||||
"down": {"uv": [10.5, 1, 9.5, 2], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [0, 20, 9.5],
|
||||
"to": [16, 31, 13.5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [4, 21, 11.5]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0.25, 4, 3], "texture": "#0"},
|
||||
"east": {"uv": [8.75, 8.25, 9.75, 11], "texture": "#0"},
|
||||
"south": {"uv": [12, 8.25, 16, 11], "texture": "#0"},
|
||||
"west": {"uv": [2.25, 8.25, 3.25, 11], "texture": "#0"},
|
||||
"up": {"uv": [8, 5.75, 4, 4.75], "texture": "#0"},
|
||||
"down": {"uv": [8, 4.75, 12, 5.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [1, 30, 8.5],
|
||||
"to": [15, 31, 9.5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [4, 21, 7.5]},
|
||||
"faces": {
|
||||
"north": {"uv": [4.25, 8.25, 7.75, 8.5], "texture": "#0"},
|
||||
"east": {"uv": [9.75, 8.25, 10, 8.5], "texture": "#0"},
|
||||
"south": {"uv": [12.25, 8.25, 15.75, 8.5], "texture": "#0"},
|
||||
"west": {"uv": [2, 8.25, 2.25, 8.5], "texture": "#0"},
|
||||
"up": {"uv": [7.75, 6, 4.25, 5.75], "texture": "#0"},
|
||||
"down": {"uv": [3.75, 4.5, 0.25, 4.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [1, 20, 8.5],
|
||||
"to": [15, 21, 9.5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [4, 11, 7.5]},
|
||||
"faces": {
|
||||
"north": {"uv": [4.25, 10.75, 7.75, 11], "texture": "#0"},
|
||||
"east": {"uv": [9.75, 10.75, 10, 11], "texture": "#0"},
|
||||
"south": {"uv": [12.25, 10.75, 15.75, 11], "texture": "#0"},
|
||||
"west": {"uv": [2, 10.75, 2.25, 11], "texture": "#0"},
|
||||
"up": {"uv": [3.75, 7.25, 0.25, 7], "texture": "#0"},
|
||||
"down": {"uv": [11.75, 5.75, 8.25, 6], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [15, 20, 8.5],
|
||||
"to": [16, 31, 9.5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [5, 13, 7.5]},
|
||||
"faces": {
|
||||
"north": {"uv": [4, 8.25, 4.25, 11], "texture": "#0"},
|
||||
"east": {"uv": [9.75, 8.25, 10, 11], "texture": "#0"},
|
||||
"south": {"uv": [15.75, 8.25, 16, 11], "texture": "#0"},
|
||||
"west": {"uv": [0, 4.5, 0.25, 7.25], "texture": "#0"},
|
||||
"up": {"uv": [4.25, 6, 4, 5.75], "texture": "#0"},
|
||||
"down": {"uv": [12, 5.75, 11.75, 6], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [0, 20, 8.5],
|
||||
"to": [1, 31, 9.5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [-10, 13, 7.5]},
|
||||
"faces": {
|
||||
"north": {"uv": [7.75, 8.25, 8, 11], "texture": "#0"},
|
||||
"east": {"uv": [3.75, 4.5, 4, 7.25], "texture": "#0"},
|
||||
"south": {"uv": [12, 8.25, 12.25, 11], "texture": "#0"},
|
||||
"west": {"uv": [2, 8.25, 2.25, 11], "texture": "#0"},
|
||||
"up": {"uv": [8, 6, 7.75, 5.75], "texture": "#0"},
|
||||
"down": {"uv": [8.25, 5.75, 8, 6], "texture": "#0"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
{
|
||||
"textures": {
|
||||
"0": "cobblemon:block/mod_station/pc/pc_hgss",
|
||||
"particle": "cobblemon:block/mod_station/pc/pc_hgss"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [2, 0, 1],
|
||||
"to": [14, 2, 15],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 2, 15]},
|
||||
"faces": {
|
||||
"north": {"uv": [4.5, 15.5, 7.5, 16], "texture": "#0"},
|
||||
"east": {"uv": [8.25, 15.5, 11.75, 16], "texture": "#0"},
|
||||
"south": {"uv": [12.5, 15.5, 15.5, 16], "texture": "#0"},
|
||||
"west": {"uv": [0.25, 15.5, 3.75, 16], "texture": "#0"},
|
||||
"up": {"uv": [7.5, 11.75, 4.5, 8.25], "texture": "#0"},
|
||||
"down": {"uv": [11.5, 8.25, 8.5, 11.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [1, 4, 8],
|
||||
"to": [15, 15, 15],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [1, 5, 6]},
|
||||
"faces": {
|
||||
"north": {"uv": [4.25, 12.25, 7.75, 15], "texture": "#0"},
|
||||
"east": {"uv": [8.25, 12.25, 10, 15], "texture": "#0"},
|
||||
"south": {"uv": [12.25, 12.25, 15.75, 15], "texture": "#0"},
|
||||
"west": {"uv": [2, 12.25, 3.75, 15], "texture": "#0"},
|
||||
"up": {"uv": [7.75, 7.75, 4.25, 6], "texture": "#0"},
|
||||
"down": {"uv": [11.75, 5.75, 8.25, 7.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [1, 4, 7],
|
||||
"to": [3, 15, 8],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [-11, 5, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [7.25, 12.25, 7.75, 15], "texture": "#0"},
|
||||
"east": {"uv": [3.25, 8.75, 3.5, 11.5], "texture": "#0"},
|
||||
"south": {"uv": [7.25, 12.25, 7.75, 15], "texture": "#0"},
|
||||
"west": {"uv": [1.75, 12.25, 2, 15], "texture": "#0"},
|
||||
"up": {"uv": [4.75, 6, 4.25, 5.75], "texture": "#0"},
|
||||
"down": {"uv": [8.75, 7.5, 8.25, 7.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [13, 4, 7],
|
||||
"to": [15, 15, 8],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [2, 5, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [4.25, 12.25, 4.75, 15], "texture": "#0"},
|
||||
"east": {"uv": [10, 12.25, 10.25, 15], "texture": "#0"},
|
||||
"south": {"uv": [4.25, 12.25, 4.75, 15], "texture": "#0"},
|
||||
"west": {"uv": [0.5, 8.75, 0.75, 11.5], "texture": "#0"},
|
||||
"up": {"uv": [7.75, 6, 7.25, 5.75], "texture": "#0"},
|
||||
"down": {"uv": [11.75, 7.5, 11.25, 7.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [3, 14, 7],
|
||||
"to": [13, 15, 8],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [-10, 15, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [4.75, 12.25, 7.25, 12.5], "texture": "#0"},
|
||||
"east": {"uv": [4.75, 12.25, 5, 12.5], "texture": "#0"},
|
||||
"south": {"uv": [4.75, 12.25, 7.25, 12.5], "texture": "#0"},
|
||||
"west": {"uv": [7, 12.25, 7.25, 12.5], "texture": "#0"},
|
||||
"up": {"uv": [7.25, 6, 4.75, 5.75], "texture": "#0"},
|
||||
"down": {"uv": [3.25, 8.75, 0.75, 9], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [3, 4, 7],
|
||||
"to": [13, 5, 8],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [-10, 5, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [4.75, 14.75, 7.25, 15], "texture": "#0"},
|
||||
"east": {"uv": [4.75, 14.75, 5, 15], "texture": "#0"},
|
||||
"south": {"uv": [4.75, 14.75, 7.25, 15], "texture": "#0"},
|
||||
"west": {"uv": [7, 14.75, 7.25, 15], "texture": "#0"},
|
||||
"up": {"uv": [3.25, 11.5, 0.75, 11.25], "texture": "#0"},
|
||||
"down": {"uv": [11.25, 7.5, 8.75, 7.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6, 2, 9],
|
||||
"to": [10, 4, 13],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [1, 3, 1]},
|
||||
"faces": {
|
||||
"north": {"uv": [5.5, 15, 6.5, 15.5], "texture": "#0"},
|
||||
"east": {"uv": [8.75, 15, 9.75, 15.5], "texture": "#0"},
|
||||
"south": {"uv": [13.5, 15, 14.5, 15.5], "texture": "#0"},
|
||||
"west": {"uv": [2.25, 15, 3.25, 15.5], "texture": "#0"},
|
||||
"up": {"uv": [6.5, 9.75, 5.5, 8.75], "texture": "#0"},
|
||||
"down": {"uv": [10.5, 8.75, 9.5, 9.75], "texture": "#0"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"parent": "cobblemon:block/pc_bottom",
|
||||
"textures": {
|
||||
"all": "cobblemon:block/mod_station/pc/pc_hgss",
|
||||
"particle": "cobblemon:block/mod_station/pc/pc_hgss"
|
||||
}
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
{
|
||||
"textures": {
|
||||
"0": "cobblemon:block/mod_station/pc/pc_hgss",
|
||||
"particle": "cobblemon:block/mod_station/pc/pc_hgss"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [2, 0, 1],
|
||||
"to": [14, 2, 15],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 2, 15]},
|
||||
"faces": {
|
||||
"north": {"uv": [4.5, 15.5, 7.5, 16], "texture": "#0"},
|
||||
"east": {"uv": [8.25, 15.5, 11.75, 16], "texture": "#0"},
|
||||
"south": {"uv": [12.5, 15.5, 15.5, 16], "texture": "#0"},
|
||||
"west": {"uv": [0.25, 15.5, 3.75, 16], "texture": "#0"},
|
||||
"up": {"uv": [7.5, 11.75, 4.5, 8.25], "texture": "#0"},
|
||||
"down": {"uv": [11.5, 8.25, 8.5, 11.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [1, 4, 8],
|
||||
"to": [15, 15, 15],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [1, 5, 6]},
|
||||
"faces": {
|
||||
"north": {"uv": [4.25, 0.25, 7.75, 3], "texture": "#0"},
|
||||
"east": {"uv": [8.25, 12.25, 10, 15], "texture": "#0"},
|
||||
"south": {"uv": [12.25, 12.25, 15.75, 15], "texture": "#0"},
|
||||
"west": {"uv": [2, 12.25, 3.75, 15], "texture": "#0"},
|
||||
"up": {"uv": [7.75, 7.75, 4.25, 6], "texture": "#0"},
|
||||
"down": {"uv": [11.75, 5.75, 8.25, 7.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [1, 4, 7],
|
||||
"to": [3, 15, 8],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [-11, 5, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [7.25, 12.25, 7.75, 15], "texture": "#0"},
|
||||
"east": {"uv": [3.25, 8.75, 3.5, 11.5], "texture": "#0"},
|
||||
"south": {"uv": [7.25, 12.25, 7.75, 15], "texture": "#0"},
|
||||
"west": {"uv": [1.75, 12.25, 2, 15], "texture": "#0"},
|
||||
"up": {"uv": [4.75, 6, 4.25, 5.75], "texture": "#0"},
|
||||
"down": {"uv": [8.75, 7.5, 8.25, 7.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [13, 4, 7],
|
||||
"to": [15, 15, 8],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [2, 5, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [4.25, 12.25, 4.75, 15], "texture": "#0"},
|
||||
"east": {"uv": [10, 12.25, 10.25, 15], "texture": "#0"},
|
||||
"south": {"uv": [4.25, 12.25, 4.75, 15], "texture": "#0"},
|
||||
"west": {"uv": [0.5, 8.75, 0.75, 11.5], "texture": "#0"},
|
||||
"up": {"uv": [7.75, 6, 7.25, 5.75], "texture": "#0"},
|
||||
"down": {"uv": [11.75, 7.5, 11.25, 7.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [3, 14, 7],
|
||||
"to": [13, 15, 8],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [-10, 15, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [4.75, 12.25, 7.25, 12.5], "texture": "#0"},
|
||||
"east": {"uv": [4.75, 12.25, 5, 12.5], "texture": "#0"},
|
||||
"south": {"uv": [4.75, 12.25, 7.25, 12.5], "texture": "#0"},
|
||||
"west": {"uv": [7, 12.25, 7.25, 12.5], "texture": "#0"},
|
||||
"up": {"uv": [7.25, 6, 4.75, 5.75], "texture": "#0"},
|
||||
"down": {"uv": [3.25, 8.75, 0.75, 9], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [3, 4, 7],
|
||||
"to": [13, 5, 8],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [-10, 5, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [4.75, 14.75, 7.25, 15], "texture": "#0"},
|
||||
"east": {"uv": [4.75, 14.75, 5, 15], "texture": "#0"},
|
||||
"south": {"uv": [4.75, 14.75, 7.25, 15], "texture": "#0"},
|
||||
"west": {"uv": [7, 14.75, 7.25, 15], "texture": "#0"},
|
||||
"up": {"uv": [3.25, 11.5, 0.75, 11.25], "texture": "#0"},
|
||||
"down": {"uv": [11.25, 7.5, 8.75, 7.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6, 2, 9],
|
||||
"to": [10, 4, 13],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [1, 3, 1]},
|
||||
"faces": {
|
||||
"north": {"uv": [5.5, 15, 6.5, 15.5], "texture": "#0"},
|
||||
"east": {"uv": [8.75, 15, 9.75, 15.5], "texture": "#0"},
|
||||
"south": {"uv": [13.5, 15, 14.5, 15.5], "texture": "#0"},
|
||||
"west": {"uv": [2.25, 15, 3.25, 15.5], "texture": "#0"},
|
||||
"up": {"uv": [6.5, 9.75, 5.5, 8.75], "texture": "#0"},
|
||||
"down": {"uv": [10.5, 8.75, 9.5, 9.75], "texture": "#0"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"parent": "cobblemon:block/pc_top",
|
||||
"textures": {
|
||||
"all": "cobblemon:block/mod_station/pc/pc_hgss",
|
||||
"particle": "cobblemon:block/mod_station/pc/pc_hgss"
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"parent": "cobblemon:block/pc_top_on",
|
||||
"textures": {
|
||||
"all": "cobblemon:block/mod_station/pc/pc_hgss",
|
||||
"particle": "cobblemon:block/mod_station/pc/pc_hgss"
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user