diff --git a/src/main/java/li/cil/oc2/common/Config.java b/src/main/java/li/cil/oc2/common/Config.java index 181c90ed..391f321f 100644 --- a/src/main/java/li/cil/oc2/common/Config.java +++ b/src/main/java/li/cil/oc2/common/Config.java @@ -20,6 +20,8 @@ public final class Config { @Path("energy.blocks") public static int chargerEnergyStorage = 10000; @Path("energy.blocks") public static int projectorEnergyPerTick = 20; @Path("energy.blocks") public static int projectorEnergyStorage = 2000; + @Path("energy.blocks") public static int cardCageEnergyPerTick = 20; + @Path("energy.blocks") public static int cardCageEnergyStorage = 2000; @Path("energy.entities") public static int robotEnergyPerTick = 5; @Path("energy.entities") public static int robotEnergyStorage = 750000; @@ -60,6 +62,10 @@ public final class Config { return projectorEnergyStorage > 0 && projectorEnergyPerTick > 0; } + public static boolean cardCagesUseEnergy() { + return cardCageEnergyStorage > 0 && cardCageEnergyPerTick > 0; + } + public static boolean robotsUseEnergy() { return robotEnergyPerTick > 0 && robotEnergyStorage > 0; } diff --git a/src/main/java/li/cil/oc2/common/block/Blocks.java b/src/main/java/li/cil/oc2/common/block/Blocks.java index 5aacb614..03401466 100644 --- a/src/main/java/li/cil/oc2/common/block/Blocks.java +++ b/src/main/java/li/cil/oc2/common/block/Blocks.java @@ -2,8 +2,10 @@ package li.cil.oc2.common.block; +import li.cil.oc2.common.blockentity.VxlanBlockEntity; import li.cil.oc2.common.util.RegistryUtils; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.RegistryObject; @@ -25,6 +27,8 @@ public final class Blocks { public static final RegistryObject PROJECTOR = BLOCKS.register("projector", ProjectorBlock::new); public static final RegistryObject REDSTONE_INTERFACE = BLOCKS.register("redstone_interface", RedstoneInterfaceBlock::new); public static final RegistryObject VXLAN_HUB = BLOCKS.register("vxlan_hub", VxlanBlock::new); + public static final RegistryObject PCI_CARD_CAGE = BLOCKS.register("pci_card_cage", PciCardCageBlock::new); + /////////////////////////////////////////////////////////////////// diff --git a/src/main/java/li/cil/oc2/common/block/PciCardCageBlock.java b/src/main/java/li/cil/oc2/common/block/PciCardCageBlock.java new file mode 100644 index 00000000..978965b9 --- /dev/null +++ b/src/main/java/li/cil/oc2/common/block/PciCardCageBlock.java @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: MIT */ + +package li.cil.oc2.common.block; + +import li.cil.oc2.common.Config; +import li.cil.oc2.common.blockentity.BlockEntities; +import li.cil.oc2.common.blockentity.TickableBlockEntity; +import li.cil.oc2.common.util.VoxelShapeUtils; +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.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.HorizontalDirectionalBlock; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +import javax.annotation.Nullable; + +public final class PciCardCageBlock extends HorizontalDirectionalBlock implements EntityBlock, EnergyConsumingBlock { + public static final BooleanProperty LIT = BlockStateProperties.LIT; + + // We bake the visual indents on the front and sides into the collision shape, to prevent stuff being + // placeable on those sides, such as network connectors, torches, etc. + private static final VoxelShape NEG_Z_SHAPE = Shapes.join(Shapes.block(), Shapes.or( + Shapes.box(0 / 16f, 2 / 16f, 2 / 16f, 1 / 16f, 6 / 16f, 14 / 16f), + Shapes.box(15 / 16f, 2 / 16f, 2 / 16f, 16 / 16f, 6 / 16f, 14 / 16f), + Shapes.box(4 / 16f, 4 / 16f, 0 / 16f, 12 / 16f, 12 / 16f, 2 / 16f) + ), (a, b) -> a && !b); + private static final VoxelShape NEG_X_SHAPE = VoxelShapeUtils.rotateHorizontalClockwise(NEG_Z_SHAPE); + private static final VoxelShape POS_Z_SHAPE = VoxelShapeUtils.rotateHorizontalClockwise(NEG_X_SHAPE); + private static final VoxelShape POS_X_SHAPE = VoxelShapeUtils.rotateHorizontalClockwise(POS_Z_SHAPE); + + public PciCardCageBlock() { + super(Properties + .of(Material.METAL) + .sound(SoundType.METAL) + .lightLevel(state -> state.getValue(LIT) ? 8 : 0) + .strength(1.5f, 6.0f)); + registerDefaultState(getStateDefinition().any() + .setValue(FACING, Direction.NORTH) + .setValue(LIT, false)); + } + + /////////////////////////////////////////////////////////////////// + + @Override + public int getEnergyConsumption() { + if (Config.cardCagesUseEnergy()) { + return Config.cardCageEnergyPerTick; + } else { + return 0; + } + } + + @Override + public BlockEntity newBlockEntity(final BlockPos pos, final BlockState state) { + return BlockEntities.PCI_CARD_CAGE.get().create(pos, state); + } + + @Nullable + @Override + public BlockEntityTicker getTicker(final Level level, final BlockState state, final BlockEntityType type) { + return TickableBlockEntity.createServerTicker(level, type, BlockEntities.PROJECTOR.get()); + } + + @SuppressWarnings("deprecation") + @Override + public VoxelShape getShape(final BlockState state, final BlockGetter level, final BlockPos blockPos, final CollisionContext context) { + return switch (state.getValue(FACING)) { + case NORTH -> NEG_Z_SHAPE; + case SOUTH -> POS_Z_SHAPE; + case WEST -> NEG_X_SHAPE; + default -> POS_X_SHAPE; + }; + } + + @Override + public BlockState getStateForPlacement(final BlockPlaceContext context) { + return super.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite()); + } + + /////////////////////////////////////////////////////////////////// + + protected void createBlockStateDefinition(final StateDefinition.Builder builder) { + builder.add(FACING, LIT); + } +} diff --git a/src/main/java/li/cil/oc2/common/blockentity/BlockEntities.java b/src/main/java/li/cil/oc2/common/blockentity/BlockEntities.java index b5aa6cbf..0ba86e6c 100644 --- a/src/main/java/li/cil/oc2/common/blockentity/BlockEntities.java +++ b/src/main/java/li/cil/oc2/common/blockentity/BlockEntities.java @@ -28,6 +28,8 @@ public final class BlockEntities { public static final RegistryObject> PROJECTOR = register(Blocks.PROJECTOR, ProjectorBlockEntity::new); public static final RegistryObject> REDSTONE_INTERFACE = register(Blocks.REDSTONE_INTERFACE, RedstoneInterfaceBlockEntity::new); public static final RegistryObject> VXLAN_HUB = register(Blocks.VXLAN_HUB, VxlanBlockEntity::new); + public static final RegistryObject> PCI_CARD_CAGE = register(Blocks.PCI_CARD_CAGE, PciCardCageBlockEntity::new); + /////////////////////////////////////////////////////////////////// diff --git a/src/main/java/li/cil/oc2/common/blockentity/PciCardCageBlockEntity.java b/src/main/java/li/cil/oc2/common/blockentity/PciCardCageBlockEntity.java new file mode 100644 index 00000000..3d9d8dbf --- /dev/null +++ b/src/main/java/li/cil/oc2/common/blockentity/PciCardCageBlockEntity.java @@ -0,0 +1,122 @@ +/* SPDX-License-Identifier: MIT */ + +package li.cil.oc2.common.blockentity; + +import li.cil.oc2.common.Config; +import li.cil.oc2.common.block.PciCardCageBlock; +import li.cil.oc2.common.bus.device.vm.block.PciCardCageDevice; +import li.cil.oc2.common.capabilities.Capabilities; +import li.cil.oc2.common.energy.FixedEnergyStorage; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.state.BlockState; + +import javax.annotation.Nullable; + + +public final class PciCardCageBlockEntity extends ModBlockEntity implements TickableBlockEntity { + + private static final String ENERGY_TAG_NAME = "energy"; + private static final String HAS_ENERGY_TAG_NAME = "has_energy"; + + /////////////////////////////////////////////////////////////// + + private final PciCardCageDevice cardCageDevice = new PciCardCageDevice(this, this::handleMountedChanged); + private boolean isMounted, hasEnergy; + private final FixedEnergyStorage energy = new FixedEnergyStorage(Config.cardCageEnergyStorage); + + + /////////////////////////////////////////////////////////////// + + public PciCardCageBlockEntity(final BlockPos pos, final BlockState state) { + super(BlockEntities.PCI_CARD_CAGE.get(), pos, state); + } + + /////////////////////////////////////////////////////////////// + + private void handleMountedChanged(final boolean value) { + + } + + + public boolean hasEnergy() { + return hasEnergy; + } + + @Override + public void serverTick() { + if (!isMounted) { + return; + } + + final boolean isPowered; + if (Config.cardCagesUseEnergy()) { + isPowered = energy.extractEnergy(Config.cardCageEnergyPerTick, true) >= Config.cardCageEnergyPerTick; + if (isPowered) { + energy.extractEnergy(Config.cardCageEnergyPerTick, false); + } + } else { + isPowered = true; + } + + + } + + @Override + public CompoundTag getUpdateTag() { + final CompoundTag tag = super.getUpdateTag(); + + tag.putBoolean(HAS_ENERGY_TAG_NAME, hasEnergy); + + return tag; + } + + @Override + public void handleUpdateTag(final CompoundTag tag) { + super.handleUpdateTag(tag); + + hasEnergy = tag.getBoolean(HAS_ENERGY_TAG_NAME); + } + + @Override + protected void saveAdditional(final CompoundTag tag) { + super.saveAdditional(tag); + + tag.put(ENERGY_TAG_NAME, energy.serializeNBT()); + } + + @Override + public void load(final CompoundTag tag) { + super.load(tag); + + energy.deserializeNBT(tag.getCompound(ENERGY_TAG_NAME)); + } + + + @SuppressWarnings("deprecation") + @Override + public void setBlockState(final BlockState state) { + super.setBlockState(state); + + } + + /////////////////////////////////////////////////////////////// + + @Override + protected void collectCapabilities(final CapabilityCollector collector, @Nullable final Direction direction) { + if (Config.cardCagesUseEnergy()) { + collector.offer(Capabilities.energyStorage(), energy); + } + + if (direction == getBlockState().getValue(PciCardCageBlock.FACING).getOpposite()) { + collector.offer(Capabilities.device(), cardCageDevice); + } + } + + /////////////////////////////////////////////////////////////// + + + + +} diff --git a/src/main/java/li/cil/oc2/common/bus/device/vm/block/PciCardCageDevice.java b/src/main/java/li/cil/oc2/common/bus/device/vm/block/PciCardCageDevice.java new file mode 100644 index 00000000..2bfb8050 --- /dev/null +++ b/src/main/java/li/cil/oc2/common/bus/device/vm/block/PciCardCageDevice.java @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: MIT */ + +package li.cil.oc2.common.bus.device.vm.block; + +import it.unimi.dsi.fastutil.booleans.BooleanConsumer; +import li.cil.oc2.api.bus.device.vm.VMDevice; +import li.cil.oc2.api.bus.device.vm.VMDeviceLoadResult; +import li.cil.oc2.api.bus.device.vm.context.VMContext; +import li.cil.oc2.common.Constants; +import li.cil.oc2.common.bus.device.util.IdentityProxy; +import li.cil.oc2.common.bus.device.util.OptionalAddress; +import li.cil.oc2.common.serialization.BlobStorage; +import li.cil.oc2.common.util.NBTTagIds; +import li.cil.oc2.common.vm.device.PciRootPortDevice; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.entity.BlockEntity; + +import javax.annotation.Nullable; +import java.io.IOException; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.util.UUID; + +public final class PciCardCageDevice extends IdentityProxy implements VMDevice { + private static final String ADDRESS_TAG_NAME = "address"; + private static final String BLOB_HANDLE_TAG_NAME = "blob"; + + public static final int BUS_COUNT = 16; + public static final int WINDOW_SIZE = 16 * 1024 * 1024; + + + /////////////////////////////////////////////////////////////// + + private final BooleanConsumer onMountedChanged; + + @Nullable private PciRootPortDevice device; + + /////////////////////////////////////////////////////////////// + + private final OptionalAddress address = new OptionalAddress(); + @Nullable private UUID blobHandle; + + /////////////////////////////////////////////////////////////// + + public PciCardCageDevice(final BlockEntity identity, final BooleanConsumer onMountedChanged) { + super(identity); + this.onMountedChanged = onMountedChanged; + } + + /////////////////////////////////////////////////////////////// + + @Override + public VMDeviceLoadResult mount(final VMContext context) { + if (!allocateDevice(context)) { + return VMDeviceLoadResult.fail(); + } + + assert device != null; + if (!address.claim(context, device)) { + return VMDeviceLoadResult.fail(); + } + + onMountedChanged.accept(true); + + return VMDeviceLoadResult.success(); + } + + @Override + public void unmount() { + final PciRootPortDevice pciRootPortDevice = device; + device = null; + if (pciRootPortDevice != null) { + pciRootPortDevice.close(); + } + + if (blobHandle != null) { + BlobStorage.close(blobHandle); + } + + onMountedChanged.accept(false); + } + + @Override + public void dispose() { + if (blobHandle != null) { + BlobStorage.delete(blobHandle); + blobHandle = null; + } + + address.clear(); + } + + @Override + public CompoundTag serializeNBT() { + final CompoundTag tag = new CompoundTag(); + + if (blobHandle != null) { + tag.putUUID(BLOB_HANDLE_TAG_NAME, blobHandle); + } + if (address.isPresent()) { + tag.putLong(ADDRESS_TAG_NAME, address.getAsLong()); + } + + return tag; + } + + @Override + public void deserializeNBT(final CompoundTag tag) { + if (tag.hasUUID(BLOB_HANDLE_TAG_NAME)) { + blobHandle = tag.getUUID(BLOB_HANDLE_TAG_NAME); + } + if (tag.contains(ADDRESS_TAG_NAME, NBTTagIds.TAG_LONG)) { + address.set(tag.getLong(ADDRESS_TAG_NAME)); + } + } + + /////////////////////////////////////////////////////////////// + + private boolean allocateDevice(final VMContext context) { + if (!context.getMemoryAllocator().claimMemory(Constants.PAGE_SIZE)) { + return false; + } + + try { + device = createPciRootPortDevice(); + } catch (final IOException e) { + return false; + } + + return true; + } + + private PciRootPortDevice createPciRootPortDevice() throws IOException { + blobHandle = BlobStorage.validateHandle(blobHandle); + final FileChannel channel = BlobStorage.getOrOpen(blobHandle); + final MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, WINDOW_SIZE * 2); + return new PciRootPortDevice(BUS_COUNT, WINDOW_SIZE, buffer); + } +} diff --git a/src/main/java/li/cil/oc2/common/item/Items.java b/src/main/java/li/cil/oc2/common/item/Items.java index 451c6b89..9f1a275e 100644 --- a/src/main/java/li/cil/oc2/common/item/Items.java +++ b/src/main/java/li/cil/oc2/common/item/Items.java @@ -35,6 +35,7 @@ public final class Items { public static final RegistryObject PROJECTOR = register(Blocks.PROJECTOR); public static final RegistryObject REDSTONE_INTERFACE = register(Blocks.REDSTONE_INTERFACE); public static final RegistryObject VXLAN_HUB = register(Blocks.VXLAN_HUB); + public static final RegistryObject PCI_CARD_CAGE = register(Blocks.PCI_CARD_CAGE); /////////////////////////////////////////////////////////////////// diff --git a/src/main/java/li/cil/oc2/common/vm/AbstractVirtualMachine.java b/src/main/java/li/cil/oc2/common/vm/AbstractVirtualMachine.java index fc649a81..5defa289 100644 --- a/src/main/java/li/cil/oc2/common/vm/AbstractVirtualMachine.java +++ b/src/main/java/li/cil/oc2/common/vm/AbstractVirtualMachine.java @@ -79,6 +79,7 @@ public abstract class AbstractVirtualMachine implements VirtualMachine { state.board.getCpu().setFrequency(Constants.CPU_FREQUENCY); state.board.setBootArguments("root=/dev/vda rw"); state.board.setStandardOutputDevice(state.builtinDevices.uart); + } /////////////////////////////////////////////////////////////////// diff --git a/src/main/java/li/cil/oc2/common/vm/device/PciRootPortDevice.java b/src/main/java/li/cil/oc2/common/vm/device/PciRootPortDevice.java new file mode 100644 index 00000000..d75d1ed1 --- /dev/null +++ b/src/main/java/li/cil/oc2/common/vm/device/PciRootPortDevice.java @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: MIT */ + +package li.cil.oc2.common.vm.device; + +import li.cil.sedna.api.device.MemoryMappedDevice; +import li.cil.sedna.api.memory.MemoryAccessException; +import li.cil.sedna.utils.DirectByteBufferUtils; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + + +public final class PciRootPortDevice implements MemoryMappedDevice { + + + /////////////////////////////////////////////////////////////// + + private final ByteBuffer buffer; + private int length; + + /////////////////////////////////////////////////////////////// + + public PciRootPortDevice(final int bus_count, final int window_size, final ByteBuffer buffer) { + + length = window_size * 2; + if (buffer.capacity() < length) { + throw new IllegalArgumentException("Buffer too small."); + } + + this.buffer = buffer.order(ByteOrder.LITTLE_ENDIAN); + + this.buffer.putInt(0, 0x12345678); + this.buffer.putInt(4, 0); + this.buffer.putInt(8, 0xFF000000); + this.buffer.putInt(12, 0x00000101); + this.buffer.putInt(16, 0x40000000); + this.buffer.putInt(0x2C, 0x12345678); + + + } + + /////////////////////////////////////////////////////////////// + + public void close() { + synchronized (buffer) { + length = 0; + DirectByteBufferUtils.release(buffer); + } + } + + + public boolean hasChanges() { + return false; + } + + + @Override + public int getLength() { + return length; + } + + @Override + public long load(final int offset, final int sizeLog2) throws MemoryAccessException { + if (offset >= 0 && offset <= length - (1 << sizeLog2)) { + System.out.println(String.format("PCI config read: %x", offset)); + return switch (sizeLog2) { + case 0 -> buffer.get(offset); + case 1 -> buffer.getShort(offset); + case 2 -> buffer.getInt(offset); + case 3 -> buffer.getLong(offset); + default -> throw new IllegalArgumentException(); + }; + } else { + return 0; + } + } + + @Override + public void store(final int offset, final long value, final int sizeLog2) throws MemoryAccessException { + if (offset >= 0 && offset <= length - (1 << sizeLog2)) { + System.out.println(String.format("PCI config write: %x %x %x", offset, value, sizeLog2)); + switch (sizeLog2) { + case 0 -> buffer.put(offset, (byte) value); + case 1 -> buffer.putShort(offset, (short) value); + case 2 -> buffer.putInt(offset, (int) value); + case 3 -> buffer.putLong(offset, value); + default -> throw new IllegalArgumentException(); + } + } + } + + /////////////////////////////////////////////////////////////// + +} diff --git a/src/main/java/li/cil/oc2/common/vm/provider/DeviceTreeProviders.java b/src/main/java/li/cil/oc2/common/vm/provider/DeviceTreeProviders.java index 5ee7bd4b..912a47f6 100644 --- a/src/main/java/li/cil/oc2/common/vm/provider/DeviceTreeProviders.java +++ b/src/main/java/li/cil/oc2/common/vm/provider/DeviceTreeProviders.java @@ -2,11 +2,13 @@ package li.cil.oc2.common.vm.provider; +import li.cil.oc2.common.vm.device.PciRootPortDevice; import li.cil.oc2.common.vm.device.SimpleFramebufferDevice; import li.cil.sedna.devicetree.DeviceTreeRegistry; public final class DeviceTreeProviders { public static void initialize() { DeviceTreeRegistry.putProvider(SimpleFramebufferDevice.class, new SimpleFramebufferDeviceProvider()); + DeviceTreeRegistry.putProvider(PciRootPortDevice.class, new PciRootPortDeviceProvider()); } } diff --git a/src/main/java/li/cil/oc2/common/vm/provider/PciRootPortDeviceProvider.java b/src/main/java/li/cil/oc2/common/vm/provider/PciRootPortDeviceProvider.java new file mode 100644 index 00000000..162323ca --- /dev/null +++ b/src/main/java/li/cil/oc2/common/vm/provider/PciRootPortDeviceProvider.java @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: MIT */ + +package li.cil.oc2.common.vm.provider; + +import li.cil.oc2.common.vm.device.PciRootPortDevice; +import li.cil.sedna.api.device.Device; +import li.cil.sedna.api.device.MemoryMappedDevice; +import li.cil.sedna.api.devicetree.DeviceNames; +import li.cil.sedna.api.devicetree.DevicePropertyNames; +import li.cil.sedna.api.devicetree.DeviceTree; +import li.cil.sedna.api.devicetree.DeviceTreeProvider; +import li.cil.sedna.api.memory.MappedMemoryRange; +import li.cil.sedna.api.memory.MemoryMap; + +import java.util.Optional; + +public final class PciRootPortDeviceProvider implements DeviceTreeProvider { + @Override + public Optional getName(final Device device) { + return Optional.of("pci"); + } + + @Override + public Optional createNode(final DeviceTree root, final MemoryMap memoryMap, final Device device, final String deviceName) { + final Optional range = memoryMap.getMemoryRange((MemoryMappedDevice) device); + return range.map(r -> { + final DeviceTree chosen = root.find("/soc"); + //chosen.addProp(DevicePropertyNames.RANGES); + + return chosen.getChild(deviceName, r.address()); + }); + } + + @Override + public void visit(final DeviceTree node, final MemoryMap memoryMap, final Device device) { + final PciRootPortDevice pr = (PciRootPortDevice) device; + final Optional range = memoryMap.getMemoryRange((MemoryMappedDevice) device); + node + .addProp(DevicePropertyNames.COMPATIBLE, "pci-host-cam-generic") + .addProp(DevicePropertyNames.DEVICE_TYPE, DeviceNames.PCI) + .addProp(DevicePropertyNames.NUM_ADDRESS_CELLS,3) + .addProp(DevicePropertyNames.NUM_SIZE_CELLS, 2) + .addProp("bus-range", 0, 1) + .addProp("linux,pci-probe-only", 1) + .addProp(DevicePropertyNames.RANGES, 0x02000000, 0, 0x40000000, 0x40000000, 0, 0x20000000); + } +} + diff --git a/src/main/java/li/cil/oc2/common/vm/provider/SimpleFramebufferDeviceProvider.java b/src/main/java/li/cil/oc2/common/vm/provider/SimpleFramebufferDeviceProvider.java index ac165c3c..1482009c 100644 --- a/src/main/java/li/cil/oc2/common/vm/provider/SimpleFramebufferDeviceProvider.java +++ b/src/main/java/li/cil/oc2/common/vm/provider/SimpleFramebufferDeviceProvider.java @@ -24,7 +24,7 @@ public final class SimpleFramebufferDeviceProvider implements DeviceTreeProvider final Optional range = memoryMap.getMemoryRange((MemoryMappedDevice) device); return range.map(r -> { final DeviceTree chosen = root.find("/chosen"); - chosen.addProp(DevicePropertyNames.RANGES); + //chosen.addProp(DevicePropertyNames.RANGES); return chosen.getChild(deviceName, r.address()); }); diff --git a/src/main/java/li/cil/oc2/data/ModBlockStateProvider.java b/src/main/java/li/cil/oc2/data/ModBlockStateProvider.java index 30d6964f..d67dcb1c 100644 --- a/src/main/java/li/cil/oc2/data/ModBlockStateProvider.java +++ b/src/main/java/li/cil/oc2/data/ModBlockStateProvider.java @@ -28,6 +28,8 @@ public final class ModBlockStateProvider extends BlockStateProvider { private static final ResourceLocation NETWORK_HUB_MODEL = new ResourceLocation(API.MOD_ID, "block/network_hub"); private static final ResourceLocation PROJECTOR_MODEL = new ResourceLocation(API.MOD_ID, "block/projector"); private static final ResourceLocation REDSTONE_INTERFACE_MODEL = new ResourceLocation(API.MOD_ID, "block/redstone_interface"); + private static final ResourceLocation PCI_CARD_CAGE_MODEL = new ResourceLocation(API.MOD_ID, "block/pci_card_cage"); + public ModBlockStateProvider(final DataGenerator generator, final ExistingFileHelper existingFileHelper) { super(generator, API.MOD_ID, existingFileHelper); @@ -57,6 +59,7 @@ public final class ModBlockStateProvider extends BlockStateProvider { horizontalBlock(Blocks.NETWORK_SWITCH, Items.NETWORK_SWITCH, NETWORK_HUB_MODEL); horizontalBlock(Blocks.PROJECTOR, Items.PROJECTOR, PROJECTOR_MODEL); horizontalBlock(Blocks.REDSTONE_INTERFACE, Items.REDSTONE_INTERFACE, REDSTONE_INTERFACE_MODEL); + horizontalBlock(Blocks.PCI_CARD_CAGE, Items.PCI_CARD_CAGE, PCI_CARD_CAGE_MODEL); registerCableStates(); } diff --git a/src/main/resources/assets/oc2/blockstates/pci_card_cage.json b/src/main/resources/assets/oc2/blockstates/pci_card_cage.json new file mode 100644 index 00000000..769b106f --- /dev/null +++ b/src/main/resources/assets/oc2/blockstates/pci_card_cage.json @@ -0,0 +1,34 @@ +{ + "variants": { + "facing=north,lit=false": { + "model": "oc2:block/pci_card_cage" + }, + "facing=south,lit=false": { + "model": "oc2:block/pci_card_cage", + "y": 180 + }, + "facing=west,lit=false": { + "model": "oc2:block/pci_card_cage", + "y": 270 + }, + "facing=east,lit=false": { + "model": "oc2:block/pci_card_cage", + "y": 90 + }, + "facing=north,lit=true": { + "model": "oc2:block/pci_card_cage" + }, + "facing=south,lit=true": { + "model": "oc2:block/pci_card_cage", + "y": 180 + }, + "facing=west,lit=true": { + "model": "oc2:block/pci_card_cage", + "y": 270 + }, + "facing=east,lit=true": { + "model": "oc2:block/pci_card_cage", + "y": 90 + } + } +} diff --git a/src/main/resources/assets/oc2/models/block/pci_card_cage.json b/src/main/resources/assets/oc2/models/block/pci_card_cage.json new file mode 100644 index 00000000..1267853b --- /dev/null +++ b/src/main/resources/assets/oc2/models/block/pci_card_cage.json @@ -0,0 +1 @@ +{"parent":"block/block","textures":{"atlas0":"oc2:block/pci_card_cage/pci_card_cage_atlas0","atlas1":"oc2:block/pci_card_cage/pci_card_cage_atlas1","atlas2":"oc2:block/pci_card_cage/pci_card_cage_atlas2","atlas3":"oc2:block/pci_card_cage/pci_card_cage_atlas3","atlas4":"oc2:block/pci_card_cage/pci_card_cage_atlas4","atlas5":"oc2:block/pci_card_cage/pci_card_cage_atlas5","particle":"#atlas0"},"elements":[{"from":[0,0,0],"to":[16,2,16],"faces":{"east":{"texture":"atlas0","cullface":"east","uv":[0.0,0.0,8.0,1.0]},"west":{"texture":"atlas0","cullface":"west","uv":[0.0,1.0,8.0,2.0]},"up":{"texture":"atlas0","uv":[0.0,2.0,8.0,10.0]},"down":{"texture":"atlas0","cullface":"down","uv":[8.0,2.0,16.0,10.0]},"north":{"texture":"atlas0","cullface":"north","uv":[0.0,10.0,8.0,11.0]},"south":{"texture":"atlas0","cullface":"south","uv":[0.0,11.0,8.0,12.0]}}},{"from":[0,2,14],"to":[16,6,16],"faces":{"east":{"texture":"atlas4","cullface":"east","uv":[15.0,4.0,16.0,6.0]},"west":{"texture":"atlas4","cullface":"west","uv":[15.0,6.0,16.0,8.0]},"up":{"texture":"atlas0","uv":[0.0,12.0,8.0,13.0]},"north":{"texture":"atlas0","uv":[0.0,13.0,8.0,15.0]},"south":{"texture":"atlas0","cullface":"south","uv":[8.0,13.0,16.0,15.0]}}},{"from":[1,2,2],"to":[15,6,14],"faces":{"east":{"texture":"atlas3","uv":[7.0,12.0,13.0,14.0]},"west":{"texture":"atlas4","uv":[8.0,14.0,14.0,16.0]},"up":{"texture":"atlas4","uv":[8.0,8.0,15.0,14.0]},"down":{"texture":"atlas4","uv":[8.0,0.0,15.0,6.0]},"north":{"texture":"atlas3","uv":[0.0,12.0,7.0,14.0]}}},{"from":[0,2,0],"to":[16,3,2],"faces":{"east":{"texture":"atlas2","cullface":"east","uv":[15.0,15.5,16.0,16.0]},"west":{"texture":"atlas2","cullface":"west","uv":[15.0,15.0,16.0,15.5]},"up":{"texture":"atlas0","uv":[0.0,15.0,8.0,16.0]},"north":{"texture":"atlas0","cullface":"north","uv":[8.0,15.0,16.0,15.5]},"south":{"texture":"atlas0","uv":[8.0,15.5,16.0,16.0]}}},{"from":[0,3,1],"to":[16,4,2],"faces":{"east":{"texture":"atlas3","cullface":"east","uv":[15.5,15.5,16.0,16.0]},"west":{"texture":"atlas3","cullface":"west","uv":[15.5,15.0,16.0,15.5]},"up":{"texture":"atlas0","uv":[8.0,12.0,16.0,12.5]},"north":{"texture":"atlas0","uv":[8.0,12.5,16.0,13.0]},"south":{"texture":"atlas0","uv":[8.0,11.0,16.0,11.5]}}},{"from":[0,3,0],"to":[7,4,1],"faces":{"east":{"texture":"atlas3","uv":[15.5,14.5,16.0,15.0]},"west":{"texture":"atlas3","cullface":"west","uv":[15.5,14.0,16.0,14.5]},"up":{"texture":"atlas3","uv":[12.0,15.5,15.5,16.0]},"north":{"texture":"atlas3","cullface":"north","uv":[4.0,15.0,7.5,15.5]}}},{"from":[9,3,0],"to":[16,4,1],"faces":{"east":{"texture":"atlas5","cullface":"east","uv":[4.0,14.5,4.5,15.0]},"west":{"texture":"atlas5","uv":[4.5,14.5,5.0,15.0]},"up":{"texture":"atlas3","uv":[7.5,15.0,11.0,15.5]},"north":{"texture":"atlas3","cullface":"north","uv":[11.0,15.0,14.5,15.5]}}},{"from":[0,4,0],"to":[4,12,2],"faces":{"east":{"texture":"atlas4","uv":[15.0,0.0,16.0,4.0]},"west":{"texture":"atlas4","cullface":"west","uv":[15.0,8.0,16.0,12.0]},"up":{"texture":"atlas4","uv":[14.0,14.0,16.0,15.0]},"down":{"texture":"atlas4","uv":[14.0,15.0,16.0,16.0]},"north":{"texture":"atlas5","cullface":"north","uv":[0.0,10.5,2.0,14.5]},"south":{"texture":"atlas5","uv":[2.0,10.5,4.0,14.5]}}},{"from":[6,4,0],"to":[10,5,2],"faces":{"east":{"texture":"atlas2","uv":[15.0,6.5,16.0,7.0]},"west":{"texture":"atlas2","uv":[15.0,3.0,16.0,3.5]},"up":{"texture":"atlas5","uv":[0.0,15.0,2.0,16.0]},"down":{"texture":"atlas5","uv":[2.0,15.0,4.0,16.0]},"north":{"texture":"atlas3","cullface":"north","uv":[13.5,14.5,15.5,15.0]}}},{"from":[12,4,0],"to":[16,12,2],"faces":{"east":{"texture":"atlas5","cullface":"east","uv":[4.0,10.5,5.0,14.5]},"west":{"texture":"atlas5","uv":[5.0,10.5,6.0,14.5]},"up":{"texture":"atlas5","uv":[4.0,15.0,6.0,16.0]},"down":{"texture":"atlas5","uv":[6.0,15.0,8.0,16.0]},"north":{"texture":"atlas5","cullface":"north","uv":[6.0,10.5,8.0,14.5]},"south":{"texture":"atlas5","uv":[8.0,10.5,10.0,14.5]}}},{"from":[0,6,15],"to":[2,7,16],"faces":{"east":{"texture":"atlas5","uv":[5.0,14.5,5.5,15.0]},"west":{"texture":"atlas5","cullface":"west","uv":[5.5,14.5,6.0,15.0]},"up":{"texture":"atlas2","uv":[15.0,2.5,16.0,3.0]},"down":{"texture":"atlas2","uv":[15.0,2.0,16.0,2.5]},"south":{"texture":"atlas3","cullface":"south","uv":[14.5,15.0,15.5,15.5]}}},{"from":[5,6,15],"to":[6,7,16],"faces":{"east":{"texture":"atlas5","uv":[6.0,14.5,6.5,15.0]},"west":{"texture":"atlas5","uv":[6.5,14.5,7.0,15.0]},"up":{"texture":"atlas5","uv":[7.0,14.5,7.5,15.0]},"down":{"texture":"atlas5","uv":[7.5,14.5,8.0,15.0]},"south":{"texture":"atlas5","cullface":"south","uv":[8.0,14.5,8.5,15.0]}}},{"from":[10,6,15],"to":[11,7,16],"faces":{"east":{"texture":"atlas5","uv":[8.5,14.5,9.0,15.0]},"west":{"texture":"atlas5","uv":[9.0,14.5,9.5,15.0]},"up":{"texture":"atlas5","uv":[9.5,14.5,10.0,15.0]},"down":{"texture":"atlas5","uv":[10.0,14.5,10.5,15.0]},"south":{"texture":"atlas5","cullface":"south","uv":[10.5,14.5,11.0,15.0]}}},{"from":[14,6,15],"to":[16,7,16],"faces":{"east":{"texture":"atlas5","cullface":"east","uv":[11.0,14.5,11.5,15.0]},"west":{"texture":"atlas5","uv":[11.5,14.5,12.0,15.0]},"up":{"texture":"atlas3","uv":[14.0,11.5,15.0,12.0]},"down":{"texture":"atlas3","uv":[15.0,11.5,16.0,12.0]},"south":{"texture":"atlas3","cullface":"south","uv":[14.0,7.5,15.0,8.0]}}},{"from":[0,6,2],"to":[16,7,15],"faces":{"east":{"texture":"atlas3","cullface":"east","uv":[0.0,14.0,6.5,14.5]},"west":{"texture":"atlas3","cullface":"west","uv":[0.0,14.5,6.5,15.0]},"up":{"texture":"atlas1","uv":[0.0,0.0,8.0,6.5]},"down":{"texture":"atlas1","uv":[0.0,6.5,8.0,13.0]},"north":{"texture":"atlas0","uv":[8.0,11.5,16.0,12.0]},"south":{"texture":"atlas0","uv":[8.0,10.0,16.0,10.5]}}},{"from":[0,7,15],"to":[6,8,16],"faces":{"east":{"texture":"atlas5","uv":[12.0,14.5,12.5,15.0]},"west":{"texture":"atlas5","cullface":"west","uv":[12.5,14.5,13.0,15.0]},"up":{"texture":"atlas3","uv":[6.5,14.0,9.5,14.5]},"down":{"texture":"atlas3","uv":[9.5,14.0,12.5,14.5]},"south":{"texture":"atlas3","cullface":"south","uv":[12.5,14.0,15.5,14.5]}}},{"from":[10,7,15],"to":[16,8,16],"faces":{"east":{"texture":"atlas5","cullface":"east","uv":[13.0,14.5,13.5,15.0]},"west":{"texture":"atlas5","uv":[13.5,14.5,14.0,15.0]},"up":{"texture":"atlas3","uv":[13.0,12.0,16.0,12.5]},"down":{"texture":"atlas3","uv":[13.0,12.5,16.0,13.0]},"south":{"texture":"atlas3","cullface":"south","uv":[13.0,13.0,16.0,13.5]}}},{"from":[0,7,8],"to":[16,11,15],"faces":{"east":{"texture":"atlas4","cullface":"east","uv":[8.0,6.0,11.5,8.0]},"west":{"texture":"atlas4","cullface":"west","uv":[11.5,6.0,15.0,8.0]},"up":{"texture":"atlas1","uv":[8.0,6.5,16.0,10.0]},"down":{"texture":"atlas1","uv":[8.0,0.0,16.0,3.5]},"north":{"texture":"atlas1","uv":[0.0,13.0,8.0,15.0]},"south":{"texture":"atlas1","uv":[8.0,13.0,16.0,15.0]}}},{"from":[1,7,7],"to":[15,14,8],"faces":{"east":{"texture":"atlas3","uv":[15.0,0.0,15.5,3.5]},"west":{"texture":"atlas3","uv":[15.5,0.0,16.0,3.5]},"up":{"texture":"atlas2","uv":[8.0,15.5,15.0,16.0]},"down":{"texture":"atlas2","uv":[8.0,15.0,15.0,15.5]},"north":{"texture":"atlas3","uv":[8.0,8.0,15.0,11.5]},"south":{"texture":"atlas3","uv":[8.0,4.0,15.0,7.5]}}},{"from":[0,7,6],"to":[16,14,7],"faces":{"east":{"texture":"atlas3","cullface":"east","uv":[15.0,4.0,15.5,7.5]},"west":{"texture":"atlas3","cullface":"west","uv":[15.5,4.0,16.0,7.5]},"up":{"texture":"atlas0","uv":[8.0,10.5,16.0,11.0]},"down":{"texture":"atlas0","uv":[8.0,1.0,16.0,1.5]},"north":{"texture":"atlas2","uv":[0.0,0.0,8.0,3.5]},"south":{"texture":"atlas2","uv":[0.0,3.5,8.0,7.0]}}},{"from":[1,7,5],"to":[15,14,6],"faces":{"east":{"texture":"atlas3","uv":[15.0,8.0,15.5,11.5]},"west":{"texture":"atlas3","uv":[15.5,8.0,16.0,11.5]},"up":{"texture":"atlas2","uv":[8.0,6.5,15.0,7.0]},"down":{"texture":"atlas2","uv":[8.0,2.0,15.0,2.5]},"north":{"texture":"atlas3","uv":[8.0,0.0,15.0,3.5]},"south":{"texture":"atlas5","uv":[0.0,0.0,7.0,3.5]}}},{"from":[0,7,4],"to":[16,14,5],"faces":{"east":{"texture":"atlas5","cullface":"east","uv":[7.0,0.0,7.5,3.5]},"west":{"texture":"atlas5","cullface":"west","uv":[7.5,0.0,8.0,3.5]},"up":{"texture":"atlas0","uv":[8.0,1.5,16.0,2.0]},"down":{"texture":"atlas0","uv":[8.0,0.0,16.0,0.5]},"north":{"texture":"atlas2","uv":[0.0,7.0,8.0,10.5]},"south":{"texture":"atlas2","uv":[0.0,10.5,8.0,14.0]}}},{"from":[1,7,3],"to":[15,14,4],"faces":{"east":{"texture":"atlas5","uv":[8.0,0.0,8.5,3.5]},"west":{"texture":"atlas5","uv":[8.5,0.0,9.0,3.5]},"up":{"texture":"atlas2","uv":[8.0,2.5,15.0,3.0]},"down":{"texture":"atlas2","uv":[8.0,3.0,15.0,3.5]},"north":{"texture":"atlas5","uv":[0.0,3.5,7.0,7.0]},"south":{"texture":"atlas5","uv":[0.0,7.0,7.0,10.5]}}},{"from":[0,7,2],"to":[16,12,3],"faces":{"east":{"texture":"atlas5","cullface":"east","uv":[9.0,0.0,9.5,2.5]},"west":{"texture":"atlas5","cullface":"west","uv":[9.5,0.0,10.0,2.5]},"up":{"texture":"atlas0","uv":[8.0,0.5,16.0,1.0]},"down":{"texture":"atlas1","uv":[0.0,15.0,8.0,15.5]},"north":{"texture":"atlas1","uv":[8.0,10.0,16.0,12.5]},"south":{"texture":"atlas1","uv":[8.0,3.5,16.0,6.0]}}},{"from":[0,8,15],"to":[2,9,16],"faces":{"east":{"texture":"atlas5","uv":[14.0,14.5,14.5,15.0]},"west":{"texture":"atlas5","cullface":"west","uv":[14.5,14.5,15.0,15.0]},"up":{"texture":"atlas3","uv":[15.0,7.5,16.0,8.0]},"down":{"texture":"atlas3","uv":[14.0,3.5,15.0,4.0]},"south":{"texture":"atlas3","cullface":"south","uv":[15.0,3.5,16.0,4.0]}}},{"from":[5,8,15],"to":[6,9,16],"faces":{"east":{"texture":"atlas5","uv":[15.0,14.5,15.5,15.0]},"west":{"texture":"atlas5","uv":[15.5,14.5,16.0,15.0]},"up":{"texture":"atlas5","uv":[10.0,10.5,10.5,11.0]},"down":{"texture":"atlas5","uv":[10.0,11.0,10.5,11.5]},"south":{"texture":"atlas5","cullface":"south","uv":[10.0,11.5,10.5,12.0]}}},{"from":[10,8,15],"to":[11,9,16],"faces":{"east":{"texture":"atlas5","uv":[10.0,12.0,10.5,12.5]},"west":{"texture":"atlas5","uv":[10.0,12.5,10.5,13.0]},"up":{"texture":"atlas5","uv":[10.0,13.0,10.5,13.5]},"down":{"texture":"atlas5","uv":[10.0,13.5,10.5,14.0]},"south":{"texture":"atlas5","cullface":"south","uv":[10.0,14.0,10.5,14.5]}}},{"from":[14,8,15],"to":[16,9,16],"faces":{"east":{"texture":"atlas5","cullface":"east","uv":[10.5,14.0,11.0,14.5]},"west":{"texture":"atlas5","uv":[11.0,14.0,11.5,14.5]},"up":{"texture":"atlas4","uv":[15.0,12.0,16.0,12.5]},"down":{"texture":"atlas4","uv":[15.0,12.5,16.0,13.0]},"south":{"texture":"atlas4","cullface":"south","uv":[15.0,13.0,16.0,13.5]}}},{"from":[0,9,15],"to":[6,10,16],"faces":{"east":{"texture":"atlas5","uv":[11.5,14.0,12.0,14.5]},"west":{"texture":"atlas5","cullface":"west","uv":[12.0,14.0,12.5,14.5]},"up":{"texture":"atlas3","uv":[13.0,13.5,16.0,14.0]},"down":{"texture":"atlas3","uv":[8.0,11.5,11.0,12.0]},"south":{"texture":"atlas3","cullface":"south","uv":[11.0,11.5,14.0,12.0]}}},{"from":[10,9,15],"to":[16,10,16],"faces":{"east":{"texture":"atlas5","cullface":"east","uv":[12.5,14.0,13.0,14.5]},"west":{"texture":"atlas5","uv":[13.0,14.0,13.5,14.5]},"up":{"texture":"atlas3","uv":[8.0,7.5,11.0,8.0]},"down":{"texture":"atlas3","uv":[11.0,7.5,14.0,8.0]},"south":{"texture":"atlas3","cullface":"south","uv":[8.0,3.5,11.0,4.0]}}},{"from":[0,10,15],"to":[2,11,16],"faces":{"east":{"texture":"atlas5","uv":[13.5,14.0,14.0,14.5]},"west":{"texture":"atlas5","cullface":"west","uv":[14.0,14.0,14.5,14.5]},"up":{"texture":"atlas4","uv":[15.0,13.5,16.0,14.0]},"down":{"texture":"atlas5","uv":[11.0,15.0,12.0,15.5]},"south":{"texture":"atlas5","cullface":"south","uv":[11.0,15.5,12.0,16.0]}}},{"from":[5,10,15],"to":[11,11,16],"faces":{"east":{"texture":"atlas5","uv":[14.5,14.0,15.0,14.5]},"west":{"texture":"atlas5","uv":[15.0,14.0,15.5,14.5]},"down":{"texture":"atlas3","uv":[11.0,3.5,14.0,4.0]},"south":{"texture":"atlas5","cullface":"south","uv":[0.0,14.5,3.0,15.0]}}},{"from":[14,10,15],"to":[16,11,16],"faces":{"east":{"texture":"atlas5","cullface":"east","uv":[15.5,14.0,16.0,14.5]},"west":{"texture":"atlas5","uv":[10.5,13.5,11.0,14.0]},"up":{"texture":"atlas5","uv":[12.0,15.5,13.0,16.0]},"down":{"texture":"atlas5","uv":[13.0,15.5,14.0,16.0]},"south":{"texture":"atlas5","cullface":"south","uv":[14.0,15.5,15.0,16.0]}}},{"from":[0,11,8],"to":[16,12,16],"faces":{"east":{"texture":"atlas3","cullface":"east","uv":[0.0,15.0,4.0,15.5]},"west":{"texture":"atlas3","cullface":"west","uv":[0.0,15.5,4.0,16.0]},"up":{"texture":"atlas3","uv":[0.0,0.0,8.0,4.0]},"down":{"texture":"atlas3","uv":[0.0,4.0,8.0,8.0]},"north":{"texture":"atlas1","uv":[0.0,15.5,8.0,16.0]},"south":{"texture":"atlas1","cullface":"south","uv":[8.0,15.5,16.0,16.0]}}},{"from":[0,12,15],"to":[2,13,16],"faces":{"east":{"texture":"atlas5","uv":[11.0,13.5,11.5,14.0]},"west":{"texture":"atlas5","cullface":"west","uv":[11.5,13.5,12.0,14.0]},"up":{"texture":"atlas5","uv":[15.0,15.5,16.0,16.0]},"down":{"texture":"atlas5","uv":[12.0,15.0,13.0,15.5]},"south":{"texture":"atlas5","cullface":"south","uv":[13.0,15.0,14.0,15.5]}}},{"from":[14,12,15],"to":[16,13,16],"faces":{"east":{"texture":"atlas5","cullface":"east","uv":[12.0,13.5,12.5,14.0]},"west":{"texture":"atlas5","uv":[12.5,13.5,13.0,14.0]},"up":{"texture":"atlas5","uv":[14.0,15.0,15.0,15.5]},"down":{"texture":"atlas5","uv":[15.0,15.0,16.0,15.5]},"south":{"texture":"atlas5","cullface":"south","uv":[3.0,14.5,4.0,15.0]}}},{"from":[0,12,8],"to":[16,13,15],"faces":{"east":{"texture":"atlas3","cullface":"east","uv":[6.5,14.5,10.0,15.0]},"west":{"texture":"atlas3","cullface":"west","uv":[10.0,14.5,13.5,15.0]},"up":{"texture":"atlas2","uv":[8.0,10.5,16.0,14.0]},"down":{"texture":"atlas2","uv":[8.0,7.0,16.0,10.5]},"north":{"texture":"atlas1","uv":[8.0,15.0,16.0,15.5]},"south":{"texture":"atlas1","uv":[8.0,12.5,16.0,13.0]}}},{"from":[0,12,0],"to":[16,14,3],"faces":{"east":{"texture":"atlas5","cullface":"east","uv":[8.0,15.0,9.5,16.0]},"west":{"texture":"atlas5","cullface":"west","uv":[9.5,15.0,11.0,16.0]},"down":{"texture":"atlas2","uv":[0.0,14.0,8.0,15.5]},"north":{"texture":"atlas2","cullface":"north","uv":[8.0,14.0,16.0,15.0]},"south":{"texture":"atlas2","uv":[8.0,3.5,16.0,4.5]}}},{"from":[0,13,8],"to":[16,14,16],"faces":{"east":{"texture":"atlas3","cullface":"east","uv":[4.0,15.5,8.0,16.0]},"west":{"texture":"atlas3","cullface":"west","uv":[8.0,15.5,12.0,16.0]},"down":{"texture":"atlas3","uv":[0.0,8.0,8.0,12.0]},"north":{"texture":"atlas1","uv":[8.0,6.0,16.0,6.5]},"south":{"texture":"atlas2","cullface":"south","uv":[0.0,15.5,8.0,16.0]}}},{"from":[0,14,0],"to":[16,16,16],"faces":{"east":{"texture":"atlas2","cullface":"east","uv":[8.0,4.5,16.0,5.5]},"west":{"texture":"atlas2","cullface":"west","uv":[8.0,5.5,16.0,6.5]},"up":{"texture":"atlas4","cullface":"up","uv":[0.0,0.0,8.0,8.0]},"down":{"texture":"atlas4","uv":[0.0,8.0,8.0,16.0]},"north":{"texture":"atlas2","cullface":"north","uv":[8.0,0.0,16.0,1.0]},"south":{"texture":"atlas2","cullface":"south","uv":[8.0,1.0,16.0,2.0]}}}]} diff --git a/src/main/resources/assets/oc2/models/item/pci_card_cage.json b/src/main/resources/assets/oc2/models/item/pci_card_cage.json new file mode 100644 index 00000000..b01fc003 --- /dev/null +++ b/src/main/resources/assets/oc2/models/item/pci_card_cage.json @@ -0,0 +1,3 @@ +{ + "parent": "oc2:block/pci_card_cage" +} diff --git a/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas0.png b/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas0.png new file mode 100644 index 00000000..cc49ffef Binary files /dev/null and b/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas0.png differ diff --git a/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas1.png b/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas1.png new file mode 100644 index 00000000..d68bbc35 Binary files /dev/null and b/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas1.png differ diff --git a/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas2.png b/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas2.png new file mode 100644 index 00000000..787d9203 Binary files /dev/null and b/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas2.png differ diff --git a/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas3.png b/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas3.png new file mode 100644 index 00000000..738c4657 Binary files /dev/null and b/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas3.png differ diff --git a/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas4.png b/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas4.png new file mode 100644 index 00000000..113d34a6 Binary files /dev/null and b/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas4.png differ diff --git a/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas5.png b/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas5.png new file mode 100644 index 00000000..3f126b89 Binary files /dev/null and b/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas5.png differ diff --git a/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas6.png b/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas6.png new file mode 100644 index 00000000..65320de0 Binary files /dev/null and b/src/main/resources/assets/oc2/textures/block/pci_card_cage/pci_card_cage_atlas6.png differ