From c196659cc1c3ef990a61cdb4db28e58ec409a860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Fri, 12 Feb 2021 01:05:26 +0100 Subject: [PATCH] Add logic for energy support, closes #3. Computer and robot now consume energy; constant amount per tick while running. Added charger block to allow charging robots. Charger can charge anything with IEnergyStorage capability and items with it in an ItemHandler on top of it. Also some renames, mostly nbt -> tag. --- .../java/li/cil/oc2/client/ClientSetup.java | 4 + .../cil/oc2/client/item/CustomItemColors.java | 2 +- .../oc2/client/renderer/CustomRenderType.java | 14 +- .../tileentity/ChargerTileEntityRenderer.java | 91 +++++++ .../ComputerTileEntityRenderer.java | 29 ++- src/main/java/li/cil/oc2/common/Config.java | 81 +++++- .../java/li/cil/oc2/common/Constants.java | 14 +- .../java/li/cil/oc2/common/block/Blocks.java | 1 + .../li/cil/oc2/common/block/ChargerBlock.java | 62 +++++ .../cil/oc2/common/block/ComputerBlock.java | 15 +- .../bus/AbstractGroupingDeviceBusElement.java | 40 +-- .../bus/ItemHandlerDeviceBusElement.java | 23 +- .../item/AbstractBlockDeviceVMDevice.java | 16 +- .../item/ByteBufferFlashMemoryVMDevice.java | 8 +- .../common/bus/device/item/MemoryDevice.java | 8 +- .../item/NetworkInterfaceCardItemDevice.java | 14 +- .../container/DeviceItemStackHandler.java | 12 +- .../common/energy/EnergyStorageItemStack.java | 69 +++++ .../oc2/common/energy/FixedEnergyStorage.java | 27 ++ .../cil/oc2/common/energy/package-info.java | 7 + .../li/cil/oc2/common/entity/RobotEntity.java | 78 ++++-- .../entity/robot/RobotMovementAction.java | 13 +- .../common/item/AbstractBlockDeviceItem.java | 16 +- .../oc2/common/item/AbstractStorageItem.java | 9 +- .../li/cil/oc2/common/item/ChargerItem.java | 22 ++ .../cil/oc2/common/item/FlashMemoryItem.java | 7 +- .../java/li/cil/oc2/common/item/Items.java | 1 + .../li/cil/oc2/common/item/RobotItem.java | 18 ++ .../serialization/NBTSerialization.java | 240 +++++++++--------- .../serialization/NBTToJsonConverter.java | 36 +-- .../common/tileentity/ChargerTileEntity.java | 96 +++++++ .../common/tileentity/ComputerTileEntity.java | 58 ++++- .../tileentity/DiskDriveTileEntity.java | 8 +- .../oc2/common/tileentity/TileEntities.java | 1 + .../cil/oc2/common/util/ItemDeviceUtils.java | 17 +- .../cil/oc2/common/util/ItemStackUtils.java | 64 +---- .../java/li/cil/oc2/common/util/NBTUtils.java | 62 ++--- .../li/cil/oc2/common/util/TooltipUtils.java | 66 +++-- .../cil/oc2/data/ModBlockStateProvider.java | 1 + .../li/cil/oc2/data/ModBlockTagsProvider.java | 3 +- .../li/cil/oc2/data/ModLootTableProvider.java | 11 +- .../assets/oc2/blockstates/charger.json | 19 ++ src/main/resources/assets/oc2/lang/en_us.json | 10 +- .../assets/oc2/models/block/charger.json | 1 + .../assets/oc2/models/item/charger.json | 3 + .../textures/block/charger/charger_atlas0.png | Bin 0 -> 1694 bytes .../textures/block/charger/charger_atlas1.png | Bin 0 -> 1909 bytes .../textures/block/charger/charger_atlas2.png | Bin 0 -> 1526 bytes .../textures/block/charger/charger_atlas3.png | Bin 0 -> 159 bytes .../oc2/textures/block/charger/effect.png | Bin 0 -> 2014 bytes .../data/oc2/loot_tables/blocks/charger.json | 19 ++ .../data/oc2/loot_tables/blocks/computer.json | 5 + .../oc2/tags/blocks/wrench_breakable.json | 3 +- 53 files changed, 988 insertions(+), 436 deletions(-) create mode 100644 src/main/java/li/cil/oc2/client/renderer/tileentity/ChargerTileEntityRenderer.java create mode 100644 src/main/java/li/cil/oc2/common/block/ChargerBlock.java create mode 100644 src/main/java/li/cil/oc2/common/energy/EnergyStorageItemStack.java create mode 100644 src/main/java/li/cil/oc2/common/energy/FixedEnergyStorage.java create mode 100644 src/main/java/li/cil/oc2/common/energy/package-info.java create mode 100644 src/main/java/li/cil/oc2/common/item/ChargerItem.java create mode 100644 src/main/java/li/cil/oc2/common/tileentity/ChargerTileEntity.java create mode 100644 src/main/resources/assets/oc2/blockstates/charger.json create mode 100644 src/main/resources/assets/oc2/models/block/charger.json create mode 100644 src/main/resources/assets/oc2/models/item/charger.json create mode 100644 src/main/resources/assets/oc2/textures/block/charger/charger_atlas0.png create mode 100644 src/main/resources/assets/oc2/textures/block/charger/charger_atlas1.png create mode 100644 src/main/resources/assets/oc2/textures/block/charger/charger_atlas2.png create mode 100644 src/main/resources/assets/oc2/textures/block/charger/charger_atlas3.png create mode 100644 src/main/resources/assets/oc2/textures/block/charger/effect.png create mode 100644 src/main/resources/data/oc2/loot_tables/blocks/charger.json diff --git a/src/main/java/li/cil/oc2/client/ClientSetup.java b/src/main/java/li/cil/oc2/client/ClientSetup.java index 41a0a69b..cc91dd92 100644 --- a/src/main/java/li/cil/oc2/client/ClientSetup.java +++ b/src/main/java/li/cil/oc2/client/ClientSetup.java @@ -10,6 +10,7 @@ import li.cil.oc2.client.item.CustomItemModelProperties; import li.cil.oc2.client.model.BusCableModelLoader; import li.cil.oc2.client.renderer.NetworkCableRenderer; import li.cil.oc2.client.renderer.entity.RobotEntityRenderer; +import li.cil.oc2.client.renderer.tileentity.ChargerTileEntityRenderer; import li.cil.oc2.client.renderer.tileentity.ComputerTileEntityRenderer; import li.cil.oc2.client.renderer.tileentity.DiskDriveTileEntityRenderer; import li.cil.oc2.client.renderer.tileentity.NetworkConnectorTileEntityRenderer; @@ -43,6 +44,7 @@ public final class ClientSetup { ClientRegistry.bindTileEntityRenderer(TileEntities.COMPUTER_TILE_ENTITY.get(), ComputerTileEntityRenderer::new); ClientRegistry.bindTileEntityRenderer(TileEntities.NETWORK_CONNECTOR_TILE_ENTITY.get(), NetworkConnectorTileEntityRenderer::new); ClientRegistry.bindTileEntityRenderer(TileEntities.DISK_DRIVE_TILE_ENTITY.get(), DiskDriveTileEntityRenderer::new); + ClientRegistry.bindTileEntityRenderer(TileEntities.CHARGER_TILE_ENTITY.get(), ChargerTileEntityRenderer::new); RenderingRegistry.registerEntityRenderingHandler(Entities.ROBOT.get(), RobotEntityRenderer::new); } @@ -65,5 +67,7 @@ public final class ClientSetup { event.addSprite(ComputerTileEntityRenderer.OVERLAY_POWER_LOCATION); event.addSprite(ComputerTileEntityRenderer.OVERLAY_STATUS_LOCATION); event.addSprite(ComputerTileEntityRenderer.OVERLAY_TERMINAL_LOCATION); + + event.addSprite(ChargerTileEntityRenderer.EFFECT_LOCATION); } } diff --git a/src/main/java/li/cil/oc2/client/item/CustomItemColors.java b/src/main/java/li/cil/oc2/client/item/CustomItemColors.java index 93745196..30943f3c 100644 --- a/src/main/java/li/cil/oc2/client/item/CustomItemColors.java +++ b/src/main/java/li/cil/oc2/client/item/CustomItemColors.java @@ -82,7 +82,7 @@ public final class CustomItemColors { public static int getColor(final ItemStack stack) { final CompoundNBT tag = ItemStackUtils.getModDataTag(stack); - if (tag != null && tag.contains(COLOR_TAG_NAME, NBTTagIds.TAG_INT)) { + if (tag.contains(COLOR_TAG_NAME, NBTTagIds.TAG_INT)) { return tag.getInt(COLOR_TAG_NAME); } else { return GREY; diff --git a/src/main/java/li/cil/oc2/client/renderer/CustomRenderType.java b/src/main/java/li/cil/oc2/client/renderer/CustomRenderType.java index 708eeca7..07150e1b 100644 --- a/src/main/java/li/cil/oc2/client/renderer/CustomRenderType.java +++ b/src/main/java/li/cil/oc2/client/renderer/CustomRenderType.java @@ -1,7 +1,6 @@ package li.cil.oc2.client.renderer; import li.cil.oc2.api.API; -import net.minecraft.client.renderer.RenderState; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.VertexFormat; @@ -13,23 +12,26 @@ public abstract class CustomRenderType extends RenderType { final TextureState texture = new TextureState(location, false, true); final RenderType.State state = RenderType.State.getBuilder() .texture(texture) - .writeMask(COLOR_WRITE) + .alpha(DEFAULT_ALPHA) .transparency(ADDITIVE_TRANSPARENCY) + .cull(CULL_DISABLED) .build(false); return RenderType.makeType( API.MOD_ID + ":unlit_block", DefaultVertexFormats.POSITION_TEX, GL11.GL_QUADS, 256, + false, + true, state); } public static RenderType getNetworkCable() { final State state = State.getBuilder() - .texture(RenderState.NO_TEXTURE) - .transparency(RenderState.NO_TRANSPARENCY) - .cull(RenderState.CULL_DISABLED) - .lightmap(RenderState.LIGHTMAP_ENABLED) + .texture(NO_TEXTURE) + .transparency(NO_TRANSPARENCY) + .cull(CULL_DISABLED) + .lightmap(LIGHTMAP_ENABLED) .build(false); return RenderType.makeType(API.MOD_ID + ":network_cable", DefaultVertexFormats.POSITION_COLOR_LIGHTMAP, diff --git a/src/main/java/li/cil/oc2/client/renderer/tileentity/ChargerTileEntityRenderer.java b/src/main/java/li/cil/oc2/client/renderer/tileentity/ChargerTileEntityRenderer.java new file mode 100644 index 00000000..236fe35d --- /dev/null +++ b/src/main/java/li/cil/oc2/client/renderer/tileentity/ChargerTileEntityRenderer.java @@ -0,0 +1,91 @@ +package li.cil.oc2.client.renderer.tileentity; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.IVertexBuilder; +import li.cil.oc2.api.API; +import li.cil.oc2.client.renderer.CustomRenderType; +import li.cil.oc2.common.tileentity.ChargerTileEntity; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.model.RenderMaterial; +import net.minecraft.client.renderer.tileentity.TileEntityRenderer; +import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; +import net.minecraft.inventory.container.PlayerContainer; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.vector.Matrix4f; + +public final class ChargerTileEntityRenderer extends TileEntityRenderer { + public static final ResourceLocation EFFECT_LOCATION = new ResourceLocation(API.MOD_ID, "block/charger/effect"); + + private static final RenderMaterial TEXTURE_EFFECT = new RenderMaterial(PlayerContainer.LOCATION_BLOCKS_TEXTURE, EFFECT_LOCATION); + + private static final int EFFECT_LAYERS = 3; + private static final float EFFECT_HEIGHT = 0.5f; + private static final float EFFECT_SPEED = 0.1f; + private static final float EFFECT_SCALE_START = 0.6f; + private static final float EFFECT_SCALE_END = 0.8f; + + /////////////////////////////////////////////////////////////////// + + private float offset = 0; + + /////////////////////////////////////////////////////////////////// + + public ChargerTileEntityRenderer(final TileEntityRendererDispatcher dispatcher) { + super(dispatcher); + } + + /////////////////////////////////////////////////////////////////// + + @Override + public void render(final ChargerTileEntity tileEntity, final float partialTicks, final MatrixStack matrixStack, final IRenderTypeBuffer buffer, final int light, final int overlay) { + offset = (offset + EFFECT_SPEED * partialTicks / 20f) % (float) (Math.PI * 2); + + matrixStack.push(); + matrixStack.translate(0.5, 1.1, 0.5); + + final IVertexBuilder builder = TEXTURE_EFFECT.getBuffer(buffer, CustomRenderType::getUnlitBlock); + + for (int i = 0; i < EFFECT_LAYERS; i++) { + final float relativeY = (1 + MathHelper.sin(offset + ((float) Math.PI * 2f * i / EFFECT_LAYERS))) * 0.5f; + final float y = relativeY * EFFECT_HEIGHT; + final float scale = EFFECT_SCALE_START + relativeY * (EFFECT_SCALE_END - EFFECT_SCALE_START); + + matrixStack.push(); + matrixStack.translate(0, y, 0); + renderScaledQuad(matrixStack, builder, scale); + matrixStack.pop(); + } + + matrixStack.pop(); + } + + private static void renderScaledQuad(final MatrixStack matrixStack, final IVertexBuilder builder, final float scale) { + matrixStack.push(); + matrixStack.scale(scale, scale, scale); + renderQuad(matrixStack.getLast().getMatrix(), builder); + matrixStack.pop(); + } + + private static void renderQuad(final Matrix4f matrix, final IVertexBuilder builder) { + // NB: We may get a SpriteAwareVertexBuilder here. Sadly, its chaining is broken, + // because methods may return the underlying vertex builder, so e.g. calling + // buffer.pos(...).tex(...) will not actually call SpriteAwareVertexBuilder.tex(...) + // but SpriteAwareVertexBuilder.vertexBuilder.tex(...), skipping the UV remapping. + builder.pos(matrix, -0.5f, 0, -0.5f); + builder.tex(0, 0); + builder.endVertex(); + + builder.pos(matrix, -0.5f, 0, 0.5f); + builder.tex(0, 1); + builder.endVertex(); + + builder.pos(matrix, 0.5f, 0, 0.5f); + builder.tex(1, 1); + builder.endVertex(); + + builder.pos(matrix, 0.5f, 0, -0.5f); + builder.tex(1, 0); + builder.endVertex(); + } +} diff --git a/src/main/java/li/cil/oc2/client/renderer/tileentity/ComputerTileEntityRenderer.java b/src/main/java/li/cil/oc2/client/renderer/tileentity/ComputerTileEntityRenderer.java index 29437ebe..a70c2c58 100644 --- a/src/main/java/li/cil/oc2/client/renderer/tileentity/ComputerTileEntityRenderer.java +++ b/src/main/java/li/cil/oc2/client/renderer/tileentity/ComputerTileEntityRenderer.java @@ -203,22 +203,25 @@ public final class ComputerTileEntityRenderer extends TileEntityRenderer 0 && computerEnergyStorage > 0; + } + + public static boolean robotsUseEnergy() { + return robotEnergyPerTick > 0 && robotEnergyStorage > 0; + } + + public static boolean chargerUseEnergy() { + return chargerEnergyPerTick > 0 && chargerEnergyStorage > 0; + } + /////////////////////////////////////////////////////////////////// @SubscribeEvent @@ -54,6 +73,15 @@ public final class Config { maxHardDriveSize = COMMON_INSTANCE.maxHardDriveSize.get(); maxFlashMemorySize = COMMON_INSTANCE.maxFlashMemorySize.get(); + computerEnergyPerTick = COMMON_INSTANCE.computerEnergyPerTick.get(); + computerEnergyStorage = COMMON_INSTANCE.computerEnergyStorage.get(); + robotEnergyPerTick = COMMON_INSTANCE.robotEnergyPerTick.get(); + robotEnergyStorage = COMMON_INSTANCE.robotEnergyStorage.get(); + chargerEnergyPerTick = COMMON_INSTANCE.chargerEnergyPerTick.get(); + chargerEnergyStorage = COMMON_INSTANCE.chargerEnergyStorage.get(); + + blockOperationsModuleToolLevel = COMMON_INSTANCE.blockOperationsModuleToolLevel.get(); + fakePlayerUUID = UUID.fromString(COMMON_INSTANCE.fakePlayerUUID.get()); } } @@ -61,14 +89,21 @@ public final class Config { /////////////////////////////////////////////////////////////////// private static final class CommonSettings { - public ForgeConfigSpec.LongValue maxAllocatedMemory; - public ForgeConfigSpec.IntValue maxMemorySize; - public ForgeConfigSpec.IntValue maxHardDriveSize; - public ForgeConfigSpec.IntValue maxFlashMemorySize; + public final ForgeConfigSpec.LongValue maxAllocatedMemory; + public final ForgeConfigSpec.IntValue maxMemorySize; + public final ForgeConfigSpec.IntValue maxHardDriveSize; + public final ForgeConfigSpec.IntValue maxFlashMemorySize; - public ForgeConfigSpec.IntValue blockOperationsModuleToolLevel; + public final ForgeConfigSpec.IntValue computerEnergyPerTick; + public final ForgeConfigSpec.IntValue computerEnergyStorage; + public final ForgeConfigSpec.IntValue robotEnergyPerTick; + public final ForgeConfigSpec.IntValue robotEnergyStorage; + public final ForgeConfigSpec.IntValue chargerEnergyPerTick; + public final ForgeConfigSpec.IntValue chargerEnergyStorage; - public ForgeConfigSpec.ConfigValue fakePlayerUUID; + public final ForgeConfigSpec.IntValue blockOperationsModuleToolLevel; + + public final ForgeConfigSpec.ConfigValue fakePlayerUUID; public CommonSettings(final ForgeConfigSpec.Builder builder) { builder.push("vm"); @@ -95,6 +130,40 @@ public final class Config { builder.pop(); + builder.push("energy"); + + computerEnergyPerTick = builder + .translation(Constants.CONFIG_COMPUTER_ENERGY_PER_TICK) + .comment("The amount of energy (Forge Energy/RF) a computer draws per tick. Set to zero to disable.") + .defineInRange("computerEnergyPerTick", Config.computerEnergyPerTick, 0, Integer.MAX_VALUE); + + computerEnergyStorage = builder + .translation(Constants.CONFIG_COMPUTER_ENERGY_STORAGE) + .comment("The amount of energy (Forge Energy/RF) a computer can store internally.") + .defineInRange("computerEnergyStorage", Config.computerEnergyStorage, 0, Integer.MAX_VALUE); + + robotEnergyPerTick = builder + .translation(Constants.CONFIG_ROBOT_ENERGY_PER_TICK) + .comment("The amount of energy (Forge Energy/RF) a robot draws per tick. Set to zero to disable.") + .defineInRange("robotEnergyPerTick", Config.robotEnergyPerTick, 0, Integer.MAX_VALUE); + + robotEnergyStorage = builder + .translation(Constants.CONFIG_ROBOT_ENERGY_STORAGE) + .comment("The amount of energy (Forge Energy/RF) a robot can store internally.") + .defineInRange("robotEnergyStorage", Config.robotEnergyStorage, 0, Integer.MAX_VALUE); + + chargerEnergyPerTick = builder + .translation(Constants.CONFIG_CHARGER_ENERGY_PER_TICK) + .comment("The maximum amount of energy (Forge Energy/RF) a charger transfers per tick. Set to zero to disable.") + .defineInRange("chargerEnergyPerTick", Config.chargerEnergyPerTick, 0, Integer.MAX_VALUE); + + chargerEnergyStorage = builder + .translation(Constants.CONFIG_CHARGER_ENERGY_STORAGE) + .comment("The amount of energy (Forge Energy/RF) a charger can store internally.") + .defineInRange("chargerEnergyStorage", Config.chargerEnergyStorage, 0, Integer.MAX_VALUE); + + builder.pop(); + builder.push("gameplay"); blockOperationsModuleToolLevel = builder diff --git a/src/main/java/li/cil/oc2/common/Constants.java b/src/main/java/li/cil/oc2/common/Constants.java index 7b02c40e..98935c2f 100644 --- a/src/main/java/li/cil/oc2/common/Constants.java +++ b/src/main/java/li/cil/oc2/common/Constants.java @@ -1,5 +1,6 @@ package li.cil.oc2.common; +import li.cil.oc2.api.API; import net.minecraft.util.Direction; public final class Constants { @@ -18,7 +19,9 @@ public final class Constants { /////////////////////////////////////////////////////////////////// public static final String BLOCK_ENTITY_TAG_NAME_IN_ITEM = "BlockEntityTag"; - public static final String INVENTORY_TAG_NAME = "items"; + public static final String MOD_TAG_NAME = API.MOD_ID; + public static final String ITEMS_TAG_NAME = "items"; + public static final String ENERGY_TAG_NAME = "energy"; /////////////////////////////////////////////////////////////////// @@ -28,6 +31,7 @@ public final class Constants { public static final String NETWORK_HUB_BLOCK_NAME = "network_hub"; public static final String DISK_DRIVE_BLOCK_NAME = "disk_drive"; public static final String REDSTONE_INTERFACE_BLOCK_NAME = "redstone_interface"; + public static final String CHARGER_BLOCK_NAME = "charger"; /////////////////////////////////////////////////////////////////// @@ -57,6 +61,7 @@ public final class Constants { public static final String TOOLTIP_FLASH_MEMORY_MISSING = "tooltip.oc2.flash_memory_missing"; public static final String TOOLTIP_MEMORY_MISSING = "tooltip.oc2.memory_missing"; public static final String TOOLTIP_HARD_DRIVE_MISSING = "tooltip.oc2.hard_drive_missing"; + public static final String TOOLTIP_ENERGY = "tooltip.oc2.energy"; /////////////////////////////////////////////////////////////////// @@ -66,6 +71,12 @@ public final class Constants { public static final String CONFIG_MAX_FLASH_MEMORY_SIZE = "config.oc2.vm.maxFlashMemorySize"; public static final String CONFIG_BLOCK_OPERATIONS_MODULE_TOOL_LEVEL = "config.oc2.modules.block_operations.toolLevel"; public static final String CONFIG_FAKE_PLAYER_UUID = "config.oc2.admin.fakePlayerUUID"; + public static final String CONFIG_COMPUTER_ENERGY_PER_TICK = "config.oc2.computerEnergyPerTick"; + public static final String CONFIG_COMPUTER_ENERGY_STORAGE = "config.oc2.computerEnergyStorage"; + public static final String CONFIG_ROBOT_ENERGY_PER_TICK = "config.oc2.robotEnergyPerTick"; + public static final String CONFIG_ROBOT_ENERGY_STORAGE = "config.oc2.robotEnergyStorage"; + public static final String CONFIG_CHARGER_ENERGY_PER_TICK = "config.oc2.chargerEnergyPerTick"; + public static final String CONFIG_CHARGER_ENERGY_STORAGE = "config.oc2.chargerEnergyStorage"; /////////////////////////////////////////////////////////////////// @@ -79,6 +90,7 @@ public final class Constants { public static final String COMPUTER_BUS_STATE_INCOMPLETE = "gui.oc2.computer.bus_state.incomplete"; public static final String COMPUTER_BUS_STATE_TOO_COMPLEX = "gui.oc2.computer.bus_state.too_complex"; public static final String COMPUTER_BUS_STATE_MULTIPLE_CONTROLLERS = "gui.oc2.computer.bus_state.multiple_controllers"; + public static final String COMPUTER_ERROR_NOT_ENOUGH_ENERGY = "gui.oc2.computer.error.not_enough_energy"; /////////////////////////////////////////////////////////////////// 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 5341d674..69dc34a6 100644 --- a/src/main/java/li/cil/oc2/common/block/Blocks.java +++ b/src/main/java/li/cil/oc2/common/block/Blocks.java @@ -19,6 +19,7 @@ public final class Blocks { public static final RegistryObject NETWORK_HUB = BLOCKS.register(Constants.NETWORK_HUB_BLOCK_NAME, NetworkHubBlock::new); public static final RegistryObject REDSTONE_INTERFACE = BLOCKS.register(Constants.REDSTONE_INTERFACE_BLOCK_NAME, RedstoneInterfaceBlock::new); public static final RegistryObject DISK_DRIVE = BLOCKS.register(Constants.DISK_DRIVE_BLOCK_NAME, DiskDriveBlock::new); + public static final RegistryObject CHARGER = BLOCKS.register(Constants.CHARGER_BLOCK_NAME, ChargerBlock::new); /////////////////////////////////////////////////////////////////// diff --git a/src/main/java/li/cil/oc2/common/block/ChargerBlock.java b/src/main/java/li/cil/oc2/common/block/ChargerBlock.java new file mode 100644 index 00000000..76383a1c --- /dev/null +++ b/src/main/java/li/cil/oc2/common/block/ChargerBlock.java @@ -0,0 +1,62 @@ +package li.cil.oc2.common.block; + +import li.cil.oc2.common.tileentity.TileEntities; +import net.minecraft.block.*; +import net.minecraft.block.material.Material; +import net.minecraft.item.BlockItemUseContext; +import net.minecraft.state.StateContainer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.Mirror; +import net.minecraft.util.Rotation; +import net.minecraft.world.IBlockReader; + +import javax.annotation.Nullable; + +public final class ChargerBlock extends BreakableBlock { + public ChargerBlock() { + super(Properties + .create(Material.IRON) + .sound(SoundType.METAL) + .hardnessAndResistance(1.5f, 6.0f)); + setDefaultState(getStateContainer().getBaseState().with(HorizontalBlock.HORIZONTAL_FACING, Direction.NORTH)); + } + + /////////////////////////////////////////////////////////////////// + + @SuppressWarnings("deprecation") + @Override + public BlockState rotate(final BlockState state, final Rotation rot) { + return state.with(HorizontalBlock.HORIZONTAL_FACING, rot.rotate(state.get(HorizontalBlock.HORIZONTAL_FACING))); + } + + @SuppressWarnings("deprecation") + @Override + public BlockState mirror(final BlockState state, final Mirror mirrorIn) { + return state.rotate(mirrorIn.toRotation(state.get(HorizontalBlock.HORIZONTAL_FACING))); + } + + @Override + public boolean hasTileEntity(final BlockState state) { + return true; + } + + @Nullable + @Override + public TileEntity createTileEntity(final BlockState state, final IBlockReader world) { + return TileEntities.CHARGER_TILE_ENTITY.get().create(); + } + + @Override + public BlockState getStateForPlacement(final BlockItemUseContext context) { + return super.getDefaultState().with(HorizontalBlock.HORIZONTAL_FACING, context.getPlacementHorizontalFacing().getOpposite()); + } + + /////////////////////////////////////////////////////////////////// + + @Override + protected void fillStateContainer(final StateContainer.Builder builder) { + super.fillStateContainer(builder); + builder.add(HorizontalBlock.HORIZONTAL_FACING); + } +} diff --git a/src/main/java/li/cil/oc2/common/block/ComputerBlock.java b/src/main/java/li/cil/oc2/common/block/ComputerBlock.java index cd49886c..1332d2a6 100644 --- a/src/main/java/li/cil/oc2/common/block/ComputerBlock.java +++ b/src/main/java/li/cil/oc2/common/block/ComputerBlock.java @@ -12,7 +12,7 @@ import li.cil.oc2.common.integration.Wrenches; import li.cil.oc2.common.item.Items; import li.cil.oc2.common.tileentity.ComputerTileEntity; import li.cil.oc2.common.tileentity.TileEntities; -import li.cil.oc2.common.util.ItemStackUtils; +import li.cil.oc2.common.util.NBTUtils; import li.cil.oc2.common.util.TooltipUtils; import li.cil.oc2.common.util.VoxelShapeUtils; import net.minecraft.block.Block; @@ -54,6 +54,8 @@ import net.minecraftforge.fml.network.NetworkHooks; import javax.annotation.Nullable; import java.util.List; +import static li.cil.oc2.common.Constants.BLOCK_ENTITY_TAG_NAME_IN_ITEM; +import static li.cil.oc2.common.Constants.ITEMS_TAG_NAME; import static li.cil.oc2.common.util.NBTUtils.makeInventoryTag; public final class ComputerBlock extends HorizontalBlock { @@ -94,6 +96,7 @@ public final class ComputerBlock extends HorizontalBlock { public void addInformation(final ItemStack stack, @Nullable final IBlockReader world, final List tooltip, final ITooltipFlag advanced) { super.addInformation(stack, world, tooltip, advanced); TooltipUtils.addTileEntityInventoryInformation(stack, tooltip); + TooltipUtils.addTileEntityEnergyInformation(stack, tooltip); } @Override @@ -246,19 +249,19 @@ public final class ComputerBlock extends HorizontalBlock { private ItemStack getPreconfiguredComputer() { final ItemStack computer = new ItemStack(Items.COMPUTER.get()); - final CompoundNBT computerItems = ItemStackUtils.getOrCreateTileEntityInventoryTag(computer); - computerItems.put(DeviceTypes.MEMORY.getRegistryName().toString(), makeInventoryTag( + final CompoundNBT itemsTag = NBTUtils.getOrCreateChildTag(computer.getOrCreateTag(), BLOCK_ENTITY_TAG_NAME_IN_ITEM, ITEMS_TAG_NAME); + itemsTag.put(DeviceTypes.MEMORY.getRegistryName().toString(), makeInventoryTag( Items.MEMORY.get().withCapacity(8 * Constants.MEGABYTE), Items.MEMORY.get().withCapacity(8 * Constants.MEGABYTE), Items.MEMORY.get().withCapacity(8 * Constants.MEGABYTE) )); - computerItems.put(DeviceTypes.HARD_DRIVE.getRegistryName().toString(), makeInventoryTag( + itemsTag.put(DeviceTypes.HARD_DRIVE.getRegistryName().toString(), makeInventoryTag( Items.HARD_DRIVE.get().withData(BlockDeviceDataRegistration.BUILDROOT.get()) )); - computerItems.put(DeviceTypes.FLASH_MEMORY.getRegistryName().toString(), makeInventoryTag( + itemsTag.put(DeviceTypes.FLASH_MEMORY.getRegistryName().toString(), makeInventoryTag( Items.FLASH_MEMORY.get().withFirmware(Firmwares.BUILDROOT.get()) )); - computerItems.put(DeviceTypes.CARD.getRegistryName().toString(), makeInventoryTag( + itemsTag.put(DeviceTypes.CARD.getRegistryName().toString(), makeInventoryTag( new ItemStack(Items.NETWORK_INTERFACE_CARD.get()) )); diff --git a/src/main/java/li/cil/oc2/common/bus/AbstractGroupingDeviceBusElement.java b/src/main/java/li/cil/oc2/common/bus/AbstractGroupingDeviceBusElement.java index 40d9d871..d3b02f47 100644 --- a/src/main/java/li/cil/oc2/common/bus/AbstractGroupingDeviceBusElement.java +++ b/src/main/java/li/cil/oc2/common/bus/AbstractGroupingDeviceBusElement.java @@ -49,31 +49,31 @@ public abstract class AbstractGroupingDeviceBusElement { - if (devicesNbt.contains(key, NBTTagIds.TAG_COMPOUND)) { - deviceInfo.device.deserializeNBT(devicesNbt.getCompound(key)); + if (devicesTag.contains(key, NBTTagIds.TAG_COMPOUND)) { + deviceInfo.device.deserializeNBT(devicesTag.getCompound(key)); } }); } @@ -128,16 +128,16 @@ public abstract class AbstractGroupingDeviceBusElement { - final CompoundNBT deviceNbt = deviceInfo.device.serializeNBT(); - if (!deviceNbt.isEmpty()) { - devicesNbt.put(key, deviceNbt); + final CompoundNBT deviceTag = deviceInfo.device.serializeNBT(); + if (!deviceTag.isEmpty()) { + devicesTag.put(key, deviceTag); } }); } - groupData[index] = devicesNbt; + groupData[index] = devicesTag; } } diff --git a/src/main/java/li/cil/oc2/common/bus/ItemHandlerDeviceBusElement.java b/src/main/java/li/cil/oc2/common/bus/ItemHandlerDeviceBusElement.java index 94d7ba9d..86116f3c 100644 --- a/src/main/java/li/cil/oc2/common/bus/ItemHandlerDeviceBusElement.java +++ b/src/main/java/li/cil/oc2/common/bus/ItemHandlerDeviceBusElement.java @@ -40,32 +40,35 @@ public class ItemHandlerDeviceBusElement extends AbstractGroupingItemDeviceBusEl return; } - final CompoundNBT exportedNbt = new CompoundNBT(); + final CompoundNBT exportedTag = new CompoundNBT(); for (final ItemDeviceInfo info : groups.get(slot)) { ItemDeviceUtils.getItemDeviceDataKey(info.provider).ifPresent(key -> { - final CompoundNBT deviceNbt = new CompoundNBT(); - info.device.exportToItemStack(deviceNbt); - if (!deviceNbt.isEmpty()) { - exportedNbt.put(key, deviceNbt); + final CompoundNBT deviceTag = new CompoundNBT(); + info.device.exportToItemStack(deviceTag); + if (!deviceTag.isEmpty()) { + exportedTag.put(key, deviceTag); } }); } - ItemDeviceUtils.setItemDeviceData(stack, exportedNbt); + if (!exportedTag.isEmpty()) { + ItemDeviceUtils.setItemDeviceData(stack, exportedTag); + } } /////////////////////////////////////////////////////////////////// private void importDeviceDataFromItemStack(final ItemStack stack, final HashSet devices) { - ItemDeviceUtils.getItemDeviceData(stack).ifPresent(exportedNbt -> { + final CompoundNBT exportedTag = ItemDeviceUtils.getItemDeviceData(stack); + if (!exportedTag.isEmpty()) { for (final ItemDeviceInfo info : devices) { ItemDeviceUtils.getItemDeviceDataKey(info.provider).ifPresent(key -> { - if (exportedNbt.contains(key, NBTTagIds.TAG_COMPOUND)) { - info.device.importFromItemStack(exportedNbt.getCompound(key)); + if (exportedTag.contains(key, NBTTagIds.TAG_COMPOUND)) { + info.device.importFromItemStack(exportedTag.getCompound(key)); } }); } - }); + } } private void insertItemNameDevice(final ItemStack stack, final HashSet devices) { diff --git a/src/main/java/li/cil/oc2/common/bus/device/item/AbstractBlockDeviceVMDevice.java b/src/main/java/li/cil/oc2/common/bus/device/item/AbstractBlockDeviceVMDevice.java index 0993c486..e2a891a5 100644 --- a/src/main/java/li/cil/oc2/common/bus/device/item/AbstractBlockDeviceVMDevice.java +++ b/src/main/java/li/cil/oc2/common/bus/device/item/AbstractBlockDeviceVMDevice.java @@ -41,7 +41,7 @@ public abstract class AbstractBlockDeviceVMDevice implements VMDe @Override public CompoundNBT serializeNBT() { - final CompoundNBT nbt = new CompoundNBT(); + final CompoundNBT tag = new CompoundNBT(); if (device != null) { blobHandle = BlobStorage.validateHandle(blobHandle); - nbt.putUniqueId(BLOB_HANDLE_TAG_NAME, blobHandle); + tag.putUniqueId(BLOB_HANDLE_TAG_NAME, blobHandle); jobHandle = BlobStorage.submitSave(blobHandle, new PhysicalMemoryInputStream(device)); } if (address.isPresent()) { - nbt.putLong(ADDRESS_TAG_NAME, address.getAsLong()); + tag.putLong(ADDRESS_TAG_NAME, address.getAsLong()); } - return nbt; + return tag; } @Override diff --git a/src/main/java/li/cil/oc2/common/bus/device/item/NetworkInterfaceCardItemDevice.java b/src/main/java/li/cil/oc2/common/bus/device/item/NetworkInterfaceCardItemDevice.java index 718ec3e7..caf85330 100644 --- a/src/main/java/li/cil/oc2/common/bus/device/item/NetworkInterfaceCardItemDevice.java +++ b/src/main/java/li/cil/oc2/common/bus/device/item/NetworkInterfaceCardItemDevice.java @@ -38,7 +38,7 @@ public final class NetworkInterfaceCardItemDevice extends IdentityProxy optional = LazyOptional.of(() -> this); + + private final ItemStack stack; + private final int capacity; + private final String[] tagPath; + + public EnergyStorageItemStack(final ItemStack stack, final int capacity, final String... tagPath) { + this.stack = stack; + this.capacity = capacity; + this.tagPath = tagPath; + } + + @Override + public int receiveEnergy(final int maxReceive, final boolean simulate) { + final int stored = getEnergyStored(); + final int receiveLimit = capacity - stored; + final int receive = Math.min(maxReceive, receiveLimit); + if (!simulate) { + NBTUtils.getOrCreateChildTag(stack.getOrCreateTag(), tagPath) + .putInt(FixedEnergyStorage.STORED_TAG_NAME, stored + receive); + } + return receive; + } + + @Override + public int extractEnergy(final int maxExtract, final boolean simulate) { + return 0; + } + + @Override + public int getEnergyStored() { + return NBTUtils.getChildTag(stack.getTag(), tagPath).getInt(FixedEnergyStorage.STORED_TAG_NAME); + } + + @Override + public int getMaxEnergyStored() { + return capacity; + } + + @Override + public boolean canExtract() { + return false; // We don't want our items to be usable as batteries. + } + + @Override + public boolean canReceive() { + return true; + } + + @NotNull + @Override + public LazyOptional getCapability(@NotNull final Capability capability, @Nullable final Direction side) { + return Capabilities.ENERGY_STORAGE.orEmpty(capability, optional); + } +} diff --git a/src/main/java/li/cil/oc2/common/energy/FixedEnergyStorage.java b/src/main/java/li/cil/oc2/common/energy/FixedEnergyStorage.java new file mode 100644 index 00000000..2a8a8c64 --- /dev/null +++ b/src/main/java/li/cil/oc2/common/energy/FixedEnergyStorage.java @@ -0,0 +1,27 @@ +package li.cil.oc2.common.energy; + +import net.minecraft.nbt.CompoundNBT; +import net.minecraftforge.common.util.INBTSerializable; +import net.minecraftforge.energy.EnergyStorage; + +public final class FixedEnergyStorage extends EnergyStorage implements INBTSerializable { + public static final String STORED_TAG_NAME = "stored"; + public static final String CAPACITY_TAG_NAME = "capacity"; + + public FixedEnergyStorage(final int capacity) { + super(capacity); + } + + @Override + public CompoundNBT serializeNBT() { + final CompoundNBT tag = new CompoundNBT(); + tag.putInt(STORED_TAG_NAME, energy); + tag.putInt(CAPACITY_TAG_NAME, capacity); // Mostly for tooltips. + return tag; + } + + @Override + public void deserializeNBT(final CompoundNBT tag) { + energy = tag.getInt(STORED_TAG_NAME); + } +} diff --git a/src/main/java/li/cil/oc2/common/energy/package-info.java b/src/main/java/li/cil/oc2/common/energy/package-info.java new file mode 100644 index 00000000..6a2d105f --- /dev/null +++ b/src/main/java/li/cil/oc2/common/energy/package-info.java @@ -0,0 +1,7 @@ +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +package li.cil.oc2.common.energy; + +import mcp.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file diff --git a/src/main/java/li/cil/oc2/common/entity/RobotEntity.java b/src/main/java/li/cil/oc2/common/entity/RobotEntity.java index 6ea681b9..f2bdff1b 100644 --- a/src/main/java/li/cil/oc2/common/entity/RobotEntity.java +++ b/src/main/java/li/cil/oc2/common/entity/RobotEntity.java @@ -7,6 +7,7 @@ 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.object.Parameter; import li.cil.oc2.api.capabilities.Robot; +import li.cil.oc2.common.Config; import li.cil.oc2.common.Constants; import li.cil.oc2.common.bus.AbstractDeviceBusElement; import li.cil.oc2.common.bus.CommonDeviceBusController; @@ -16,13 +17,17 @@ import li.cil.oc2.common.capabilities.Capabilities; import li.cil.oc2.common.container.FixedSizeItemStackHandler; import li.cil.oc2.common.container.RobotContainer; import li.cil.oc2.common.container.RobotTerminalContainer; +import li.cil.oc2.common.energy.FixedEnergyStorage; import li.cil.oc2.common.entity.robot.*; import li.cil.oc2.common.integration.Wrenches; import li.cil.oc2.common.item.Items; import li.cil.oc2.common.network.Network; import li.cil.oc2.common.network.message.*; import li.cil.oc2.common.serialization.NBTSerialization; -import li.cil.oc2.common.util.*; +import li.cil.oc2.common.util.NBTTagIds; +import li.cil.oc2.common.util.NBTUtils; +import li.cil.oc2.common.util.TerminalUtils; +import li.cil.oc2.common.util.WorldUtils; import li.cil.oc2.common.vm.*; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -54,6 +59,7 @@ import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShapes; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TranslationTextComponent; import net.minecraft.world.World; import net.minecraft.world.server.ServerWorld; import net.minecraftforge.api.distmarker.Dist; @@ -61,7 +67,6 @@ import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraftforge.common.util.Constants.BlockFlags; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.event.world.ChunkEvent; import net.minecraftforge.event.world.WorldEvent; @@ -74,6 +79,8 @@ import java.nio.ByteBuffer; import java.util.*; import java.util.function.Consumer; +import static li.cil.oc2.common.Constants.*; + public final class RobotEntity extends Entity implements Robot { public static final DataParameter TARGET_POSITION = EntityDataManager.createKey(RobotEntity.class, DataSerializers.BLOCK_POS); public static final DataParameter TARGET_DIRECTION = EntityDataManager.createKey(RobotEntity.class, DataSerializers.DIRECTION); @@ -105,9 +112,10 @@ public final class RobotEntity extends Entity implements Robot { private final RobotActionProcessor actionProcessor = new RobotActionProcessor(); private final Terminal terminal = new Terminal(); private final RobotVirtualMachine virtualMachine; - private final RobotItemStackHandlers deviceItems = new RobotItemStackHandlers(); - private final ItemStackHandler inventory = new FixedSizeItemStackHandler(INVENTORY_SIZE); private final RobotBusElement busElement = new RobotBusElement(); + private final RobotItemStackHandlers deviceItems = new RobotItemStackHandlers(); + private final FixedEnergyStorage energy = new FixedEnergyStorage(Config.robotEnergyStorage); + private final ItemStackHandler inventory = new FixedSizeItemStackHandler(INVENTORY_SIZE); private long lastPistonMovement; /////////////////////////////////////////////////////////////////// @@ -164,6 +172,9 @@ public final class RobotEntity extends Entity implements Robot { if (capability == Capabilities.ITEM_HANDLER) { return LazyOptional.of(() -> inventory).cast(); } + if (capability == Capabilities.ENERGY_STORAGE && Config.robotsUseEnergy()) { + return LazyOptional.of(() -> energy).cast(); + } if (capability == Capabilities.ROBOT) { return LazyOptional.of(() -> this).cast(); } @@ -342,17 +353,20 @@ public final class RobotEntity extends Entity implements Robot { } public void exportToItemStack(final ItemStack stack) { - final CompoundNBT tag = ItemStackUtils.getOrCreateEntityInventoryTag(stack); - deviceItems.serialize(tag); - tag.put(INVENTORY_TAG_NAME, inventory.serializeNBT()); + final CompoundNBT itemsTag = NBTUtils.getOrCreateChildTag(stack.getOrCreateTag(), MOD_TAG_NAME, Constants.ITEMS_TAG_NAME); + deviceItems.serialize(itemsTag); // Puts one tag per device type, as expected by TooltipUtils. + itemsTag.put(INVENTORY_TAG_NAME, inventory.serializeNBT()); // Won't show up in tooltip. + + NBTUtils.getOrCreateChildTag(stack.getOrCreateTag(), MOD_TAG_NAME) + .put(ENERGY_TAG_NAME, energy.serializeNBT()); } public void importFromItemStack(final ItemStack stack) { - final CompoundNBT tag = ItemStackUtils.getEntityInventoryTag(stack); - if (tag != null) { - deviceItems.deserialize(tag); - inventory.deserializeNBT(tag.getCompound(INVENTORY_TAG_NAME)); - } + final CompoundNBT itemsTag = NBTUtils.getChildTag(stack.getTag(), MOD_TAG_NAME, ITEMS_TAG_NAME); + deviceItems.deserialize(itemsTag); + inventory.deserializeNBT(itemsTag.getCompound(INVENTORY_TAG_NAME)); + + energy.deserializeNBT(NBTUtils.getChildTag(stack.getTag(), MOD_TAG_NAME, ENERGY_TAG_NAME)); } /////////////////////////////////////////////////////////////////// @@ -371,7 +385,8 @@ public final class RobotEntity extends Entity implements Robot { tag.put(TERMINAL_TAG_NAME, NBTSerialization.serialize(terminal)); tag.put(COMMAND_PROCESSOR_TAG_NAME, actionProcessor.serialize()); tag.put(BUS_ELEMENT_TAG_NAME, busElement.serialize()); - tag.put(Constants.INVENTORY_TAG_NAME, deviceItems.serialize()); + tag.put(Constants.ITEMS_TAG_NAME, deviceItems.serialize()); + tag.put(ENERGY_TAG_NAME, energy.serializeNBT()); tag.put(INVENTORY_TAG_NAME, inventory.serializeNBT()); tag.putByte(SELECTED_SLOT_TAG_NAME, dataManager.get(SELECTED_SLOT)); } @@ -382,11 +397,9 @@ public final class RobotEntity extends Entity implements Robot { NBTSerialization.deserialize(tag.getCompound(TERMINAL_TAG_NAME), terminal); actionProcessor.deserialize(tag.getCompound(COMMAND_PROCESSOR_TAG_NAME)); busElement.deserialize(tag.getCompound(BUS_ELEMENT_TAG_NAME)); + deviceItems.deserialize(tag.getCompound(Constants.ITEMS_TAG_NAME)); + energy.deserializeNBT(tag.getCompound(ENERGY_TAG_NAME)); inventory.deserializeNBT(tag.getCompound(INVENTORY_TAG_NAME)); - - if (tag.contains(Constants.INVENTORY_TAG_NAME, NBTTagIds.TAG_COMPOUND)) { - deviceItems.deserialize(tag.getCompound(Constants.INVENTORY_TAG_NAME)); - } setSelectedSlot(tag.getByte(SELECTED_SLOT_TAG_NAME)); } @@ -780,8 +793,30 @@ public final class RobotEntity extends Entity implements Robot { } @Override - protected AbstractTerminalVMRunner createRunner() { - return new RobotVMRunner(this, terminal); + protected void load() { + if (Config.robotsUseEnergy()) { + // Don't even start running if we couldn't keep running. + if (energy.getEnergyStored() < Config.robotEnergyPerTick) { + error(new TranslationTextComponent(Constants.COMPUTER_ERROR_NOT_ENOUGH_ENERGY)); + return; + } + } + + super.load(); + } + + @Override + protected void run() { + if (Config.robotsUseEnergy()) { + if (energy.getEnergyStored() >= Config.robotEnergyPerTick) { + energy.extractEnergy(Config.robotEnergyPerTick, false); + } else { + error(new TranslationTextComponent(Constants.COMPUTER_ERROR_NOT_ENOUGH_ENERGY)); + return; + } + } + + super.run(); } @Override @@ -794,6 +829,11 @@ public final class RobotEntity extends Entity implements Robot { actionProcessor.clear(); } + @Override + protected AbstractTerminalVMRunner createRunner() { + return new RobotVMRunner(this, terminal); + } + @Override protected void handleBusStateChanged(final CommonDeviceBusController.BusState value) { Network.sendToClientsTrackingEntity(new RobotBusStateMessage(RobotEntity.this), RobotEntity.this); diff --git a/src/main/java/li/cil/oc2/common/entity/robot/RobotMovementAction.java b/src/main/java/li/cil/oc2/common/entity/robot/RobotMovementAction.java index f86365de..852c2cdd 100644 --- a/src/main/java/li/cil/oc2/common/entity/robot/RobotMovementAction.java +++ b/src/main/java/li/cil/oc2/common/entity/robot/RobotMovementAction.java @@ -7,6 +7,7 @@ import li.cil.oc2.common.util.NBTTagIds; import li.cil.oc2.common.util.NBTUtils; import net.minecraft.entity.MoverType; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.NBTUtil; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3d; @@ -116,13 +117,13 @@ public final class RobotMovementAction extends AbstractRobotAction { NBTUtils.putEnum(tag, DIRECTION_TAG_NAME, direction); if (origin != null) { - NBTUtils.putBlockPos(tag, ORIGIN_TAG_NAME, origin); + tag.put(ORIGIN_TAG_NAME, NBTUtil.writeBlockPos(origin)); } if (start != null) { - NBTUtils.putBlockPos(tag, START_TAG_NAME, start); + tag.put(START_TAG_NAME, NBTUtil.writeBlockPos(start)); } if (target != null) { - NBTUtils.putBlockPos(tag, TARGET_TAG_NAME, target); + tag.put(TARGET_TAG_NAME, NBTUtil.writeBlockPos(target)); } return tag; @@ -134,13 +135,13 @@ public final class RobotMovementAction extends AbstractRobotAction { direction = NBTUtils.getEnum(tag, DIRECTION_TAG_NAME, MovementDirection.class); if (tag.contains(ORIGIN_TAG_NAME, NBTTagIds.TAG_COMPOUND)) { - origin = NBTUtils.getBlockPos(tag, ORIGIN_TAG_NAME); + origin = NBTUtil.readBlockPos(tag.getCompound(ORIGIN_TAG_NAME)); } if (tag.contains(START_TAG_NAME, NBTTagIds.TAG_COMPOUND)) { - start = NBTUtils.getBlockPos(tag, START_TAG_NAME); + start = NBTUtil.readBlockPos(tag.getCompound(START_TAG_NAME)); } if (tag.contains(TARGET_TAG_NAME, NBTTagIds.TAG_COMPOUND)) { - target = NBTUtils.getBlockPos(tag, TARGET_TAG_NAME); + target = NBTUtil.readBlockPos(tag.getCompound(TARGET_TAG_NAME)); targetPos = getTargetPositionInBlock(target); } } diff --git a/src/main/java/li/cil/oc2/common/item/AbstractBlockDeviceItem.java b/src/main/java/li/cil/oc2/common/item/AbstractBlockDeviceItem.java index d77b9682..17560b73 100644 --- a/src/main/java/li/cil/oc2/common/item/AbstractBlockDeviceItem.java +++ b/src/main/java/li/cil/oc2/common/item/AbstractBlockDeviceItem.java @@ -3,11 +3,10 @@ package li.cil.oc2.common.item; import li.cil.oc2.api.bus.device.data.BlockDeviceData; import li.cil.oc2.common.bus.device.data.BlockDeviceDataRegistration; import li.cil.oc2.common.util.ItemStackUtils; -import li.cil.oc2.common.util.NBTTagIds; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocationException; +import net.minecraft.util.StringUtils; import net.minecraft.util.text.ITextComponent; import javax.annotation.Nullable; @@ -24,13 +23,11 @@ public abstract class AbstractBlockDeviceItem extends AbstractStorageItem { return null; } - final CompoundNBT modNbt = ItemStackUtils.getModDataTag(stack); - if (modNbt == null || !modNbt.contains(DATA_TAG_NAME, NBTTagIds.TAG_STRING)) { + final String registryName = ItemStackUtils.getModDataTag(stack).getString(DATA_TAG_NAME); + if (StringUtils.isNullOrEmpty(registryName)) { return null; } - final String registryName = modNbt.getString(DATA_TAG_NAME); - try { return BlockDeviceDataRegistration.REGISTRY.get().getValue(new ResourceLocation(registryName)); } catch (final ResourceLocationException ignored) { @@ -58,12 +55,7 @@ public abstract class AbstractBlockDeviceItem extends AbstractStorageItem { return false; } - final CompoundNBT modNbt = ItemStackUtils.getModDataTag(stack); - if (modNbt == null) { - return false; - } - - return modNbt.getBoolean(READONLY_TAG_NAME); + return ItemStackUtils.getModDataTag(stack).getBoolean(READONLY_TAG_NAME); } public static ItemStack withReadonly(final ItemStack stack, final boolean readonly) { diff --git a/src/main/java/li/cil/oc2/common/item/AbstractStorageItem.java b/src/main/java/li/cil/oc2/common/item/AbstractStorageItem.java index 8535e869..b8d88f91 100644 --- a/src/main/java/li/cil/oc2/common/item/AbstractStorageItem.java +++ b/src/main/java/li/cil/oc2/common/item/AbstractStorageItem.java @@ -26,13 +26,12 @@ public abstract class AbstractStorageItem extends ModItem { return 0; } - final CompoundNBT modNbt = ItemStackUtils.getModDataTag(stack); - if (modNbt == null || !modNbt.contains(CAPACITY_TAG_NAME, NBTTagIds.TAG_INT)) { - final AbstractStorageItem storageItem = (AbstractStorageItem) item; - return storageItem.defaultCapacity; + final CompoundNBT tag = ItemStackUtils.getModDataTag(stack); + if (!tag.contains(CAPACITY_TAG_NAME, NBTTagIds.TAG_INT)) { + return ((AbstractStorageItem) item).defaultCapacity; } - return modNbt.getInt(CAPACITY_TAG_NAME); + return tag.getInt(CAPACITY_TAG_NAME); } public static ItemStack withCapacity(final ItemStack stack, final int capacity) { diff --git a/src/main/java/li/cil/oc2/common/item/ChargerItem.java b/src/main/java/li/cil/oc2/common/item/ChargerItem.java new file mode 100644 index 00000000..52947fcf --- /dev/null +++ b/src/main/java/li/cil/oc2/common/item/ChargerItem.java @@ -0,0 +1,22 @@ +package li.cil.oc2.common.item; + +import li.cil.oc2.common.Config; +import net.minecraft.block.Block; +import net.minecraft.item.ItemGroup; +import net.minecraft.item.ItemStack; +import net.minecraft.util.NonNullList; + +public final class ChargerItem extends ModBlockItem { + public ChargerItem(final Block block) { + super(block); + } + + /////////////////////////////////////////////////////////////////// + + @Override + public void fillItemGroup(final ItemGroup group, final NonNullList items) { + if (Config.chargerUseEnergy()) { + super.fillItemGroup(group, items); + } + } +} diff --git a/src/main/java/li/cil/oc2/common/item/FlashMemoryItem.java b/src/main/java/li/cil/oc2/common/item/FlashMemoryItem.java index c920901a..cf2e3772 100644 --- a/src/main/java/li/cil/oc2/common/item/FlashMemoryItem.java +++ b/src/main/java/li/cil/oc2/common/item/FlashMemoryItem.java @@ -13,6 +13,7 @@ import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.NonNullList; import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocationException; +import net.minecraft.util.StringUtils; import net.minecraft.util.text.ITextComponent; import javax.annotation.Nullable; @@ -30,13 +31,11 @@ public final class FlashMemoryItem extends AbstractStorageItem { return null; } - final CompoundNBT modNbt = ItemStackUtils.getModDataTag(stack); - if (modNbt == null || !modNbt.contains(FIRMWARE_TAG_NAME, NBTTagIds.TAG_STRING)) { + final String registryName = ItemStackUtils.getModDataTag(stack).getString(FIRMWARE_TAG_NAME); + if (StringUtils.isNullOrEmpty(registryName)) { return null; } - final String registryName = modNbt.getString(FIRMWARE_TAG_NAME); - try { return Firmwares.REGISTRY.get().getValue(new ResourceLocation(registryName)); } catch (final ResourceLocationException ignored) { 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 9959c7fb..fda7155d 100644 --- a/src/main/java/li/cil/oc2/common/item/Items.java +++ b/src/main/java/li/cil/oc2/common/item/Items.java @@ -25,6 +25,7 @@ public final class Items { public static final RegistryObject NETWORK_HUB = register(Constants.NETWORK_HUB_BLOCK_NAME, Blocks.NETWORK_HUB); public static final RegistryObject REDSTONE_INTERFACE = register(Constants.REDSTONE_INTERFACE_BLOCK_NAME, Blocks.REDSTONE_INTERFACE); public static final RegistryObject DISK_DRIVE = register(Constants.DISK_DRIVE_BLOCK_NAME, Blocks.DISK_DRIVE); + public static final RegistryObject CHARGER = register(Constants.CHARGER_BLOCK_NAME, Blocks.CHARGER, ChargerItem::new); /////////////////////////////////////////////////////////////////// diff --git a/src/main/java/li/cil/oc2/common/item/RobotItem.java b/src/main/java/li/cil/oc2/common/item/RobotItem.java index 2c56808e..9a737bb9 100644 --- a/src/main/java/li/cil/oc2/common/item/RobotItem.java +++ b/src/main/java/li/cil/oc2/common/item/RobotItem.java @@ -1,6 +1,8 @@ package li.cil.oc2.common.item; import li.cil.oc2.client.renderer.tileentity.RobotItemStackRenderer; +import li.cil.oc2.common.Config; +import li.cil.oc2.common.energy.EnergyStorageItemStack; import li.cil.oc2.common.entity.Entities; import li.cil.oc2.common.entity.RobotEntity; import li.cil.oc2.common.entity.robot.RobotActions; @@ -11,6 +13,7 @@ import net.minecraft.client.util.ITooltipFlag; import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUseContext; +import net.minecraft.nbt.CompoundNBT; import net.minecraft.stats.Stats; import net.minecraft.util.ActionResultType; import net.minecraft.util.Direction; @@ -18,10 +21,14 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.text.ITextComponent; import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.ICapabilityProvider; import org.jetbrains.annotations.Nullable; import java.util.List; +import static li.cil.oc2.common.Constants.ENERGY_TAG_NAME; +import static li.cil.oc2.common.Constants.MOD_TAG_NAME; + public final class RobotItem extends ModItem { public RobotItem() { super(createProperties().setISTER(() -> RobotItemStackRenderer::new)); @@ -33,6 +40,17 @@ public final class RobotItem extends ModItem { public void addInformation(final ItemStack stack, @Nullable final World world, final List tooltip, final ITooltipFlag flag) { super.addInformation(stack, world, tooltip, flag); TooltipUtils.addEntityInventoryInformation(stack, tooltip); + TooltipUtils.addEntityEnergyInformation(stack, tooltip); + } + + @Nullable + @Override + public ICapabilityProvider initCapabilities(final ItemStack stack, @Nullable final CompoundNBT nbt) { + if (Config.robotsUseEnergy()) { + return new EnergyStorageItemStack(stack, Config.robotEnergyStorage, MOD_TAG_NAME, ENERGY_TAG_NAME); + } else { + return null; + } } @Override diff --git a/src/main/java/li/cil/oc2/common/serialization/NBTSerialization.java b/src/main/java/li/cil/oc2/common/serialization/NBTSerialization.java index b7491a85..1fadf3f4 100644 --- a/src/main/java/li/cil/oc2/common/serialization/NBTSerialization.java +++ b/src/main/java/li/cil/oc2/common/serialization/NBTSerialization.java @@ -16,38 +16,38 @@ import java.util.Map; import java.util.UUID; public final class NBTSerialization { - public static void serialize(final CompoundNBT nbt, final T value, final Class type) throws SerializationException { - Ceres.getSerializer(type).serialize(new Serializer(nbt), type, value); + public static void serialize(final CompoundNBT tag, final T value, final Class type) throws SerializationException { + Ceres.getSerializer(type).serialize(new Serializer(tag), type, value); } - public static void serialize(final CompoundNBT nbt, final T value) throws SerializationException { + public static void serialize(final CompoundNBT tag, final T value) throws SerializationException { @SuppressWarnings("unchecked") final Class type = (Class) value.getClass(); - serialize(nbt, value, type); + serialize(tag, value, type); } public static CompoundNBT serialize(final T value, final Class type) throws SerializationException { - final CompoundNBT nbt = new CompoundNBT(); - serialize(nbt, value, type); - return nbt; + final CompoundNBT tag = new CompoundNBT(); + serialize(tag, value, type); + return tag; } public static CompoundNBT serialize(final T value) throws SerializationException { - final CompoundNBT nbt = new CompoundNBT(); - serialize(nbt, value); - return nbt; + final CompoundNBT tag = new CompoundNBT(); + serialize(tag, value); + return tag; } - public static T deserialize(final CompoundNBT nbt, final Class type, @Nullable final T into) throws SerializationException { - return Ceres.getSerializer(type).deserialize(new Deserializer(nbt), type, into); + public static T deserialize(final CompoundNBT tag, final Class type, @Nullable final T into) throws SerializationException { + return Ceres.getSerializer(type).deserialize(new Deserializer(tag), type, into); } - public static T deserialize(final CompoundNBT nbt, final Class type) throws SerializationException { - return deserialize(nbt, type, null); + public static T deserialize(final CompoundNBT tag, final Class type) throws SerializationException { + return deserialize(tag, type, null); } - public static T deserialize(final CompoundNBT nbt, final T into) throws SerializationException { + public static T deserialize(final CompoundNBT tag, final T into) throws SerializationException { @SuppressWarnings("unchecked") final Class type = (Class) into.getClass(); - return deserialize(nbt, type, into); + return deserialize(tag, type, into); } /////////////////////////////////////////////////////////////////// @@ -71,50 +71,50 @@ public final class NBTSerialization { } private static final class Serializer implements SerializationVisitor { - private final CompoundNBT nbt; + private final CompoundNBT tag; - private Serializer(final CompoundNBT nbt) { - this.nbt = nbt; + private Serializer(final CompoundNBT tag) { + this.tag = tag; } @Override public void putBoolean(final String name, final boolean value) { - nbt.putBoolean(name, value); + tag.putBoolean(name, value); } @Override public void putByte(final String name, final byte value) { - nbt.putByte(name, value); + tag.putByte(name, value); } @Override public void putChar(final String name, final char value) { - nbt.putInt(name, value); + tag.putInt(name, value); } @Override public void putShort(final String name, final short value) { - nbt.putShort(name, value); + tag.putShort(name, value); } @Override public void putInt(final String name, final int value) { - nbt.putInt(name, value); + tag.putInt(name, value); } @Override public void putLong(final String name, final long value) { - nbt.putLong(name, value); + tag.putLong(name, value); } @Override public void putFloat(final String name, final float value) { - nbt.putFloat(name, value); + tag.putFloat(name, value); } @Override public void putDouble(final String name, final double value) { - nbt.putDouble(name, value); + tag.putDouble(name, value); } @SuppressWarnings({"unchecked", "rawtypes"}) @@ -125,20 +125,20 @@ public final class NBTSerialization { } if (type.isArray()) { - nbt.put(name, putArray(name, type, value)); + tag.put(name, putArray(name, type, value)); } else if (type.isEnum()) { - nbt.putString(name, ((Enum) value).name()); + tag.putString(name, ((Enum) value).name()); } else if (type == String.class) { - nbt.putString(name, (String) value); + tag.putString(name, (String) value); } else if (type == UUID.class) { - final CompoundNBT uuidNBT = new CompoundNBT(); - uuidNBT.putUniqueId(name, (UUID) value); - nbt.put(name, uuidNBT); + final CompoundNBT uuidTag = new CompoundNBT(); + uuidTag.putUniqueId(name, (UUID) value); + tag.put(name, uuidTag); } else { - final CompoundNBT valueNBT = new CompoundNBT(); - Ceres.getSerializer(type).serialize(new Serializer(valueNBT), (Class) type, value); - if (!valueNBT.isEmpty()) { - nbt.put(name, valueNBT); + final CompoundNBT valueTag = new CompoundNBT(); + Ceres.getSerializer(type).serialize(new Serializer(valueTag), (Class) type, value); + if (!valueTag.isEmpty()) { + tag.put(name, valueTag); } } } @@ -162,13 +162,13 @@ public final class NBTSerialization { } else { final li.cil.ceres.api.Serializer serializer = Ceres.getSerializer(componentType); componentSerializer = (t, v) -> { - final CompoundNBT nbt = new CompoundNBT(); - serializer.serialize(new Serializer(nbt), (Class) t, v); - return nbt; + final CompoundNBT tag = new CompoundNBT(); + serializer.serialize(new Serializer(tag), (Class) t, v); + return tag; }; } - final ListNBT listNBT = new ListNBT(); + final ListNBT listTag = new ListNBT(); final IntArrayList nullIndices = new IntArrayList(); final Object[] data = (Object[]) value; @@ -180,18 +180,18 @@ public final class NBTSerialization { if (datum.getClass() != componentType) { throw new SerializationException(String.format("Polymorphism detected in generic array [%s]. This is not supported.", name)); } - listNBT.add(componentSerializer.serialize(componentType, datum)); + listTag.add(componentSerializer.serialize(componentType, datum)); } } if (nullIndices.isEmpty()) { - return listNBT; + return listTag; } else { - final CompoundNBT arrayNbt = new CompoundNBT(); - arrayNbt.put("value", listNBT); - arrayNbt.putIntArray("nulls", nullIndices); + final CompoundNBT arrayTag = new CompoundNBT(); + arrayTag.put("value", listTag); + arrayTag.putIntArray("nulls", nullIndices); - return arrayNbt; + return arrayTag; } } } @@ -200,59 +200,59 @@ public final class NBTSerialization { private boolean putIsNull(final String name, @Nullable final Object value) { final boolean isNull = value == null; if (isNull) { - final CompoundNBT nullNBT = new CompoundNBT(); - nullNBT.putBoolean(IS_NULL_KEY, true); - nbt.put(name, nullNBT); + final CompoundNBT nullTag = new CompoundNBT(); + nullTag.putBoolean(IS_NULL_KEY, true); + tag.put(name, nullTag); } return isNull; } } private static final class Deserializer implements DeserializationVisitor { - private final CompoundNBT nbt; + private final CompoundNBT tag; - private Deserializer(final CompoundNBT nbt) { - this.nbt = nbt; + private Deserializer(final CompoundNBT tag) { + this.tag = tag; } @Override public boolean getBoolean(final String name) { - return nbt.getBoolean(name); + return tag.getBoolean(name); } @Override public byte getByte(final String name) { - return nbt.getByte(name); + return tag.getByte(name); } @Override public char getChar(final String name) { - return (char) nbt.getInt(name); + return (char) tag.getInt(name); } @Override public short getShort(final String name) { - return nbt.getShort(name); + return tag.getShort(name); } @Override public int getInt(final String name) { - return nbt.getInt(name); + return tag.getInt(name); } @Override public long getLong(final String name) { - return nbt.getLong(name); + return tag.getLong(name); } @Override public float getFloat(final String name) { - return nbt.getFloat(name); + return tag.getFloat(name); } @Override public double getDouble(final String name) { - return nbt.getDouble(name); + return tag.getDouble(name); } @SuppressWarnings({"unchecked", "rawtypes"}) @@ -264,40 +264,40 @@ public final class NBTSerialization { } // Do not overwrite values which were not serialized before. - if (!nbt.contains(name)) { + if (!tag.contains(name)) { return into; } if (type.isArray()) { - final INBT arrayNbt = nbt.get(name); - assert arrayNbt != null; - return getArray(arrayNbt, type, into); + final INBT arrayTag = tag.get(name); + assert arrayTag != null; + return getArray(arrayTag, type, into); } else if (type.isEnum()) { - return Enum.valueOf((Class) type, nbt.getString(name)); + return Enum.valueOf((Class) type, tag.getString(name)); } else if (type == String.class) { - return nbt.getString(name); + return tag.getString(name); } else if (type == UUID.class) { - return nbt.getCompound(name).getUniqueId(name); + return tag.getCompound(name).getUniqueId(name); } else { - final CompoundNBT valueNBT = nbt.getCompound(name); - return Ceres.getSerializer(type).deserialize(new Deserializer(valueNBT), (Class) type, into); + final CompoundNBT valueTag = tag.getCompound(name); + return Ceres.getSerializer(type).deserialize(new Deserializer(valueTag), (Class) type, into); } } @FunctionalInterface private interface ArrayComponentDeserializer { @Nullable - Object deserialize(INBT nbt, Class type, @Nullable Object into); + Object deserialize(INBT tag, Class type, @Nullable Object into); } @SuppressWarnings({"unchecked", "rawtypes"}) @Nullable - private static Object getArray(final INBT nbt, final Class type, final @Nullable Object into) { + private static Object getArray(final INBT tag, final Class type, final @Nullable Object into) { final Class componentType = type.getComponentType(); final ArraySerializer arraySerializer = ARRAY_SERIALIZERS.get(componentType); if (arraySerializer != null) { - return arraySerializer.deserialize(nbt, type, into); + return arraySerializer.deserialize(tag, type, into); } else { final ArrayComponentDeserializer componentDeserializer; if (componentType.isArray()) { @@ -308,24 +308,24 @@ public final class NBTSerialization { } Object[] data = (Object[]) into; - final ListNBT listNBT; + final ListNBT listTag; final int[] nulls; int nullsIndex = 0; - if (nbt instanceof ListNBT) { - listNBT = (ListNBT) nbt; + if (tag instanceof ListNBT) { + listTag = (ListNBT) tag; nulls = new int[0]; - } else if (nbt instanceof CompoundNBT) { - listNBT = (ListNBT) ((CompoundNBT) nbt).get("value"); - nulls = ((CompoundNBT) nbt).getIntArray("nulls"); + } else if (tag instanceof CompoundNBT) { + listTag = (ListNBT) ((CompoundNBT) tag).get("value"); + nulls = ((CompoundNBT) tag).getIntArray("nulls"); } else { return data; } - if (listNBT == null) { + if (listTag == null) { return data; } - final int length = listNBT.size() + nulls.length; + final int length = listTag.size() + nulls.length; if (data == null || data.length != length) { data = (Object[]) Array.newInstance(componentType, length); } @@ -336,12 +336,12 @@ public final class NBTSerialization { continue; } - final INBT itemNBT = listNBT.get(i - nullsIndex); - if (itemNBT == null) { + final INBT itemTag = listTag.get(i - nullsIndex); + if (itemTag == null) { continue; } - data[i] = componentDeserializer.deserialize(itemNBT, componentType, data[i]); + data[i] = componentDeserializer.deserialize(itemTag, componentType, data[i]); } return data; @@ -350,11 +350,11 @@ public final class NBTSerialization { @Override public boolean exists(final String name) { - return nbt.contains(name); + return tag.contains(name); } private boolean isNull(final String name) { - return nbt.getCompound(name).getBoolean(IS_NULL_KEY); + return tag.getCompound(name).getBoolean(IS_NULL_KEY); } } @@ -364,7 +364,7 @@ public final class NBTSerialization { INBT serialize(Object value); @Nullable - Object deserialize(INBT nbt, final Class type, @Nullable final Object into); + Object deserialize(INBT tag, final Class type, @Nullable final Object into); } private static final class BooleanArraySerializer implements ArraySerializer { @@ -379,10 +379,10 @@ public final class NBTSerialization { } @Override - public Object deserialize(final INBT nbt, final Class type, @Nullable final Object into) { + public Object deserialize(final INBT tag, final Class type, @Nullable final Object into) { boolean[] data = (boolean[]) into; - if (nbt instanceof ByteArrayNBT) { - final byte[] convertedData = ((ByteArrayNBT) nbt).getByteArray(); + if (tag instanceof ByteArrayNBT) { + final byte[] convertedData = ((ByteArrayNBT) tag).getByteArray(); if (data == null || data.length != convertedData.length) { data = new boolean[convertedData.length]; } @@ -401,10 +401,10 @@ public final class NBTSerialization { } @Override - public Object deserialize(final INBT nbt, final Class type, @Nullable final Object into) { + public Object deserialize(final INBT tag, final Class type, @Nullable final Object into) { final byte[] data = (byte[]) into; - if (nbt instanceof ByteArrayNBT) { - final byte[] serializedData = ((ByteArrayNBT) nbt).getByteArray(); + if (tag instanceof ByteArrayNBT) { + final byte[] serializedData = ((ByteArrayNBT) tag).getByteArray(); if (data == null || data.length != serializedData.length) { return serializedData; } @@ -426,10 +426,10 @@ public final class NBTSerialization { } @Override - public Object deserialize(final INBT nbt, final Class type, @Nullable final Object into) { + public Object deserialize(final INBT tag, final Class type, @Nullable final Object into) { char[] data = (char[]) into; - if (nbt instanceof IntArrayNBT) { - final int[] convertedData = ((IntArrayNBT) nbt).getIntArray(); + if (tag instanceof IntArrayNBT) { + final int[] convertedData = ((IntArrayNBT) tag).getIntArray(); if (data == null || data.length != convertedData.length) { data = new char[convertedData.length]; } @@ -453,10 +453,10 @@ public final class NBTSerialization { } @Override - public Object deserialize(final INBT nbt, final Class type, @Nullable final Object into) { + public Object deserialize(final INBT tag, final Class type, @Nullable final Object into) { short[] data = (short[]) into; - if (nbt instanceof IntArrayNBT) { - final int[] convertedData = ((IntArrayNBT) nbt).getIntArray(); + if (tag instanceof IntArrayNBT) { + final int[] convertedData = ((IntArrayNBT) tag).getIntArray(); if (data == null || data.length != convertedData.length) { data = new short[convertedData.length]; } @@ -475,10 +475,10 @@ public final class NBTSerialization { } @Override - public Object deserialize(final INBT nbt, final Class type, @Nullable final Object into) { + public Object deserialize(final INBT tag, final Class type, @Nullable final Object into) { final int[] data = (int[]) into; - if (nbt instanceof IntArrayNBT) { - final int[] serializedData = ((IntArrayNBT) nbt).getIntArray(); + if (tag instanceof IntArrayNBT) { + final int[] serializedData = ((IntArrayNBT) tag).getIntArray(); if (data == null || data.length != serializedData.length) { return serializedData; } @@ -495,10 +495,10 @@ public final class NBTSerialization { } @Override - public Object deserialize(final INBT nbt, final Class type, @Nullable final Object into) { + public Object deserialize(final INBT tag, final Class type, @Nullable final Object into) { final long[] data = (long[]) into; - if (nbt instanceof LongArrayNBT) { - final long[] serializedData = ((LongArrayNBT) nbt).getAsLongArray(); + if (tag instanceof LongArrayNBT) { + final long[] serializedData = ((LongArrayNBT) tag).getAsLongArray(); if (data == null || data.length != serializedData.length) { return serializedData; } @@ -520,10 +520,10 @@ public final class NBTSerialization { } @Override - public Object deserialize(final INBT nbt, final Class type, @Nullable final Object into) { + public Object deserialize(final INBT tag, final Class type, @Nullable final Object into) { float[] data = (float[]) into; - if (nbt instanceof IntArrayNBT) { - final int[] convertedData = ((IntArrayNBT) nbt).getIntArray(); + if (tag instanceof IntArrayNBT) { + final int[] convertedData = ((IntArrayNBT) tag).getIntArray(); if (data == null || data.length != convertedData.length) { data = new float[convertedData.length]; } @@ -547,10 +547,10 @@ public final class NBTSerialization { } @Override - public Object deserialize(final INBT nbt, final Class type, @Nullable final Object into) { + public Object deserialize(final INBT tag, final Class type, @Nullable final Object into) { double[] data = (double[]) into; - if (nbt instanceof LongArrayNBT) { - final long[] convertedData = ((LongArrayNBT) nbt).getAsLongArray(); + if (tag instanceof LongArrayNBT) { + final long[] convertedData = ((LongArrayNBT) tag).getAsLongArray(); if (data == null || data.length != convertedData.length) { data = new double[convertedData.length]; } @@ -575,13 +575,13 @@ public final class NBTSerialization { } @Override - public Object deserialize(final INBT nbt, final Class type, @Nullable final Object into) { + public Object deserialize(final INBT tag, final Class type, @Nullable final Object into) { final Class componentType = type.getComponentType(); final Object[] enumConstants = componentType.getEnumConstants(); Enum[] data = (Enum[]) into; - if (nbt instanceof IntArrayNBT) { - final int[] serializedData = ((IntArrayNBT) nbt).getIntArray(); + if (tag instanceof IntArrayNBT) { + final int[] serializedData = ((IntArrayNBT) tag).getIntArray(); if (data == null || data.length != serializedData.length) { data = (Enum[]) Array.newInstance(componentType, serializedData.length); } @@ -605,10 +605,10 @@ public final class NBTSerialization { } @Override - public Object deserialize(final INBT nbt, final Class type, @Nullable final Object into) { + public Object deserialize(final INBT tag, final Class type, @Nullable final Object into) { String[] data = (String[]) into; - if (nbt instanceof ListNBT) { - final ListNBT serializedData = (ListNBT) nbt; + if (tag instanceof ListNBT) { + final ListNBT serializedData = (ListNBT) tag; if (serializedData.isEmpty() || serializedData.getTagType() == NBTTagIds.TAG_STRING) { if (data == null || data.length != serializedData.size()) { data = new String[serializedData.size()]; @@ -634,10 +634,10 @@ public final class NBTSerialization { } @Override - public Object deserialize(final INBT nbt, final Class type, @Nullable final Object into) { + public Object deserialize(final INBT tag, final Class type, @Nullable final Object into) { UUID[] data = (UUID[]) into; - if (nbt instanceof ListNBT) { - final ListNBT serializedData = (ListNBT) nbt; + if (tag instanceof ListNBT) { + final ListNBT serializedData = (ListNBT) tag; if (serializedData.isEmpty() || serializedData.getTagType() == NBTTagIds.TAG_STRING) { if (data == null || data.length != serializedData.size()) { data = new UUID[serializedData.size()]; diff --git a/src/main/java/li/cil/oc2/common/serialization/NBTToJsonConverter.java b/src/main/java/li/cil/oc2/common/serialization/NBTToJsonConverter.java index 512e1359..a4fa0b44 100644 --- a/src/main/java/li/cil/oc2/common/serialization/NBTToJsonConverter.java +++ b/src/main/java/li/cil/oc2/common/serialization/NBTToJsonConverter.java @@ -7,60 +7,60 @@ import net.minecraft.nbt.*; import javax.annotation.Nullable; public final class NBTToJsonConverter { - public static JsonElement convert(@Nullable final INBT nbt) { - if (nbt == null) { + public static JsonElement convert(@Nullable final INBT tag) { + if (tag == null) { return JsonNull.INSTANCE; } - switch (nbt.getId()) { + switch (tag.getId()) { case NBTTagIds.TAG_BYTE: { - return new JsonPrimitive(((ByteNBT) nbt).getByte()); + return new JsonPrimitive(((ByteNBT) tag).getByte()); } case NBTTagIds.TAG_SHORT: { - return new JsonPrimitive(((ShortNBT) nbt).getShort()); + return new JsonPrimitive(((ShortNBT) tag).getShort()); } case NBTTagIds.TAG_INT: { - return new JsonPrimitive(((IntNBT) nbt).getInt()); + return new JsonPrimitive(((IntNBT) tag).getInt()); } case NBTTagIds.TAG_LONG: { - return new JsonPrimitive(((LongNBT) nbt).getLong()); + return new JsonPrimitive(((LongNBT) tag).getLong()); } case NBTTagIds.TAG_FLOAT: { - return new JsonPrimitive(((FloatNBT) nbt).getFloat()); + return new JsonPrimitive(((FloatNBT) tag).getFloat()); } case NBTTagIds.TAG_DOUBLE: { - return new JsonPrimitive(((DoubleNBT) nbt).getDouble()); + return new JsonPrimitive(((DoubleNBT) tag).getDouble()); } case NBTTagIds.TAG_BYTE_ARRAY: { final JsonArray json = new JsonArray(); - final byte[] array = ((ByteArrayNBT) nbt).getByteArray(); + final byte[] array = ((ByteArrayNBT) tag).getByteArray(); for (int i = 0; i < array.length; i++) { json.add(array[i]); } return json; } case NBTTagIds.TAG_STRING: { - return new JsonPrimitive(nbt.getString()); + return new JsonPrimitive(tag.getString()); } case NBTTagIds.TAG_LIST: { final JsonArray json = new JsonArray(); - final ListNBT list = (ListNBT) nbt; - for (final INBT item : list) { + final ListNBT listTag = (ListNBT) tag; + for (final INBT item : listTag) { json.add(convert(item)); } return json; } case NBTTagIds.TAG_COMPOUND: { final JsonObject json = new JsonObject(); - final CompoundNBT compound = (CompoundNBT) nbt; - for (final String key : compound.keySet()) { - json.add(key, convert(compound.get(key))); + final CompoundNBT compoundTag = (CompoundNBT) tag; + for (final String key : compoundTag.keySet()) { + json.add(key, convert(compoundTag.get(key))); } return json; } case NBTTagIds.TAG_INT_ARRAY: { final JsonArray json = new JsonArray(); - final int[] array = ((IntArrayNBT) nbt).getIntArray(); + final int[] array = ((IntArrayNBT) tag).getIntArray(); for (int i = 0; i < array.length; i++) { json.add(array[i]); } @@ -68,7 +68,7 @@ public final class NBTToJsonConverter { } case NBTTagIds.TAG_LONG_ARRAY: { final JsonArray json = new JsonArray(); - final long[] array = ((LongArrayNBT) nbt).getAsLongArray(); + final long[] array = ((LongArrayNBT) tag).getAsLongArray(); for (int i = 0; i < array.length; i++) { json.add(array[i]); } diff --git a/src/main/java/li/cil/oc2/common/tileentity/ChargerTileEntity.java b/src/main/java/li/cil/oc2/common/tileentity/ChargerTileEntity.java new file mode 100644 index 00000000..5e8f9ada --- /dev/null +++ b/src/main/java/li/cil/oc2/common/tileentity/ChargerTileEntity.java @@ -0,0 +1,96 @@ +package li.cil.oc2.common.tileentity; + +import li.cil.oc2.common.Config; +import li.cil.oc2.common.Constants; +import li.cil.oc2.common.capabilities.Capabilities; +import li.cil.oc2.common.energy.FixedEnergyStorage; +import net.minecraft.block.BlockState; +import net.minecraft.entity.Entity; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.tileentity.ITickableTileEntity; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.energy.IEnergyStorage; +import net.minecraftforge.items.IItemHandler; + +import java.util.List; + +public final class ChargerTileEntity extends TileEntity implements ITickableTileEntity { + private final FixedEnergyStorage energy = new FixedEnergyStorage(Config.chargerEnergyStorage); + + /////////////////////////////////////////////////////////////////// + + ChargerTileEntity() { + super(TileEntities.CHARGER_TILE_ENTITY.get()); + } + + /////////////////////////////////////////////////////////////////// + + @Override + public void tick() { + chargeBlock(); + chargeEntities(); + } + + @Override + public CompoundNBT write(CompoundNBT tag) { + tag = super.write(tag); + + tag.put(Constants.ENERGY_TAG_NAME, energy.serializeNBT()); + + return tag; + } + + @Override + public void read(final BlockState state, final CompoundNBT tag) { + super.read(state, tag); + + energy.deserializeNBT(tag.getCompound(Constants.ENERGY_TAG_NAME)); + } + + /////////////////////////////////////////////////////////////////// + + private void chargeBlock() { + if (energy.getEnergyStored() == 0) { + return; + } + + final TileEntity tileEntity = getWorld().getTileEntity(getPos().up()); + if (tileEntity != null) { + chargeCapabilityProvider(tileEntity); + } + } + + private void chargeEntities() { + if (energy.getEnergyStored() == 0) { + return; + } + + final List entities = getWorld().getEntitiesInAABBexcluding(null, new AxisAlignedBB(getPos().up()), null); + for (final Entity entity : entities) { + chargeCapabilityProvider(entity); + } + } + + private void chargeCapabilityProvider(final ICapabilityProvider capabilityProvider) { + capabilityProvider.getCapability(Capabilities.ENERGY_STORAGE, Direction.DOWN).ifPresent(this::charge); + capabilityProvider.getCapability(Capabilities.ITEM_HANDLER, Direction.DOWN).ifPresent(this::chargeItems); + } + + private void chargeItems(final IItemHandler itemHandler) { + for (int slot = 0; slot < itemHandler.getSlots(); slot++) { + final ItemStack stack = itemHandler.getStackInSlot(slot); + if (!stack.isEmpty()) { + stack.getCapability(Capabilities.ENERGY_STORAGE).ifPresent(this::charge); + } + } + } + + private void charge(final IEnergyStorage energyStorage) { + final int amount = Math.min(energy.getEnergyStored(), Config.chargerEnergyPerTick); + energy.extractEnergy(energyStorage.receiveEnergy(amount, false), false); + } +} diff --git a/src/main/java/li/cil/oc2/common/tileentity/ComputerTileEntity.java b/src/main/java/li/cil/oc2/common/tileentity/ComputerTileEntity.java index 6f66f054..c670aee8 100644 --- a/src/main/java/li/cil/oc2/common/tileentity/ComputerTileEntity.java +++ b/src/main/java/li/cil/oc2/common/tileentity/ComputerTileEntity.java @@ -4,6 +4,7 @@ import li.cil.oc2.api.bus.DeviceBusElement; import li.cil.oc2.api.bus.device.Device; import li.cil.oc2.api.bus.device.DeviceTypes; import li.cil.oc2.client.audio.LoopingSoundManager; +import li.cil.oc2.common.Config; import li.cil.oc2.common.Constants; import li.cil.oc2.common.block.ComputerBlock; import li.cil.oc2.common.bus.CommonDeviceBusController; @@ -14,6 +15,7 @@ import li.cil.oc2.common.bus.device.util.Devices; import li.cil.oc2.common.bus.device.util.ItemDeviceInfo; import li.cil.oc2.common.capabilities.Capabilities; import li.cil.oc2.common.container.DeviceItemStackHandler; +import li.cil.oc2.common.energy.FixedEnergyStorage; import li.cil.oc2.common.network.Network; import li.cil.oc2.common.network.message.ComputerBootErrorMessage; import li.cil.oc2.common.network.message.ComputerBusStateMessage; @@ -28,6 +30,7 @@ import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.util.Direction; import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TranslationTextComponent; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import net.minecraftforge.common.capabilities.Capability; @@ -41,6 +44,9 @@ import java.util.Collection; import java.util.List; import java.util.Optional; +import static li.cil.oc2.common.Constants.BLOCK_ENTITY_TAG_NAME_IN_ITEM; +import static li.cil.oc2.common.Constants.ITEMS_TAG_NAME; + public final class ComputerTileEntity extends AbstractTileEntity implements ITickableTileEntity { private static final String BUS_ELEMENT_TAG_NAME = "busElement"; private static final String TERMINAL_TAG_NAME = "terminal"; @@ -62,8 +68,9 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic private final Terminal terminal = new Terminal(); private final TileEntityDeviceBusElement busElement = new ComputerBusElement(); - private final ComputerItemStackHandlers items = new ComputerItemStackHandlers(); - private final ComputerVirtualMachine virtualMachine = new ComputerVirtualMachine(new TileEntityDeviceBusController(busElement, this), items::getDeviceAddressBase); + private final ComputerItemStackHandlers deviceItems = new ComputerItemStackHandlers(); + private final FixedEnergyStorage energy = new FixedEnergyStorage(Config.computerEnergyStorage); + private final ComputerVirtualMachine virtualMachine = new ComputerVirtualMachine(new TileEntityDeviceBusController(busElement, this), deviceItems::getDeviceAddressBase); /////////////////////////////////////////////////////////////////// @@ -83,7 +90,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic } public VMItemStackHandlers getItemStackHandlers() { - return items; + return deviceItems; } public void start() { @@ -195,7 +202,8 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic tag.put(STATE_TAG_NAME, virtualMachine.serialize()); tag.put(TERMINAL_TAG_NAME, NBTSerialization.serialize(terminal)); tag.put(BUS_ELEMENT_TAG_NAME, NBTSerialization.serialize(busElement)); - tag.put(Constants.INVENTORY_TAG_NAME, items.serialize()); + tag.put(Constants.ITEMS_TAG_NAME, deviceItems.serialize()); + tag.put(Constants.ENERGY_TAG_NAME, energy.serializeNBT()); return tag; } @@ -211,21 +219,24 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic NBTSerialization.deserialize(tag.getCompound(BUS_ELEMENT_TAG_NAME), busElement); } - if (tag.contains(Constants.INVENTORY_TAG_NAME, NBTTagIds.TAG_COMPOUND)) { - items.deserialize(tag.getCompound(Constants.INVENTORY_TAG_NAME)); - } + deviceItems.deserialize(tag.getCompound(Constants.ITEMS_TAG_NAME)); + energy.deserializeNBT(tag.getCompound(Constants.ENERGY_TAG_NAME)); } public void exportToItemStack(final ItemStack stack) { - items.serialize(ItemStackUtils.getOrCreateTileEntityInventoryTag(stack)); + deviceItems.serialize(NBTUtils.getOrCreateChildTag(stack.getOrCreateTag(), BLOCK_ENTITY_TAG_NAME_IN_ITEM, ITEMS_TAG_NAME)); } /////////////////////////////////////////////////////////////////// @Override protected void collectCapabilities(final CapabilityCollector collector, @Nullable final Direction direction) { - collector.offer(Capabilities.ITEM_HANDLER, items.combinedItemHandlers); + collector.offer(Capabilities.ITEM_HANDLER, deviceItems.combinedItemHandlers); collector.offer(Capabilities.DEVICE_BUS_ELEMENT, busElement); + + if (Config.computersUseEnergy()) { + collector.offer(Capabilities.ENERGY_STORAGE, energy); + } } @Override @@ -291,7 +302,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic public Optional>> getNeighbors() { return super.getNeighbors().map(neighbors -> { final ArrayList> list = new ArrayList<>(neighbors); - list.add(LazyOptional.of(() -> items.busElement)); + list.add(LazyOptional.of(() -> deviceItems.busElement)); return list; }); } @@ -347,6 +358,33 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic super.tick(); } + @Override + protected void load() { + if (Config.computersUseEnergy()) { + // Don't even start running if we couldn't keep running. + if (energy.getEnergyStored() < Config.computerEnergyPerTick) { + error(new TranslationTextComponent(Constants.COMPUTER_ERROR_NOT_ENOUGH_ENERGY)); + return; + } + } + + super.load(); + } + + @Override + protected void run() { + if (Config.computersUseEnergy()) { + if (energy.getEnergyStored() >= Config.computerEnergyPerTick) { + energy.extractEnergy(Config.computerEnergyPerTick, false); + } else { + error(new TranslationTextComponent(Constants.COMPUTER_ERROR_NOT_ENOUGH_ENERGY)); + return; + } + } + + super.run(); + } + @Override public void stopRunnerAndReset() { super.stopRunnerAndReset(); diff --git a/src/main/java/li/cil/oc2/common/tileentity/DiskDriveTileEntity.java b/src/main/java/li/cil/oc2/common/tileentity/DiskDriveTileEntity.java index 2f74ea3b..44b010c4 100644 --- a/src/main/java/li/cil/oc2/common/tileentity/DiskDriveTileEntity.java +++ b/src/main/java/li/cil/oc2/common/tileentity/DiskDriveTileEntity.java @@ -112,21 +112,21 @@ public final class DiskDriveTileEntity extends AbstractTileEntity { @Override public CompoundNBT getUpdateTag() { final CompoundNBT tag = super.getUpdateTag(); - tag.put(Constants.INVENTORY_TAG_NAME, itemHandler.serializeNBT()); + tag.put(Constants.ITEMS_TAG_NAME, itemHandler.serializeNBT()); return tag; } @Override public void handleUpdateTag(final BlockState state, final CompoundNBT tag) { super.handleUpdateTag(state, tag); - itemHandler.deserializeNBT(tag.getCompound(Constants.INVENTORY_TAG_NAME)); + itemHandler.deserializeNBT(tag.getCompound(Constants.ITEMS_TAG_NAME)); } @Override public CompoundNBT write(CompoundNBT tag) { tag = super.write(tag); - tag.put(Constants.INVENTORY_TAG_NAME, itemHandler.serializeNBT()); + tag.put(Constants.ITEMS_TAG_NAME, itemHandler.serializeNBT()); return tag; } @@ -135,7 +135,7 @@ public final class DiskDriveTileEntity extends AbstractTileEntity { public void read(final BlockState state, final CompoundNBT tag) { super.read(state, tag); - itemHandler.deserializeNBT(tag.getCompound(Constants.INVENTORY_TAG_NAME)); + itemHandler.deserializeNBT(tag.getCompound(Constants.ITEMS_TAG_NAME)); } /////////////////////////////////////////////////////////////////// diff --git a/src/main/java/li/cil/oc2/common/tileentity/TileEntities.java b/src/main/java/li/cil/oc2/common/tileentity/TileEntities.java index 1340e459..929aa57b 100644 --- a/src/main/java/li/cil/oc2/common/tileentity/TileEntities.java +++ b/src/main/java/li/cil/oc2/common/tileentity/TileEntities.java @@ -24,6 +24,7 @@ public final class TileEntities { public static final RegistryObject> NETWORK_CONNECTOR_TILE_ENTITY = register(Constants.NETWORK_CONNECTOR_BLOCK_NAME, Blocks.NETWORK_CONNECTOR, NetworkConnectorTileEntity::new); public static final RegistryObject> NETWORK_HUB_TILE_ENTITY = register(Constants.NETWORK_HUB_BLOCK_NAME, Blocks.NETWORK_HUB, NetworkHubTileEntity::new); public static final RegistryObject> DISK_DRIVE_TILE_ENTITY = register(Constants.DISK_DRIVE_BLOCK_NAME, Blocks.DISK_DRIVE, DiskDriveTileEntity::new); + public static final RegistryObject> CHARGER_TILE_ENTITY = register(Constants.CHARGER_BLOCK_NAME, Blocks.CHARGER, ChargerTileEntity::new); /////////////////////////////////////////////////////////////////// diff --git a/src/main/java/li/cil/oc2/common/util/ItemDeviceUtils.java b/src/main/java/li/cil/oc2/common/util/ItemDeviceUtils.java index c19306a4..e48f8015 100644 --- a/src/main/java/li/cil/oc2/common/util/ItemDeviceUtils.java +++ b/src/main/java/li/cil/oc2/common/util/ItemDeviceUtils.java @@ -13,24 +13,11 @@ public final class ItemDeviceUtils { /////////////////////////////////////////////////////////////////// - public static Optional getItemDeviceData(final ItemStack stack) { - if (stack.isEmpty()) { - return Optional.empty(); - } - - final CompoundNBT nbt = ItemStackUtils.getModDataTag(stack); - if (nbt == null) { - return Optional.empty(); - } - - return Optional.of(nbt.getCompound(ITEM_DEVICE_DATA_TAG_NAME)); + public static CompoundNBT getItemDeviceData(final ItemStack stack) { + return ItemStackUtils.getModDataTag(stack).getCompound(ITEM_DEVICE_DATA_TAG_NAME); } public static void setItemDeviceData(final ItemStack stack, final CompoundNBT data) { - if (data.isEmpty()) { - return; - } - ItemStackUtils.getOrCreateModDataTag(stack).put(ITEM_DEVICE_DATA_TAG_NAME, data); } diff --git a/src/main/java/li/cil/oc2/common/util/ItemStackUtils.java b/src/main/java/li/cil/oc2/common/util/ItemStackUtils.java index 668822f0..03cde38a 100644 --- a/src/main/java/li/cil/oc2/common/util/ItemStackUtils.java +++ b/src/main/java/li/cil/oc2/common/util/ItemStackUtils.java @@ -1,6 +1,5 @@ package li.cil.oc2.common.util; -import li.cil.oc2.api.API; import net.minecraft.entity.item.ItemEntity; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; @@ -13,72 +12,15 @@ import javax.annotation.Nullable; import java.util.Optional; import java.util.Random; -import static li.cil.oc2.common.Constants.BLOCK_ENTITY_TAG_NAME_IN_ITEM; -import static li.cil.oc2.common.Constants.INVENTORY_TAG_NAME; +import static li.cil.oc2.common.Constants.MOD_TAG_NAME; public final class ItemStackUtils { - private static final String MOD_TAG_NAME = API.MOD_ID; - - @Nullable public static CompoundNBT getModDataTag(final ItemStack stack) { - if (stack.isEmpty()) { - return null; - } - - return stack.getChildTag(MOD_TAG_NAME); + return NBTUtils.getChildTag(stack.getTag(), MOD_TAG_NAME); } public static CompoundNBT getOrCreateModDataTag(final ItemStack stack) { - if (stack.isEmpty()) { - throw new IllegalArgumentException(); - } - - return stack.getOrCreateChildTag(MOD_TAG_NAME); - } - - @Nullable - public static CompoundNBT getInventoryTag(@Nullable final CompoundNBT tag) { - return tag != null && tag.contains(INVENTORY_TAG_NAME, NBTTagIds.TAG_COMPOUND) - ? tag.getCompound(INVENTORY_TAG_NAME) : null; - } - - public static CompoundNBT getOrCreateInventoryTag(final CompoundNBT tag) { - if (tag.contains(INVENTORY_TAG_NAME, NBTTagIds.TAG_COMPOUND)) { - return tag.getCompound(INVENTORY_TAG_NAME); - } - - final CompoundNBT inventoryTag = new CompoundNBT(); - tag.put(INVENTORY_TAG_NAME, inventoryTag); - return inventoryTag; - } - - @Nullable - public static CompoundNBT getTileEntityTag(final ItemStack stack) { - return stack.getChildTag(BLOCK_ENTITY_TAG_NAME_IN_ITEM); - } - - public static CompoundNBT getOrCreateTileEntityTag(final ItemStack stack) { - return stack.getOrCreateChildTag(BLOCK_ENTITY_TAG_NAME_IN_ITEM); - } - - @Nullable - public static CompoundNBT getTileEntityInventoryTag(final ItemStack stack) { - return getInventoryTag(getTileEntityTag(stack)); - } - - @Nullable - public static CompoundNBT getOrCreateTileEntityInventoryTag(final ItemStack stack) { - return getOrCreateInventoryTag(getOrCreateTileEntityTag(stack)); - } - - @Nullable - public static CompoundNBT getEntityInventoryTag(final ItemStack stack) { - return getInventoryTag(getModDataTag(stack)); - } - - @Nullable - public static CompoundNBT getOrCreateEntityInventoryTag(final ItemStack stack) { - return getOrCreateInventoryTag(getOrCreateModDataTag(stack)); + return NBTUtils.getOrCreateChildTag(stack.getOrCreateTag(), MOD_TAG_NAME); } public static Optional spawnAsEntity(final World world, final BlockPos pos, final ItemStack stack) { diff --git a/src/main/java/li/cil/oc2/common/util/NBTUtils.java b/src/main/java/li/cil/oc2/common/util/NBTUtils.java index e43a4390..5e773087 100644 --- a/src/main/java/li/cil/oc2/common/util/NBTUtils.java +++ b/src/main/java/li/cil/oc2/common/util/NBTUtils.java @@ -2,8 +2,7 @@ package li.cil.oc2.common.util; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.util.NonNullList; import net.minecraftforge.items.ItemStackHandler; import javax.annotation.Nullable; @@ -29,45 +28,34 @@ public final class NBTUtils { } } - public static void putBlockPos(final CompoundNBT tag, final String key, final BlockPos value) { - final CompoundNBT valueTag = new CompoundNBT(); - valueTag.putInt("x", value.getX()); - valueTag.putInt("y", value.getY()); - valueTag.putInt("z", value.getZ()); - tag.put(key, valueTag); + public static CompoundNBT getChildTag(@Nullable final CompoundNBT tag, final String... path) { + if (tag == null) { + return new CompoundNBT(); + } + + CompoundNBT childTag = tag; + for (final String tagName : path) { + if (!childTag.contains(tagName, NBTTagIds.TAG_COMPOUND)) { + return new CompoundNBT(); + } + childTag = childTag.getCompound(tagName); + } + + return childTag; } - public static BlockPos getBlockPos(final CompoundNBT tag, final String key) { - final CompoundNBT valueTag = tag.getCompound(key); - return new BlockPos( - valueTag.getInt("x"), - valueTag.getInt("y"), - valueTag.getInt("z") - ); - } - - public static void putVector3d(final CompoundNBT tag, final String key, final Vector3d value) { - final CompoundNBT valueTag = new CompoundNBT(); - valueTag.putDouble("x", value.getX()); - valueTag.putDouble("y", value.getY()); - valueTag.putDouble("z", value.getZ()); - tag.put(key, valueTag); - } - - public static Vector3d getVector3d(final CompoundNBT tag, final String key) { - final CompoundNBT valueTag = tag.getCompound(key); - return new Vector3d( - valueTag.getDouble("x"), - valueTag.getDouble("y"), - valueTag.getDouble("z") - ); + public static CompoundNBT getOrCreateChildTag(final CompoundNBT tag, final String... path) { + CompoundNBT childTag = tag; + for (final String tagName : path) { + if (!childTag.contains(tagName, NBTTagIds.TAG_COMPOUND)) { + childTag.put(tagName, new CompoundNBT()); + } + childTag = childTag.getCompound(tagName); + } + return childTag; } public static CompoundNBT makeInventoryTag(final ItemStack... items) { - final ItemStackHandler itemStackHandler = new ItemStackHandler(items.length); - for (int i = 0; i < items.length; i++) { - itemStackHandler.setStackInSlot(i, items[i]); - } - return itemStackHandler.serializeNBT(); + return new ItemStackHandler(NonNullList.from(ItemStack.EMPTY, items)).serializeNBT(); } } diff --git a/src/main/java/li/cil/oc2/common/util/TooltipUtils.java b/src/main/java/li/cil/oc2/common/util/TooltipUtils.java index 459a53d7..8e631f61 100644 --- a/src/main/java/li/cil/oc2/common/util/TooltipUtils.java +++ b/src/main/java/li/cil/oc2/common/util/TooltipUtils.java @@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import li.cil.oc2.api.bus.device.DeviceType; import li.cil.oc2.common.Constants; +import li.cil.oc2.common.energy.FixedEnergyStorage; import li.cil.oc2.common.tags.ItemTags; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -14,10 +15,11 @@ import net.minecraft.util.text.*; import net.minecraftforge.registries.ForgeRegistry; import net.minecraftforge.registries.RegistryManager; -import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; +import static li.cil.oc2.common.Constants.*; + public final class TooltipUtils { private static final ThreadLocal> ITEM_STACKS = ThreadLocal.withInitial(ArrayList::new); private static final ThreadLocal ITEM_STACKS_SIZES = ThreadLocal.withInitial(IntArrayList::new); @@ -47,40 +49,28 @@ public final class TooltipUtils { } public static void addTileEntityInventoryInformation(final ItemStack stack, final List tooltip) { - addInventoryInformation(ItemStackUtils.getTileEntityInventoryTag(stack), tooltip); - } - - public static void addTileEntityInventoryInformation(final ItemStack stack, final List tooltip, final String... subInventoryNames) { - addInventoryInformation(ItemStackUtils.getTileEntityInventoryTag(stack), tooltip, subInventoryNames); + addInventoryInformation(NBTUtils.getChildTag(stack.getTag(), BLOCK_ENTITY_TAG_NAME_IN_ITEM, ITEMS_TAG_NAME), tooltip); } public static void addEntityInventoryInformation(final ItemStack stack, final List tooltip) { - addInventoryInformation(ItemStackUtils.getEntityInventoryTag(stack), tooltip); + addInventoryInformation(NBTUtils.getChildTag(stack.getTag(), MOD_TAG_NAME, ITEMS_TAG_NAME), tooltip); } - public static void addEntityInventoryInformation(final ItemStack stack, final List tooltip, final String... subInventoryNames) { - addInventoryInformation(ItemStackUtils.getEntityInventoryTag(stack), tooltip, subInventoryNames); + public static void addInventoryInformation(final CompoundNBT itemsTag, final List tooltip) { + addInventoryInformation(itemsTag, tooltip, getDeviceTypeNames()); } - public static void addInventoryInformation(@Nullable final CompoundNBT inventoryTag, final List tooltip) { - addInventoryInformation(inventoryTag, tooltip, getDeviceTypeNames()); - } - - public static void addInventoryInformation(@Nullable final CompoundNBT inventoryTag, final List tooltip, final String... subInventoryNames) { - if (inventoryTag == null) { - return; - } - + public static void addInventoryInformation(final CompoundNBT itemsTag, final List tooltip, final String... subInventoryNames) { final List itemStacks = ITEM_STACKS.get(); itemStacks.clear(); final IntList itemStackSizes = ITEM_STACKS_SIZES.get(); itemStackSizes.clear(); - collectItemStacks(inventoryTag, itemStacks, itemStackSizes); + collectItemStacks(itemsTag, itemStacks, itemStackSizes); for (final String subInventoryName : subInventoryNames) { - if (inventoryTag.contains(subInventoryName, NBTTagIds.TAG_COMPOUND)) { - collectItemStacks(inventoryTag.getCompound(subInventoryName), itemStacks, itemStackSizes); + if (itemsTag.contains(subInventoryName, NBTTagIds.TAG_COMPOUND)) { + collectItemStacks(itemsTag.getCompound(subInventoryName), itemStacks, itemStackSizes); } } @@ -96,6 +86,30 @@ public final class TooltipUtils { } } + public static void addTileEntityEnergyInformation(final ItemStack stack, final List tooltip) { + addEnergyInformation(NBTUtils.getChildTag(stack.getTag(), BLOCK_ENTITY_TAG_NAME_IN_ITEM, ENERGY_TAG_NAME), tooltip); + } + + public static void addEntityEnergyInformation(final ItemStack stack, final List tooltip) { + addEnergyInformation(NBTUtils.getChildTag(stack.getTag(), MOD_TAG_NAME, ENERGY_TAG_NAME), tooltip); + } + + public static void addEnergyInformation(final CompoundNBT energyTag, final List tooltip) { + final int stored = energyTag.getInt(FixedEnergyStorage.STORED_TAG_NAME); + if (stored == 0) { + return; + } + + final int capacity = energyTag.getInt(FixedEnergyStorage.CAPACITY_TAG_NAME); + if (capacity > 0) { + tooltip.add(new TranslationTextComponent(Constants.TOOLTIP_ENERGY, stored + "/" + capacity)); + } else { + tooltip.add(new TranslationTextComponent(Constants.TOOLTIP_ENERGY, stored)); + } + } + + /////////////////////////////////////////////////////////////////// + private static String[] getDeviceTypeNames() { final ForgeRegistry registry = RegistryManager.ACTIVE.getRegistry(DeviceType.REGISTRY); if (registry != null) { @@ -106,11 +120,11 @@ public final class TooltipUtils { } } - private static void collectItemStacks(final CompoundNBT nbt, final List stacks, final IntList stackSizes) { - final ListNBT itemsNbt = nbt.getList("Items", NBTTagIds.TAG_COMPOUND); - for (int i = 0; i < itemsNbt.size(); i++) { - final CompoundNBT itemNbt = itemsNbt.getCompound(i); - final ItemStack itemStack = ItemStack.read(itemNbt); + private static void collectItemStacks(final CompoundNBT tag, final List stacks, final IntList stackSizes) { + final ListNBT itemsTag = tag.getList("Items", NBTTagIds.TAG_COMPOUND); + for (int i = 0; i < itemsTag.size(); i++) { + final CompoundNBT itemTag = itemsTag.getCompound(i); + final ItemStack itemStack = ItemStack.read(itemTag); boolean didMerge = false; for (int j = 0; j < stacks.size(); j++) { diff --git a/src/main/java/li/cil/oc2/data/ModBlockStateProvider.java b/src/main/java/li/cil/oc2/data/ModBlockStateProvider.java index 0d0db995..0784e424 100644 --- a/src/main/java/li/cil/oc2/data/ModBlockStateProvider.java +++ b/src/main/java/li/cil/oc2/data/ModBlockStateProvider.java @@ -36,6 +36,7 @@ public class ModBlockStateProvider extends BlockStateProvider { .end(); horizontalBlock(Blocks.NETWORK_HUB, Items.NETWORK_HUB); horizontalBlock(Blocks.DISK_DRIVE, Items.DISK_DRIVE); + horizontalBlock(Blocks.CHARGER, Items.CHARGER); registerCableStates(); } diff --git a/src/main/java/li/cil/oc2/data/ModBlockTagsProvider.java b/src/main/java/li/cil/oc2/data/ModBlockTagsProvider.java index 8de1d0a9..fdd972a1 100644 --- a/src/main/java/li/cil/oc2/data/ModBlockTagsProvider.java +++ b/src/main/java/li/cil/oc2/data/ModBlockTagsProvider.java @@ -30,7 +30,8 @@ public final class ModBlockTagsProvider extends BlockTagsProvider { NETWORK_CONNECTOR.get(), NETWORK_HUB.get(), REDSTONE_INTERFACE.get(), - DISK_DRIVE.get() + DISK_DRIVE.get(), + CHARGER.get() ); } } diff --git a/src/main/java/li/cil/oc2/data/ModLootTableProvider.java b/src/main/java/li/cil/oc2/data/ModLootTableProvider.java index 1498018d..f653a765 100644 --- a/src/main/java/li/cil/oc2/data/ModLootTableProvider.java +++ b/src/main/java/li/cil/oc2/data/ModLootTableProvider.java @@ -21,8 +21,7 @@ import java.util.stream.Collectors; import java.util.stream.StreamSupport; import static java.util.Objects.requireNonNull; -import static li.cil.oc2.common.Constants.BLOCK_ENTITY_TAG_NAME_IN_ITEM; -import static li.cil.oc2.common.Constants.INVENTORY_TAG_NAME; +import static li.cil.oc2.common.Constants.*; public final class ModLootTableProvider extends LootTableProvider { public ModLootTableProvider(final DataGenerator generator) { @@ -46,6 +45,7 @@ public final class ModLootTableProvider extends LootTableProvider { registerDropSelfLootTable(Blocks.NETWORK_CONNECTOR.get()); registerDropSelfLootTable(Blocks.NETWORK_HUB.get()); registerDropSelfLootTable(Blocks.DISK_DRIVE.get()); + registerDropSelfLootTable(Blocks.CHARGER.get()); registerLootTable(Blocks.COMPUTER.get(), ModBlockLootTables::droppingWithInventory); } @@ -64,8 +64,11 @@ public final class ModLootTableProvider extends LootTableProvider { .rolls(ConstantRange.of(1)) .addEntry(ItemLootEntry.builder(block) .acceptFunction(CopyNbt.builder(CopyNbt.Source.BLOCK_ENTITY) - .addOperation(INVENTORY_TAG_NAME, - concat(BLOCK_ENTITY_TAG_NAME_IN_ITEM, INVENTORY_TAG_NAME), + .addOperation(ITEMS_TAG_NAME, + concat(BLOCK_ENTITY_TAG_NAME_IN_ITEM, ITEMS_TAG_NAME), + CopyNbt.Action.REPLACE) + .addOperation(ENERGY_TAG_NAME, + concat(BLOCK_ENTITY_TAG_NAME_IN_ITEM, ENERGY_TAG_NAME), CopyNbt.Action.REPLACE) ) ) diff --git a/src/main/resources/assets/oc2/blockstates/charger.json b/src/main/resources/assets/oc2/blockstates/charger.json new file mode 100644 index 00000000..77ef6577 --- /dev/null +++ b/src/main/resources/assets/oc2/blockstates/charger.json @@ -0,0 +1,19 @@ +{ + "variants": { + "facing=north": { + "model": "oc2:block/charger" + }, + "facing=south": { + "model": "oc2:block/charger", + "y": 180 + }, + "facing=west": { + "model": "oc2:block/charger", + "y": 270 + }, + "facing=east": { + "model": "oc2:block/charger", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/oc2/lang/en_us.json b/src/main/resources/assets/oc2/lang/en_us.json index 3f4ebe12..14a3576e 100644 --- a/src/main/resources/assets/oc2/lang/en_us.json +++ b/src/main/resources/assets/oc2/lang/en_us.json @@ -10,6 +10,8 @@ "block.oc2.redstone_interface": "Redstone Interface", "block.oc2.disk_drive": "Disk Drive", "block.oc2.disk_drive.desc": "Used to access Floppy Disks.", + "block.oc2.charger": "Charger", + "block.oc2.charger.desc": "Charges entities and items in containers on top of it.", "item.oc2.wrench": "Scrench", "item.oc2.wrench.desc": "Used to configure devices and to dismantle them (while sneaking).", @@ -35,9 +37,14 @@ "config.oc2.vm.maxMemorySize:": "Maximum memory device size", "config.oc2.vm.maxHardDriveSize": "Maximum hard drive device size", "config.oc2.vm.maxFlashMemorySize:": "Maximum flash memory device size", - "config.oc2.computerEnergyPerTick": "Energy/tick used by computers", "config.oc2.modules.block_operations.toolLevel": "Block operations module tool level", "config.oc2.admin.fakePlayerUUID": "Fake Player UUID", + "config.oc2.computerEnergyPerTick": "Energy/tick used by computers", + "config.oc2.computerEnergyStorage": "Computer energy storage", + "config.oc2.robotEnergyPerTick": "Energy/tick used by robots", + "config.oc2.robotEnergyStorage": "Robot energy storage", + "config.oc2.chargerEnergyPerTick": "Energy/tick transferred by chargers", + "config.oc2.chargerEnergyStorage": "Charge energy storage", "gui.oc2.computer.error.unknown": "Unknown Error", "gui.oc2.computer.error.missing_firmware": "Missing Firmware", @@ -65,6 +72,7 @@ "tooltip.oc2.flash_memory_missing": "A flash memory containing a firmware is required to boot.", "tooltip.oc2.memory_missing": "Some memory is required to load the flash memory for execution to boot.", "tooltip.oc2.hard_drive_missing": "Most systems will require a root file system to boot.", + "tooltip.oc2.energy": "Energy: %s", "subtitles.oc2.computer": "Computer fans running", "subtitles.oc2.floppy": "Floppy access", diff --git a/src/main/resources/assets/oc2/models/block/charger.json b/src/main/resources/assets/oc2/models/block/charger.json new file mode 100644 index 00000000..84664a15 --- /dev/null +++ b/src/main/resources/assets/oc2/models/block/charger.json @@ -0,0 +1 @@ +{"parent":"block/block","textures":{"atlas0":"oc2:block/charger/charger_atlas0","atlas1":"oc2:block/charger/charger_atlas1","atlas2":"oc2:block/charger/charger_atlas2","atlas3":"oc2:block/charger/charger_atlas3","particle":"#atlas0"},"elements":[{"from":[0,0,0],"to":[16,12,16],"faces":{"east":{"texture":"atlas0","cullface":"east","uv":[0.0,0.0,8.0,6.0]},"west":{"texture":"atlas0","cullface":"west","uv":[0.0,6.0,8.0,12.0]},"up":{"texture":"atlas1","uv":[0.0,0.0,8.0,8.0]},"down":{"texture":"atlas1","cullface":"down","uv":[0.0,8.0,8.0,16.0]},"north":{"texture":"atlas0","cullface":"north","uv":[8.0,6.0,16.0,12.0]},"south":{"texture":"atlas0","cullface":"south","uv":[8.0,0.0,16.0,6.0]}}},{"from":[0,12,15],"to":[3,13,16],"faces":{"east":{"texture":"atlas2","uv":[15.5,12.0,16.0,12.5]},"west":{"texture":"atlas2","cullface":"west","uv":[15.5,12.5,16.0,13.0]},"up":{"texture":"atlas2","uv":[14.0,7.5,15.5,8.0]},"down":{"texture":"atlas2","uv":[14.0,7.0,15.5,7.5]},"south":{"texture":"atlas2","cullface":"south","uv":[14.0,6.5,15.5,7.0]}}},{"from":[13,12,15],"to":[16,13,16],"faces":{"east":{"texture":"atlas2","cullface":"east","uv":[15.5,13.0,16.0,13.5]},"west":{"texture":"atlas2","uv":[15.5,13.5,16.0,14.0]},"up":{"texture":"atlas2","uv":[8.0,6.0,9.5,6.5]},"down":{"texture":"atlas2","uv":[9.5,6.0,11.0,6.5]},"south":{"texture":"atlas2","cullface":"south","uv":[11.0,6.0,12.5,6.5]}}},{"from":[0,12,13],"to":[16,13,15],"faces":{"east":{"texture":"atlas2","cullface":"east","uv":[15.0,10.5,16.0,11.0]},"west":{"texture":"atlas2","cullface":"west","uv":[15.0,10.0,16.0,10.5]},"up":{"texture":"atlas0","uv":[0.0,12.0,8.0,13.0]},"down":{"texture":"atlas0","uv":[0.0,13.0,8.0,14.0]},"north":{"texture":"atlas0","uv":[0.0,14.0,8.0,14.5]},"south":{"texture":"atlas0","uv":[0.0,14.5,8.0,15.0]}}},{"from":[1,12,3],"to":[15,13,13],"faces":{"east":{"texture":"atlas2","uv":[8.0,8.5,13.0,9.0]},"west":{"texture":"atlas2","uv":[8.0,9.0,13.0,9.5]},"up":{"texture":"atlas2","uv":[0.0,11.0,7.0,16.0]},"down":{"texture":"atlas2","uv":[7.0,11.0,14.0,16.0]},"north":{"texture":"atlas2","uv":[8.0,10.5,15.0,11.0]},"south":{"texture":"atlas2","uv":[8.0,10.0,15.0,10.5]}}},{"from":[0,12,1],"to":[16,13,3],"faces":{"east":{"texture":"atlas2","cullface":"east","uv":[11.0,4.5,12.0,5.0]},"west":{"texture":"atlas2","cullface":"west","uv":[12.0,4.5,13.0,5.0]},"up":{"texture":"atlas0","uv":[0.0,15.0,8.0,16.0]},"down":{"texture":"atlas0","uv":[8.0,15.0,16.0,16.0]},"north":{"texture":"atlas0","uv":[8.0,14.5,16.0,15.0]},"south":{"texture":"atlas0","uv":[8.0,14.0,16.0,14.5]}}},{"from":[0,12,0],"to":[3,13,1],"faces":{"east":{"texture":"atlas2","uv":[15.5,7.5,16.0,8.0]},"west":{"texture":"atlas2","cullface":"west","uv":[15.5,7.0,16.0,7.5]},"up":{"texture":"atlas2","uv":[12.5,6.0,14.0,6.5]},"down":{"texture":"atlas2","uv":[14.0,6.0,15.5,6.5]},"north":{"texture":"atlas2","cullface":"north","uv":[8.0,5.5,9.5,6.0]}}},{"from":[13,12,0],"to":[16,13,1],"faces":{"east":{"texture":"atlas2","cullface":"east","uv":[15.5,6.5,16.0,7.0]},"west":{"texture":"atlas2","uv":[15.5,6.0,16.0,6.5]},"up":{"texture":"atlas2","uv":[9.5,5.5,11.0,6.0]},"down":{"texture":"atlas2","uv":[11.0,5.5,12.5,6.0]},"north":{"texture":"atlas2","cullface":"north","uv":[12.5,5.5,14.0,6.0]}}},{"from":[0,13,0],"to":[16,15,16],"faces":{"east":{"texture":"atlas0","cullface":"east","uv":[8.0,13.0,16.0,14.0]},"west":{"texture":"atlas0","cullface":"west","uv":[8.0,12.0,16.0,13.0]},"up":{"texture":"atlas1","uv":[8.0,8.0,16.0,16.0]},"down":{"texture":"atlas1","uv":[8.0,0.0,16.0,8.0]},"north":{"texture":"atlas2","cullface":"north","uv":[0.0,0.0,8.0,1.0]},"south":{"texture":"atlas2","cullface":"south","uv":[0.0,1.0,8.0,2.0]}}},{"from":[0,15,13],"to":[16,16,16],"faces":{"east":{"texture":"atlas2","cullface":"east","uv":[14.0,5.5,15.5,6.0]},"west":{"texture":"atlas2","cullface":"west","uv":[8.0,4.5,9.5,5.0]},"up":{"texture":"atlas2","cullface":"up","uv":[0.0,2.0,8.0,3.5]},"north":{"texture":"atlas2","uv":[0.0,3.5,8.0,4.0]},"south":{"texture":"atlas2","cullface":"south","uv":[0.0,4.0,8.0,4.5]}}},{"from":[0,15,12],"to":[6,16,13],"faces":{"east":{"texture":"atlas2","uv":[15.5,5.5,16.0,6.0]},"west":{"texture":"atlas2","cullface":"west","uv":[15.5,5.0,16.0,5.5]},"up":{"texture":"atlas2","cullface":"up","uv":[8.0,9.5,11.0,10.0]},"north":{"texture":"atlas2","uv":[11.0,9.5,14.0,10.0]},"south":{"texture":"atlas2","uv":[13.0,9.0,16.0,9.5]}}},{"from":[10,15,12],"to":[16,16,13],"faces":{"east":{"texture":"atlas2","cullface":"east","uv":[13.0,4.0,13.5,4.5]},"west":{"texture":"atlas2","uv":[13.5,4.0,14.0,4.5]},"up":{"texture":"atlas2","cullface":"up","uv":[13.0,8.5,16.0,9.0]},"north":{"texture":"atlas2","uv":[8.0,8.0,11.0,8.5]},"south":{"texture":"atlas2","uv":[11.0,8.0,14.0,8.5]}}},{"from":[0,15,10],"to":[16,16,12],"faces":{"east":{"texture":"atlas2","cullface":"east","uv":[13.0,4.5,14.0,5.0]},"west":{"texture":"atlas2","cullface":"west","uv":[14.0,4.5,15.0,5.0]},"up":{"texture":"atlas2","cullface":"up","uv":[0.0,4.5,8.0,5.5]},"north":{"texture":"atlas2","uv":[0.0,5.5,8.0,6.0]},"south":{"texture":"atlas2","uv":[0.0,6.0,8.0,6.5]}}},{"from":[0,15,6],"to":[3,16,10],"faces":{"east":{"texture":"atlas2","uv":[14.0,11.0,16.0,11.5]},"west":{"texture":"atlas2","cullface":"west","uv":[14.0,11.5,16.0,12.0]},"up":{"texture":"atlas2","cullface":"up","uv":[14.0,12.0,15.5,14.0]},"north":{"texture":"atlas2","uv":[8.0,5.0,9.5,5.5]},"south":{"texture":"atlas2","uv":[9.5,5.0,11.0,5.5]}}},{"from":[4,15,6],"to":[6,16,10],"faces":{"east":{"texture":"atlas2","uv":[14.0,14.0,16.0,14.5]},"west":{"texture":"atlas2","uv":[14.0,14.5,16.0,15.0]},"up":{"texture":"atlas3","cullface":"up","uv":[0.0,0.0,1.0,2.0]},"north":{"texture":"atlas2","uv":[15.0,4.5,16.0,5.0]},"south":{"texture":"atlas2","uv":[8.0,4.0,9.0,4.5]}}},{"from":[10,15,6],"to":[12,16,10],"faces":{"east":{"texture":"atlas2","uv":[14.0,15.0,16.0,15.5]},"west":{"texture":"atlas2","uv":[14.0,15.5,16.0,16.0]},"up":{"texture":"atlas3","cullface":"up","uv":[1.0,0.0,2.0,2.0]},"north":{"texture":"atlas2","uv":[9.0,4.0,10.0,4.5]},"south":{"texture":"atlas2","uv":[10.0,4.0,11.0,4.5]}}},{"from":[13,15,6],"to":[16,16,10],"faces":{"east":{"texture":"atlas2","cullface":"east","uv":[14.0,9.5,16.0,10.0]},"west":{"texture":"atlas2","uv":[14.0,8.0,16.0,8.5]},"up":{"texture":"atlas3","cullface":"up","uv":[2.0,0.0,3.5,2.0]},"north":{"texture":"atlas2","uv":[11.0,5.0,12.5,5.5]},"south":{"texture":"atlas2","uv":[12.5,5.0,14.0,5.5]}}},{"from":[0,15,4],"to":[16,16,6],"faces":{"east":{"texture":"atlas2","cullface":"east","uv":[11.0,4.0,12.0,4.5]},"west":{"texture":"atlas2","cullface":"west","uv":[12.0,4.0,13.0,4.5]},"up":{"texture":"atlas2","cullface":"up","uv":[0.0,6.5,8.0,7.5]},"north":{"texture":"atlas2","uv":[0.0,7.5,8.0,8.0]},"south":{"texture":"atlas2","uv":[0.0,8.0,8.0,8.5]}}},{"from":[0,15,3],"to":[6,16,4],"faces":{"east":{"texture":"atlas2","uv":[14.0,4.0,14.5,4.5]},"west":{"texture":"atlas2","cullface":"west","uv":[14.5,4.0,15.0,4.5]},"up":{"texture":"atlas2","cullface":"up","uv":[8.0,7.5,11.0,8.0]},"north":{"texture":"atlas2","uv":[11.0,7.5,14.0,8.0]},"south":{"texture":"atlas2","uv":[8.0,6.5,11.0,7.0]}}},{"from":[10,15,3],"to":[16,16,4],"faces":{"east":{"texture":"atlas2","cullface":"east","uv":[15.0,4.0,15.5,4.5]},"west":{"texture":"atlas2","uv":[15.5,4.0,16.0,4.5]},"up":{"texture":"atlas2","cullface":"up","uv":[8.0,7.0,11.0,7.5]},"north":{"texture":"atlas2","uv":[11.0,7.0,14.0,7.5]},"south":{"texture":"atlas2","uv":[11.0,6.5,14.0,7.0]}}},{"from":[0,15,0],"to":[16,16,3],"faces":{"east":{"texture":"atlas2","cullface":"east","uv":[14.0,5.0,15.5,5.5]},"west":{"texture":"atlas2","cullface":"west","uv":[9.5,4.5,11.0,5.0]},"up":{"texture":"atlas2","cullface":"up","uv":[0.0,8.5,8.0,10.0]},"north":{"texture":"atlas2","cullface":"north","uv":[0.0,10.0,8.0,10.5]},"south":{"texture":"atlas2","uv":[0.0,10.5,8.0,11.0]}}}]} \ No newline at end of file diff --git a/src/main/resources/assets/oc2/models/item/charger.json b/src/main/resources/assets/oc2/models/item/charger.json new file mode 100644 index 00000000..07b7176c --- /dev/null +++ b/src/main/resources/assets/oc2/models/item/charger.json @@ -0,0 +1,3 @@ +{ + "parent": "oc2:block/charger" +} \ No newline at end of file diff --git a/src/main/resources/assets/oc2/textures/block/charger/charger_atlas0.png b/src/main/resources/assets/oc2/textures/block/charger/charger_atlas0.png new file mode 100644 index 0000000000000000000000000000000000000000..c8d1da2d4622480247f191586432aa881db034f2 GIT binary patch literal 1694 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/oc2/textures/block/charger/charger_atlas2.png b/src/main/resources/assets/oc2/textures/block/charger/charger_atlas2.png new file mode 100644 index 0000000000000000000000000000000000000000..c64768c8c9d30e63f06781e2cc303b6512973e96 GIT binary patch literal 1526 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