From 1f16bafe4e7e8475d07dfbef81b64ff77cf865dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 29 Dec 2020 18:09:44 +0100 Subject: [PATCH] Add redstone interface card. --- src/main/java/li/cil/oc2/Constants.java | 1 + .../item/RedstoneInterfaceCardItemDevice.java | 165 ++++++++++++++++++ ...dstoneInterfaceCardItemDeviceProvider.java | 23 +++ .../java/li/cil/oc2/common/init/Items.java | 1 + .../li/cil/oc2/common/init/Providers.java | 2 + src/main/java/li/cil/oc2/data/ItemModels.java | 1 + src/main/resources/assets/oc2/lang/en_us.json | 1 + .../models/item/redstone_interface_card.json | 6 + 8 files changed, 200 insertions(+) create mode 100644 src/main/java/li/cil/oc2/common/bus/device/item/RedstoneInterfaceCardItemDevice.java create mode 100644 src/main/java/li/cil/oc2/common/bus/device/provider/item/RedstoneInterfaceCardItemDeviceProvider.java create mode 100644 src/main/resources/assets/oc2/models/item/redstone_interface_card.json diff --git a/src/main/java/li/cil/oc2/Constants.java b/src/main/java/li/cil/oc2/Constants.java index a55fceb5..888053e7 100644 --- a/src/main/java/li/cil/oc2/Constants.java +++ b/src/main/java/li/cil/oc2/Constants.java @@ -23,6 +23,7 @@ public final class Constants { public static final String FLASH_MEMORY_ITEM_NAME = "flash_memory"; public static final String MEMORY_ITEM_NAME = "memory"; public static final String HARD_DRIVE_ITEM_NAME = "hard_drive"; + public static final String REDSTONE_INTERFACE_CARD_NAME = "redstone_interface_card"; /////////////////////////////////////////////////////////////////// diff --git a/src/main/java/li/cil/oc2/common/bus/device/item/RedstoneInterfaceCardItemDevice.java b/src/main/java/li/cil/oc2/common/bus/device/item/RedstoneInterfaceCardItemDevice.java new file mode 100644 index 00000000..ab116607 --- /dev/null +++ b/src/main/java/li/cil/oc2/common/bus/device/item/RedstoneInterfaceCardItemDevice.java @@ -0,0 +1,165 @@ +package li.cil.oc2.common.bus.device.item; + +import li.cil.oc2.api.bus.device.ItemDevice; +import li.cil.oc2.api.bus.device.capabilities.RedstoneEmitter; +import li.cil.oc2.api.bus.device.object.Callback; +import li.cil.oc2.api.bus.device.object.ObjectDevice; +import li.cil.oc2.api.bus.device.rpc.RPCDevice; +import li.cil.oc2.api.bus.device.rpc.RPCMethod; +import li.cil.oc2.common.bus.device.util.IdentityProxy; +import li.cil.oc2.common.capabilities.Capabilities; +import li.cil.oc2.common.util.HorizontalBlockUtils; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.common.util.LazyOptional; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Objects; + +public final class RedstoneInterfaceCardItemDevice extends IdentityProxy implements RPCDevice, ItemDevice, ICapabilityProvider { + private static final int FACE_COUNT = Direction.values().length; + + private static final String OUTPUT_TAG_NAME = "output"; + + /////////////////////////////////////////////////////////////////// + + private final TileEntity tileEntity; + private final ObjectDevice device; + private final RedstoneEmitter[] capabilities; + private final byte[] output = new byte[FACE_COUNT]; + + /////////////////////////////////////////////////////////////////// + + public RedstoneInterfaceCardItemDevice(final ItemStack value, final TileEntity tileEntity) { + super(value); + this.tileEntity = tileEntity; + this.device = new ObjectDevice(this, "redstone"); + + capabilities = new RedstoneEmitter[FACE_COUNT]; + for (int i = 0; i < FACE_COUNT; i++) { + final int indexForClosure = i; + capabilities[i] = () -> output[indexForClosure]; + } + } + + /////////////////////////////////////////////////////////////////// + + @Override + public List getTypeNames() { + return device.getTypeNames(); + } + + @Override + public List getMethods() { + return device.getMethods(); + } + + @Nonnull + @Override + public LazyOptional getCapability(@Nonnull final Capability cap, @Nullable final Direction side) { + if (cap == Capabilities.REDSTONE_EMITTER && side != null) { + return LazyOptional.of(() -> capabilities[side.getIndex()]).cast(); + } + + return LazyOptional.empty(); + } + + @Override + public CompoundNBT serializeNBT() { + final CompoundNBT nbt = new CompoundNBT(); + nbt.putByteArray(OUTPUT_TAG_NAME, output); + return nbt; + } + + @Override + public void deserializeNBT(final CompoundNBT nbt) { + final byte[] serializedOutput = nbt.getByteArray(OUTPUT_TAG_NAME); + System.arraycopy(serializedOutput, 0, output, 0, Math.min(serializedOutput.length, output.length)); + } + + /////////////////////////////////////////////////////////////////// + + @Callback(synchronize = false) + public int getRedstoneOutput(final Direction side) { + return output[side.getIndex()]; + } + + @Callback + public void setRedstoneOutput(final Direction side, final int value) { + final byte clampedValue = (byte) MathHelper.clamp(value, 0, 15); + if (clampedValue == output[side.getIndex()]) { + return; + } + + output[side.getIndex()] = clampedValue; + + final Direction direction = HorizontalBlockUtils.toGlobal(tileEntity.getBlockState(), side); + if (direction != null) { + notifyNeighbors(direction); + } + } + + @Callback + public int getRedstoneInput(final Direction side) { + final World world = tileEntity.getWorld(); + if (world == null) { + return 0; + } + + final BlockPos pos = tileEntity.getPos(); + final Direction direction = HorizontalBlockUtils.toGlobal(tileEntity.getBlockState(), side); + assert direction != null; + + final BlockPos neighborPos = pos.offset(direction); + final ChunkPos chunkPos = new ChunkPos(neighborPos.getX(), neighborPos.getZ()); + if (!world.chunkExists(chunkPos.x, chunkPos.z)) { + return 0; + } + + return world.getRedstonePower(neighborPos, direction); + } + + /////////////////////////////////////////////////////////////////// + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + final RedstoneInterfaceCardItemDevice that = (RedstoneInterfaceCardItemDevice) o; + return tileEntity.equals(that.tileEntity); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), tileEntity); + } + + /////////////////////////////////////////////////////////////////// + + private void notifyNeighbors(final Direction direction) { + final World world = tileEntity.getWorld(); + if (world == null) { + return; + } + + final BlockPos pos = tileEntity.getPos(); + final BlockState state = tileEntity.getBlockState(); + final Block block = state.getBlock(); + + world.notifyNeighborsOfStateChange(pos, block); + world.notifyNeighborsOfStateChange(pos.offset(direction), block); + } +} diff --git a/src/main/java/li/cil/oc2/common/bus/device/provider/item/RedstoneInterfaceCardItemDeviceProvider.java b/src/main/java/li/cil/oc2/common/bus/device/provider/item/RedstoneInterfaceCardItemDeviceProvider.java new file mode 100644 index 00000000..59c3cb4b --- /dev/null +++ b/src/main/java/li/cil/oc2/common/bus/device/provider/item/RedstoneInterfaceCardItemDeviceProvider.java @@ -0,0 +1,23 @@ +package li.cil.oc2.common.bus.device.provider.item; + +import li.cil.oc2.api.bus.device.ItemDevice; +import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery; +import li.cil.oc2.common.bus.device.item.RedstoneInterfaceCardItemDevice; +import li.cil.oc2.common.bus.device.provider.util.AbstractItemDeviceProvider; +import li.cil.oc2.common.init.Items; + +import java.util.Optional; + +public final class RedstoneInterfaceCardItemDeviceProvider extends AbstractItemDeviceProvider { + public RedstoneInterfaceCardItemDeviceProvider() { + super(Items.REDSTONE_INTERFACE_CARD_ITEM); + } + + /////////////////////////////////////////////////////////////////// + + @Override + protected Optional getItemDevice(final ItemDeviceQuery query) { + return query.getContainerTileEntity().map(tileEntity -> + new RedstoneInterfaceCardItemDevice(query.getItemStack(), tileEntity)); + } +} diff --git a/src/main/java/li/cil/oc2/common/init/Items.java b/src/main/java/li/cil/oc2/common/init/Items.java index 4c0fae4f..66113f1f 100644 --- a/src/main/java/li/cil/oc2/common/init/Items.java +++ b/src/main/java/li/cil/oc2/common/init/Items.java @@ -30,6 +30,7 @@ public final class Items { public static final RegistryObject MEMORY_ITEM = register(Constants.MEMORY_ITEM_NAME, MemoryItem::new, new Item.Properties()); public static final RegistryObject HARD_DRIVE_ITEM = register(Constants.HARD_DRIVE_ITEM_NAME, HardDriveItem::new, new Item.Properties()); public static final RegistryObject FLASH_MEMORY_ITEM = register(Constants.FLASH_MEMORY_ITEM_NAME, FlashMemoryItem::new, new Item.Properties()); + public static final RegistryObject REDSTONE_INTERFACE_CARD_ITEM = register(Constants.REDSTONE_INTERFACE_CARD_NAME); /////////////////////////////////////////////////////////////////// diff --git a/src/main/java/li/cil/oc2/common/init/Providers.java b/src/main/java/li/cil/oc2/common/init/Providers.java index ed251503..fc4a23cd 100644 --- a/src/main/java/li/cil/oc2/common/init/Providers.java +++ b/src/main/java/li/cil/oc2/common/init/Providers.java @@ -7,6 +7,7 @@ import li.cil.oc2.common.bus.device.provider.block.*; import li.cil.oc2.common.bus.device.provider.item.FlashMemoryItemDeviceProvider; import li.cil.oc2.common.bus.device.provider.item.HardDriveItemDeviceProvider; import li.cil.oc2.common.bus.device.provider.item.MemoryItemDeviceProvider; +import li.cil.oc2.common.bus.device.provider.item.RedstoneInterfaceCardItemDeviceProvider; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.IForgeRegistry; @@ -36,6 +37,7 @@ public final class Providers { ITEM_DEVICE_PROVIDERS.register("item_memory", MemoryItemDeviceProvider::new); ITEM_DEVICE_PROVIDERS.register("item_hard_drive", HardDriveItemDeviceProvider::new); ITEM_DEVICE_PROVIDERS.register("item_flash_memory", FlashMemoryItemDeviceProvider::new); + ITEM_DEVICE_PROVIDERS.register("item_redstone_interface_card", RedstoneInterfaceCardItemDeviceProvider::new); BLOCK_DEVICE_PROVIDERS.register(FMLJavaModLoadingContext.get().getModEventBus()); ITEM_DEVICE_PROVIDERS.register(FMLJavaModLoadingContext.get().getModEventBus()); diff --git a/src/main/java/li/cil/oc2/data/ItemModels.java b/src/main/java/li/cil/oc2/data/ItemModels.java index 48b802dd..d5b611e4 100644 --- a/src/main/java/li/cil/oc2/data/ItemModels.java +++ b/src/main/java/li/cil/oc2/data/ItemModels.java @@ -43,6 +43,7 @@ public final class ItemModels extends ItemModelProvider { .end(); simple(Items.FLASH_MEMORY_ITEM, "items/flash_memory"); + simple(Items.REDSTONE_INTERFACE_CARD_ITEM, "items/redstone_interface_card"); } private ItemModelBuilder simple(final RegistryObject item, final String texturePath) { diff --git a/src/main/resources/assets/oc2/lang/en_us.json b/src/main/resources/assets/oc2/lang/en_us.json index 116b480d..8bd4189b 100644 --- a/src/main/resources/assets/oc2/lang/en_us.json +++ b/src/main/resources/assets/oc2/lang/en_us.json @@ -11,6 +11,7 @@ "item.oc2.memory": "Memory", "item.oc2.hard_drive": "Hard Drive", "item.oc2.flash_memory": "Flash Memory", + "item.oc2.redstone_interface_card": "Redstone Interface Card", "gui.oc2.computer.boot_error.unknown": "Unknown Error", "gui.oc2.computer.boot_error.no_memory": "Insufficient Memory", diff --git a/src/main/resources/assets/oc2/models/item/redstone_interface_card.json b/src/main/resources/assets/oc2/models/item/redstone_interface_card.json new file mode 100644 index 00000000..4ae881f8 --- /dev/null +++ b/src/main/resources/assets/oc2/models/item/redstone_interface_card.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/handheld", + "textures": { + "layer0": "oc2:items/redstone_interface_card" + } +} \ No newline at end of file