From b1382eaac2c2ff254eab77ef1ad09b1800fb4e67 Mon Sep 17 00:00:00 2001 From: Bob Date: Thu, 15 Jul 2021 23:22:20 +0200 Subject: [PATCH] more anvil work, RBMK irradiation channel IO --- .../blocks/machine/rbmk/RBMKOutgasser.java | 2 +- src/main/java/com/hbm/handler/GUIHandler.java | 2 +- .../java/com/hbm/inventory/AnvilRecipes.java | 20 +- .../inventory/container/ContainerAnvil.java | 5 +- .../java/com/hbm/inventory/gui/GUIAnvil.java | 247 +++++++++++++----- src/main/java/com/hbm/items/ModItems.java | 4 +- .../java/com/hbm/packet/AnvilCraftPacket.java | 59 +++++ .../java/com/hbm/packet/PacketDispatcher.java | 2 + .../com/hbm/render/tileentity/RenderFEL.java | 8 +- .../machine/rbmk/TileEntityRBMKOutgasser.java | 15 ++ src/main/java/com/hbm/util/InventoryUtil.java | 10 + .../hbm/textures/gui/processing/gui_anvil.png | Bin 3225 -> 3425 bytes 12 files changed, 301 insertions(+), 73 deletions(-) create mode 100644 src/main/java/com/hbm/packet/AnvilCraftPacket.java diff --git a/src/main/java/com/hbm/blocks/machine/rbmk/RBMKOutgasser.java b/src/main/java/com/hbm/blocks/machine/rbmk/RBMKOutgasser.java index 5a2f5dff7..303fb345b 100644 --- a/src/main/java/com/hbm/blocks/machine/rbmk/RBMKOutgasser.java +++ b/src/main/java/com/hbm/blocks/machine/rbmk/RBMKOutgasser.java @@ -17,7 +17,7 @@ public class RBMKOutgasser extends RBMKBase { return new TileEntityRBMKOutgasser(); if(hasExtra(meta)) - return new TileEntityProxyCombo(false, false, true); + return new TileEntityProxyCombo(true, false, true); return null; } diff --git a/src/main/java/com/hbm/handler/GUIHandler.java b/src/main/java/com/hbm/handler/GUIHandler.java index b6d064c25..7d3f92f55 100644 --- a/src/main/java/com/hbm/handler/GUIHandler.java +++ b/src/main/java/com/hbm/handler/GUIHandler.java @@ -845,7 +845,7 @@ public class GUIHandler implements IGuiHandler { case ModBlocks.guiID_anvil: { if(world.getBlock(x, y, z) instanceof NTMAnvil) { - return new ContainerAnvil(player.inventory); + return new ContainerAnvil(player.inventory, ((NTMAnvil)world.getBlock(x, y, z)).tier); } return null; } diff --git a/src/main/java/com/hbm/inventory/AnvilRecipes.java b/src/main/java/com/hbm/inventory/AnvilRecipes.java index 5ea71bc3d..8814598ec 100644 --- a/src/main/java/com/hbm/inventory/AnvilRecipes.java +++ b/src/main/java/com/hbm/inventory/AnvilRecipes.java @@ -82,7 +82,7 @@ public class AnvilRecipes { constructionRecipes.add(new AnvilConstructionRecipe( new OreDictStack("plateGold"), new AnvilOutput(new ItemStack(ModItems.wire_gold, 8)) - ).setTier(1)); + ).setTierRange(1, 4)); } public static List getSmithing() { @@ -151,7 +151,8 @@ public class AnvilRecipes { public static class AnvilConstructionRecipe { public List input = new ArrayList(); public List output = new ArrayList(); - int tier = 0; + int tierLower = 0; + int tierUpper = -1; OverlayType overlay = OverlayType.NONE; public AnvilConstructionRecipe(AStack input, AnvilOutput output) { @@ -179,12 +180,21 @@ public class AnvilRecipes { } public AnvilConstructionRecipe setTier(int tier) { - this.tier = tier; + this.tierLower = tier; return this; } - public int getTier() { - return this.tier; + public AnvilConstructionRecipe setTierRange(int lower, int upper) { + this.tierLower = lower; + this.tierUpper = upper; + return this; + } + + public boolean isTierValid(int tier) { + if(this.tierUpper == -1) + return tier >= this.tierLower; + + return tier >= this.tierLower && tier <= this.tierUpper; } public AnvilConstructionRecipe setOverlay(OverlayType overlay) { diff --git a/src/main/java/com/hbm/inventory/container/ContainerAnvil.java b/src/main/java/com/hbm/inventory/container/ContainerAnvil.java index 32ab9eaa7..259ce4d80 100644 --- a/src/main/java/com/hbm/inventory/container/ContainerAnvil.java +++ b/src/main/java/com/hbm/inventory/container/ContainerAnvil.java @@ -18,7 +18,10 @@ public class ContainerAnvil extends Container { public InventoryBasic input = new InventoryBasic("Input", false, 8); public IInventory output = new InventoryCraftResult(); - public ContainerAnvil(InventoryPlayer inventory) { + public int tier; //because we can't trust these rascals with their packets + + public ContainerAnvil(InventoryPlayer inventory, int tier) { + this.tier = tier; this.addSlotToContainer(new SmithingSlot(input, 0, 17, 27)); this.addSlotToContainer(new SmithingSlot(input, 1, 53, 27)); diff --git a/src/main/java/com/hbm/inventory/gui/GUIAnvil.java b/src/main/java/com/hbm/inventory/gui/GUIAnvil.java index 2517d54e6..6d6bb9453 100644 --- a/src/main/java/com/hbm/inventory/gui/GUIAnvil.java +++ b/src/main/java/com/hbm/inventory/gui/GUIAnvil.java @@ -3,6 +3,7 @@ package com.hbm.inventory.gui; import java.util.ArrayList; import java.util.List; +import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.GL11; import com.hbm.inventory.AnvilRecipes; @@ -13,13 +14,11 @@ import com.hbm.inventory.RecipesCommon.ComparableStack; import com.hbm.inventory.RecipesCommon.OreDictStack; import com.hbm.inventory.container.ContainerAnvil; import com.hbm.lib.RefStrings; -import com.hbm.packet.AuxButtonPacket; -import com.hbm.packet.PacketDispatcher; import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiTextField; import net.minecraft.client.gui.inventory.GuiContainer; -import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.InventoryPlayer; @@ -34,34 +33,90 @@ public class GUIAnvil extends GuiContainer { public static ResourceLocation texture = new ResourceLocation(RefStrings.MODID + ":textures/gui/processing/gui_anvil.png"); private int tier; + private List originList = new ArrayList(); private List recipes = new ArrayList(); int index; int size; int selection; + private GuiTextField search; public GUIAnvil(InventoryPlayer player, int tier) { - super(new ContainerAnvil(player)); + super(new ContainerAnvil(player, tier)); this.tier = tier; this.xSize = 176; this.ySize = 222; - this.index = 0; - this.selection = -1; - - guiLeft = (this.width - this.xSize) / 2; - guiTop = (this.height - this.ySize) / 2; for(AnvilConstructionRecipe recipe : AnvilRecipes.getConstruction()) { - if(recipe.getTier() <= this.tier) - this.recipes.add(recipe); + if(recipe.isTierValid(this.tier)) + this.originList.add(recipe); } - this.size = (int)Math.ceil((this.recipes.size() - 10) / 2D); + regenerateRecipes(); + + guiLeft = (this.width - this.xSize) / 2; + guiTop = (this.height - this.ySize) / 2; } + + @Override + public void initGui() { + super.initGui(); + + Keyboard.enableRepeatEvents(true); + this.search = new GuiTextField(this.fontRendererObj, guiLeft + 10, guiTop + 111, 84, 12); + this.search.setTextColor(-1); + this.search.setDisabledTextColour(-1); + this.search.setEnableBackgroundDrawing(false); + this.search.setMaxStringLength(25); + } + + private void regenerateRecipes() { + + this.recipes.clear(); + this.recipes.addAll(this.originList); + + resetPaging(); + } + + private void search(String search) { + + search = search.toLowerCase(); + + this.recipes.clear(); + + if(search.isEmpty()) { + this.recipes.addAll(this.originList); + + } else { + for(AnvilConstructionRecipe recipe : this.originList) { + List list = recipeToSearchList(recipe); + + for(String s : list) { + if(s.contains(search)) { + this.recipes.add(recipe); + break; + } + } + } + } + + resetPaging(); + } + + private void resetPaging() { + + this.index = 0; + this.selection = -1; + this.size = Math.max(0, (int)Math.ceil((this.recipes.size() - 10) / 2D)); + } + + @Override protected void mouseClicked(int x, int y, int k) { super.mouseClicked(x, y, k); + this.search.mouseClicked(x, y, k); + if(guiLeft + 7 <= x && guiLeft + 7 + 9 > x && guiTop + 71 < y && guiTop + 71 + 36 >= y) { mc.getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F)); if(this.index > 0) @@ -85,6 +140,12 @@ public class GUIAnvil extends GuiContainer { return; } + if(guiLeft + 97 <= x && guiLeft + 97 + 18 > x && guiTop + 107 < y && guiTop + 107 + 18 >= y) { + mc.getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F)); + search(this.search.getText()); + return; + } + for(int i = index * 2; i < index * 2 + 10; i++) { if(i >= this.recipes.size()) @@ -106,55 +167,24 @@ public class GUIAnvil extends GuiContainer { } } } - + + @Override protected void drawGuiContainerForegroundLayer(int mX, int mY) { String name = I18n.format("container.anvil", tier); this.fontRendererObj.drawString(name, 61 - this.fontRendererObj.getStringWidth(name) / 2, 8, 4210752); this.fontRendererObj.drawString(I18n.format("container.inventory"), 8, this.ySize - 96 + 2, 4210752); if(this.selection >= 0) { - int longest = 1; - List list = new ArrayList(); + AnvilConstructionRecipe recipe = recipes.get(this.selection); + List list = recipeToList(recipe); + int longest = 0; - list.add(EnumChatFormatting.YELLOW + "Inputs:"); - - for(AStack stack : recipe.input) { - if(stack instanceof ComparableStack) { - ItemStack input = ((ComparableStack) stack).toStack(); - String toAdd = ">" + input.stackSize + "x " + input.getDisplayName(); - int len = this.fontRendererObj.getStringWidth(toAdd); - if(len > longest) - longest = len; - list.add(toAdd); - - } else if(stack instanceof OreDictStack) { - OreDictStack input = (OreDictStack) stack; - ArrayList ores = OreDictionary.getOres(input.name); - - if(ores.size() > 0) { - ItemStack inStack = ores.get((int) (Math.abs(System.currentTimeMillis() / 1000) % ores.size())); - String toAdd = ">" + input.stacksize + "x " + inStack.getDisplayName(); - int len = this.fontRendererObj.getStringWidth(toAdd); - if(len > longest) - longest = len; - list.add(toAdd); - - } else { - list.add("I AM ERROR"); - } - } - } - - list.add(""); - list.add(EnumChatFormatting.YELLOW + "Outputs:"); - - for(AnvilOutput stack : recipe.output) { - String toAdd = ">" + stack.stack.stackSize + "x " + stack.stack.getDisplayName() + (stack.chance != 1F ? (" (" + (stack.chance * 100) + "%)" ) : ""); - int len = this.fontRendererObj.getStringWidth(toAdd); - if(len > longest) - longest = len; - list.add(toAdd); + for(String s : list) { + int length = this.fontRendererObj.getStringWidth(s); + + if(length > longest) + longest = length; } double scale = 0.5D; @@ -173,27 +203,109 @@ public class GUIAnvil extends GuiContainer { } } + /** + * Generates the neat structured list for showing ingredients + * @param recipe + * @return + */ + public List recipeToList(AnvilConstructionRecipe recipe) { + + List list = new ArrayList(); + + list.add(EnumChatFormatting.YELLOW + "Inputs:"); + + for(AStack stack : recipe.input) { + if(stack instanceof ComparableStack) { + ItemStack input = ((ComparableStack) stack).toStack(); + list.add(">" + input.stackSize + "x " + input.getDisplayName()); + + } else if(stack instanceof OreDictStack) { + OreDictStack input = (OreDictStack) stack; + ArrayList ores = OreDictionary.getOres(input.name); + + if(ores.size() > 0) { + ItemStack inStack = ores.get((int) (Math.abs(System.currentTimeMillis() / 1000) % ores.size())); + list.add(">" + input.stacksize + "x " + inStack.getDisplayName()); + + } else { + list.add("I AM ERROR"); + } + } + } + + list.add(""); + list.add(EnumChatFormatting.YELLOW + "Outputs:"); + + for(AnvilOutput stack : recipe.output) { + list.add(">" + stack.stack.stackSize + "x " + stack.stack.getDisplayName() + (stack.chance != 1F ? (" (" + (stack.chance * 100) + "%)" ) : "")); + } + + return list; + } + + /** + * Generates a simple, unstructured list of inputs (and all ore dict variants) and outputs for searching + * @param recipe + * @return + */ + public List recipeToSearchList(AnvilConstructionRecipe recipe) { + + List list = new ArrayList(); + + for(AStack stack : recipe.input) { + if(stack instanceof ComparableStack) { + ItemStack input = ((ComparableStack) stack).toStack(); + list.add(input.getDisplayName().toLowerCase()); + + } else if(stack instanceof OreDictStack) { + OreDictStack input = (OreDictStack) stack; + ArrayList ores = OreDictionary.getOres(input.name); + + if(ores.size() > 0) { + for(ItemStack ore : ores) { + list.add(ore.getDisplayName().toLowerCase()); + } + + } + } + } + + for(AnvilOutput stack : recipe.output) { + list.add(stack.stack.getDisplayName().toLowerCase()); + } + + return list; + } + int lastSize = 1; - + + @Override protected void drawGuiContainerBackgroundLayer(float inter, int mX, int mY) { - + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); this.mc.getTextureManager().bindTexture(texture); - + this.drawTexturedModalRect(guiLeft, guiTop, 0, 0, this.xSize, this.ySize); int slide = MathHelper.clamp_int(this.lastSize - 42, 0, 1000); this.drawTexturedModalRect(guiLeft + 125 + slide, guiTop + 17, 125, 17, 54, 108); - if(guiLeft + 7 <= mX && guiLeft + 7 + 9 > mX && guiTop + 71 < mY && guiTop + 71 + 36 >=mY) { + if(this.search.isFocused()) { + drawTexturedModalRect(guiLeft + 8, guiTop + 108, 168, 222, 88, 16); + } + + if(guiLeft + 7 <= mX && guiLeft + 7 + 9 > mX && guiTop + 71 < mY && guiTop + 71 + 36 >= mY) { drawTexturedModalRect(guiLeft + 7, guiTop + 71, 176, 186, 9, 36); } - if(guiLeft + 106 <= mX && guiLeft + 106 + 9 > mX && guiTop + 71 < mY && guiTop + 71 + 36 >=mY) { + if(guiLeft + 106 <= mX && guiLeft + 106 + 9 > mX && guiTop + 71 < mY && guiTop + 71 + 36 >= mY) { drawTexturedModalRect(guiLeft + 106, guiTop + 71, 185, 186, 9, 36); } - if(guiLeft + 52 <= mX && guiLeft + 52 + 18 > mX && guiTop + 53 < mY && guiTop + 53 + 18 >=mY) { + if(guiLeft + 52 <= mX && guiLeft + 52 + 18 > mX && guiTop + 53 < mY && guiTop + 53 + 18 >= mY) { drawTexturedModalRect(guiLeft + 52, guiTop + 53, 176, 150, 18, 18); } + if(guiLeft + 97 <= mX && guiLeft + 97 + 18 > mX && guiTop + 107 < mY && guiTop + 107 + 18 >= mY) { + drawTexturedModalRect(guiLeft + 97, guiTop + 107, 176, 168, 18, 18); + } for(int i = index * 2; i < index * 2 + 10; i++) { if(i >= recipes.size()) @@ -225,5 +337,22 @@ public class GUIAnvil extends GuiContainer { if(selection == i) this.drawTexturedModalRect(guiLeft + 16 + 18 * (ind / 2), guiTop + 71 + 18 * (ind % 2), 0, 222, 18, 18); } + + this.search.drawTextBox(); + } + + @Override + protected void keyTyped(char c, int key) { + + if(!this.search.textboxKeyTyped(c, key)) { + + if(key == 28) { + this.search.setFocused(false); + search(this.search.getText()); + } + + super.keyTyped(c, key); + + } } } diff --git a/src/main/java/com/hbm/items/ModItems.java b/src/main/java/com/hbm/items/ModItems.java index d5672d834..854803585 100644 --- a/src/main/java/com/hbm/items/ModItems.java +++ b/src/main/java/com/hbm/items/ModItems.java @@ -3488,7 +3488,7 @@ public class ModItems { .setHeat(2D) .setMeltingPoint(5211).setUnlocalizedName("rbmk_fuel_heaus").setTextureName(RefStrings.MODID + ":rbmk_fuel_heaus"); rbmk_fuel_po210be = (ItemRBMKRod) new ItemRBMKRod(rbmk_pellet_po210be) - .setYield(1000000D) + .setYield(25000000D) .setStats(15, 40) .setFunction(EnumBurnFunc.SQUARE_ROOT) .setHeat(0.1D) @@ -3506,7 +3506,7 @@ public class ModItems { .addRadiation(ItemHazard.rabe * ItemHazard.rod_rbmk).toItem() .setUnlocalizedName("rbmk_fuel_ra226be").setTextureName(RefStrings.MODID + ":rbmk_fuel_ra226be"); rbmk_fuel_pu238be = (ItemRBMKRod) new ItemRBMKRod(rbmk_pellet_pu238be) - .setYield(10000000D) + .setYield(50000000D) .setStats(10, 50) .setFunction(EnumBurnFunc.SQUARE_ROOT) .setHeat(0.1D) diff --git a/src/main/java/com/hbm/packet/AnvilCraftPacket.java b/src/main/java/com/hbm/packet/AnvilCraftPacket.java new file mode 100644 index 000000000..eda383cac --- /dev/null +++ b/src/main/java/com/hbm/packet/AnvilCraftPacket.java @@ -0,0 +1,59 @@ +package com.hbm.packet; + +import com.hbm.inventory.AnvilRecipes; +import com.hbm.inventory.AnvilRecipes.AnvilConstructionRecipe; +import com.hbm.inventory.container.ContainerAnvil; + +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.player.EntityPlayer; + +public class AnvilCraftPacket implements IMessage { + + int recipeIndex; + int mode; + + public AnvilCraftPacket() { } + + public AnvilCraftPacket(AnvilConstructionRecipe recipe, int mode) { + this.recipeIndex = AnvilRecipes.getConstruction().indexOf(recipe); + this.mode = mode; + } + + @Override + public void fromBytes(ByteBuf buf) { + this.recipeIndex = buf.readInt(); + this.mode = buf.readInt(); + } + + @Override + public void toBytes(ByteBuf buf) { + buf.writeInt(this.recipeIndex); + buf.writeInt(this.mode); + } + + public static class Handler implements IMessageHandler { + + @Override + public IMessage onMessage(AnvilCraftPacket m, MessageContext ctx) { + + if(m.recipeIndex < 0 || m.recipeIndex >= AnvilRecipes.getConstruction().size()) //recipe is out of range -> bad + return null; + + EntityPlayer p = ctx.getServerHandler().playerEntity; + + if(!(p.openContainer instanceof ContainerAnvil)) //player isn't even using an anvil -> bad + return null; + + ContainerAnvil anvil = (ContainerAnvil)p.openContainer; + AnvilConstructionRecipe recipe = AnvilRecipes.getConstruction().get(m.recipeIndex); + + if(!recipe.isTierValid(anvil.tier)) //player is using the wrong type of anvil -> bad + return null; + + return null; + } + } +} diff --git a/src/main/java/com/hbm/packet/PacketDispatcher.java b/src/main/java/com/hbm/packet/PacketDispatcher.java index 1bd1dc951..f3699218b 100644 --- a/src/main/java/com/hbm/packet/PacketDispatcher.java +++ b/src/main/java/com/hbm/packet/PacketDispatcher.java @@ -99,6 +99,8 @@ public class PacketDispatcher { wrapper.registerMessage(KeybindPacket.Handler.class, KeybindPacket.class, i++, Side.SERVER); //Packet to send NBT data from clients to serverside TEs wrapper.registerMessage(NBTControlPacket.Handler.class, NBTControlPacket.class, i++, Side.SERVER); + //Packet to send for anvil recipes to be crafted + wrapper.registerMessage(AnvilCraftPacket.Handler.class, AnvilCraftPacket.class, i++, Side.SERVER); } } diff --git a/src/main/java/com/hbm/render/tileentity/RenderFEL.java b/src/main/java/com/hbm/render/tileentity/RenderFEL.java index 40a473997..00b8c928d 100644 --- a/src/main/java/com/hbm/render/tileentity/RenderFEL.java +++ b/src/main/java/com/hbm/render/tileentity/RenderFEL.java @@ -42,11 +42,11 @@ public class RenderFEL extends TileEntitySpecialRenderer { switch(fel.mode) { case 0: color = 0x303000; break; - case 1: color = 0x400000; break; + case 1: color = 0xFF1010; break; case 2: color = Color.HSBtoRGB(fel.getWorldObj().getTotalWorldTime() / 50.0F, 1F, 0.3F) & 16777215; break; - case 3: color = 0x100040; break; - case 4: color = 0x003000; break; - case 5: color = 0x306000; break; + case 3: color = 0x150560; break; + case 4: color = 0x054005; break; + case 5: color = 0x156015; break; } int length = 25; diff --git a/src/main/java/com/hbm/tileentity/machine/rbmk/TileEntityRBMKOutgasser.java b/src/main/java/com/hbm/tileentity/machine/rbmk/TileEntityRBMKOutgasser.java index fbebe354c..0c8fcf1be 100644 --- a/src/main/java/com/hbm/tileentity/machine/rbmk/TileEntityRBMKOutgasser.java +++ b/src/main/java/com/hbm/tileentity/machine/rbmk/TileEntityRBMKOutgasser.java @@ -261,4 +261,19 @@ public class TileEntityRBMKOutgasser extends TileEntityRBMKSlottedBase implement nbt.setDouble("progress", this.progress); this.gas.writeToNBT(nbt, "gas"); } + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemStack) { + return getOutput(itemStack) != null && i == 0; + } + + @Override + public boolean canExtractItem(int i, ItemStack itemStack, int j) { + return i == 1; + } + + @Override + public int[] getAccessibleSlotsFromSide(int p_94128_1_) { + return new int[] {0, 1}; + } } diff --git a/src/main/java/com/hbm/util/InventoryUtil.java b/src/main/java/com/hbm/util/InventoryUtil.java index 56f7b4f84..38cee78cc 100644 --- a/src/main/java/com/hbm/util/InventoryUtil.java +++ b/src/main/java/com/hbm/util/InventoryUtil.java @@ -2,6 +2,9 @@ package com.hbm.util; import java.util.List; +import com.hbm.inventory.RecipesCommon.AStack; + +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; @@ -185,4 +188,11 @@ public class InventoryUtil { return stack1.getTagCompound().equals(stack2.getTagCompound()); } + + public static boolean doesPlayerHaveAStacks(EntityPlayer player, List stacks) { + + //ItemStack[] inventory TODO + + return false; + } } diff --git a/src/main/resources/assets/hbm/textures/gui/processing/gui_anvil.png b/src/main/resources/assets/hbm/textures/gui/processing/gui_anvil.png index d8d000cf95ae6da6b26aca2580261b9ea6e5716c..cb4b14457cb7502cccaa62679b059f98ba7f54e6 100755 GIT binary patch literal 3425 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 literal 3225 zcma)9c{r497r&pG!IW*LWEo)$$xFgVL&~mDw)!kt(>AurmdTXxP?kd8NJOGdLMUZq zm-n@#>`bVLGS;zYAKz2&`+e8d_r2G9efK~2Ip@Bw=XuUKzwtf z3d(x<)?B}s2vb->77PW_!)e}VE}UzQkg+fdl>(rBG=J|q;k!PHdS{0_J+b}jO@7V}RB4vvd!k5Bq9HtDK^}HrWjZHQ7Gudi>)H4n{`gv^cCJV&g-a1pdT+m}}=_=z+ZF z!qW03c7R+B9lof^kNx4|g{@$9-R0YAaDOcbA2bJi+wNg9@IU~En%)KtV5NZ+|2OaI zbNopgE03DvnI6;YAuY=n=@DWe^S!GZSXS~V%pwMdbKv?kMJHFcZTJ!oz}@H6OGv#%adI|17>oG`bxI=F}gv>1Izh( zEg%q8>p^pHxe50ZB+#z3UJjKkE{us#iwlIXVIi$+zE8STflDmh|8GbB%vFkp2D)nx zAs@+8Q$M1c4rh-63SkmXX6OHMlaZYI3MFf5&Sx)cUItRT%fU zPnu)aI&`ugtlS+I-s9NM|9)`_Gd)an6+aXADG&>S$1aIfciHB9r)yq6Lr$~rvanpG zsop)@1*OXK!#Q0v+gzIm!;LZb-F<0P!-wND))iF)o-aveu222Bt%~>Ct_)tkpWQ_q zo_j@QIF8-y#6RIU;y~e}LD9d#_NlQJ=M^g&_g?dQ#ZXaqrGfEgDA{R+1r^CdiUVTk2<8I4ml8{Detq$>!*_ehZ`1 z6)rK+4V0oAqX7zK$x?@BI}F}N#dNo52#vNNWomZ5EPXU+f8~>MiKX!>&hnNatI^3c zsjtk${umQKbYIFl%Hv3$v7DEZ)qNVe=d}frTq;%qKQrgllnLU_9u@NP9~62MifG1m zn!GB+o`WsTsP6GS^`}}lpeT)DLv z@abQpf6L!9pKCf7^+Fi*D)J+>X0e$2V4vUiK!u5n;Hxs`dPJSGKZ|i*lq5tL|ogsu`#bI*`2CtzYoo*wMiuZRINb zg$nA+-GDdW&Ey1tQX^Gc7;DgisPAWXqTp zPpvfp^i38oXt1;Kf1B;?0m<84r`myc*r$mJv+(Se+r4u*Mpm_wX+gn)4vl=Mt(sb+SeSQYX%r z^$vYjCx+wdXGR~4tvVgPT;0u+X@=2CmPJrOeB$r=G>G4c4quEZs02QWL4VG7?eC9d`YMu&$V^WttG(SP^8GsC8iBmSv8z z3=!aNK9>vB7B}g?rP5zbjyK=v6YVH*;mjPk=l}g7<Cz3(!D`Zrl~NV&}V4;C*fF2$buxx+jo;b`2)c|NL=5+1Tt?KL5t zV+BkS>3I)T)-<7=IY}iaA{n#`X^9b0?se`O`sFY91K(^)1~uf%;Am*k*Ti1*b{Y2j(6bB-&d17T9uQB+2ABbL@8H*dQ@d4ueqc z9u&}b_s{vYBL)LdCp%izH}FWlJA)Pdwm*}X4?mY*d*)vj2J72cA-<6zW2T;Zl`0W}4B4540 znpuKu`@H{^iBm-zk$GB9Z?4w(6Stm%6o!1ys`yc0+nU*iY5-!fzubLxe{#ph z8jE#(6EO5I6>qICTe(JHT)k98ev)){WsTKSfHoZT*8er$D4)|>**vSi%iXvMACqA;j;ri^m}U5r4V#9&MmsIzD%nH{o3Pe!=vBg;BnNYxutafEJU$