From e9b864b1027d2009076304a3bf779cfa120b6717 Mon Sep 17 00:00:00 2001 From: Raoul Van den Berge Date: Sat, 13 Aug 2016 20:55:10 +0200 Subject: [PATCH] Fluid Destructor --- .../java/refinedstorage/RefinedStorage.java | 2 + .../refinedstorage/RefinedStorageBlocks.java | 1 + .../refinedstorage/RefinedStorageGui.java | 1 + .../refinedstorage/block/BlockDestructor.java | 6 +- .../block/BlockFluidDestructor.java | 37 ++++ .../container/ContainerFluidDestructor.java | 51 ++++++ .../gui/GuiFluidDestructor.java | 40 +++++ .../java/refinedstorage/gui/GuiHandler.java | 4 + .../refinedstorage/proxy/ClientProxy.java | 1 + .../refinedstorage/proxy/CommonProxy.java | 14 ++ .../tile/TileFluidDestructor.java | 162 ++++++++++++++++++ .../blockstates/fluid_destructor.json | 83 +++++++++ .../assets/refinedstorage/lang/en_US.lang | 2 + .../textures/blocks/controller_7.png | Bin 798 -> 799 bytes .../textures/blocks/fluid_destructor.png | Bin 0 -> 638 bytes .../assets/refinedstorage/textures/icons.png | Bin 2972 -> 3729 bytes 16 files changed, 403 insertions(+), 1 deletion(-) create mode 100755 src/main/java/refinedstorage/block/BlockFluidDestructor.java create mode 100755 src/main/java/refinedstorage/container/ContainerFluidDestructor.java create mode 100755 src/main/java/refinedstorage/gui/GuiFluidDestructor.java create mode 100755 src/main/java/refinedstorage/tile/TileFluidDestructor.java create mode 100755 src/main/resources/assets/refinedstorage/blockstates/fluid_destructor.json create mode 100755 src/main/resources/assets/refinedstorage/textures/blocks/fluid_destructor.png diff --git a/src/main/java/refinedstorage/RefinedStorage.java b/src/main/java/refinedstorage/RefinedStorage.java index 3c3d26f9a..105a4a828 100755 --- a/src/main/java/refinedstorage/RefinedStorage.java +++ b/src/main/java/refinedstorage/RefinedStorage.java @@ -49,6 +49,7 @@ public final class RefinedStorage { public int crafterPerPatternUsage; public int craftingMonitorUsage; public int destructorUsage; + public int fluidDestructorUsage; public int detectorUsage; public int diskDriveUsage; public int diskDrivePerDiskUsage; @@ -97,6 +98,7 @@ public final class RefinedStorage { crafterPerPatternUsage = config.getInt("crafterPerPattern", "energy", 1, 0, Integer.MAX_VALUE, "The additional energy used per Pattern in a Crafter"); craftingMonitorUsage = config.getInt("craftingMonitor", "energy", 2, 0, Integer.MAX_VALUE, "The energy used by Crafting Monitors"); destructorUsage = config.getInt("destructor", "energy", 1, 0, Integer.MAX_VALUE, "The energy used by Destructors"); + fluidDestructorUsage = config.getInt("fluidDestructor", "energy", 1, 0, Integer.MAX_VALUE, "The energy used by Fluid Destructors"); detectorUsage = config.getInt("detector", "energy", 2, 0, Integer.MAX_VALUE, "The energy used by Detectors"); diskDriveUsage = config.getInt("diskDrive", "energy", 0, 0, Integer.MAX_VALUE, "The base energy used by Disk Drives"); diskDrivePerDiskUsage = config.getInt("diskDrivePerDisk", "energy", 1, 0, Integer.MAX_VALUE, "The additional energy used by Storage Disks in Disk Drives"); diff --git a/src/main/java/refinedstorage/RefinedStorageBlocks.java b/src/main/java/refinedstorage/RefinedStorageBlocks.java index 33394ade9..0abad81c3 100755 --- a/src/main/java/refinedstorage/RefinedStorageBlocks.java +++ b/src/main/java/refinedstorage/RefinedStorageBlocks.java @@ -26,4 +26,5 @@ public final class RefinedStorageBlocks { public static final BlockNetworkReceiver NETWORK_RECEIVER = new BlockNetworkReceiver(); public static final BlockFluidDiskDrive FLUID_DISK_DRIVE = new BlockFluidDiskDrive(); public static final BlockFluidConstructor FLUID_CONSTRUCTOR = new BlockFluidConstructor(); + public static final BlockFluidDestructor FLUID_DESTRUCTOR = new BlockFluidDestructor(); } \ No newline at end of file diff --git a/src/main/java/refinedstorage/RefinedStorageGui.java b/src/main/java/refinedstorage/RefinedStorageGui.java index 4d70c70e9..697d347b0 100755 --- a/src/main/java/refinedstorage/RefinedStorageGui.java +++ b/src/main/java/refinedstorage/RefinedStorageGui.java @@ -22,4 +22,5 @@ public final class RefinedStorageGui { public static final int NETWORK_TRANSMITTER = 18; public static final int FLUID_DISK_DRIVE = 19; public static final int FLUID_CONSTRUCTOR = 20; + public static final int FLUID_DESTRUCTOR = 21; } diff --git a/src/main/java/refinedstorage/block/BlockDestructor.java b/src/main/java/refinedstorage/block/BlockDestructor.java index a8978ff03..306b31418 100755 --- a/src/main/java/refinedstorage/block/BlockDestructor.java +++ b/src/main/java/refinedstorage/block/BlockDestructor.java @@ -17,8 +17,12 @@ import refinedstorage.tile.TileDestructor; import java.util.List; public class BlockDestructor extends BlockCable { + public BlockDestructor(String name) { + super(name); + } + public BlockDestructor() { - super("destructor"); + this("destructor"); } @Override diff --git a/src/main/java/refinedstorage/block/BlockFluidDestructor.java b/src/main/java/refinedstorage/block/BlockFluidDestructor.java new file mode 100755 index 000000000..2a0c8999d --- /dev/null +++ b/src/main/java/refinedstorage/block/BlockFluidDestructor.java @@ -0,0 +1,37 @@ +package refinedstorage.block; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import refinedstorage.RefinedStorage; +import refinedstorage.RefinedStorageGui; +import refinedstorage.tile.TileFluidDestructor; + +public class BlockFluidDestructor extends BlockDestructor { + public BlockFluidDestructor() { + super("fluid_destructor"); + } + + @Override + public TileEntity createTileEntity(World world, IBlockState state) { + return new TileFluidDestructor(); + } + + @Override + public boolean onBlockActivatedDefault(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, ItemStack heldItem, EnumFacing side, float hitX, float hitY, float hitZ) { + if (hitCablePart(state, world, pos, hitX, hitY, hitZ)) { + return false; + } + + if (!world.isRemote) { + player.openGui(RefinedStorage.INSTANCE, RefinedStorageGui.FLUID_DESTRUCTOR, world, pos.getX(), pos.getY(), pos.getZ()); + } + + return true; + } +} diff --git a/src/main/java/refinedstorage/container/ContainerFluidDestructor.java b/src/main/java/refinedstorage/container/ContainerFluidDestructor.java new file mode 100755 index 000000000..3cd84f2e7 --- /dev/null +++ b/src/main/java/refinedstorage/container/ContainerFluidDestructor.java @@ -0,0 +1,51 @@ +package refinedstorage.container; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraftforge.items.SlotItemHandler; +import refinedstorage.container.slot.SlotSpecimenFluid; +import refinedstorage.tile.TileFluidDestructor; + +public class ContainerFluidDestructor extends ContainerBase { + public ContainerFluidDestructor(TileFluidDestructor fluidDestructor, EntityPlayer player) { + super(fluidDestructor, player); + + for (int i = 0; i < 4; ++i) { + addSlotToContainer(new SlotItemHandler(fluidDestructor.getUpgrades(), i, 187, 6 + (i * 18))); + } + + for (int i = 0; i < 9; ++i) { + addSlotToContainer(new SlotSpecimenFluid(!fluidDestructor.getWorld().isRemote, fluidDestructor.getInventory(), i, 8 + (18 * i), 20)); + } + + addPlayerInventory(8, 55); + } + + @Override + public ItemStack transferStackInSlot(EntityPlayer player, int index) { + ItemStack stack = null; + + Slot slot = getSlot(index); + + if (slot != null && slot.getHasStack()) { + stack = slot.getStack(); + + if (index < 4) { + if (!mergeItemStack(stack, 4 + 9, inventorySlots.size(), false)) { + return null; + } + } else if (!mergeItemStack(stack, 0, 4, false)) { + return mergeItemStackToSpecimen(stack, 4, 4 + 9); + } + + if (stack.stackSize == 0) { + slot.putStack(null); + } else { + slot.onSlotChanged(); + } + } + + return stack; + } +} diff --git a/src/main/java/refinedstorage/gui/GuiFluidDestructor.java b/src/main/java/refinedstorage/gui/GuiFluidDestructor.java new file mode 100755 index 000000000..676997d89 --- /dev/null +++ b/src/main/java/refinedstorage/gui/GuiFluidDestructor.java @@ -0,0 +1,40 @@ +package refinedstorage.gui; + +import refinedstorage.api.storage.CompareUtils; +import refinedstorage.container.ContainerFluidDestructor; +import refinedstorage.gui.sidebutton.SideButtonCompare; +import refinedstorage.gui.sidebutton.SideButtonMode; +import refinedstorage.gui.sidebutton.SideButtonRedstoneMode; +import refinedstorage.tile.TileFluidDestructor; + +public class GuiFluidDestructor extends GuiBase { + public GuiFluidDestructor(ContainerFluidDestructor container) { + super(container, 211, 137); + } + + @Override + public void init(int x, int y) { + addSideButton(new SideButtonRedstoneMode(TileFluidDestructor.REDSTONE_MODE)); + + addSideButton(new SideButtonMode(TileFluidDestructor.MODE)); + + addSideButton(new SideButtonCompare(TileFluidDestructor.COMPARE, CompareUtils.COMPARE_NBT)); + } + + @Override + public void update(int x, int y) { + } + + @Override + public void drawBackground(int x, int y, int mouseX, int mouseY) { + bindTexture("gui/destructor.png"); + + drawTexture(x, y, 0, 0, width, height); + } + + @Override + public void drawForeground(int mouseX, int mouseY) { + drawString(7, 7, t("gui.refinedstorage:fluid_destructor")); + drawString(7, 43, t("container.inventory")); + } +} diff --git a/src/main/java/refinedstorage/gui/GuiHandler.java b/src/main/java/refinedstorage/gui/GuiHandler.java index 425c3f11f..a2f5c02e5 100755 --- a/src/main/java/refinedstorage/gui/GuiHandler.java +++ b/src/main/java/refinedstorage/gui/GuiHandler.java @@ -55,6 +55,8 @@ public class GuiHandler implements IGuiHandler { return new ContainerFluidDiskDrive((TileFluidDiskDrive) tile, player); case RefinedStorageGui.FLUID_CONSTRUCTOR: return new ContainerFluidConstructor((TileFluidConstructor) tile, player); + case RefinedStorageGui.FLUID_DESTRUCTOR: + return new ContainerFluidDestructor((TileFluidDestructor) tile, player); default: return null; } @@ -130,6 +132,8 @@ public class GuiHandler implements IGuiHandler { return new GuiStorage((ContainerFluidDiskDrive) getContainer(ID, player, tile), (IStorageGui) tile, "gui/disk_drive.png"); case RefinedStorageGui.FLUID_CONSTRUCTOR: return new GuiFluidConstructor((ContainerFluidConstructor) getContainer(ID, player, tile)); + case RefinedStorageGui.FLUID_DESTRUCTOR: + return new GuiFluidDestructor((ContainerFluidDestructor) getContainer(ID, player, tile)); default: return null; } diff --git a/src/main/java/refinedstorage/proxy/ClientProxy.java b/src/main/java/refinedstorage/proxy/ClientProxy.java index 3fcb573fa..73c4f6a07 100755 --- a/src/main/java/refinedstorage/proxy/ClientProxy.java +++ b/src/main/java/refinedstorage/proxy/ClientProxy.java @@ -259,5 +259,6 @@ public class ClientProxy extends CommonProxy { ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(RefinedStorageBlocks.STORAGE), EnumItemStorageType.TYPE_CREATIVE.getId(), new ModelResourceLocation("refinedstorage:storage", "type=creative")); ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(RefinedStorageBlocks.FLUID_DISK_DRIVE), 0, new ModelResourceLocation("refinedstorage:disk_drive", "inventory")); ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(RefinedStorageBlocks.FLUID_CONSTRUCTOR), 0, new ModelResourceLocation("refinedstorage:fluid_constructor", "inventory")); + ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(RefinedStorageBlocks.FLUID_DESTRUCTOR), 0, new ModelResourceLocation("refinedstorage:fluid_destructor", "inventory")); } } diff --git a/src/main/java/refinedstorage/proxy/CommonProxy.java b/src/main/java/refinedstorage/proxy/CommonProxy.java index 8e81028df..c8da6af95 100755 --- a/src/main/java/refinedstorage/proxy/CommonProxy.java +++ b/src/main/java/refinedstorage/proxy/CommonProxy.java @@ -87,6 +87,7 @@ public class CommonProxy { registerTile(TileNetworkTransmitter.class, "network_transmitter"); registerTile(TileFluidDiskDrive.class, "fluid_disk_drive"); registerTile(TileFluidConstructor.class, "fluid_constructor"); + registerTile(TileFluidDestructor.class, "fluid_destructor"); registerBlock(RefinedStorageBlocks.CONTROLLER); registerBlock(RefinedStorageBlocks.GRID); @@ -111,6 +112,7 @@ public class CommonProxy { registerBlock(RefinedStorageBlocks.NETWORK_RECEIVER); registerBlock(RefinedStorageBlocks.FLUID_DISK_DRIVE); registerBlock(RefinedStorageBlocks.FLUID_CONSTRUCTOR); + registerBlock(RefinedStorageBlocks.FLUID_DESTRUCTOR); registerItem(RefinedStorageItems.QUARTZ_ENRICHED_IRON); registerItem(RefinedStorageItems.STORAGE_DISK); @@ -348,6 +350,18 @@ public class CommonProxy { 'I', new ItemStack(RefinedStorageItems.PROCESSOR, 1, ItemProcessor.TYPE_IMPROVED) ); + // Fluid Destructor + GameRegistry.addShapedRecipe(new ItemStack(RefinedStorageBlocks.DESTRUCTOR), + "EDE", + "RMR", + "EIE", + 'E', new ItemStack(RefinedStorageItems.QUARTZ_ENRICHED_IRON), + 'D', new ItemStack(RefinedStorageItems.CORE, 1, ItemCore.TYPE_DESTRUCTION), + 'R', new ItemStack(Items.BUCKET), + 'M', new ItemStack(RefinedStorageBlocks.CABLE), + 'I', new ItemStack(RefinedStorageItems.PROCESSOR, 1, ItemProcessor.TYPE_IMPROVED) + ); + // Constructor GameRegistry.addShapedRecipe(new ItemStack(RefinedStorageBlocks.CONSTRUCTOR), "ECE", diff --git a/src/main/java/refinedstorage/tile/TileFluidDestructor.java b/src/main/java/refinedstorage/tile/TileFluidDestructor.java new file mode 100755 index 000000000..e39fb7547 --- /dev/null +++ b/src/main/java/refinedstorage/tile/TileFluidDestructor.java @@ -0,0 +1,162 @@ +package refinedstorage.tile; + +import mcmultipart.microblock.IMicroblock; +import net.minecraft.block.Block; +import net.minecraft.block.BlockLiquid; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidBlock; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.wrappers.BlockLiquidWrapper; +import net.minecraftforge.fluids.capability.wrappers.FluidBlockWrapper; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import refinedstorage.RefinedStorage; +import refinedstorage.inventory.ItemHandlerFluid; +import refinedstorage.inventory.ItemHandlerUpgrade; +import refinedstorage.item.ItemUpgrade; +import refinedstorage.tile.config.IComparable; +import refinedstorage.tile.config.IFilterable; +import refinedstorage.tile.data.TileDataParameter; + +public class TileFluidDestructor extends TileMultipartNode implements IComparable, IFilterable { + public static final TileDataParameter COMPARE = IComparable.createParameter(); + public static final TileDataParameter MODE = IFilterable.createParameter(); + + private static final String NBT_COMPARE = "Compare"; + private static final String NBT_MODE = "Mode"; + + private static final int BASE_SPEED = 20; + + private ItemHandlerFluid filters = new ItemHandlerFluid(9, this); + private ItemHandlerUpgrade upgrades = new ItemHandlerUpgrade(4, this, ItemUpgrade.TYPE_SPEED); + + private int compare = 0; + private int mode = IFilterable.WHITELIST; + + public TileFluidDestructor() { + dataManager.addWatchedParameter(COMPARE); + dataManager.addWatchedParameter(MODE); + } + + @Override + public boolean canAddMicroblock(IMicroblock microblock) { + return !isBlockingMicroblock(microblock, getDirection()); + } + + @Override + public int getEnergyUsage() { + return RefinedStorage.INSTANCE.fluidDestructorUsage + upgrades.getEnergyUsage(); + } + + @Override + public void updateNode() { + if (ticks % upgrades.getSpeed(BASE_SPEED, 4) == 0) { + BlockPos front = pos.offset(getDirection()); + + Block frontBlock = worldObj.getBlockState(front).getBlock(); + + IFluidHandler handler = null; + + if (frontBlock instanceof BlockLiquid) { + handler = new BlockLiquidWrapper((BlockLiquid) frontBlock, worldObj, front); + } else if (frontBlock instanceof IFluidBlock) { + handler = new FluidBlockWrapper((IFluidBlock) frontBlock, worldObj, front); + } + + if (handler != null) { + FluidStack stack = handler.drain(Fluid.BUCKET_VOLUME, false); + + if (IFilterable.canTakeFluids(filters, mode, compare, stack) && network.insertFluid(stack, stack.amount, true) == null) { + FluidStack drained = handler.drain(Fluid.BUCKET_VOLUME, true); + + network.insertFluid(drained, drained.amount, false); + } + } + } + } + + @Override + public int getCompare() { + return compare; + } + + @Override + public void setCompare(int compare) { + this.compare = compare; + + markDirty(); + } + + @Override + public int getMode() { + return mode; + } + + @Override + public void setMode(int mode) { + this.mode = mode; + + markDirty(); + } + + @Override + public void read(NBTTagCompound tag) { + super.read(tag); + + if (tag.hasKey(NBT_COMPARE)) { + compare = tag.getInteger(NBT_COMPARE); + } + + if (tag.hasKey(NBT_MODE)) { + mode = tag.getInteger(NBT_MODE); + } + + readItems(filters, 0, tag); + readItems(upgrades, 1, tag); + } + + @Override + public NBTTagCompound write(NBTTagCompound tag) { + super.write(tag); + + tag.setInteger(NBT_COMPARE, compare); + tag.setInteger(NBT_MODE, mode); + + writeItems(filters, 0, tag); + writeItems(upgrades, 1, tag); + + return tag; + } + + public IItemHandler getUpgrades() { + return upgrades; + } + + public IItemHandler getInventory() { + return filters; + } + + @Override + public IItemHandler getDrops() { + return upgrades; + } + + @Override + public T getCapability(Capability capability, EnumFacing facing) { + if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { + return (T) upgrades; + } + + return super.getCapability(capability, facing); + } + + @Override + public boolean hasCapability(Capability capability, EnumFacing facing) { + return capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY || super.hasCapability(capability, facing); + } +} diff --git a/src/main/resources/assets/refinedstorage/blockstates/fluid_destructor.json b/src/main/resources/assets/refinedstorage/blockstates/fluid_destructor.json new file mode 100755 index 000000000..77d6c66b5 --- /dev/null +++ b/src/main/resources/assets/refinedstorage/blockstates/fluid_destructor.json @@ -0,0 +1,83 @@ +{ + "forge_marker": 1, + "defaults": { + "textures": { + "all": "refinedstorage:blocks/cable", + "particle": "refinedstorage:blocks/cable", + "front": "refinedstorage:blocks/fluid_destructor", + "line": "refinedstorage:blocks/cable_part" + }, + "model": "refinedstorage:cable_core", + "uvlock": true + }, + "variants": { + "inventory": [ + { + "model": "refinedstorage:constructor_destructor", + "transform": "forge:default-block" + } + ], + "direction": { + "north": { + "submodel": "refinedstorage:constructor_destructor_north" + }, + "east": { + "submodel": "refinedstorage:constructor_destructor_east" + }, + "south": { + "submodel": "refinedstorage:constructor_destructor_south" + }, + "west": { + "submodel": "refinedstorage:constructor_destructor_west" + }, + "up": { + "submodel": "refinedstorage:constructor_destructor_up" + }, + "down": { + "submodel": "refinedstorage:constructor_destructor_down" + } + }, + "north": { + "true": { + "submodel": "refinedstorage:cable_north" + }, + "false": { + } + }, + "east": { + "true": { + "submodel": "refinedstorage:cable_east" + }, + "false": { + } + }, + "south": { + "true": { + "submodel": "refinedstorage:cable_south" + }, + "false": { + } + }, + "west": { + "true": { + "submodel": "refinedstorage:cable_west" + }, + "false": { + } + }, + "up": { + "true": { + "submodel": "refinedstorage:cable_up" + }, + "false": { + } + }, + "down": { + "true": { + "submodel": "refinedstorage:cable_down" + }, + "false": { + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/refinedstorage/lang/en_US.lang b/src/main/resources/assets/refinedstorage/lang/en_US.lang index f60cf3519..0f4806dcd 100755 --- a/src/main/resources/assets/refinedstorage/lang/en_US.lang +++ b/src/main/resources/assets/refinedstorage/lang/en_US.lang @@ -41,6 +41,7 @@ gui.refinedstorage:network_transmitter.missing_card=Missing Network Card gui.refinedstorage:network_transmitter.missing_upgrade=Insert upgrade gui.refinedstorage:fluid_disk_drive=Fluid Disk Drive gui.refinedstorage:fluid_constructor=Fluid Constructor +gui.refinedstorage:fluid_destructor=Fluid Destructor misc.refinedstorage:energy_stored=%d / %d RS misc.refinedstorage:energy_usage=Usage: %d RS/t @@ -130,6 +131,7 @@ block.refinedstorage:network_receiver.name=Network Receiver block.refinedstorage:network_transmitter.name=Network Transmitter block.refinedstorage:fluid_disk_drive.name=Fluid Disk Drive block.refinedstorage:fluid_constructor.name=Fluid Constructor +block.refinedstorage:fluid_destructor.name=Fluid Destructor item.refinedstorage:storage_disk.0.name=1k Storage Disk item.refinedstorage:storage_disk.1.name=4k Storage Disk diff --git a/src/main/resources/assets/refinedstorage/textures/blocks/controller_7.png b/src/main/resources/assets/refinedstorage/textures/blocks/controller_7.png index 203a34401fdcbaa7de1c4a5bdc193114cef155dc..e4b82d6e0e276c0ac2cb2b5a4bda7f7015f6e5d7 100755 GIT binary patch delta 35 rcmbQoHlJ;R4c`F<2EGG~S=Tx_85kHOCwfV<85*qR;ySP~YYP(qwXq6K delta 34 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