From fef10740baf336fda32a84717e0a89340083bbb3 Mon Sep 17 00:00:00 2001 From: drcrazy Date: Thu, 12 Apr 2018 15:42:12 +0300 Subject: [PATCH] Feature/fluidreplicator (#1482) Added Fluid Replicator multiblock machine. --- src/main/java/techreborn/api/Reference.java | 1 + .../FluidReplicatorRecipe.java | 139 ++++++++++++ .../FluidReplicatorRecipeCrafter.java | 204 ++++++++++++++++++ .../FluidReplicatorRecipeList.java | 78 +++++++ .../BlockFluidReplicator.java} | 39 ++-- src/main/java/techreborn/client/EGui.java | 3 +- .../java/techreborn/client/GuiHandler.java | 2 + .../client/gui/GuiFluidReplicator.java | 148 +++++++++++++ .../compat/crafttweaker/RecipeSettings.java | 24 +++ .../compat/crafttweaker/ZenDocumentation.java | 24 +++ .../compat/jei/RecipeCategoryUids.java | 1 + .../compat/jei/TechRebornJeiPlugin.java | 119 +++++----- .../FluidReplicatorRecipeCategory.java | 90 ++++++++ .../FluidReplicatorRecipeWrapper.java | 73 +++++++ .../jei/grinder/GrinderRecipeCategory.java | 8 +- .../RecipeThermalExpansion.java | 5 + src/main/java/techreborn/init/ModBlocks.java | 5 + src/main/java/techreborn/init/ModRecipes.java | 34 +-- src/main/java/techreborn/init/OreDict.java | 2 +- .../init/recipes/CraftingTableRecipes.java | 37 ++-- .../init/recipes/FluidReplicatorRecipes.java | 56 +++++ .../techreborn/tiles/TileGenericMachine.java | 4 +- .../tiles/multiblock/TileFluidReplicator.java | 165 ++++++++++++++ .../tier3_machines/fluid_replicator.json | 49 +++++ .../assets/techreborn/lang/en_us.lang | 1 + .../fluid_replicator_front_off.png} | Bin .../fluid_replicator_front_on.png | Bin 0 -> 1068 bytes .../fluid_replicator_front_on.png.mcmeta | 12 ++ .../assets/techreborn/textures/gui/jei.png | Bin 2282 -> 2748 bytes 29 files changed, 1202 insertions(+), 121 deletions(-) create mode 100644 src/main/java/techreborn/api/fluidreplicator/FluidReplicatorRecipe.java create mode 100644 src/main/java/techreborn/api/fluidreplicator/FluidReplicatorRecipeCrafter.java create mode 100644 src/main/java/techreborn/api/fluidreplicator/FluidReplicatorRecipeList.java rename src/main/java/techreborn/blocks/{BlockPump.java => advanced_machine/BlockFluidReplicator.java} (66%) create mode 100644 src/main/java/techreborn/client/gui/GuiFluidReplicator.java create mode 100644 src/main/java/techreborn/compat/jei/fluidReplicator/FluidReplicatorRecipeCategory.java create mode 100644 src/main/java/techreborn/compat/jei/fluidReplicator/FluidReplicatorRecipeWrapper.java create mode 100644 src/main/java/techreborn/init/recipes/FluidReplicatorRecipes.java create mode 100644 src/main/java/techreborn/tiles/multiblock/TileFluidReplicator.java create mode 100644 src/main/resources/assets/techreborn/blockstates/machines/tier3_machines/fluid_replicator.json rename src/main/resources/assets/techreborn/textures/blocks/machines/{tier1_machines/pump_side.png => tier3_machines/fluid_replicator_front_off.png} (100%) create mode 100644 src/main/resources/assets/techreborn/textures/blocks/machines/tier3_machines/fluid_replicator_front_on.png create mode 100644 src/main/resources/assets/techreborn/textures/blocks/machines/tier3_machines/fluid_replicator_front_on.png.mcmeta diff --git a/src/main/java/techreborn/api/Reference.java b/src/main/java/techreborn/api/Reference.java index b8dd05293..5a7a0c480 100644 --- a/src/main/java/techreborn/api/Reference.java +++ b/src/main/java/techreborn/api/Reference.java @@ -68,4 +68,5 @@ public class Reference { public static String RECYCLER_RECIPE = "RECYCLER_RECIPE"; public static String SCRAPBOX_RECIPE = "SCRAPBOX_RECIPE"; public static String VACUUM_FREEZER_RECIPE = "VACUUM_FREEZER_RECIPE"; + public static String FLUID_REPLICATOR_RECIPE = "FLUID_REPLICATOR_RECIPE"; } diff --git a/src/main/java/techreborn/api/fluidreplicator/FluidReplicatorRecipe.java b/src/main/java/techreborn/api/fluidreplicator/FluidReplicatorRecipe.java new file mode 100644 index 000000000..afdc17f67 --- /dev/null +++ b/src/main/java/techreborn/api/fluidreplicator/FluidReplicatorRecipe.java @@ -0,0 +1,139 @@ +/* + * This file is part of TechReborn, licensed under the MIT License (MIT). + * + * Copyright (c) 2018 TechReborn + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package techreborn.api.fluidreplicator; + +import java.util.ArrayList; +import java.util.List; + +import javax.annotation.Nonnull; + +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; +import techreborn.init.ModItems; +import techreborn.tiles.multiblock.TileFluidReplicator; + +/** + * @author drcrazy + * + */ +public class FluidReplicatorRecipe implements Cloneable { + + /** + * This is the UU matter amount that is required as input + *

+ * This cannot be null + */ + @Nonnull + private final int input; + + /** + * This is the fluid we will produce + *

+ * This cannot be null + */ + @Nonnull + private final Fluid output; + + /** + * This is the time in ticks that the recipe takes to complete + */ + private final int tickTime; + + /** + * This is the EU that charges every tick to replicate fluid. + */ + private final int euPerTick; + + /** + * @param input int Amount of UU-matter per bucket + * @param output Fluid Fluid to replicate + * @param tickTime int Production time for recipe + * @param euPerTick int EU amount per tick + */ + public FluidReplicatorRecipe(int input, Fluid output, int tickTime, int euPerTick) { + this.input = input; + this.output = output; + this.tickTime = tickTime; + this.euPerTick = euPerTick; + } + + public int getInput() { + return input; + } + + public Fluid getFluid() { + return output; + } + + public int getTickTime() { + return tickTime; + } + + public int getEuTick() { + return euPerTick; + } + + public List getInputs() { + ArrayList inputs = new ArrayList<>(); + inputs.add(new ItemStack(ModItems.UU_MATTER, input)); + return inputs; + } + + public boolean useOreDic() { + return false; + } + + public boolean canCraft(TileFluidReplicator tile) { + if (!tile.getMultiBlock()) { + return false; + } + final BlockPos hole = tile.getPos().offset(tile.getFacing().getOpposite(), 2); + final Fluid fluid = FluidRegistry.lookupFluidForBlock(tile.getWorld().getBlockState(hole).getBlock()); + if (fluid == null) { + return false; + } + if (!fluid.equals(output)) { + return false; + } + final Fluid tankFluid = tile.tank.getFluidType(); + if (tankFluid != null && !tankFluid.equals(output)) { + return false; + } + + return true; + } + + public boolean onCraft(TileFluidReplicator tile) { + return true; + } + + // Cloneable + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } +} diff --git a/src/main/java/techreborn/api/fluidreplicator/FluidReplicatorRecipeCrafter.java b/src/main/java/techreborn/api/fluidreplicator/FluidReplicatorRecipeCrafter.java new file mode 100644 index 000000000..94de47214 --- /dev/null +++ b/src/main/java/techreborn/api/fluidreplicator/FluidReplicatorRecipeCrafter.java @@ -0,0 +1,204 @@ +/* + * This file is part of TechReborn, licensed under the MIT License (MIT). + * + * Copyright (c) 2018 TechReborn + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package techreborn.api.fluidreplicator; + +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; +import reborncore.common.recipes.RecipeCrafter; +import reborncore.common.util.Inventory; +import reborncore.common.util.Tank; +import techreborn.api.Reference; +import techreborn.init.ModItems; +import techreborn.tiles.multiblock.TileFluidReplicator; + +/** + * @author drcrazy + * + */ +public class FluidReplicatorRecipeCrafter extends RecipeCrafter { + + public FluidReplicatorRecipe currentRecipe; + int ticksSinceLastChange; + + /** + * RecipeCrafter for Fluid Replicator + * + * @param parentTile TileEntity Reference to the tile having this crafter + * @param inventory Inventory reference to inventory used for crafting + * @param inputSlots This is the list of the slots that the crafting logic should look for the input UU-Matter. + * @param outputSlots This is the list of slots that the crafting logic should look for output fluid + */ + public FluidReplicatorRecipeCrafter(TileEntity parentTile, Inventory inventory, int[] inputSlots, int[] outputSlots) { + super(Reference.FLUID_REPLICATOR_RECIPE, parentTile, 1, 1, inventory, inputSlots, outputSlots); + } + + /** + * FluidReplicatorRecipe version of hasAllInputs + */ + private boolean hasAllInputs(FluidReplicatorRecipe recipe) { + if (recipe == null) { + return false; + } + ItemStack inputStack = inventory.getStackInSlot(inputSlots[0]); + if (!inputStack.isItemEqual(new ItemStack(ModItems.UU_MATTER))) { + return false; + } + if (inputStack.getCount() < recipe.getInput()) { + return false; + } + + return true; + } + + private boolean canFit(Fluid fluid, Tank tank) { + if (tank.fill(new FluidStack(fluid, Fluid.BUCKET_VOLUME), false) != Fluid.BUCKET_VOLUME) { + return false; + } + return true; + } + + public void setCurrentRecipe(FluidReplicatorRecipe recipe) { + try { + this.currentRecipe = (FluidReplicatorRecipe) recipe.clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + } + + // RecipeCrafter + @Override + public void updateEntity() { + if (parentTile.getWorld().isRemote) { + return; + } + ticksSinceLastChange++; + // Force a has changed every second + if (ticksSinceLastChange >= 20) { + setInvDirty(true); + ticksSinceLastChange = 0; + } + // It will now look for new recipes. + if (currentRecipe == null && isInvDirty()) { + updateCurrentRecipe(); + } + if(currentRecipe != null) { + // If it doesn't have all the inputs reset + if (isInvDirty() && !hasAllInputs()) { + currentRecipe = null; + currentTickTime = 0; + setIsActive(); + } + // If it has reached the recipe tick time + if (currentRecipe != null && currentTickTime >= currentNeededTicks && hasAllInputs()) { + TileFluidReplicator tileFluidReplicator = (TileFluidReplicator) parentTile; + // Checks to see if it can fit the output + // And fill tank with replicated fluid + if (canFit(currentRecipe.getFluid(), tileFluidReplicator.tank) && currentRecipe.onCraft(tileFluidReplicator)) { + tileFluidReplicator.tank.fill(new FluidStack(currentRecipe.getFluid(), Fluid.BUCKET_VOLUME), true); + // This uses all the inputs + useAllInputs(); + // Reset + currentRecipe = null; + currentTickTime = 0; + updateCurrentRecipe(); + //Update active state if the tile isnt going to start crafting again + if(currentRecipe == null){ + setIsActive(); + } + } + } else if (currentRecipe != null && currentTickTime < currentNeededTicks) { + // This uses the power + if (energy.canUseEnergy(getEuPerTick(currentRecipe.getEuTick()))) { + energy.useEnergy(getEuPerTick(currentRecipe.getEuTick())); + // Increase the ticktime + currentTickTime ++; + if(currentTickTime == 1 || currentTickTime % 20 == 0 && soundHanlder != null){ + soundHanlder.playSound(false, parentTile); + } + } + } + } + setInvDirty(false); + } + + @Override + public void updateCurrentRecipe() { + TileFluidReplicator tileFluidReplicator = (TileFluidReplicator) parentTile; + for (FluidReplicatorRecipe recipe : FluidReplicatorRecipeList.recipes) { + if (recipe.canCraft(tileFluidReplicator) && hasAllInputs(recipe)) { + if (!canFit(recipe.getFluid(), tileFluidReplicator.tank)) { + this.currentRecipe = null; + currentTickTime = 0; + setIsActive(); + return; + } + setCurrentRecipe(recipe); + currentNeededTicks = Math.max((int) (currentRecipe.getTickTime()* (1.0 - getSpeedMultiplier())), 1); + currentTickTime = 0; + setIsActive(); + return; + } + } + } + + @Override + public boolean hasAllInputs() { + if (this.currentRecipe == null) { + return false; + } + else { + return hasAllInputs(this.currentRecipe); + } + } + + @Override + public void useAllInputs() { + if (currentRecipe == null) { + return; + } + if (hasAllInputs(currentRecipe)) { + inventory.decrStackSize(inputSlots[0], currentRecipe.getInput()); + } + } + + @Override + public boolean canCraftAgain() { + TileFluidReplicator tileFluidReplicator = (TileFluidReplicator) parentTile; + for (FluidReplicatorRecipe recipe : FluidReplicatorRecipeList.recipes) { + if (recipe.canCraft(tileFluidReplicator) && hasAllInputs(recipe)) { + if (!canFit(recipe.getFluid(), tileFluidReplicator.tank)) { + return false; + } + if (energy.getEnergy() < recipe.getEuTick()) { + return false; + } + return true; + } + } + return false; + } +} \ No newline at end of file diff --git a/src/main/java/techreborn/api/fluidreplicator/FluidReplicatorRecipeList.java b/src/main/java/techreborn/api/fluidreplicator/FluidReplicatorRecipeList.java new file mode 100644 index 000000000..33f03fba1 --- /dev/null +++ b/src/main/java/techreborn/api/fluidreplicator/FluidReplicatorRecipeList.java @@ -0,0 +1,78 @@ +/* + * This file is part of TechReborn, licensed under the MIT License (MIT). + * + * Copyright (c) 2018 TechReborn + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package techreborn.api.fluidreplicator; + +import java.util.ArrayList; +import java.util.Optional; + +import org.apache.commons.lang3.Validate; + +import net.minecraftforge.fluids.Fluid; + +/** + * @author drcrazy + * + */ +public class FluidReplicatorRecipeList { + + /** + * This is the list of all the recipes + */ + public static ArrayList recipes = new ArrayList<>(); + + /** + * Register your Fluid Replicator recipe + * + * @param recipe FluidReplicatorRecipe The recipe you want to add + */ + public static void addRecipe(FluidReplicatorRecipe recipe) { + Validate.notNull(recipe); + Validate.isTrue(!recipes.contains(recipe)); + Validate.validState(recipe.getInput() >= 1); + Validate.validState(!getRecipeForFluid(recipe.getFluid()).isPresent()); + + recipes.add(recipe); + } + + /** + * Fluid Replicator recipe you want to remove + * + * @param recipe FluidReplicatorRecipe Recipe to remove + * @return boolean true if recipe was removed from list of recipes + */ + public static boolean removeRecipe(FluidReplicatorRecipe recipe) { + return recipes.remove(recipe); + } + + /** + * Check if there is a Fluid Replicator recipe for that fluid + * + * @param fluid Fluid Fluid to search for + * @return FluidReplicatorRecipe Recipe for fluid provided + */ + public static Optional getRecipeForFluid(Fluid fluid) { + return recipes.stream().filter(recipe -> recipe.getFluid().equals(fluid)).findAny(); + } +} \ No newline at end of file diff --git a/src/main/java/techreborn/blocks/BlockPump.java b/src/main/java/techreborn/blocks/advanced_machine/BlockFluidReplicator.java similarity index 66% rename from src/main/java/techreborn/blocks/BlockPump.java rename to src/main/java/techreborn/blocks/advanced_machine/BlockFluidReplicator.java index 0a4fab186..764f7d0f7 100644 --- a/src/main/java/techreborn/blocks/BlockPump.java +++ b/src/main/java/techreborn/blocks/advanced_machine/BlockFluidReplicator.java @@ -22,28 +22,39 @@ * SOFTWARE. */ -package techreborn.blocks; +package techreborn.blocks.advanced_machine; -import net.minecraft.block.material.Material; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; -import reborncore.common.BaseTileBlock; +import prospector.shootingstar.ShootingStar; +import prospector.shootingstar.model.ModelCompound; +import reborncore.api.tile.IMachineGuiHandler; +import reborncore.common.blocks.BlockMachineBase; +import techreborn.client.EGui; import techreborn.client.TechRebornCreativeTab; -import techreborn.tiles.TilePump; +import techreborn.lib.ModInfo; +import techreborn.tiles.multiblock.TileFluidReplicator; -/** - * Created by modmuss50 on 08/05/2016. - */ -public class BlockPump extends BaseTileBlock { - public BlockPump() { - super(Material.IRON); - setHardness(2f); - setUnlocalizedName("techreborn.pump"); +public class BlockFluidReplicator extends BlockMachineBase { + + public BlockFluidReplicator() { + super(); setCreativeTab(TechRebornCreativeTab.instance); + ShootingStar.registerModel(new ModelCompound(ModInfo.MOD_ID, this, "machines/tier3_machines")); } @Override public TileEntity createNewTileEntity(World worldIn, int meta) { - return new TilePump(); + return new TileFluidReplicator(); } -} + + @Override + public IMachineGuiHandler getGui() { + return EGui.FLUID_REPLICATOR; + } + + @Override + public boolean isAdvanced() { + return true; + } +} \ No newline at end of file diff --git a/src/main/java/techreborn/client/EGui.java b/src/main/java/techreborn/client/EGui.java index aa2a717ad..1922d1a02 100644 --- a/src/main/java/techreborn/client/EGui.java +++ b/src/main/java/techreborn/client/EGui.java @@ -73,7 +73,8 @@ public enum EGui implements IMachineGuiHandler { SCRAPBOXINATOR(true), SEMIFLUID_GENERATOR(true), THERMAL_GENERATOR(true), - VACUUM_FREEZER(true); + VACUUM_FREEZER(true), + FLUID_REPLICATOR(true); private final boolean containerBuilder; diff --git a/src/main/java/techreborn/client/GuiHandler.java b/src/main/java/techreborn/client/GuiHandler.java index 132367f90..21174ea77 100644 --- a/src/main/java/techreborn/client/GuiHandler.java +++ b/src/main/java/techreborn/client/GuiHandler.java @@ -158,6 +158,8 @@ public class GuiHandler implements IGuiHandler { return new GuiDistillationTower(player, (TileDistillationTower) tile); case MANUAL: return new GuiManual(player); + case FLUID_REPLICATOR: + return new GuiFluidReplicator(player, (TileFluidReplicator) tile); default: break; diff --git a/src/main/java/techreborn/client/gui/GuiFluidReplicator.java b/src/main/java/techreborn/client/gui/GuiFluidReplicator.java new file mode 100644 index 000000000..a751c3a22 --- /dev/null +++ b/src/main/java/techreborn/client/gui/GuiFluidReplicator.java @@ -0,0 +1,148 @@ +/* + * This file is part of TechReborn, licensed under the MIT License (MIT). + * + * Copyright (c) 2018 TechReborn + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package techreborn.client.gui; + +import java.io.IOException; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import reborncore.client.multiblock.Multiblock; +import reborncore.client.multiblock.MultiblockRenderEvent; +import reborncore.client.multiblock.MultiblockSet; +import techreborn.blocks.BlockMachineCasing; +import techreborn.client.gui.widget.GuiButtonHologram; +import techreborn.init.ModBlocks; +import techreborn.proxies.ClientProxy; +import techreborn.tiles.multiblock.TileFluidReplicator; + +/** + * @author drcrazy + * + */ +public class GuiFluidReplicator extends GuiBase { + + TileFluidReplicator tile; + + public GuiFluidReplicator(final EntityPlayer player, final TileFluidReplicator tile) { + super(player, tile, tile.createContainer(player)); + this.tile = tile; + } + + public void addHologramButton(int x, int y, int id, Layer layer) { + if (id == 0) + buttonList.clear(); + int factorX = 0; + int factorY = 0; + if (layer == Layer.BACKGROUND) { + factorX = guiLeft; + factorY = guiTop; + } + buttonList.add(new GuiButtonHologram(id, x + factorX, y + factorY, this, layer)); + } + + public void addComponent(final int x, final int y, final int z, final IBlockState blockState, final Multiblock multiblock) { + multiblock.addComponent(new BlockPos(x, y, z), blockState); + } + + // GuiBase + @Override + public void initGui() { + super.initGui(); + ClientProxy.multiblockRenderEvent.setMultiblock(null); + } + + @Override + protected void drawGuiContainerBackgroundLayer(final float f, final int mouseX, final int mouseY) { + super.drawGuiContainerBackgroundLayer(f, mouseX, mouseY); + final GuiBase.Layer layer = GuiBase.Layer.BACKGROUND; + // Battery slot + drawSlot(8, 72, layer); + // Input slot + drawSlot(55, 45, layer); + // Liquid input slot + drawSlot(124, 35, layer); + // Liquid output slot + drawSlot(124, 55, layer); + // JEI button + builder.drawJEIButton(this, 150, 4, layer); + } + + @Override + protected void drawGuiContainerForegroundLayer(final int mouseX, final int mouseY) { + super.drawGuiContainerForegroundLayer(mouseX, mouseY); + final GuiBase.Layer layer = GuiBase.Layer.FOREGROUND; + + builder.drawMultiEnergyBar(this, 9, 19, (int) tile.getEnergy(), (int) tile.getMaxPower(), mouseX, mouseY, 0, layer); + builder.drawTank(this, 99, 25, mouseX, mouseY, tile.tank.getFluid(), tile.tank.getCapacity(), tile.tank.isEmpty(), layer); + builder.drawProgressBar(this, tile.getProgressScaled(100), 100, 76, 48, mouseX, mouseY, TRBuilder.ProgressDirection.RIGHT, layer); + if (tile.getMultiBlock()) { + addHologramButton(6, 4, 212, layer); + builder.drawHologramButton(this, 6, 4, mouseX, mouseY, layer); + } else { + builder.drawMultiblockMissingBar(this, layer); + addHologramButton(76, 56, 212, layer); + builder.drawHologramButton(this, 76, 56, mouseX, mouseY, layer); + } + } + + // GuiScreen + @Override + public void actionPerformed(final GuiButton button) throws IOException { + super.actionPerformed(button); + if (button.id == 212 && !GuiBase.showSlotConfig) { + if (ClientProxy.multiblockRenderEvent.currentMultiblock == null) { + { + // This code here makes a basic multiblock and then sets to the selected one. + final Multiblock multiblock = new Multiblock(); + final IBlockState reinforcedCasing = ModBlocks.MACHINE_CASINGS.getDefaultState() + .withProperty(BlockMachineCasing.TYPE, "reinforced"); + + addComponent(1, 0, 0, reinforcedCasing, multiblock); + addComponent(0, 0, 1, reinforcedCasing, multiblock); + addComponent(-1, 0, 0, reinforcedCasing, multiblock); + addComponent(0, 0, -1, reinforcedCasing, multiblock); + addComponent(-1, 0, -1, reinforcedCasing, multiblock); + addComponent(-1, 0, 1, reinforcedCasing, multiblock); + addComponent(1, 0, -1, reinforcedCasing, multiblock); + addComponent(1, 0, 1, reinforcedCasing, multiblock); + + final MultiblockSet set = new MultiblockSet(multiblock); + ClientProxy.multiblockRenderEvent.setMultiblock(set); + ClientProxy.multiblockRenderEvent.parent = tile.getPos(); + MultiblockRenderEvent.anchor = new BlockPos( + this.tile.getPos().getX() + - EnumFacing.getFront(this.tile.getFacingInt()).getFrontOffsetX() * 2, + this.tile.getPos().getY() - 1, this.tile.getPos().getZ() + - EnumFacing.getFront(this.tile.getFacingInt()).getFrontOffsetZ() * 2); + } + } else { + ClientProxy.multiblockRenderEvent.setMultiblock(null); + } + } + } +} diff --git a/src/main/java/techreborn/compat/crafttweaker/RecipeSettings.java b/src/main/java/techreborn/compat/crafttweaker/RecipeSettings.java index d90fb5de6..dcce21c4e 100644 --- a/src/main/java/techreborn/compat/crafttweaker/RecipeSettings.java +++ b/src/main/java/techreborn/compat/crafttweaker/RecipeSettings.java @@ -1,3 +1,27 @@ +/* + * This file is part of TechReborn, licensed under the MIT License (MIT). + * + * Copyright (c) 2018 TechReborn + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + package techreborn.compat.crafttweaker; import stanhebben.zenscript.annotations.ZenClass; diff --git a/src/main/java/techreborn/compat/crafttweaker/ZenDocumentation.java b/src/main/java/techreborn/compat/crafttweaker/ZenDocumentation.java index 721147d5d..4d72f622f 100644 --- a/src/main/java/techreborn/compat/crafttweaker/ZenDocumentation.java +++ b/src/main/java/techreborn/compat/crafttweaker/ZenDocumentation.java @@ -1,3 +1,27 @@ +/* + * This file is part of TechReborn, licensed under the MIT License (MIT). + * + * Copyright (c) 2018 TechReborn + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + package techreborn.compat.crafttweaker; import java.lang.annotation.ElementType; diff --git a/src/main/java/techreborn/compat/jei/RecipeCategoryUids.java b/src/main/java/techreborn/compat/jei/RecipeCategoryUids.java index 528330973..0fe0ebc6b 100644 --- a/src/main/java/techreborn/compat/jei/RecipeCategoryUids.java +++ b/src/main/java/techreborn/compat/jei/RecipeCategoryUids.java @@ -42,6 +42,7 @@ public class RecipeCategoryUids { public static final String SCRAPBOX = "TechReborn.Scrapbox"; public static final String INDUSTRIAL_SAWMILL = "TechReborn.IndustrialSawmill"; public static final String DISTILLATION_TOWER = "TechReborn.DistillationTower"; + public static final String FLUID_REPLICATOR = "TechReborn.FluidReplicator"; private RecipeCategoryUids() { } diff --git a/src/main/java/techreborn/compat/jei/TechRebornJeiPlugin.java b/src/main/java/techreborn/compat/jei/TechRebornJeiPlugin.java index 00834a8dd..2e3df4d18 100644 --- a/src/main/java/techreborn/compat/jei/TechRebornJeiPlugin.java +++ b/src/main/java/techreborn/compat/jei/TechRebornJeiPlugin.java @@ -48,6 +48,8 @@ import net.minecraftforge.fml.relauncher.SideOnly; import org.lwjgl.input.Mouse; import reborncore.api.recipe.RecipeHandler; import techreborn.Core; +import techreborn.api.fluidreplicator.FluidReplicatorRecipe; +import techreborn.api.fluidreplicator.FluidReplicatorRecipeList; import techreborn.api.generator.EFluidGenerator; import techreborn.api.generator.FluidGeneratorRecipe; import techreborn.api.generator.GeneratorRecipeHelper; @@ -75,6 +77,8 @@ import techreborn.compat.jei.distillationTower.DistillationTowerRecipeCategory; import techreborn.compat.jei.distillationTower.DistillationTowerRecipeWrapper; import techreborn.compat.jei.extractor.ExtractorRecipeCategory; import techreborn.compat.jei.extractor.ExtractorRecipeWrapper; +import techreborn.compat.jei.fluidReplicator.FluidReplicatorRecipeCategory; +import techreborn.compat.jei.fluidReplicator.FluidReplicatorRecipeWrapper; import techreborn.compat.jei.fusionReactor.FusionReactorRecipeCategory; import techreborn.compat.jei.fusionReactor.FusionReactorRecipeWrapper; import techreborn.compat.jei.generators.fluid.FluidGeneratorRecipeCategory; @@ -146,41 +150,37 @@ public class TechRebornJeiPlugin implements IModPlugin { final IJeiHelpers jeiHelpers = registry.getJeiHelpers(); final IGuiHelper guiHelper = jeiHelpers.getGuiHelper(); - registry.addRecipeCategories( - new AlloySmelterRecipeCategory(guiHelper), - new AssemblingMachineRecipeCategory(guiHelper), - new BlastFurnaceRecipeCategory(guiHelper), - new CentrifugeRecipeCategory(guiHelper), - new ChemicalReactorRecipeCategory(guiHelper), - new DistillationTowerRecipeCategory(guiHelper), - new FusionReactorRecipeCategory(guiHelper), - new GrinderRecipeCategory(guiHelper), - new ImplosionCompressorRecipeCategory(guiHelper), - new IndustrialGrinderRecipeCategory(guiHelper), - new IndustrialElectrolyzerRecipeCategory(guiHelper), - new IndustrialSawmillRecipeCategory(guiHelper), - new RollingMachineRecipeCategory(guiHelper), - new VacuumFreezerRecipeCategory(guiHelper)); + registry.addRecipeCategories(new AlloySmelterRecipeCategory(guiHelper)); + registry.addRecipeCategories(new AssemblingMachineRecipeCategory(guiHelper)); + registry.addRecipeCategories(new BlastFurnaceRecipeCategory(guiHelper)); + registry.addRecipeCategories(new CentrifugeRecipeCategory(guiHelper)); + registry.addRecipeCategories(new ChemicalReactorRecipeCategory(guiHelper)); + registry.addRecipeCategories(new DistillationTowerRecipeCategory(guiHelper)); + registry.addRecipeCategories(new FusionReactorRecipeCategory(guiHelper)); + registry.addRecipeCategories(new GrinderRecipeCategory(guiHelper)); + registry.addRecipeCategories(new ImplosionCompressorRecipeCategory(guiHelper)); + registry.addRecipeCategories(new IndustrialGrinderRecipeCategory(guiHelper)); + registry.addRecipeCategories(new IndustrialElectrolyzerRecipeCategory(guiHelper)); + registry.addRecipeCategories(new IndustrialSawmillRecipeCategory(guiHelper)); + registry.addRecipeCategories(new RollingMachineRecipeCategory(guiHelper)); + registry.addRecipeCategories(new VacuumFreezerRecipeCategory(guiHelper)); + registry.addRecipeCategories(new FluidReplicatorRecipeCategory(guiHelper)); + + for (final EFluidGenerator type : EFluidGenerator.values()) + registry.addRecipeCategories(new FluidGeneratorRecipeCategory(type, guiHelper)); if (CompatConfigs.showScrapbox) { registry.addRecipeCategories(new ScrapboxRecipeCategory(guiHelper)); } - for (final EFluidGenerator type : EFluidGenerator.values()) - registry.addRecipeCategories(new FluidGeneratorRecipeCategory(type, guiHelper)); - if (!IC2Duplicates.deduplicate()) { - registry.addRecipeCategories( - new CompressorRecipeCategory(guiHelper), - new ExtractorRecipeCategory(guiHelper)); + registry.addRecipeCategories(new CompressorRecipeCategory(guiHelper)); + registry.addRecipeCategories(new ExtractorRecipeCategory(guiHelper)); } } @Override - public void register( - @Nonnull - final - IModRegistry registry) { + public void register(@Nonnull final IModRegistry registry) { final IJeiHelpers jeiHelpers = registry.getJeiHelpers(); jeiHelpers.getIngredientBlacklist().addIngredientToBlacklist(new ItemStack(ModFluids.BLOCK_BERYLLIUM)); @@ -218,6 +218,11 @@ public class TechRebornJeiPlugin implements IModPlugin { jeiHelpers.getIngredientBlacklist().addIngredientToBlacklist(new ItemStack(ModFluids.BLOCK_ELECTROLYZED_WATER)); jeiHelpers.getIngredientBlacklist().addIngredientToBlacklist(new ItemStack(ModFluids.BLOCK_COMPRESSED_AIR)); jeiHelpers.getIngredientBlacklist().addIngredientToBlacklist(new ItemStack(ModItems.MISSING_RECIPE_PLACEHOLDER)); + + if (CompatManager.isQuantumStorageLoaded) { + jeiHelpers.getIngredientBlacklist().addIngredientToBlacklist(new ItemStack(ModBlocks.QUANTUM_CHEST)); + jeiHelpers.getIngredientBlacklist().addIngredientToBlacklist(new ItemStack(ModBlocks.QUANTUM_TANK)); + } if (IC2Duplicates.deduplicate()) { for (final IC2Duplicates duplicate : IC2Duplicates.values()) { @@ -256,8 +261,13 @@ public class TechRebornJeiPlugin implements IModPlugin { registry.handleRecipes(IndustrialSawmillRecipe.class, recipe -> new IndustrialSawmillRecipeWrapper(jeiHelpers, recipe), RecipeCategoryUids.INDUSTRIAL_SAWMILL); registry.handleRecipes(VacuumFreezerRecipe.class, recipe -> new VacuumFreezerRecipeWrapper(jeiHelpers, recipe), RecipeCategoryUids.VACUUM_FREEZER); registry.handleRecipes(DistillationTowerRecipe.class, recipe -> new DistillationTowerRecipeWrapper(jeiHelpers, recipe), RecipeCategoryUids.DISTILLATION_TOWER); + registry.handleRecipes(FluidReplicatorRecipe.class, recipe -> new FluidReplicatorRecipeWrapper(jeiHelpers,recipe), RecipeCategoryUids.FLUID_REPLICATOR); registry.addRecipeHandlers(new RollingMachineRecipeHandler()); + for (final EFluidGenerator type : EFluidGenerator.values()) { + registry.handleRecipes(FluidGeneratorRecipe.class, recipe -> new FluidGeneratorRecipeWrapper(jeiHelpers, recipe), type.getRecipeID()); + } + if (CompatConfigs.showScrapbox) { registry.handleRecipes(ScrapboxRecipe.class, recipe -> new ScrapboxRecipeWrapper(jeiHelpers, recipe), RecipeCategoryUids.SCRAPBOX); } @@ -267,18 +277,15 @@ public class TechRebornJeiPlugin implements IModPlugin { registry.handleRecipes(ExtractorRecipe.class, recipe -> new ExtractorRecipeWrapper(jeiHelpers, recipe), RecipeCategoryUids.EXTRACTOR); } - for (final EFluidGenerator type : EFluidGenerator.values()) { - registry.handleRecipes(FluidGeneratorRecipe.class, recipe -> new FluidGeneratorRecipeWrapper(jeiHelpers, recipe), type.getRecipeID()); - } - registry.addRecipes(RecipeHandler.recipeList.stream().filter(recipe -> { - if(recipe instanceof ScrapboxRecipe){ + if (recipe instanceof ScrapboxRecipe) { return CompatConfigs.showScrapbox; } return true; }).collect(Collectors.toList())); registry.addRecipes(FusionReactorRecipeHelper.reactorRecipes, RecipeCategoryUids.FUSION_REACTOR); + registry.addRecipes(FluidReplicatorRecipeList.recipes, RecipeCategoryUids.FLUID_REPLICATOR); GeneratorRecipeHelper.fluidRecipes.forEach((type, list) -> registry.addRecipes(list.getRecipes(), type.getRecipeID())); try { @@ -324,7 +331,8 @@ public class TechRebornJeiPlugin implements IModPlugin { addRecipeClickArea(GuiScrapboxinator.class, 150, 4, 18, 18, RecipeCategoryUids.SCRAPBOX); addRecipeClickArea(GuiFusionReactor.class, 150, 4, 18, 18, RecipeCategoryUids.FUSION_REACTOR); addRecipeClickArea(GuiRollingMachine.class, 150, 4, 20, 12, RecipeCategoryUids.ROLLING_MACHINE); - + addRecipeClickArea(GuiFluidReplicator.class, 150, 4, 20, 12, RecipeCategoryUids.FLUID_REPLICATOR); + //OLD ONES addRecipeClickArea(GuiAlloyFurnace.class, 80, 35, 26, 20, RecipeCategoryUids.ALLOY_SMELTER, VanillaRecipeCategoryUid.FUEL); @@ -356,6 +364,7 @@ public class TechRebornJeiPlugin implements IModPlugin { registry.addRecipeCatalyst(new ItemStack(ModBlocks.INDUSTRIAL_SAWMILL), RecipeCategoryUids.INDUSTRIAL_SAWMILL); registry.addRecipeCatalyst(new ItemStack(ModBlocks.ROLLING_MACHINE), RecipeCategoryUids.ROLLING_MACHINE); registry.addRecipeCatalyst(new ItemStack(ModBlocks.DISTILLATION_TOWER), RecipeCategoryUids.DISTILLATION_TOWER); + registry.addRecipeCatalyst(new ItemStack(ModBlocks.FLUID_REPLICATOR), RecipeCategoryUids.FLUID_REPLICATOR); if (CompatConfigs.showScrapbox) { registry.addRecipeCatalyst(new ItemStack(ModItems.SCRAP_BOX), RecipeCategoryUids.SCRAPBOX); @@ -364,52 +373,43 @@ public class TechRebornJeiPlugin implements IModPlugin { final IRecipeTransferRegistry recipeTransferRegistry = registry.getRecipeTransferRegistry(); recipeTransferRegistry.addRecipeTransferHandler( - new BuiltContainerTransferInfo("fusionreactor", RecipeCategoryUids.FUSION_REACTOR, 36, 2, 0, 36)); + new BuiltContainerTransferInfo("fusionreactor", RecipeCategoryUids.FUSION_REACTOR, 36, 2, 0, 36)); recipeTransferRegistry.addRecipeTransferHandler( - new BuiltContainerTransferInfo("industrialelectrolyzer", RecipeCategoryUids.INDUSTRIAL_ELECTROLYZER, 36, - 2, 0, 36)); + new BuiltContainerTransferInfo("industrialelectrolyzer", RecipeCategoryUids.INDUSTRIAL_ELECTROLYZER, 36, 2, 0, 36)); recipeTransferRegistry.addRecipeTransferHandler( - new BuiltContainerTransferInfo("industrialgrinder", RecipeCategoryUids.GRINDER, 36, 2, 0, 36)); + new BuiltContainerTransferInfo("industrialgrinder", RecipeCategoryUids.GRINDER, 36, 2, 0, 36)); recipeTransferRegistry.addRecipeTransferHandler( - new BuiltContainerTransferInfo("implosioncompressor", RecipeCategoryUids.IMPLOSION_COMPRESSOR, 36, 2, 0, - 36)); + new BuiltContainerTransferInfo("implosioncompressor", RecipeCategoryUids.IMPLOSION_COMPRESSOR, 36, 2, 0, 36)); recipeTransferRegistry.addRecipeTransferHandler( - new BuiltContainerTransferInfo("vacuumfreezer", RecipeCategoryUids.VACUUM_FREEZER, 36, 1, 0, 36)); + new BuiltContainerTransferInfo("vacuumfreezer", RecipeCategoryUids.VACUUM_FREEZER, 36, 1, 0, 36)); recipeTransferRegistry.addRecipeTransferHandler( - new BuiltContainerTransferInfo("blastfurnace", RecipeCategoryUids.BLAST_FURNACE, 36, 2, 0, 36)); + new BuiltContainerTransferInfo("blastfurnace", RecipeCategoryUids.BLAST_FURNACE, 36, 2, 0, 36)); recipeTransferRegistry.addRecipeTransferHandler( - new BuiltContainerTransferInfo("rollingmachine", RecipeCategoryUids.ROLLING_MACHINE, 36, 9, 0, 36)); + new BuiltContainerTransferInfo("rollingmachine", RecipeCategoryUids.ROLLING_MACHINE, 36, 9, 0, 36)); recipeTransferRegistry.addRecipeTransferHandler( - new BuiltContainerTransferInfo("alloyfurnace", RecipeCategoryUids.ALLOY_SMELTER, 36, 2, 0, 36)); + new BuiltContainerTransferInfo("alloyfurnace", RecipeCategoryUids.ALLOY_SMELTER, 36, 2, 0, 36)); recipeTransferRegistry.addRecipeTransferHandler( - new BuiltContainerTransferInfo("alloyfurnace", VanillaRecipeCategoryUid.FUEL, 36, 2, 0, 36)); + new BuiltContainerTransferInfo("alloyfurnace", VanillaRecipeCategoryUid.FUEL, 36, 2, 0, 36)); recipeTransferRegistry.addRecipeTransferHandler( - new BuiltContainerTransferInfo("alloysmelter", RecipeCategoryUids.ALLOY_SMELTER, 36, 2, 0, 36)); + new BuiltContainerTransferInfo("alloysmelter", RecipeCategoryUids.ALLOY_SMELTER, 36, 2, 0, 36)); recipeTransferRegistry.addRecipeTransferHandler( - new BuiltContainerTransferInfo("assemblingmachine", RecipeCategoryUids.ASSEMBLING_MACHINE, 36, 2, 0, - 36)); + new BuiltContainerTransferInfo("assemblingmachine", RecipeCategoryUids.ASSEMBLING_MACHINE, 36, 2, 0, 36)); recipeTransferRegistry.addRecipeTransferHandler( - new BuiltContainerTransferInfo("chemicalreactor", RecipeCategoryUids.CHEMICAL_REACTOR, 36, 2, 0, 36)); + new BuiltContainerTransferInfo("chemicalreactor", RecipeCategoryUids.CHEMICAL_REACTOR, 36, 2, 0, 36)); recipeTransferRegistry.addRecipeTransferHandler( - new BuiltContainerTransferInfo("centrifuge", RecipeCategoryUids.CENTRIFUGE, 36, 2, 0, 36)); + new BuiltContainerTransferInfo("centrifuge", RecipeCategoryUids.CENTRIFUGE, 36, 2, 0, 36)); recipeTransferRegistry.addRecipeTransferHandler( - new BuiltContainerTransferInfo("grinder", RecipeCategoryUids.GRINDER, 36, 1, 0, 36)); + new BuiltContainerTransferInfo("grinder", RecipeCategoryUids.GRINDER, 36, 1, 0, 36)); recipeTransferRegistry.addRecipeTransferHandler( - new BuiltContainerTransferInfo("extractor", RecipeCategoryUids.EXTRACTOR, 36, 1, 0, 36)); + new BuiltContainerTransferInfo("extractor", RecipeCategoryUids.EXTRACTOR, 36, 1, 0, 36)); recipeTransferRegistry.addRecipeTransferHandler( - new BuiltContainerTransferInfo("compressor", RecipeCategoryUids.COMPRESSOR, 36, 1, 0, 36)); + new BuiltContainerTransferInfo("compressor", RecipeCategoryUids.COMPRESSOR, 36, 1, 0, 36)); recipeTransferRegistry.addRecipeTransferHandler( - new BuiltContainerTransferInfo("industrialsawmill", RecipeCategoryUids.INDUSTRIAL_SAWMILL, 36, 2, 0, 36)); + new BuiltContainerTransferInfo("industrialsawmill", RecipeCategoryUids.INDUSTRIAL_SAWMILL, 36, 2, 0, 36)); recipeTransferRegistry.addRecipeTransferHandler( - new BuiltContainerTransferInfo("distillationtower", RecipeCategoryUids.DISTILLATION_TOWER, 36, 2, 0, 36)); - - if (CompatManager.isQuantumStorageLoaded) { - registry.getJeiHelpers().getIngredientBlacklist().addIngredientToBlacklist(new ItemStack(ModBlocks.QUANTUM_CHEST)); - registry.getJeiHelpers().getIngredientBlacklist().addIngredientToBlacklist(new ItemStack(ModBlocks.QUANTUM_TANK)); - } + new BuiltContainerTransferInfo("distillationtower", RecipeCategoryUids.DISTILLATION_TOWER, 36, 2, 0, 36)); registry.addAdvancedGuiHandlers(new AdvancedGuiHandler()); - } @Override @@ -439,8 +439,6 @@ public class TechRebornJeiPlugin implements IModPlugin { //Taken from JEI so we can have a custom impliemntation of it //This is done as I didnt see an easy way to disable the show recipes button when a certain condition is met - - public void addRecipeClickArea(Class guiContainerClass, int xPos, int yPos, int width, int height, String... recipeCategoryUids) { ErrorUtil.checkNotNull(guiContainerClass, "guiContainerClass"); ErrorUtil.checkNotEmpty(recipeCategoryUids, "recipeCategoryUids"); @@ -495,6 +493,5 @@ public class TechRebornJeiPlugin implements IModPlugin { } } } - } } diff --git a/src/main/java/techreborn/compat/jei/fluidReplicator/FluidReplicatorRecipeCategory.java b/src/main/java/techreborn/compat/jei/fluidReplicator/FluidReplicatorRecipeCategory.java new file mode 100644 index 000000000..78b85e9c5 --- /dev/null +++ b/src/main/java/techreborn/compat/jei/fluidReplicator/FluidReplicatorRecipeCategory.java @@ -0,0 +1,90 @@ +/* + * This file is part of TechReborn, licensed under the MIT License (MIT). + * + * Copyright (c) 2018 TechReborn + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package techreborn.compat.jei.fluidReplicator; + +import mezz.jei.api.IGuiHelper; +import mezz.jei.api.gui.IDrawable; +import mezz.jei.api.gui.IGuiFluidStackGroup; +import mezz.jei.api.gui.IGuiItemStackGroup; +import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.ingredients.IIngredients; +import mezz.jei.api.recipe.IRecipeCategory; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.translation.I18n; +import techreborn.compat.jei.RecipeCategoryUids; +import techreborn.compat.jei.RecipeUtil; +import techreborn.lib.ModInfo; + +import javax.annotation.Nonnull; + +/** + * @author drcrazy + * + */ +@SuppressWarnings("deprecation") +public class FluidReplicatorRecipeCategory implements IRecipeCategory { + public static final ResourceLocation texture = new ResourceLocation("techreborn", "textures/gui/jei.png"); + private static final int[] OUTPUT_TANKS = { 0 }; + private static final int[] INPUT_SLOTS = { 0 }; + private final IDrawable background; + private final IDrawable tankOverlay; + private final String title; + + public FluidReplicatorRecipeCategory(@Nonnull IGuiHelper guiHelper) { + this.background = guiHelper.createDrawable(texture, 125, 0, 72, 60); + this.tankOverlay = guiHelper.createDrawable(texture, 196, 0, 12, 47); + this.title = I18n.translateToLocal("tile.techreborn:fluid_replicator.name"); + } + + @Override + public String getUid() { + return RecipeCategoryUids.FLUID_REPLICATOR; + } + + @Override + public String getTitle() { + return title; + } + + @Override + public String getModName() { + return ModInfo.MOD_NAME; + } + + @Override + public IDrawable getBackground() { + return background; + } + + @Override + public void setRecipe(IRecipeLayout recipeLayout, FluidReplicatorRecipeWrapper recipeWrapper, IIngredients ingredients) { + IGuiItemStackGroup guiItemStacks = recipeLayout.getItemStacks(); + guiItemStacks.init(INPUT_SLOTS[0], true, 2, 21); + IGuiFluidStackGroup guiFluidStacks = recipeLayout.getFluidStacks(); + guiFluidStacks.init(OUTPUT_TANKS[0], false, 52, 6, 12, 47, 10_000, true, tankOverlay); + RecipeUtil.setRecipeItems(recipeLayout, ingredients, INPUT_SLOTS, null, null, OUTPUT_TANKS); + } + +} diff --git a/src/main/java/techreborn/compat/jei/fluidReplicator/FluidReplicatorRecipeWrapper.java b/src/main/java/techreborn/compat/jei/fluidReplicator/FluidReplicatorRecipeWrapper.java new file mode 100644 index 000000000..26e34d3ae --- /dev/null +++ b/src/main/java/techreborn/compat/jei/fluidReplicator/FluidReplicatorRecipeWrapper.java @@ -0,0 +1,73 @@ +/* + * This file is part of TechReborn, licensed under the MIT License (MIT). + * + * Copyright (c) 2018 TechReborn + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package techreborn.compat.jei.fluidReplicator; + +import mezz.jei.api.IGuiHelper; +import mezz.jei.api.IJeiHelpers; +import mezz.jei.api.gui.IDrawableAnimated; +import mezz.jei.api.gui.IDrawableStatic; +import mezz.jei.api.ingredients.IIngredients; +import mezz.jei.api.recipe.IRecipeWrapper; +import net.minecraft.client.Minecraft; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; +import techreborn.api.fluidreplicator.FluidReplicatorRecipe; +import techreborn.client.gui.TRBuilder; +import techreborn.init.ModItems; + +import javax.annotation.Nonnull; + +/** + * @author drcrazy + * + */ +public class FluidReplicatorRecipeWrapper implements IRecipeWrapper { + private final FluidReplicatorRecipe recipe; + private final IDrawableAnimated progress; + + public FluidReplicatorRecipeWrapper(@Nonnull IJeiHelpers jeiHelpers, @Nonnull FluidReplicatorRecipe recipe) { + this.recipe = recipe; + IGuiHelper guiHelper = jeiHelpers.getGuiHelper(); + IDrawableStatic progressStatic = guiHelper.createDrawable(TRBuilder.GUI_SHEET, 100, 151, 16, 10); + int ticksPerCycle = recipe.getTickTime(); + this.progress = guiHelper.createAnimatedDrawable(progressStatic, ticksPerCycle, + IDrawableAnimated.StartDirection.LEFT, false); + } + + /* (non-Javadoc) + * @see mezz.jei.api.recipe.IRecipeWrapper#getIngredients(mezz.jei.api.ingredients.IIngredients) + */ + @Override + public void getIngredients(IIngredients ingredients) { + ingredients.setInput(ItemStack.class, new ItemStack(ModItems.UU_MATTER, recipe.getInput())); + ingredients.setOutput(FluidStack.class, new FluidStack(recipe.getFluid(), Fluid.BUCKET_VOLUME)); + } + + @Override + public void drawInfo(Minecraft minecraft, int recipeWidth, int recipeHeight, int mouseX, int mouseY) { + progress.draw(minecraft, 25, 25); + } +} diff --git a/src/main/java/techreborn/compat/jei/grinder/GrinderRecipeCategory.java b/src/main/java/techreborn/compat/jei/grinder/GrinderRecipeCategory.java index a88d3b98d..01b38ef88 100644 --- a/src/main/java/techreborn/compat/jei/grinder/GrinderRecipeCategory.java +++ b/src/main/java/techreborn/compat/jei/grinder/GrinderRecipeCategory.java @@ -76,13 +76,7 @@ public class GrinderRecipeCategory implements IRecipeCategory= 10) { + if (!inventory.getStackInSlot(1).isEmpty()) { + FluidUtils.fillContainers(tank, inventory, 1, 2, tank.getFluidType()); + } + ticksSinceLastChange = 0; + } + + if (getMultiBlock()) { + super.update(); + } + + tank.compareAndUpdate(); + } + + @Override + public RecipeCrafter getRecipeCrafter() { + return (RecipeCrafter) crafter; + } + + // TilePowerAcceptor + @Override + public void readFromNBT(final NBTTagCompound tagCompound) { + super.readFromNBT(tagCompound); + tank.readFromNBT(tagCompound); + } + + @Override + public NBTTagCompound writeToNBT(final NBTTagCompound tagCompound) { + super.writeToNBT(tagCompound); + tank.writeToNBT(tagCompound); + return tagCompound; + } + + @Override + public boolean hasCapability(final Capability capability, final EnumFacing facing) { + if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { + return true; + } + return super.hasCapability(capability, facing); + } + + @SuppressWarnings("unchecked") + @Override + public T getCapability(final Capability capability, final EnumFacing facing) { + if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { + return (T) this.tank; + } + return super.getCapability(capability, facing); + } + + // TileLegacyMachineBase + @Override + public boolean isItemValidForSlot(int slotIndex, ItemStack itemStack) { + if (slotIndex == 0) { + if (itemStack.isItemEqual(new ItemStack(ModItems.UU_MATTER))) { + return true; + } else { + return false; + } + } + return true; + } + + // IContainerProvider + @Override + public BuiltContainer createContainer(EntityPlayer player) { + return new ContainerBuilder("fluidreplicator").player(player.inventory).inventory().hotbar().addInventory() + .tile(this).fluidSlot(1, 124, 35).filterSlot(0, 55, 45, stack -> stack.getItem() == ModItems.UU_MATTER) + .outputSlot(2, 124, 55).energySlot(3, 8, 72).syncEnergyValue().syncCrafterValue().addInventory() + .create(this); + } +} diff --git a/src/main/resources/assets/techreborn/blockstates/machines/tier3_machines/fluid_replicator.json b/src/main/resources/assets/techreborn/blockstates/machines/tier3_machines/fluid_replicator.json new file mode 100644 index 000000000..fbf9b276d --- /dev/null +++ b/src/main/resources/assets/techreborn/blockstates/machines/tier3_machines/fluid_replicator.json @@ -0,0 +1,49 @@ +{ + "forge_marker": 1, + "defaults": { + "transform": "forge:default-block", + "model": "orientable", + "textures": { + "particle": "techreborn:blocks/machines/tier3_machines/fluid_replicator_front_off", + "top": "techreborn:blocks/machines/tier3_machines/machine_top", + "down": "techreborn:blocks/machines/tier3_machines/machine_bottom", + "south": "techreborn:blocks/machines/tier3_machines/machine_back", + "west": "techreborn:blocks/machines/tier3_machines/machine_west", + "east": "techreborn:blocks/machines/tier3_machines/machine_east" + } + }, + "variants": { + "inventory": { + "transform": "forge:default-block", + "model": "orientable", + "textures": { + "front": "techreborn:blocks/machines/tier3_machines/fluid_replicator_front_off" + } + }, + "facing": { + "north": { + }, + "east": { + "y": 90 + }, + "south": { + "y": 180 + }, + "west": { + "y": 270 + } + }, + "active": { + "true": { + "textures": { + "front": "techreborn:blocks/machines/tier3_machines/fluid_replicator_front_on" + } + }, + "false": { + "textures": { + "front": "techreborn:blocks/machines/tier3_machines/fluid_replicator_front_off" + } + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/techreborn/lang/en_us.lang b/src/main/resources/assets/techreborn/lang/en_us.lang index 0ed723d5e..8d92921b9 100644 --- a/src/main/resources/assets/techreborn/lang/en_us.lang +++ b/src/main/resources/assets/techreborn/lang/en_us.lang @@ -81,6 +81,7 @@ tile.techreborn:mv_transformer.name=MV Transformer tile.techreborn:hv_transformer.name=HV Transformer tile.techreborn:ev_transformer.name=EV Transformer tile.techreborn:auto_crafting_table.name=Auto Crafting Table +tile.techreborn:fluid_replicator.name=Fluid Replicator #Blocks diff --git a/src/main/resources/assets/techreborn/textures/blocks/machines/tier1_machines/pump_side.png b/src/main/resources/assets/techreborn/textures/blocks/machines/tier3_machines/fluid_replicator_front_off.png similarity index 100% rename from src/main/resources/assets/techreborn/textures/blocks/machines/tier1_machines/pump_side.png rename to src/main/resources/assets/techreborn/textures/blocks/machines/tier3_machines/fluid_replicator_front_off.png diff --git a/src/main/resources/assets/techreborn/textures/blocks/machines/tier3_machines/fluid_replicator_front_on.png b/src/main/resources/assets/techreborn/textures/blocks/machines/tier3_machines/fluid_replicator_front_on.png new file mode 100644 index 0000000000000000000000000000000000000000..e75f4f81520034be6f919404a1924befa43be595 GIT binary patch literal 1068 zcmV+{1k?M8P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6Fc00(qQO+^Rb3JnPq z2uN2bZe?^JG%heMF*(%MvSa`N1BppQK~z{r z?Uz|kQ&AAd?+5Y87f65v!WZxp_~x@DNI@iE*jo0q0#=0}c4M(+v!#?Gg|L*>vIw{U zDk8`xr3-CA0sR1f=Uj8OX-<7GnkaUX$?461Iy2|oo?oWIv-K@3u5Dswc@0y~R>gH< zaT&vNOBh>t3CHw298aENfZR4d1M~1C95YL>P0YeF`UJw_+6Io#zF^;Xh|tNI=)TY~ zLZ_eMWh*@gKb>OVAHcTTiw_jHxwnsl;1Ns?CxrRcx8j!{Q^r23(Cc);POELqg(FJB z67V!n@EAI4KZM!kHwb(@LC@$k;^N{&Pe@2W&&U)!fe^e@iKlHJ_@L_Md=)#CjkU;vn5Cws!ZJK1p241nudVO8 zq3;=l;G!+K>40o>qRf($laZ2=f^Ir(*4Zv4;At!G-lM+L_N@c2&krl@i&bF(%&a5R z@CAbKQgWWQ=l1;A0(!sM_}}?CiVIHQ*FQ$vfyBv$x>( z2e}%1JK`3c^lN*&{Q(v_+4lZXbPbN9b6^Zc`w&((w(y*OXgtmJ;x#ng4hXddBN{ro zQEf0mO`mI?Zvlv2w>JGHDg z1Ctr8HU~7F-Kc-q33ZbRcU#)g&}K%BmbRyRh+B=#$e?7m^{q(DErd{9Q-{2YYGhH> z49c9Ps6=|c92rH_4SmioQz4xy%jh{RuL##zH}VR|ipz1mREZc5I6Pp+E)90pYh}8ZZ52Q;IZ9b5+znBM7o6+V2 mN&AO*ApKw9ap7F>K#8v$&vorXnW1L@0000`T;U7+ER1oL94^=QQZ7N~V@jl9Ok9XvO`SZ%AS@-rcT8w+taJ9uS#vAa#vs?`C$dOd0SL~_L>B9a9&Rr-+v z?H0GWx!zoP3`xLNYE0fVS|t<)e;Vy*{k-5tDl!LM6(en9jDI^l8?f>APy^#`5uD#K zK~s#w?hU0~KT4S?v@ccO=knFcaB)bdh&GZiwZ_Z>#qoMN-*v#&!3)=*%s;hk3l`Z$ zC`r;Oz2O5amAxS+24kD4pH-m`ZkS)om>}2|_*4&462wF7cpVL|iT}miKCnd=41_iW zQOv#in(C(FeUqS`p7iTGSb~~h8`TxX&q=&3U~F_g#l!T+bf~szwwv#f$nUMmo8A13 z9QOFrLM}h09ElQ6p}t0KDCVkZvk`fG%T&HW6Kil%mr8w;G*Y#VZ+!O_b~tk($u}>B zNTdQ=CGpIv@&~9sLQr~8C=%Q!#cC>y_2&@xw)eKlq?t+uo>ph zxRF@c3$YbsV!%XCrBWC>fk^ny;Cp7k#KZA@5qFgN+^?}&E5+b_Hxs%Et+PCKUCn8u z5f*d*GR(IFzJO8sk{}qnkzNvqHZx+5Cr6Lu*{@(RhIG!I`ABuA4Pr>KXcCyH@ma*m zhsC0b3th*3<{etU?9~VAaq+syAS>t%oyhg=4q{Fd-^1CMzZr4r-%X$@3Tp+O-lrdb z60AgJ*;_zgKD##3$BxFh@lM`i`^BbS>%svXg%UNWnYQ%Beg1!jqWj*vjTVfR9Z(sf z9duT1w+LfjIyBkbvVXF`trKCsbwLy*??3^`rjWabhuadk8gvTD(?|H}u}^P^!rp?&Ph*r@6FksW zIg{_|m4@>@m@vD0JLz6k1V9@$&R%;Q^CBLrv&UAEJ z@}#s+O9tN^$!9D044D(x9&L~Np~YmVZYQjEM$DH?-2^h^z>JpuhnKRV-bQdx6^vi) zH)hg3`)An<*QEG^RQVoY{Z%Zk%d(*;Bv=wI_ zI?W3}%`HFaE$hpYcpba$6>{8ZWa|gB>|e#M+ZoYEX-A{m@~1VXJRQxzEiG7Zm$t|q zH6kB!Mp&o_QvaKg_+|YNmX}w?C9)+W9A4dreS5+|4n)kQb2$aG_K5?1=r(WWD}%$D z%qt^zX_{iiZ~_&{f>ZX?8*zK5-i|^!Z~qp%}X)> zNqz*q$bALuUe4nDs`aG(pktfvtQJ&TE`mx~Qf`aGkn}{xG{DHDJnO!J$Pk7^Pi&8h zbP|CSJZ!}d#e9JjfP$SRT%F&ep#o!sgYk<14rK%qAs9GHJcj1)y-BCCOnSJ9WUd_c zynpq6`HGti@jljDzK77&mzLU!@Kbtj3G_antbejRCguM1?Y*%LLMP^Kkolfie#Mir34at6P}R!UM9Bdz_Cm=0 z7w9&DeSnt^T~pt3P&Lg&9TcZlz+KI>^%yYW_now>h!YTfU-vqxd zs0yx^13H(>E=84>K6L_S5+N2ZZqu|@S0N`+-w)1?Qsajnr0q&-?~y-m>H|HG} zzQ#2>9o8h8wWch4$l-)i&*KXtGr_f1H29tjWt*t!Ib%S0wV2BG>O0kEBR(4bv=!0` z!hn1k5S0sxF@I{X%T#TACuqFAn9VLw2aS%P%NIrJ>@(H4Y@(tU*Um%3PnF+(q}a@* z9bNt8rE}~?Wt}U{=1Cs1bTR9lz|S8J!jqIGrd!AiTvF4-#C|NQ7|*~Ww;+eIX#TPa z7gkV~M8D-pc`ZM4awA*-feD$ouB%p(Bzpds0bbWxVFwrq&E>|o8+$&wy8R?Vsh&N^ z;XdxsLXk?0Kbz+wmzE^tLQ%4)z<{*<4X&#mj&yr zK=ZRbtdHplb^n03EI(1No0Q8-$v-eL{_+A^S42Le)^N;G;SeBS+EA9GPSmvU{s U1Uyg^Z$T{BSvgtO9QFJ5XNU_3qyPW_ literal 2282 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5Fo{p?&#~tz_78O`%fY(0|PTd zfKP}kP~6RZakrM(BmgRp3Wt5U2zhGecAIX3r_&d8QFy=W6 zJR*x37=-dbnDGqTkvO0rdx@v7EBga3L4E<_w$p1t#foH!YeY$Kep*R+Vo@qXL1JcJ ziC$i6iGqoqfu5nkS}v{wz%s|i)5S5QBJS;+#-dvW0<5=9{{KJyQc^#?hv9aG*V5|z zbes2XLXNj27D=e@uRF4lA!yoVrn>u|U5_iw5&uwn++4Off$_=h2!_{wIt_h}8yG(2 z>NJ$9Gjk=dZ!SpD4|ZY*_U~JBkg38aiLr#IiSiyE zZZgviO+A}C#+SBV_#C>anMq=Tjf~|L$yCO|2!_u-*M$4nv;rB;*<4t4*t)oG+&g_l zNiQ<3h*`I;VGrI9I8Dw3szfQut+pVl0W*lL9 zA<^P_VCCFsR>tKU7_QBYV8HaO)*V%~Ue*blA{aEgSttB{aH;-uf;`)uf&hlubK4Hq z{kRVd9lI{B2c>&Hd=ZTeWmxSoPwzOB#DxS#9*KTgrbUfjUwJyjfWFgzC$cvv#zAU= zki%S`Trr2c0f7f}FP3?RGF~(hU&OSi)hpP+Bw*z{MsBeK4Q$*A2P%A+zSZvu4>?e$ z)9}?Sf`R$i;~5R#?mprIGnya{0=jEw+j$Q0PvVb?Yy=PdQw4-VfpjZVE^;y@0hqdlvxVC{#O2?+3@}> z`;2+Hb?@{xG+5{yU;?5UciA^EaBpbfWBrhQ%l$>rf%J_HKX>j<5V~;h(f{=`=kMlL zW4r_p8c>u$V-A)2{a{v_xBvHA*~beQ-p$FC`0f|Pt?)fCgkk;T*5&J8JZAdQ#l3fL zbPUUet|vc>Bra_DFSvKEwwORWtHJgoOwa5(*j54KcG;|z3JoO%I!0EuI zHM)#}XI+Dw9rSXX9Ym(@Nlak8a`MWzD2CEc9|Xk=wwATTGZp6e8O?f@D@+PYPRLN@qhcHM29w1*Qd{)#UHEBI(+@{)vv(9hQZU-&t;ucLK6UXkORB`