From a847e1827ab7ecc8413cb3add709b972f20aa1cf Mon Sep 17 00:00:00 2001 From: stfwi Date: Tue, 16 Apr 2019 22:03:41 +0200 Subject: [PATCH] Crafting table: History refab and JEI integration. --- 1.12/gradle.properties | 2 +- 1.12/meta/update.json | 3 +- 1.12/readme.md | 8 + .../blocks/BlockDecorCraftingTable.java | 640 +++++++++++++++--- .../wile/engineersdecor/detail/ModConfig.java | 11 +- .../engineersdecor/eapi/jei/JEIPlugin.java | 23 +- .../treated_wood_crafting_table_front.png | Bin 516 -> 521 bytes .../treated_wood_crafting_table_side.png | Bin 483 -> 489 bytes .../treated_wood_crafting_table_top.png | Bin 601 -> 604 bytes .../treated_wood_crafting_table_tray.png | Bin 529 -> 532 bytes .../blocks/furnace/small_lab_furnace_back.png | Bin 574 -> 550 bytes .../furnace/small_lab_furnace_bottom.png | Bin 504 -> 489 bytes .../furnace/small_lab_furnace_front.png | Bin 534 -> 518 bytes .../small_lab_furnace_front_gloom_off.png | Bin 537 -> 184 bytes .../small_lab_furnace_front_gloom_on.png | Bin 667 -> 693 bytes .../furnace/small_lab_furnace_handles.png | Bin 417 -> 399 bytes .../blocks/furnace/small_lab_furnace_left.png | Bin 557 -> 533 bytes .../furnace/small_lab_furnace_right.png | Bin 550 -> 539 bytes .../blocks/furnace/small_lab_furnace_top.png | Bin 515 -> 503 bytes .../gui/treated_wood_crafting_table.png | Bin 25665 -> 27102 bytes meta/update.json | 3 +- 21 files changed, 605 insertions(+), 85 deletions(-) diff --git a/1.12/gradle.properties b/1.12/gradle.properties index 44450e2..a1820e4 100644 --- a/1.12/gradle.properties +++ b/1.12/gradle.properties @@ -4,4 +4,4 @@ org.gradle.jvmargs=-Xmx8G version_minecraft=1.12.2 version_forge=14.23.5.2768 version_jei=4.10.0.198 -version_engineersdecor=1.0.3 +version_engineersdecor=1.0.4-b1 diff --git a/1.12/meta/update.json b/1.12/meta/update.json index f4ccff1..7748218 100644 --- a/1.12/meta/update.json +++ b/1.12/meta/update.json @@ -1,6 +1,7 @@ { "homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/", "1.12.2": { + "1.0.4-b1": "[A] Crafting table: JEI integration for recipe placement added.\n[A] Crafting table: History re-fab added, allowing to quickly select and re-craft recent recipes. Selection with arrow buttons, ingredient placement by clicking the result slot. Automatic item distribution on shift-click. Quick-move buttons.\n[F] Crafting table textures modified to prevent optifine glitches on the edges of the legs.", "1.0.3": "[R] Release based on v1.0.3-b5. Release-to-release changes: * Small laboratory furnace added. * Extensive config options for mod packing and tuning added. * Rendering issues fixes (window bleeding, optifine). * Steel framed window added. * Treated wood pole \"end pieces\" added (two support variants). * Sitting on treated wood stool added including mobs (but not villagers, as these are obviously very upright people). * Lang ru_ru added (github contribution from Yaroslavik). * Creative tab logo changed to mod logo. * Table/crafting table bounding boxes refined. * Standalone \"escape\" recipes added if IE is not installed.", "1.0.3-b5": "[F] Fixed typo in en-en lang file.\n[F] Fixed IE concrete texture missing bailout in log if IE is not installed.\n[F] Using forge multi-layer models for windows to circumvent glitches.\n[M] Changed creative tab logo to the mod logo.\n[A] Added alternative recipes for crafting table and furnace if main IE ingredients are missing (for \"stand-alone\" mod usage).", "1.0.3-b4": "[A] Lab furnace supports electrical speedup when a IE external is placed in one of the two auxiliary slots.\n[F] Fixed window rendering issue (issue #15, thanks to ILLOMIURGE).\n[M] Updated ru_ru lang file (Yaroslavik).", @@ -24,6 +25,6 @@ }, "promos": { "1.12.2-recommended": "1.0.3", - "1.12.2-latest": "1.0.3" + "1.12.2-latest": "1.0.4-b1" } } \ No newline at end of file diff --git a/1.12/readme.md b/1.12/readme.md index d307c08..c3d1e3e 100644 --- a/1.12/readme.md +++ b/1.12/readme.md @@ -10,6 +10,14 @@ Mod sources for Minecraft version 1.12.2. ---- ## Revision history + - v1.0.4-b1 [A] Crafting table: JEI integration for recipe placement added. + [A] Crafting table: History re-fab added, allowing to quickly select + and re-craft recent recipes. Selection with arrow buttons, + ingredient placement by clicking the result slot. Automatic + item distribution on shift-click. Quick-move buttons. + [F] Crafting table textures modified to prevent optifine glitches + on the edges of the legs. + ------------------------------------------------------------------- - v1.0.3 [R] Release based on v1.0.3-b5. Release-to-release changes: * Small laboratory furnace added. diff --git a/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorCraftingTable.java b/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorCraftingTable.java index d9a7d74..c7e4f87 100644 --- a/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorCraftingTable.java +++ b/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorCraftingTable.java @@ -9,7 +9,6 @@ */ package wile.engineersdecor.blocks; -import net.minecraft.client.gui.GuiButtonImage; import wile.engineersdecor.ModEngineersDecor; import net.minecraft.block.Block; import net.minecraft.block.SoundType; @@ -25,6 +24,8 @@ import net.minecraft.inventory.*; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.init.Items; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.item.crafting.Ingredient; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.*; @@ -37,8 +38,11 @@ import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiButtonImage; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import net.minecraftforge.fml.common.registry.GameRegistry; +import net.minecraftforge.registries.IForgeRegistry; import com.google.common.collect.ImmutableList; import wile.engineersdecor.detail.Networking; import javax.annotation.Nonnull; @@ -51,10 +55,14 @@ import java.util.List; public class BlockDecorCraftingTable extends BlockDecorDirected { public static boolean with_assist = true; + public static boolean with_assist_direct_history_refab = false; + public static boolean with_assist_quickmove_buttons = false; - public static final void on_config(boolean without_crafting_assist) + public static final void on_config(boolean without_crafting_assist, boolean with_assist_immediate_history_refab, boolean with_quickmove_buttons) { with_assist = !without_crafting_assist; + with_assist_direct_history_refab = with_assist_immediate_history_refab; + with_assist_quickmove_buttons = with_quickmove_buttons; CraftingHistory.max_history_size(32); } @@ -157,11 +165,15 @@ public class BlockDecorCraftingTable extends BlockDecorDirected private static class CraftingHistory { + public static final int RESULT_STACK_INDEX = 0; + public static final int INPUT_STACKS_BEGIN = 1; public static final List NOTHING = new ArrayList(); + private static int max_history_size_ = 5; private List history_ = new ArrayList(); private int current_ = -1; - private static int max_history_size_ = 5; + private List current_stacks_ = new ArrayList(); + private IRecipe current_recipe_ = null; public CraftingHistory() {} @@ -186,6 +198,7 @@ public class BlockDecorCraftingTable extends BlockDecorDirected } } current_ = (!subsect.hasKey("current")) ? (-1) : MathHelper.clamp(subsect.getInteger("current"), -1, history_.size()-1); + update_current(); } catch(Throwable ex) { ModEngineersDecor.logger.error("Exception reading crafting table history NBT, resetting, exception is:" + ex.getMessage()); clear(); @@ -201,27 +214,39 @@ public class BlockDecorCraftingTable extends BlockDecorDirected } public void clear() - { current_ = -1; history_.clear(); } + { reset_current(); history_.clear(); } - public void reset_curent() - { current_ = -1; } + public void reset_current() + { current_ = -1; current_stacks_ = NOTHING; current_recipe_ = null; } - public void add(final List grid_stacks) + void update_current() { - if(!with_assist) { clear(); return; } - String s = stacks2str(grid_stacks); - if(s.isEmpty()) return; - history_.removeIf(e->e.equals(s)); - history_.add(s); - while(history_.size() > max_history_size()) history_.remove(0); - if(current_ >= history_.size()) current_ = -1; + if((current_ < 0) || (current_ >= history_.size())) { reset_current(); return; } + Tuple> data = str2stacks(history_.get(current_)); + if(data == null) { reset_current(); return; } + current_recipe_ = data.getFirst(); + current_stacks_ = data.getSecond(); } - public String stacks2str(final List grid_stacks) + public void add(final List grid_stacks, IRecipe recipe) { - if((grid_stacks==null) || (grid_stacks.size() != 10)) return ""; + if(!with_assist) { clear(); return; } + String s = stacks2str(grid_stacks, recipe); + String recipe_filter = recipe.getRegistryName().toString() + ";"; + if(s.isEmpty()) return; + history_.removeIf(e->e.equals(s)); + history_.removeIf(e->e.startsWith(recipe_filter)); + history_.add(s); + while(history_.size() > max_history_size()) history_.remove(0); + if(current_ >= history_.size()) reset_current(); + } + + public String stacks2str(final List grid_stacks, IRecipe recipe) + { + if((grid_stacks==null) || (grid_stacks.size() != 10) || (recipe==null)) return ""; if(grid_stacks.get(0).isEmpty()) return ""; final ArrayList items = new ArrayList(); + items.add(recipe.getRegistryName().toString().trim()); for(ItemStack st:grid_stacks) { int meta = st.getMetadata(); items.add( (st.isEmpty()) ? ("") : ((st.getItem().getRegistryName().toString().trim()) + ((meta==0)?(""):("/"+meta)) )); @@ -229,13 +254,21 @@ public class BlockDecorCraftingTable extends BlockDecorDirected return String.join(";", items); } - public List str2stacks(final String entry) + public @Nullable Tuple> str2stacks(final String entry) { try { - if((entry == null) || (entry.isEmpty())) return NOTHING; + if((entry == null) || (entry.isEmpty())) return null; ArrayList item_regnames = new ArrayList(Arrays.asList(entry.split("[;]"))); - if((item_regnames == null) || (item_regnames.size() > 10)) return NOTHING; - while(item_regnames.size() < 10) item_regnames.add(""); + if((item_regnames == null) || (item_regnames.size() < 2) || (item_regnames.size() > 11)) return null; + while(item_regnames.size() < 11) item_regnames.add(""); + IRecipe recipe = null; + try { + final IForgeRegistry recipe_registry = GameRegistry.findRegistry(IRecipe.class); + recipe = recipe_registry.getValue(new ResourceLocation(item_regnames.remove(0))); + } catch(Throwable e) { + ModEngineersDecor.logger.error("Recipe lookup failed: " + e.getMessage()); + } + if(recipe==null) return null; List stacks = new ArrayList(); for(String regname : item_regnames) { ItemStack stack = ItemStack.EMPTY; @@ -244,42 +277,54 @@ public class BlockDecorCraftingTable extends BlockDecorDirected if(regname.indexOf('/') >= 0) { String[] itemdetails = regname.split("[/]"); if(itemdetails.length>0) regname = itemdetails[0]; - try { if(itemdetails.length>1) meta = Integer.parseInt(itemdetails[1]); } catch(Throwable e){meta=0;} // ignore exception here + if(itemdetails.length>1) try { meta=Integer.parseInt(itemdetails[1]); } catch(Throwable e){ meta=0; } // ignore exception here } final Item item = Item.REGISTRY.getObject(new ResourceLocation(regname)); stack = ((item == null) || (item == Items.AIR)) ? ItemStack.EMPTY : (new ItemStack(item, 1, meta)); } stacks.add(stack); } - if((stacks.size() != 10) || (stacks.get(0).isEmpty())) return NOTHING; // invalid size or no result - return stacks; + if((stacks.size() != 10) || (stacks.get(0).isEmpty())) return null; // invalid size or no result + return new Tuple>(recipe, stacks); } catch(Throwable ex) { ModEngineersDecor.logger.error("History stack building failed: " + ex.getMessage()); - return NOTHING; + return null; } } public List current() - { - if((current_ < 0) || (current_ >= history_.size())) { current_ = -1; return NOTHING; } - return str2stacks(history_.get(current_)); - } + { return current_stacks_; } + + public IRecipe current_recipe() + { return current_recipe_; } public void next() { - if(history_.isEmpty()) { current_ = -1; return; } - current_ = ((++current_) >= history_.size()) ? (-1) : (current_); + if(history_.isEmpty()) { + current_ = -1; + } else { + current_ = ((++current_) >= history_.size()) ? (-1) : (current_); + } + update_current(); } public void prev() { - if(history_.isEmpty()) { current_ = -1; return; } - current_ = ((--current_) < -1) ? (history_.size()-1) : (current_); + if(history_.isEmpty()) { + current_ = -1; + } else { + current_ = ((--current_) < -1) ? (history_.size()-1) : (current_); + } + update_current(); } + public void reset_selection() + { current_ = -1; update_current(); } + public String toString() { - StringBuilder s = new StringBuilder("{ current:" + current_ + ", elements:[ "); + String rec = (current_recipe_==null) ? "none" : (current_recipe_.getRegistryName().toString()); + StringBuilder s = new StringBuilder("{ current:" + current_ + ", recipe:'" + rec + "', elements:[ "); for(int i=0; i buttons = new ArrayList(); + protected final boolean history_slot_tooltip[] = {false,false,false,false,false,false,false,false,false,false}; public BGui(InventoryPlayer playerInventory, World world, BlockPos pos, BTileEntity te) - { super(new BContainer(playerInventory, world, pos, te)); this.te = te; } + { super(new BContainer(playerInventory, world, pos, te)); this.te = te; this.player=playerInventory.player; } @Override @SuppressWarnings("unused") @@ -315,12 +366,15 @@ public class BlockDecorCraftingTable extends BlockDecorDirected final int x0=((width - xSize)/2), y0=((height - ySize)/2); buttons.clear(); if(with_assist) { - buttons.add(addButton(new GuiButtonImage(BUTTON_NEXT, x0+156,y0+44, 12,12, 194,44, 12, BACKGROUND))); - buttons.add(addButton(new GuiButtonImage(BUTTON_PREV, x0+156,y0+30, 12,12, 180,30, 12, BACKGROUND))); - // buttons.add(addButton(new GuiButtonImage(BUTTON_FROM_STORAGE, x0+49,y0+34, 9,17, 219,34, 17, BACKGROUND))); - // buttons.add(addButton(new GuiButtonImage(BUTTON_TO_STORAGE, x0+49,y0+52, 9,17, 208,16, 17, BACKGROUND))); - // buttons.add(addButton(new GuiButtonImage(BUTTON_FROM_PLAYER, x0+77,y0+71, 17,9, 198,71, 9, BACKGROUND))); - // buttons.add(addButton(new GuiButtonImage(BUTTON_TO_PLAYER, x0+59,y0+71, 17,9, 180,71, 9, BACKGROUND))); + buttons.add(addButton(new GuiButtonImage(BUTTON_NEXT, x0+158,y0+44, 12,12, 194,44, 12, BACKGROUND))); + buttons.add(addButton(new GuiButtonImage(BUTTON_PREV, x0+158,y0+30, 12,12, 180,30, 12, BACKGROUND))); + buttons.add(addButton(new GuiButtonImage(BUTTON_CLEAR_GRID, x0+158,y0+58, 12,12, 194,8, 12, BACKGROUND))); + if(with_assist_quickmove_buttons) { + buttons.add(addButton(new GuiButtonImage(BUTTON_FROM_STORAGE, x0+49, y0+34, 9,17, 219,34, 17, BACKGROUND))); + buttons.add(addButton(new GuiButtonImage(BUTTON_TO_STORAGE, x0+49, y0+52, 9,17, 208,16, 17, BACKGROUND))); + buttons.add(addButton(new GuiButtonImage(BUTTON_FROM_PLAYER, x0+77, y0+71, 17,9, 198,71, 9, BACKGROUND))); + buttons.add(addButton(new GuiButtonImage(BUTTON_TO_PLAYER, x0+59, y0+71, 17,9, 180,71, 9, BACKGROUND))); + } } } @@ -332,6 +386,26 @@ public class BlockDecorCraftingTable extends BlockDecorDirected renderHoveredToolTip(mouseX, mouseY); } + @Override + protected void renderHoveredToolTip(int mouseX, int mouseY) + { + if((!player.inventory.getItemStack().isEmpty()) || (getSlotUnderMouse() == null)) return; + final Slot slot = getSlotUnderMouse(); + if(!slot.getStack().isEmpty()) { renderToolTip(slot.getStack(), mouseX, mouseY); return; } + if(with_assist) { + int hist_index = -1; + if(slot instanceof BSlotCrafting) { + hist_index = 0; + } else if(slot.inventory instanceof BInventoryCrafting) { + hist_index = slot.getSlotIndex() + 1; + } + if((hist_index < 0) || (hist_index >= history_slot_tooltip.length)) return; + if(!history_slot_tooltip[hist_index]) return; + ItemStack hist_stack = te.history.current().get(hist_index); + if(!hist_stack.isEmpty()) renderToolTip(hist_stack, mouseX, mouseY); + } + } + @Override protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { @@ -340,14 +414,15 @@ public class BlockDecorCraftingTable extends BlockDecorDirected final int x0=((width - xSize)/2), y0=((height - ySize)/2); drawTexturedModalRect(x0, y0, 0, 0, xSize, ySize); if(with_assist) { + for(int i=0; i crafting_template = te.history.current(); if((crafting_template == null) || (crafting_template.isEmpty())) return; - if(inventorySlots.getSlot(0).getHasStack()) return; { int i = 0; for(Tuple e : ((BContainer) inventorySlots).CRAFTING_SLOT_POSITIONS) { + if(i==0) continue; // explicitly here, that is the result slot. if((inventorySlots.getSlot(i).getHasStack())) { - if(!inventorySlots.getSlot(i).getStack().getItem().equals(crafting_template.get(i).getItem())) { + if(!inventorySlots.getSlot(i).getStack().isItemEqual(crafting_template.get(i))) { return; // user has placed another recipe } } @@ -358,7 +433,14 @@ public class BlockDecorCraftingTable extends BlockDecorDirected int i = 0; for(Tuple e : ((BContainer) inventorySlots).CRAFTING_SLOT_POSITIONS) { final ItemStack stack = crafting_template.get(i); - if(!stack.isEmpty()) drawTemplateItemAt(stack, x0, y0, e.getFirst(), e.getSecond()); + if(!stack.isEmpty()) { + if(!inventorySlots.getSlot(i).getHasStack()) history_slot_tooltip[i] = true; + if((i==0) && inventorySlots.getSlot(i).getStack().isItemEqual(crafting_template.get(i))) { + continue; // don't shade the output slot if the result can be crafted. + } else { + drawTemplateItemAt(stack, x0, y0, e.getFirst(), e.getSecond()); + } + } ++i; } } @@ -367,9 +449,10 @@ public class BlockDecorCraftingTable extends BlockDecorDirected protected void drawTemplateItemAt(ItemStack stack, int x0, int y0, int x, int y) { + final float main_zl = zLevel; RenderHelper.disableStandardItemLighting(); RenderHelper.enableGUIStandardItemLighting(); - float zl = itemRender.zLevel; + final float zl = itemRender.zLevel; itemRender.zLevel = -50; itemRender.renderItemIntoGUI(stack, x0+x, y0+y); itemRender.zLevel = zl; @@ -377,7 +460,9 @@ public class BlockDecorCraftingTable extends BlockDecorDirected GlStateManager.color(0.7f, 0.7f, 0.7f, 0.8f); mc.getTextureManager().bindTexture(BACKGROUND); drawTexturedModalRect(x0+x, y0+y, x, y, 16, 16); + RenderHelper.enableGUIStandardItemLighting(); RenderHelper.enableStandardItemLighting(); + zLevel = main_zl; } @Override @@ -386,17 +471,58 @@ public class BlockDecorCraftingTable extends BlockDecorDirected switch(button.id) { case BUTTON_NEXT: case BUTTON_PREV: + case BUTTON_CLEAR_GRID: case BUTTON_FROM_STORAGE: case BUTTON_TO_STORAGE: case BUTTON_FROM_PLAYER: - case BUTTON_TO_PLAYER: { + case BUTTON_TO_PLAYER: + case ACTION_PLACE_CURRENT_HISTORY_SEL: { NBTTagCompound nbt = new NBTTagCompound(); - nbt.setInteger("button", button.id); + nbt.setInteger("action", button.id); Networking.PacketTileNotify.sendToServer(te, nbt); break; } } } + + @Override + protected void handleMouseClick(Slot slot, int slotId, int mouseButton, ClickType type) + { + if(type == ClickType.PICKUP) { + boolean place_refab = (slot instanceof BSlotCrafting) && (!slot.getHasStack()); + if(place_refab && with_assist_direct_history_refab) onHistoryItemPlacement(); // place before crafting -> direct item pick + super.handleMouseClick(slot, slotId, mouseButton, type); + if(place_refab && (!with_assist_direct_history_refab)) onHistoryItemPlacement(); // place after crafting -> confirmation first + return; + } + if((type == ClickType.QUICK_MOVE) && (slotId > 9) && (slot.getHasStack())) { // container slots 0..9 are crafting output and grid + List history = te.history.current(); + boolean palce_in_crafting_grid = (!history.isEmpty()); + if(!palce_in_crafting_grid) { + for(int i=0; i<9; ++i) { + if(!(te.getStackInSlot(i).isEmpty())) { palce_in_crafting_grid = true; break; } + } + } + if(palce_in_crafting_grid) { + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setInteger("action", ACTION_PLACE_SHIFTCLICKED_STACK); + nbt.setInteger("containerslot", slotId); + Networking.PacketTileNotify.sendToServer(te, nbt); + return; + } + } + super.handleMouseClick(slot, slotId, mouseButton, type); + } + + private void onHistoryItemPlacement() + { + if(te.history.current().isEmpty()) return; + final Slot resultSlot = this.getSlotUnderMouse(); // double check + if(!(resultSlot instanceof BSlotCrafting)) return; + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setInteger("action", ACTION_PLACE_CURRENT_HISTORY_SEL); + Networking.PacketTileNotify.sendToServer(te, nbt); + } } //-------------------------------------------------------------------------------------------------------------------- @@ -415,11 +541,12 @@ public class BlockDecorCraftingTable extends BlockDecorDirected protected void onCrafting(ItemStack stack) { if((with_assist) && ((player.world!=null) && (!(player.world.isRemote))) && (!stack.isEmpty())) { + final IRecipe recipe = ((InventoryCraftResult)this.inventory).getRecipeUsed(); final ArrayList grid = new ArrayList(); grid.add(stack); for(int i = 0; i < 9; ++i) grid.add(te.stacks.get(i)); - te.history.add(grid); - te.history.reset_curent(); + te.history.add(grid, recipe); + te.history.reset_current(); te.syncHistory(player); } super.onCrafting(stack); @@ -430,7 +557,7 @@ public class BlockDecorCraftingTable extends BlockDecorDirected // Crafting container //-------------------------------------------------------------------------------------------------------------------- - private static class BContainer extends Container + public static class BContainer extends Container { private final World world; private final BlockPos pos; @@ -449,28 +576,33 @@ public class BlockDecorCraftingTable extends BlockDecorDirected this.te = te; craftMatrix = new BInventoryCrafting(this, te); craftMatrix.openInventory(player); + // container slotId 0 === crafting output addSlotToContainer(new BSlotCrafting(te, playerInventory.player, craftMatrix, craftResult, 0, 134, 35)); slotpositions.add(new Tuple<>(134, 35)); + // container slotId 1..9 === TE slots 0..8 for(int y=0; y<3; ++y) { for(int x=0; x<3; ++x) { int xpos = 60+x*18; int ypos = 17+y*18; - addSlotToContainer(new Slot(craftMatrix, x+y*3, xpos, ypos)); // block slots 0..8 + addSlotToContainer(new Slot(craftMatrix, x+y*3, xpos, ypos)); slotpositions.add(new Tuple<>(xpos, ypos)); } } CRAFTING_SLOT_POSITIONS = ImmutableList.copyOf(slotpositions); + // container slotId 10..36 === player slots: 9..35 for(int y=0; y<3; ++y) { - for (int x=0; x<9; ++x) { - addSlotToContainer(new Slot(playerInventory, x+y*9+9, 8+x*18, 86+y*18)); // player slots: 9..35 + for(int x=0; x<9; ++x) { + addSlotToContainer(new Slot(playerInventory, x+y*9+9, 8+x*18, 86+y*18)); } } + // container slotId 37..45 === player slots: 0..8 for(int x=0; x<9; ++x) { - addSlotToContainer(new Slot(playerInventory, x, 8+x*18, 144)); // player slots: 0..8 + addSlotToContainer(new Slot(playerInventory, x, 8+x*18, 144)); } + // container slotId 46..53 === TE slots 9..17 (storage) for(int y=0; y<4; ++y) { - for (int x=0; x<2; ++x) { - addSlotToContainer(new Slot(craftMatrix, x+y*2+9, 8+x*18, 9+y*18)); // block slots 9..17 + for(int x=0; x<2; ++x) { + addSlotToContainer(new Slot(craftMatrix, x+y*2+9, 8+x*18, 9+y*18)); } } onCraftMatrixChanged(craftMatrix); @@ -541,6 +673,9 @@ public class BlockDecorCraftingTable extends BlockDecorDirected } return stack; } + + public void setCraftingMatrixSlot(int slot_index, ItemStack stack) + { craftMatrix.setInventorySlotContents(slot_index, stack.copy()); } } //-------------------------------------------------------------------------------------------------------------------- @@ -599,7 +734,9 @@ public class BlockDecorCraftingTable extends BlockDecorDirected //-------------------------------------------------------------------------------------------------------------------- public static class BTileEntity extends TileEntity implements IInventory, Networking.IPacketReceiver { + public static final int CRAFTING_SLOTS_BEGIN = 0; public static final int NUM_OF_CRAFTING_SLOTS = 9; + public static final int STORAGE_SLOTS_BEGIN = NUM_OF_CRAFTING_SLOTS; public static final int NUM_OF_STORAGE_SLOTS = 8; public static final int NUM_OF_SLOTS = NUM_OF_CRAFTING_SLOTS+NUM_OF_STORAGE_SLOTS; protected NonNullList stacks; @@ -625,35 +762,384 @@ public class BlockDecorCraftingTable extends BlockDecorDirected history.write(compound); } + // private aux methods --------------------------------------------------------------------- + + private boolean itemstack_recipe_match(ItemStack grid_stack, ItemStack history_stack) + { + if(history.current_recipe()!=null) { + boolean grid_match, dist_match; + for(final Ingredient ingredient:history.current_recipe().getIngredients()) { + grid_match = false; dist_match = false; + for(final ItemStack match:ingredient.getMatchingStacks()) { + if(match.isItemEqualIgnoreDurability(grid_stack)) dist_match = true; + if(match.isItemEqualIgnoreDurability(history_stack)) grid_match = true; + if(dist_match && grid_match) return true; + } + } + } + return false; + } + + private List crafting_slot_stacks_to_add() + { + final ArrayList slots = new ArrayList(); + final List tocraft = history.current(); + final int stack_sizes[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1}; + if(tocraft.isEmpty()) return slots; + for(int i=0; i<9; ++i) { + if((i+CraftingHistory.INPUT_STACKS_BEGIN) >= tocraft.size()) break; + final ItemStack needed = tocraft.get(i+CraftingHistory.INPUT_STACKS_BEGIN); + final ItemStack palced = getStackInSlot(i+CRAFTING_SLOTS_BEGIN); + if(needed.isEmpty() && (!palced.isEmpty())) return slots; // history vs grid mismatch. + if((!palced.isEmpty()) && (!itemstack_recipe_match(needed, palced))) return slots; // also mismatch + if(!needed.isEmpty()) stack_sizes[i] = palced.getCount(); + } + int min_placed = 64, max_placed=0; + for(int i=0; i<9; ++i) { // todo: check if java has something like std::accumulate<>() + if(stack_sizes[i] < 0) continue; + min_placed = Math.min(min_placed, stack_sizes[i]); + max_placed = Math.max(max_placed, stack_sizes[i]); + } + int fillup_size = (max_placed <= min_placed) ? (min_placed + 1) : max_placed; + for(int i=0; i<9; ++i) { + if(stack_sizes[i] < 0) continue; + if(fillup_size > getStackInSlot(i+CRAFTING_SLOTS_BEGIN).getMaxStackSize()) return slots; // can't fillup all + } + for(int i=0; i<9; ++i) { + if(stack_sizes[i] < 0) { + slots.add(ItemStack.EMPTY); + } else { + ItemStack st = getStackInSlot(i+CRAFTING_SLOTS_BEGIN).copy(); + if(st.isEmpty()) { + st = tocraft.get(i+CraftingHistory.INPUT_STACKS_BEGIN).copy(); + st.setCount(Math.min(st.getMaxStackSize(), fillup_size)); + } else { + st.setCount(MathHelper.clamp(fillup_size-st.getCount(), 0, st.getMaxStackSize())); + } + slots.add(st); + } + } + return slots; + } + + /** + * Moves as much items from the stack to the slots in range [first_slot, last_slot] of the inventory, + * filling up existing stacks first, then (player inventory only) checks appropriate empty slots next + * to stacks that have that item already, and last uses any empty slot that can be found. + * Returns the stack that is still remaining in the referenced `stack`. + */ + private ItemStack move_stack_to_inventory(final ItemStack stack_to_move, IInventory inventory, final int slot_begin, final int slot_end, boolean only_fillup) + { + final ItemStack mvstack = stack_to_move.copy(); + if((mvstack.isEmpty()) || (slot_begin < 0) || (slot_end > inventory.getSizeInventory())) return mvstack; + // first iteration: fillup existing stacks + for(int i = slot_begin; i < slot_end; ++i) { + final ItemStack stack = inventory.getStackInSlot(i); + if((stack.isEmpty()) || (!stack.isItemEqual(mvstack))) continue; + int nmax = stack.getMaxStackSize() - stack.getCount(); + if(mvstack.getCount() <= nmax) { + stack.setCount(stack.getCount()+mvstack.getCount()); + mvstack.setCount(0); + inventory.setInventorySlotContents(i, stack); + return mvstack; + } else { + stack.setCount(stack.getMaxStackSize()); + mvstack.shrink(nmax); + inventory.setInventorySlotContents(i, stack); + } + } + if(only_fillup) return mvstack; + if(inventory instanceof InventoryPlayer) { + // second iteration: use appropriate empty slots + for(int i = slot_begin+1; i < slot_end-1; ++i) { + final ItemStack stack = inventory.getStackInSlot(i); + if(!stack.isEmpty()) continue; + if((!inventory.getStackInSlot(i+1).isItemEqual(mvstack)) && (!inventory.getStackInSlot(i-1).isItemEqual(mvstack))) continue; + inventory.setInventorySlotContents(i, mvstack.copy()); + mvstack.setCount(0); + return mvstack; + } + } + // third iteration: use any empty slots + for(int i = slot_begin; i < slot_end; ++i) { + final ItemStack stack = inventory.getStackInSlot(i); + if(!stack.isEmpty()) continue; + inventory.setInventorySlotContents(i, mvstack.copy()); + mvstack.setCount(0); + return mvstack; + } + return mvstack; + } + + /** + * Moves as much items from the slots in range [first_slot, last_slot] of the inventory into a new stack. + * Implicitly shrinks the inventory stacks and the `request_stack`. + */ + private ItemStack move_stack_from_inventory(IInventory inventory, final ItemStack request_stack, final int slot_begin, final int slot_end) + { + ItemStack fetched_stack = request_stack.copy(); + fetched_stack.setCount(0); + int n_left = request_stack.getCount(); + while(n_left > 0) { + int smallest_stack_size = 0; + int smallest_stack_index = -1; + for(int i = slot_begin; i < slot_end; ++i) { + final ItemStack stack = inventory.getStackInSlot(i); + if((!stack.isEmpty()) && (stack.isItemEqual(request_stack))) { + // Never automatically place stuff with nbt (except a few allowed like "Damage"), + // as this could be a full crate, a valuable tool item, etc. For these recipes + // the user has to place this item manually. + if(stack.hasTagCompound()) { + final NBTTagCompound nbt = stack.getTagCompound(); + int n = stack.getTagCompound().getSize(); + if((n > 0) && (stack.getTagCompound().hasKey("Damage"))) --n; + if(n > 0) continue; + } + fetched_stack = stack.copy(); // copy exact stack with nbt and tool damage, otherwise we have an automagical repair of items. + fetched_stack.setCount(0); + int n = stack.getCount(); + if((n < smallest_stack_size) || (smallest_stack_size <= 0)) { + smallest_stack_size = n; + smallest_stack_index = i; + } + } + } + if(smallest_stack_index < 0) { + break; // no more items available + } else { + int n = Math.min(n_left, smallest_stack_size); + n_left -= n; + fetched_stack.grow(n); + ItemStack st = inventory.getStackInSlot(smallest_stack_index); + st.shrink(n); + inventory.setInventorySlotContents(smallest_stack_index, st); + } + } + return fetched_stack; + } + + private boolean clear_grid_to_storage(EntityPlayer player) + { + boolean changed = false; + for(int grid_i = CRAFTING_SLOTS_BEGIN; grid_i < (CRAFTING_SLOTS_BEGIN + NUM_OF_CRAFTING_SLOTS); ++grid_i) { + ItemStack stack = getStackInSlot(grid_i); + if(stack.isEmpty()) continue; + ItemStack remaining = move_stack_to_inventory(stack, this, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN+NUM_OF_STORAGE_SLOTS, false); + setInventorySlotContents(grid_i, remaining); + changed = true; + } + return changed; + } + + private boolean clear_grid_to_player(EntityPlayer player) + { + boolean changed = false; + for(int grid_i = CRAFTING_SLOTS_BEGIN; grid_i < (CRAFTING_SLOTS_BEGIN + NUM_OF_CRAFTING_SLOTS); ++grid_i) { + ItemStack remaining = getStackInSlot(grid_i); + if(remaining.isEmpty()) continue; + remaining = move_stack_to_inventory(remaining, player.inventory,9, 36, true); // prefer filling up inventory stacks + remaining = move_stack_to_inventory(remaining, player.inventory,0, 9, true); // then fill up the hotbar stacks + remaining = move_stack_to_inventory(remaining, player.inventory,9, 36, false); // then allow empty stacks in inventory + remaining = move_stack_to_inventory(remaining, player.inventory,0, 9, false); // then new stacks in the hotbar + this.setInventorySlotContents(grid_i, remaining); + changed = true; + } + return changed; + } + + enum EnumRefabPlacement { UNCHANGED, INCOMPLETE, PLACED } + private EnumRefabPlacement place_refab_stacks(IInventory inventory, final int slot_begin, final int slot_end) + { + List to_fill = crafting_slot_stacks_to_add(); + boolean slots_changed = false; + boolean missing_item = false; + int num_slots_placed = 0; + if(!to_fill.isEmpty()) { + for(int it_guard=63; it_guard>=0; --it_guard) { + boolean slots_updated = false; + for(int i = 0; i < 9; ++i) { + final ItemStack req_stack = to_fill.get(i).copy(); + if(req_stack.isEmpty()) continue; + req_stack.setCount(1); + to_fill.get(i).shrink(1); + final ItemStack mv_stack = move_stack_from_inventory(inventory, req_stack, slot_begin, slot_end); + if(mv_stack.isEmpty()) { missing_item=true; continue; } + // sizes already checked + ItemStack grid_stack = getStackInSlot(i + CRAFTING_SLOTS_BEGIN).copy(); + if(grid_stack.isEmpty()) { + grid_stack = mv_stack.copy(); + } else { + grid_stack.grow(mv_stack.getCount()); + } + setInventorySlotContents(i + CRAFTING_SLOTS_BEGIN, grid_stack); + slots_changed = true; + slots_updated = true; + } + if(!slots_updated) break; + } + } + if(!slots_changed) { + return EnumRefabPlacement.UNCHANGED; + } else if(missing_item) { + return EnumRefabPlacement.INCOMPLETE; + } else { + return EnumRefabPlacement.PLACED; + } + } + + private EnumRefabPlacement distribute_stack(IInventory inventory, final int slotno) + { + List to_refab = crafting_slot_stacks_to_add(); + ItemStack to_distribute = inventory.getStackInSlot(slotno).copy(); + if(to_distribute.isEmpty()) return EnumRefabPlacement.UNCHANGED; + int matching_grid_stack_sizes[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1}; + int max_matching_stack_size = -1; + int min_matching_stack_size = 65; + int total_num_missing_stacks = 0; + for(int i=0; i<9; ++i) { + final ItemStack grid_stack = getStackInSlot(i + CRAFTING_SLOTS_BEGIN); + final ItemStack refab_stack = to_refab.isEmpty() ? ItemStack.EMPTY : to_refab.get(i).copy(); + if((!grid_stack.isEmpty()) && (grid_stack.isItemEqual(to_distribute))) { + matching_grid_stack_sizes[i] = grid_stack.getCount(); + total_num_missing_stacks += grid_stack.getMaxStackSize()-grid_stack.getCount(); + if(max_matching_stack_size < matching_grid_stack_sizes[i]) max_matching_stack_size = matching_grid_stack_sizes[i]; + if(min_matching_stack_size > matching_grid_stack_sizes[i]) min_matching_stack_size = matching_grid_stack_sizes[i]; + } else if((!refab_stack.isEmpty()) && (refab_stack.isItemEqual(to_distribute))) { + matching_grid_stack_sizes[i] = 0; + total_num_missing_stacks += grid_stack.getMaxStackSize(); + if(max_matching_stack_size < matching_grid_stack_sizes[i]) max_matching_stack_size = matching_grid_stack_sizes[i]; + if(min_matching_stack_size > matching_grid_stack_sizes[i]) min_matching_stack_size = matching_grid_stack_sizes[i]; + } else if(grid_stack.isEmpty() && (!refab_stack.isEmpty())) { + if(itemstack_recipe_match(to_distribute, refab_stack)) { + matching_grid_stack_sizes[i] = 0; + total_num_missing_stacks += grid_stack.getMaxStackSize(); + if(max_matching_stack_size < matching_grid_stack_sizes[i]) max_matching_stack_size = matching_grid_stack_sizes[i]; + if(min_matching_stack_size > matching_grid_stack_sizes[i]) min_matching_stack_size = matching_grid_stack_sizes[i]; + } + } + } + if(min_matching_stack_size < 0) return EnumRefabPlacement.UNCHANGED; + final int stack_limit_size = Math.min(to_distribute.getMaxStackSize(), getInventoryStackLimit()); + if(min_matching_stack_size >= stack_limit_size) return EnumRefabPlacement.UNCHANGED; + int n_to_distribute = to_distribute.getCount(); + for(int it_guard=63; it_guard>=0; --it_guard) { + if(n_to_distribute <= 0) break; + for(int i=0; i<9; ++i) { + if(n_to_distribute <= 0) break; + if(matching_grid_stack_sizes[i] == min_matching_stack_size) { + ++matching_grid_stack_sizes[i]; + --n_to_distribute; + } + } + if(min_matching_stack_size < max_matching_stack_size) { + ++min_matching_stack_size; // distribute short stacks + } else { + ++min_matching_stack_size; // stacks even, increase all + max_matching_stack_size = min_matching_stack_size; + } + if(min_matching_stack_size >= stack_limit_size) break; // all full + } + if(n_to_distribute == to_distribute.getCount()) return EnumRefabPlacement.UNCHANGED; // was already full + if(n_to_distribute <= 0) { + inventory.setInventorySlotContents(slotno, ItemStack.EMPTY); + } else { + to_distribute.setCount(n_to_distribute); + inventory.setInventorySlotContents(slotno, to_distribute); + } + for(int i=0; i<9; ++i) { + if(matching_grid_stack_sizes[i] < 0) continue; + ItemStack grid_stack = getStackInSlot(i + CRAFTING_SLOTS_BEGIN).copy(); + if(grid_stack.isEmpty()) grid_stack = to_distribute.copy(); + grid_stack.setCount(matching_grid_stack_sizes[i]); + setInventorySlotContents(i + CRAFTING_SLOTS_BEGIN, grid_stack); + } + return EnumRefabPlacement.PLACED; + } + // Networking.IPacketReceiver -------------------------------------------------------------- @Override public void onClientPacketReceived(EntityPlayer player, NBTTagCompound nbt) { - if(with_assist && nbt.hasKey("button")) { - switch(nbt.getInteger("button")) { - case BGui.BUTTON_NEXT: + if((world.isRemote) || (!(player.openContainer instanceof BContainer))) return; + final BContainer container = (BContainer)player.openContainer; + if(container.te != this) return; + boolean te_changed = false; + boolean player_inventory_changed = false; + if(with_assist && nbt.hasKey("action")) { + switch(nbt.getInteger("action")) { + case BGui.BUTTON_NEXT: { history.next(); syncHistory(player); - break; - case BGui.BUTTON_PREV: + // implicitly clear the grid, so that the player can see the refab, and that no recipe is active. + if(clear_grid_to_player(player)) { te_changed = true; player_inventory_changed = true; } + if(clear_grid_to_storage(player)) te_changed = true; + } break; + case BGui.BUTTON_PREV: { history.prev(); syncHistory(player); - break; - case BGui.BUTTON_FROM_STORAGE: - //System.out.println("BUTTON_FROM_STORAGE"); - break; - case BGui.BUTTON_TO_STORAGE: - //System.out.println("BUTTON_TO_STORAGE"); - break; - case BGui.BUTTON_FROM_PLAYER: - //System.out.println("BUTTON_FROM_PLAYER"); - break; - case BGui.BUTTON_TO_PLAYER: - //System.out.println("BUTTON_TO_PLAYER"); - break; + if(clear_grid_to_player(player)) { te_changed = true; player_inventory_changed = true; } + if(clear_grid_to_storage(player)) te_changed = true; + } break; + case BGui.BUTTON_CLEAR_GRID: { + history.reset_selection(); + syncHistory(player); + if(clear_grid_to_player(player)) { te_changed = true; player_inventory_changed = true; } + if(clear_grid_to_storage(player)) te_changed = true; + } break; + case BGui.BUTTON_TO_STORAGE: { + if(clear_grid_to_storage(player)) te_changed = true; + } break; + case BGui.BUTTON_TO_PLAYER: { + if(clear_grid_to_player(player)) { te_changed = true; player_inventory_changed = true; } + } break; + case BGui.BUTTON_FROM_STORAGE: { + EnumRefabPlacement from_storage = place_refab_stacks(this, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN + NUM_OF_STORAGE_SLOTS); + if(from_storage != EnumRefabPlacement.UNCHANGED) te_changed = true; + } break; + case BGui.BUTTON_FROM_PLAYER: { + EnumRefabPlacement from_player_inv = place_refab_stacks(player.inventory, 9, 36); + if(from_player_inv != EnumRefabPlacement.UNCHANGED) { te_changed = true; player_inventory_changed = true; } + if(from_player_inv != EnumRefabPlacement.PLACED) { + EnumRefabPlacement from_hotbar = place_refab_stacks(player.inventory, 0, 9); + if(from_hotbar != EnumRefabPlacement.UNCHANGED) { te_changed = true; player_inventory_changed = true; } + } + } break; + case BGui.ACTION_PLACE_CURRENT_HISTORY_SEL: { + EnumRefabPlacement from_storage = place_refab_stacks(this, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN + NUM_OF_STORAGE_SLOTS); + if(from_storage != EnumRefabPlacement.UNCHANGED) te_changed = true; + if(from_storage != EnumRefabPlacement.PLACED) { + EnumRefabPlacement from_player_inv = place_refab_stacks(player.inventory, 9, 36); + if(from_player_inv != EnumRefabPlacement.UNCHANGED) { te_changed = true; player_inventory_changed = true; } + if(from_player_inv != EnumRefabPlacement.PLACED) { + EnumRefabPlacement from_hotbar = place_refab_stacks(player.inventory, 0, 9); + if(from_hotbar != EnumRefabPlacement.UNCHANGED) { te_changed = true; player_inventory_changed = true; } + } + } + } break; + case BGui.ACTION_PLACE_SHIFTCLICKED_STACK: { + final int container_slot_id = nbt.getInteger("containerslot"); + if((container_slot_id < 10) || (container_slot_id > 53)) break; // out of range + if(container_slot_id >= 46) { + // from storage + final int storage_slot = container_slot_id - 46 + STORAGE_SLOTS_BEGIN; + EnumRefabPlacement stat = distribute_stack(this, storage_slot); + if(stat != EnumRefabPlacement.UNCHANGED) te_changed = true; + } else { + // from player + int player_slot = (container_slot_id >= 37) ? (container_slot_id-37) : (container_slot_id-10+9); + EnumRefabPlacement stat = distribute_stack(player.inventory, player_slot); + if(stat != EnumRefabPlacement.UNCHANGED) { player_inventory_changed = true; te_changed = true; } + } + } break; } } + if(te_changed) markDirty(); + if(player_inventory_changed) player.inventory.markDirty(); + if(te_changed || player_inventory_changed) { + container.onCraftMatrixChanged(this); + container.detectAndSendChanges(); + } } @Override diff --git a/1.12/src/main/java/wile/engineersdecor/detail/ModConfig.java b/1.12/src/main/java/wile/engineersdecor/detail/ModConfig.java index 280dd24..4feaf14 100644 --- a/1.12/src/main/java/wile/engineersdecor/detail/ModConfig.java +++ b/1.12/src/main/java/wile/engineersdecor/detail/ModConfig.java @@ -107,6 +107,9 @@ public class ModConfig @Config.Name("Without ladder speed boost") public boolean without_ladder_speed_boost = false; + @Config.Comment({"Disable history refabrication feature of the treated wood crafting table."}) + @Config.Name("Without crafting table history") + public boolean without_crafting_table_history = false; } @Config.Comment({ @@ -192,6 +195,12 @@ public class ModConfig @Config.Name("Chairs: Stand up chance %") @Config.RangeDouble(min=0.001, max=10) public double chair_mob_standup_probability_percent = 1; + + @Config.Comment({"Enables small quick-move arrows from/to player/block storage. " + + "Makes the UI a bit too busy, therefore disabled by default." + }) + @Config.Name("Crafting table: Move buttons") + public boolean with_crafting_quickmove_buttons = false; } @SuppressWarnings("unused") @@ -251,7 +260,7 @@ public class ModConfig if(tweaks.furnace_smelts_nuggets) ModRecipes.furnaceRecipeOverrideSmeltsOresToNuggets(); BlockDecorChair.on_config(optout.without_chair_sitting, optout.without_mob_chair_sitting, tweaks.chair_mob_sitting_probability_percent, tweaks.chair_mob_standup_probability_percent); BlockDecorLadder.on_config(optout.without_ladder_speed_boost); - BlockDecorCraftingTable.on_config(!zmisc.with_experimental); + BlockDecorCraftingTable.on_config(optout.without_crafting_table_history, false, tweaks.with_crafting_quickmove_buttons); } } diff --git a/1.12/src/main/java/wile/engineersdecor/eapi/jei/JEIPlugin.java b/1.12/src/main/java/wile/engineersdecor/eapi/jei/JEIPlugin.java index 36262a5..8c1d110 100644 --- a/1.12/src/main/java/wile/engineersdecor/eapi/jei/JEIPlugin.java +++ b/1.12/src/main/java/wile/engineersdecor/eapi/jei/JEIPlugin.java @@ -8,12 +8,13 @@ */ package wile.engineersdecor.eapi.jei; +import wile.engineersdecor.ModEngineersDecor; +import wile.engineersdecor.blocks.BlockDecorCraftingTable; +import wile.engineersdecor.blocks.ModBlocks; +import wile.engineersdecor.detail.ModConfig; import net.minecraft.block.Block; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import wile.engineersdecor.ModEngineersDecor; -import wile.engineersdecor.blocks.ModBlocks; -import wile.engineersdecor.detail.ModConfig; @mezz.jei.api.JEIPlugin public class JEIPlugin implements mezz.jei.api.IModPlugin @@ -22,6 +23,7 @@ public class JEIPlugin implements mezz.jei.api.IModPlugin @SuppressWarnings("deprecation") public void register(mezz.jei.api.IModRegistry registry) { + // Block/item hiding try { for(Block e:ModBlocks.getRegisteredBlocks()) { if(ModConfig.isOptedOut(e)) { @@ -37,7 +39,20 @@ public class JEIPlugin implements mezz.jei.api.IModPlugin } } } catch(Throwable e) { - ModEngineersDecor.logger.warn("Exception in JEI opt-out processing: '" + e.getMessage() + "', skipping further JEI processing."); + ModEngineersDecor.logger.warn("Exception in JEI opt-out processing: '" + e.getMessage() + "', skipping further JEI optout processing."); + } + // Crafting table registration + if(!ModConfig.optout.without_crafting_table) { + try { + mezz.jei.api.recipe.transfer.IRecipeTransferRegistry recipeTranferRegistry = registry.getRecipeTransferRegistry(); + recipeTranferRegistry.addRecipeTransferHandler( + BlockDecorCraftingTable.BContainer.class, + mezz.jei.api.recipe.VanillaRecipeCategoryUid.CRAFTING, + 1, 9, 10, 44 + ); + } catch(Throwable e) { + ModEngineersDecor.logger.warn("Exception in JEI crafting table handler registration: '" + e.getMessage() + "'."); + } } } } diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/blocks/crafting_table/treated_wood_crafting_table_front.png b/1.12/src/main/resources/assets/engineersdecor/textures/blocks/crafting_table/treated_wood_crafting_table_front.png index 8fc207a6cabaf3ad3a47a8a49af17fb7d9e96d96..06069e9209c5d07195e47c5ae1e1fd556c5af0cd 100644 GIT binary patch delta 495 zcmVm7{C`hPla3-3i6S<`?94pd6f^UWw*gIFjZ7^@glScRAEz%=6^v~3z-Q(dSW6%XNAd~ zX?BuC5mW^PGQm=5G)VY01(_g#6~&(4+;Dey2f&Yq2e!K%DuPF#s)($VHD2HM?60n< zwQ_%dkFjR2wNgsK%&4`}T0>Pav*p}OGJ>Cn17^lFjsOcFA`lTGlgwnl->=0vW`))q zfWzTHSL;%?>VLn0%%qe;DTSw}N8E#=g4GRVl0dD-IM1hOfC7|K7{_tR?#_}H5+ObC z2;80HaHNRPzr64&1DNNTuIm_vfrwa_AtMk~Hf9{hk<7&1`EY&BG)*T!YYl*px3{P& z<7%$8LMC%-yxVS>=a~eCVfgb42JrapD>vIqp86v%yJ%bfr;F$BynlPib3efD)6zj_ zN&-%DP8Y9U&r^w$2OjHiM*Wz0Kq;I6Rh1%1`1uP^D3Z&ozXCRE>&KL{`<)31%=2Fn l+Dd%8IS-g)@owtk{SEkM>`)*Y(-i;!002ovPDHLkV1mZ{yG6&+ht~S}XVW z_hPKsYps-0Ff(ecwAN5n%xpO~lZ@c!;eeSjjUxaC5D|z7kx6E<+wIok9J4}e4#44X zpsRH$TlHT+W`9yjp_IaY|A>1~RIs{%OcJQo80YyE4N!nm3gb8~+1**vLL#IG9)Y`a z9F7zb`llzJWdQR$({&xgFc1;zGGqjz%EpZ2IFgyTJ8y1on5O9jXsrS8{`MACWn9g* zR>)*-jaS<(^E{KlFbscw!2lk=e&*fwf_;DF%lBURk7GW*eVMN>FZj_9rw%$(5^$1p zdhzV_JOL&TJl5fi`Z4iWk11#OI};L^=f5Jfm3X;1 g513=|ZtCLw4HFve5sKwjPXGV_07*qoM6N<$f-A$^LI3~& diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/blocks/crafting_table/treated_wood_crafting_table_side.png b/1.12/src/main/resources/assets/engineersdecor/textures/blocks/crafting_table/treated_wood_crafting_table_side.png index 273905e6cd306ca0af527197242ac24e5184cf1c..f059bb7a9362da9efe28a9056e87931031af8c55 100644 GIT binary patch delta 463 zcmV;=0WkjK1L*^hB!3BTNLh0L01m(a01m(bYSxJf0004-Nklz`5423_* zcK6hfN~+i-74E_PPr#Z3P}xCcL13nB>9O!k6E=)i{(1WJWZ6DH-zy{xFf$BjwJ;*V zz|8=NNB}Uy45~XRQ2``zTo*z~b;r%879*6H!O|*`$x;iF0Dn-3DqwAuErP8FLO6!I zfq^uu4F(8)Wg>wAwK($*~F zrPhkOvn~s#^Le*gYu(qG$@zTdbUMwu`9MKy4R@!Mf`HygTyx_8T5P;Q(uO1O(z%9Io1!S_jx7iAcO`Zp7PJM8ai?GpD&zOk~`4 zfI~6OuYLtAfPjhdg*n1#^W4Id_ zNVD2tfZ%r~5*Sd6V*pQ2Pb#HgW@IF7X=EmuQ?|R$R?Lt@L?DUh=Vz+`>$*~FrPhkO zvn~slZ9AmaT90#PvTYle%VqlJfP&TK)uF%BH4|S3_xpPU;T6+QX-Z`C4NJ0|5&njjH z9+5 diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/blocks/crafting_table/treated_wood_crafting_table_top.png b/1.12/src/main/resources/assets/engineersdecor/textures/blocks/crafting_table/treated_wood_crafting_table_top.png index 2e9aeadf18f5f614aa9198de84b6abf9042eaf7e..0462c679bec5110773e234593cccc0fe3dfbb58b 100644 GIT binary patch delta 29 icmcb~a))JtiV$akM`SSr1K$A0 delta 26 fcmcb^a+76(3O`$tx4R3&e-K=-clqRvW@=0ThE57% diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/blocks/crafting_table/treated_wood_crafting_table_tray.png b/1.12/src/main/resources/assets/engineersdecor/textures/blocks/crafting_table/treated_wood_crafting_table_tray.png index 530e0bf6e33eefe9447ca80c417f1c3056d14133..cc16e1fe21364f8d72d3f509029e95278d5e3ae9 100644 GIT binary patch delta 29 icmbQpGKFP=iV$akM`SSr1K$A$ zcy3O9B>Vqg7LRwvMp7OaXQ`s#0Yvv{p+8?=RarzP-W)R{GogyiqP0e5keNgTW{$hj z+<8aPGLv=-P=c7Incf3KZ0m-ZBQu(rA&HE{-DxI3 z%*#wwA%wX>!8A>nfGUb%&t!(lhzMlDWSEIzQpk*~y0|1VRg2 zL}iY>Km`#A)PJxbVLgJ(k$^OASJgEGnIS<*WF;AaJ_W^qn3+8GoyX$=z;l1{{d`_B zljAtJdE<4y$V#63PG(UBX6Bd)H}U)TFRFf0InRTtA~Odx6YVzrSOUyVxI0Mvee8q0 zgqb0RXGvoPp8F2yQjl2H#jRl5HsXTzNkHO?*x0r^_ka5xfQT4UNTH_z|mo>1V8Q8-B P0000|5=iIWHgp$2p|i}v8q_&f&#l=xAgJ(S(Qa(;>|HLG83xEELv-12AN4jVCJ|R z&7D^SEi+lS8&u(DAQ2Hn22>#l%0VEBs-k(L0G>};WuYpLT%#ffYf3lK{K;Hw!fS8%w_nrIw4!~o7@b!3H zGLz#tc=N{de3F$s_MOb43e3zg6K>-D{TEd~shsCQRgswknu+!{{a6CbO}INq{Jrmk zyo8w{hG$9R4LtT8(4`=;s*78}wr#`(?K=U9D`I2YZrpA+03u@aq9`KAl&`PHkOiE_ zb{EUM46uUe9jY)10q#Z#ny%dEX{N_Gw5%)o?nc2fFaOg)u&gWYK8gp$et!_zfg#ym zhPx9zFgGGPZbp3%L7d0I0{gn>{X z!3xaRr!T-0V2}{dHW7)tiA=f*Bmk;58Oi;AC%T)+g)xc%gMV$@rmHZwbr+~<_%lW5jpy4L-v&oPbnfW;+gQ)#Ja(kxOg#?icG4f%Y85cbJ z8>D0bLI3e1h8wsb$!P7PRZy-u@t9*U-05gwG@-GLn^v zF;$b;T#NPm{O#KF_4g~?b1aHL3cBhFnqtoT<>mWT^B>hSG>a;U?MeUu002ovPDHLk FV1mv1(|-T} delta 458 zcmV;*0X6>V1NZ}wBo78+OGiWi{{a60|De66laV19f0#)`K~y-)MUz2t96<;Kv!K`V zC#{{MfZKPY6cx1oHXHA}=C=0Hw=;sOjcvM(1d@;fcZ0y)NP$8a2n7rk+_@4q^m#zplXwme0+Qm-A&}e7)5}=Hg3~Z7-Jg*dq1$7j36>m zhydu?e+UqP&XkdAFkmBzP*7)JcXNi{s5S=L4bmt&N~ELc>+1%a3}Hi56&V45-2<|U zh`=5eXD=dyPz=;*AoA>T{;3*hxXFAzGUP>OK8IuwwI3t5XNp}&5V;T|AI6z+!Lz?X zN)|wbz@iN+Z|uDXrh-hS4%~=QFzy_PUCr5ae|+u+LsgA4=yJ!0g+gOzRq<6h$jJjL zGckQV?Kb!OU;f?i2eMh2NvtG*T?4M`8Q-sRkLM2PODs#p>PCp#MuxSQLR2bk!9!#hmy1+uPOmADLe@Tjdd!r2qf`07*qoM6N<$g3u$< A(EtDd diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_lab_furnace_front.png b/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_lab_furnace_front.png index 218c945877ebdc1e6b49aae8772293f421bf7c60..4185ff0c00adf7de02af7a537355930732df2f79 100644 GIT binary patch delta 492 zcmVQ&mJH znZd|puVQpJuiw6d&FAMQ5>(ZbWZMJ=1d^yKe*SpJ0NciJ8-Ll@;5L`rmCNOF+zT5r z0|V~nvG0_dkeG8P0E|(9SyMT{C{T#*B|(t{Fme!)D1s3YNTRFhD(n+1Y$JqHaHw4D zUPC2@A_xU>2_lkEfWW=53eh%nvyNt;6G_+*A!sk@(*LjwNb#K5K;y%X5epZyif%uB zF8q>r%7_R~tA9EML1w3Fh7plOh=}0*{TJ1y zdxd#=ltgAyeKu4}2{1C&Bfy`(|IV17RkmS_#0Ckv&D-1Cp|TnFVmblaW20&=iX)51 zeM!ztUT!bI+SWOXVNA7G9l$!JHJj=}3a-}|bbz~h5p delta 488 zcmVf1R>OdQ{`sQ z9xAa^MX9JuQPq?R1o6hIgcGpYA9FhnB#}Usz}eEJUttB1>M_xP$!RBujjLk@I}e{5 zzvbO!R26rtItNr25-ixVB4L})j}PpS1SfQFe`}IBjsqunj8r7Bs+uZMRlL4_WgP4s z=G~(tx|{L6q1j4+)wO>DeE;#!J?2N14y@HAAb}lTUS3X>W+j{H4*2rrc_(`=&wz@x z7D@Q|^Iu@!*5eo|WJ~*XW`~7{H>(7mV>d-1&f6&{si+cj49BrS4>|uQdRQ|7x|{B1 zPC=N%j0dTBe}6}3Z60rO4_)VbI4hoGXceowxn4i9&GYj!5W1U^7@N}WJ7-SEapU9j e6Jnk&Py7dx=|FzAwxo0b0000^jcus7f@nOe^g^O85x1T;2 ze#tv!LJj&Pm&JHBw;1h)5ztMDYIpi)z!o z!aO}nA~UHz8>*!Q7#Zsk;LqQGXUxwk+b~9Ag9P2??d|PQ*$jIzoq+AJxoR$oBa6p< zNzP1OZZCqht#cN`m};*&fPL=xsBEp+8Eqfwzaoz96bvbd5H*WACmBJVm2$jQJ)2l% zQo_h2GZ|oNHr0g`T(2+E0q*KW&_%}j4}I9GS)_uInQYsG?&fy80VXpEiRvb_`u362 ioICf&1KeCMSH1v29zw9(QviAZ0000f&Vp diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_lab_furnace_front_gloom_on.png b/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_lab_furnace_front_gloom_on.png index 8bcef559718a82ac38ddc48acb1a15b9f36fadae..02da0360fe33acdd23c7f887409f9b706e6c3f4c 100644 GIT binary patch delta 669 zcmV;O0%HA}1+@i`B!3BTNLh0L01FcU01FcV0GgZ_0007KNklK!4-#LASGos2~WUidk_U zg5d77CTIQ(z@4k-noKO5VtnBYjqy1wACUJpxwrPRx&i^#*7p(Jz}WzbH>+5Aw*oLV zdo1-q0wlo5d>|mAh$!X`2q7r$R?i2Q7jwqvPjK}3N#sZy@_l0Vm6gZu>iOW&+a@9% zj5pv8?mw$aK7UAn1o-DZKtRB)n1n+k;6Q7#UHv&cLd*Sd8U-5I}_1RFx0JS-yB02~A?Q z%doeN4;`Ay>WiH^J`h%(y$2Mt2&IukwXjsB4`$|4AAcl30*t~3y>96PS8yYmA%GtE zpfWEY+`O`cdy_cK$@enE4fl-uPe1(r^x&)CUQW03-21zlVx|16VP!yAeXbsWTtAargEzW|6%AiD74h{hdvm z$b;v*HRpp63LnHAFDsC8e^8lN(tMBr2{0-j^mb5Dz>B;P^I!6U*89J3>-q)qY`}2) zBiYs_@p~T~3p`vOtD6^!Y+x}5bKD(KP;LB&c^2UZzUdTDfe9UT00000NkvXXu0mjf DM3Xm5 delta 622 zcmV-!0+Ic-1)BwsBo78+OGiWi%K*y&%l66uERi7?e>+J;K~!ko?U}J^6j2n0zjN+v zG_g<=6at#;CRR2IR@Od%osEKMWhxcH=dg-k6MX@-wN+5a6Nr;dkRXVL7?O>X&D?V= zW){>HGd6?B{mMIcE(b1rbN(}sNc78usNOx{r z>@YPwf6wIfIkL&)SUI5FUgzPH*9TY7n>k%opc!6oad%V<5b~8(Nf(z$wB`c=5k*8X zcR&b1akpkZxOTo|^28|)pPWSw9fNY8SbSme*}K2+fhblVh&!XI^8Q-#K_bzv4-gP= ztG>}83pkMHtAF-^05>lkB|9=j=qP0|z=~ZQe`o1U9IGJvU0F+ScR&W18JOW_s4Ai% z-B}{hq7Pcg^;r1pzbm%BcueKWW2i+OhAb?^P zp*E7JA_#du<%L9|9Ut_1wGUjujcA4dI`YARc>&?h^$WOnh{KX{uRz>zFL?A~tw{x4 zf7el7Fax)Geo$>sc_EQ#&j;Pw2UTh}HxMDHHp>f$aR2sI%u2i*5cfV~d!LBI0gKN! z4z6IXH|G+niDu=4h`ZJEgN%HopL~!=wBv*Mc~=pt(Y{q3yBi?{oF@H&8xQU+U=}HN zJ~I6Jp8c(LoXF#syA6#LLgj;4;&la5RL>96|Aj=NH6P6NTtxw|@GDL=4yAfzu>^D69Z^ut{=vNP9reB#m+>YISO5S307*qo IM6N<$f_BIsxBvhE diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_lab_furnace_handles.png b/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_lab_furnace_handles.png index 96988056de52da79d0e346fd2b47269d6f72e0a4..1998de055106e7fc0a67d3f872e4ed30943f5417 100644 GIT binary patch delta 10 RcmZ3;+|N8gWusX(BLEXk13mx% delta 26 fcmeBYUdTK_g`X|S+ueoXKL{?^yL|FS#XLp;d0Yw& diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_lab_furnace_left.png b/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_lab_furnace_left.png index 14c1b1bb0d68c1d880fe2b54fde96673d2d57c8a..039f7198c40361d6c47b4a7bbd272ff2069ec39d 100644 GIT binary patch delta 507 zcmVG&(Gb}WEC+2+f)^FQ`L+ys7k7e%)|~N z%!t4-7*)l?_aD$r*dURaWF>SX2|7R^iSA~^;O&0r_4NgJHGk@chWac3EU&vPY$1uN zLN?h2G?|kD&@}Suew+sax*BL4rmB&R9T?#V(i7PX+pBxlr67=zfi^;T_{$;m;=^(~ zWMdg`CT9X5i^>LsY^s~S1UgJslQZcCTToqJz~sdM3CYYkp&`4dE-KgjT3;A5lTrPj zGEMh7P>eBvCVwKxg7^1> zra8|8NgT&PX7YA_yLc={5MNazl8PP&WkrmC<9 zW0*MxA0Ho@-ObDIe?Y>pL87XtE=Z6B86c2E66TnEJ|2Ae@@Je5N+8fb9{`s3UNyFm zM0X>be@X+PYB2#qkhl8td?FwnAb6PWARBvNgvX$~kj=Ec)vGTDfs72q2;u2p2_c&g zJMEN>WqdQW3IJJj1rW07gj@z0raIIr60ilG{sm0l43Ln_S_=Y|rqguo`L(YwR~57K zKV?F)7c_HDAdE4noe4>J7{P|v-9$owhe>aNf9^&SV+;n`NoqkscL-p6V2ia*<{W(g z{v?F+d?JbG^GQ|l`S`qeY(^6N{q37Pyd5mDs>#J-x5JgfWKRj%aJ$3n>udb;;5hEA z^JL7)^E|oT4yuaV?Z)Hr;N|5v&hzAczXR;wT8%@f3u5P@3s@o-0|>Pi>BbkUF-!!O zWsEIq)$TOmI1Z4w9e0Gd%^Lv6aqO0WF($T|5dQt=KdKk7=l1Dc+bTRv)neELu6no8 zxYF?U_MYzEKjZ4$64i~hMRW06>qH)q=C7|`^#cH2JZmAnb`$^r002ovPDHLkV1hpt B_~-xt diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_lab_furnace_right.png b/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_lab_furnace_right.png index 95dd1c1a6d1dff731b60d055285e3d72868f71a6..5c417d5139bdc939d08aa835d324a5207bc63db5 100644 GIT binary patch delta 492 zcmV?Nei?uK{PCUVcP~6YJ&_S0 zQB_nI*hm5=2qa;fkplx92VsM3F!Wmk5DGA>-VK1g>g5K^oF@ao7zNnoI1dE4SGOVv zB?{qgK#Uv!D1spgNpv;cjY6P60eG>HKAptB)W~=1guF_#r=PN=kMb$+rD$2lYQS;SjJ$^ zll%S7d7j*EJ5{wDF;Kmd2p~g9gjSf|nD}xkF6x}%J2j_9FE=*=pQ&cxG-^46z inDa!D;AR-#@B9PfwKmR)%}d7s0000oZk!=}&JRT1d!Jn5GG6E#3is}Lz zN#F#5By2NsV1VNwY>*9x{%HV00cO>^0kBuS+<=+$WB?eW0NWhrfdKdFRs^9$A>0j! zkplolFeD*~uBN+D2oxv)FBO^VZpC`H7pcTh1QEg51~uzK7F`B}BB)tJtkLEyA`^U# z6yn!)Ns9r0Ktc-UoFM34fDuU`#4>eM72PW`Nf=|V1I-u%Fl{qy5(qNLOf*?0b~n|H zfXKkT0JW-#Z84af1kVw%|I>+1_+p2xx1ZYwFV2wz`c zota3YE@nwY1QJv=Qc%@|R+N(HHg*%RkgAIN{m%D)^P6qoInT+y?`v7cV9t~K{myxw z+-^HnwGuHLzrJaDApZPZSAm{(XGt ZKk#%CFDws#TW|mX002ovPDHLkV1nqX*Ps9Z diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_lab_furnace_top.png b/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_lab_furnace_top.png index 391188d8487ddbd9b3faaab48bc977db809fc458..d711b45a410373cc01c74408a2e1e54bbe8c9531 100644 GIT binary patch delta 477 zcmV<30V4i`1os1wB!3BTNLh0L01FcU01FcV0GgZ_00050NklBmZss8B{SP&+M&~zG=>lwJNkA6$UZHQ_e}uE%e!gLeP9Px(V+^{RBy<(>;Pv(O z?-l09$8Y2T3144c5MotPU63FN0th6Lg!On3VA#xb`11J^34h39jKNy#SuqK74gz#H z9s>YN{Ca<90)!y%^y_gUARQohnC>7OdtmeokX zodpnre|*xP&j$gS0KsKuf^6)<=p7=PWgAIM56|-;3&|%oL32XV%_LaxVV|NBOE#AA z%XBvYua6hgLjd2y>0$OKvH9Hl@&H>fnK!W4$Lr!fFWGxTpfkuOGe8gr>e}6`$(u4j zu0j~rTENlSmyIM`Mw)0FfSEx$e`boKv)N1!l1X6Mg)M9&isV?~LP~Oi ztB_5t*98p%T-UuMcAtrpZlIuVweGok2M{wM8JyET5rLr)_W+yOa| zJ4CI8E@Z^pOz);-R#ovlKbV=@`*prW&*1%&Ljrq$a(?gd@%rFD1P>_G3Ib9300000 LNkvXXu0mjfik90x diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/gui/treated_wood_crafting_table.png b/1.12/src/main/resources/assets/engineersdecor/textures/gui/treated_wood_crafting_table.png index 58d1131c1d09efb77a288acf0560bb727d78f8aa..bc26abf9cc0fff2b24bdc5ad61762bff742425bf 100644 GIT binary patch literal 27102 zcmX_{bx_-1u=azyL!fA((Bke|++B(lw*tii1a}WooZ?d4-Q9`=*W#`XT3lX!_s)GM zllh*>Upbp|p56UCn@BYkSuAu?bN~Q=B`+tX0RX_gE#UyD$ZrormlCVD2eO%>tQ6q& zzgKQ&apK!2Xijo^AOHY^;J-HZXN=vPuC)!9$LD zA|JI}9x;G_e|Y zAY^F~$d`Z{XYSTcTO-jDC`Et@g*y;xuYRWMvUWCgAFlWSb45(PQ-Sp4js~zR8rJ_* zm%eySvgYO|D-Ils05XAeO|v0a;g|-y4p@6}RuO+G`7J3VSvh z_&-uT`w_HsVr_P!48NRv>~2km4S)L3NccmSeJ$FVYpQ+PpqQ{QDXR7AsGQ<#Rb>B6 zOl${-GW+~!`DO9NC!n}Jl1i)-F;mR*mO71VPU5!3*_Od1ti&meR0Cr@CLbPE`igQ4 z%gO=EaEf%2sVs@6!3q^wgPq7e{f7og7@VEV>Q(J#89Fp;Jtj(RSRqGf4Xe^~wtc$2 zo&p1xY}BP2!oOx7&k%%0uVOdEPB<>U<_srEKY+Yt_}xBCjc6cLKXf4rmPHdqod!lM zjLJvfSK*Qs2IlX5Y29PumgmatLyC^RpZl^`cj|UX_2rt zX4_#*L|MgEenykEdcogfU&N(2z)|QFl9-77hU$1)k(wh}>t>SgY)#Y2q!EeplKQxz zNo8pQY17IiW%;DTMJ=;l!_o{ittEu>9=^_Ti3D+j6;Uac@^bbPYlrv2_YW@xQb4dm zEle{`rF6LXbkb;wb#f`EQwlO;U`@gZ;u|-eD;dqFz_n#)A&XFhIHeVM zomvS`ZWu}3o$u|P@dYlf0lHp?zWO_HyMPUjPB^rBux?w#_3e`MOGrgpXvTY*P#>|= z24kP?{6uSvb_Vwb!mWi~Hha-loO5*s^@p+4@=B(dfgPU3Nl}~8=+eopWQ|gufA+Kg z$|hBn={3nBd_F_QuaxPX()b3{9-PZ-+bU~dShpVQYTO-J@-`>uZQ)L$?^MoDW=98Q zaAcM_KSU}x&|iGLUI(Iv)B@+S(26BGV5`%6jdj|QT>^YXr+E-TOYbOh)(hc7sCh8E zU5lc<5)gw_y@E_dOAjg-ES0k!sGeNVQE20iw^Pds0`1x)%J-sj2@J^CNSZL#_7orHG!g_)hTX%0D8ttf`MTfrK zuUlTXwXs*&2$KKZK7)2LLEtj4p@+G_@ToRvcoN@z`PqMM5@o^8=gJlGvo?clqXmrr z$woU}U_JUTzgm=L)s9W0&L~ftMla>`rt|*xYy6`@lml^3?8|gMQ*_=QEpr>w`z;n1aqF!rq3>ZKbue`WSYE zczUr$!j6F>ATcnCv2s}ch|vb#QJ*LWA(^#o-0I#JZOu!In^6gB&OsfW0e5!s5Tz;g ztzNU7(?B-LMHJit9y0yRQ6bLN6B2-9nk}Tfv+ay%*-Y$~E%Mdk@8RaNMZ^5%eT~@ePy*aXUJ?Jce)a6u zU@c@4OPN!5Kh(UGy}I>Fs?pu!5|2&nk>L*+MKLx43d1<`o4!pxcal+3(R(`Jjqk+r zbtLNq6JC^%*=Gjs9%)aHj=h~P?HkpbZ`aQX310HuEhTTk`iPQgC|fZyc;5S_Wwy|r-Vw5sbhwF82hfyH}jo^GD+ z?!u*Te7Uu->(wDOXJM#>(Z1lJ{ItQorq*7ypEu$3i)ggIOh~CV#R@?o+r0s5Nup%h zA!B2aP9U^6vp%G?L%jfI` zQg~F#Wk%rUYNXs!b+l|wMgN!PUjOx{+8>v9#J(yl-XB3APmfMELsZ=algnB$q1!`# zoYs^`r^CFZh^ayg{nDW)^Wtqem} z;~l;iU5N5vKJCxj8UK=7gnl&_tX>mKOBnJeWv{Ag^C++>ds4!9z&5c&N#*S7)o1FD4Z;|m!|ac@iY|N)--s*Cny^#G8>4j&Y#O~STHxY$UDlUHVCx} z+&{D4DM7WY7+;%?p+Ouh;{TwgqSA6mF)l!gJP_jxB%00JqF)hDvxa6&1Y-e^BZ20Q zc|4!RQtEvS_ahiA{!si~=$)~fstLi#LeI@tSirAk%0 zrO|~h2QXjkN0F;<2WqMuarHMpu8->iGmspdm;MTz;*d9yWp{hXGf6yNQypFn?9Afj zu<_dxWE5bjvPJ*x2)^%e*F3r!kXL7I8Y-^bfz3JZ#ybQle+$#H+}M63Q$&*)$ZTKP zS^)N~+{Qlpd!AKlJ1yuJe>^AW(`2XH?#p@IHGgfhho6s>z8fju-J)~gJP8vb$FCG= zV0I?1jYa(q)8$^wix|nbSF_w8UCZQp(y0QanKiRX*LE!D7%K7i&DDX4de?%e9K|{0 z8FWF&Xg!rFeO+Xdk(AvLQx_&U!r$bG(!*;l=-nVg zfn2l}dto!S2LVxv_>GSoaqN8L4S+ORzg`r}iJeb8V-2qa7Oc~Uiwu7XaOd41 z^l8|F-N0Fe*-0b0Uq#zUw>2R=LM%3>1-gTa zX~@4LPq<%I8Xn|Z4)cLmt))VgSu%~u&4yt>+tw!zWlh0VA*-y9=)k`r7~GILe;14Z z)qEdf4y~Q9ZXs3_Zr1Ly6+4;`QQZR9n^sfG!q$Ib5u9$Sty%2NvAVy{D%@^BV@S;9 zKZ^gjjN;Dygtnm46LRhIKdGHf`=PcdIz4xCwaiXU3GmC|P;PuxJ88&yVVQXexSI3} zv!`@v>9Fvx-I*vrY49vcl5ou0Ni<08>5}pVeC6t{jmdB&Y1++3e0i1lX#L4OJKK7aNMoE;y(E!zN zpa=%U^wJuNxzyq*Eh5mEQl6syInoM+i;@av8z81RIiuUMO+YOw3b%f=l@du69WN?h zM`1-XSPNZR^GMD<*J^qqWSs9%jA43WT(dYu;v_47=;gV);3Ob!g56=MQ!w1qOw@a1 ze}W@32lRU3>t$ys>fQIjKa?D?T19BXxq~6eU1g1aDKI<#SDVN-*~Sa@EH}vA9r+RD zjwKOmVMx-kq`E5b$LY4^a?`cH30+mdiB;t+C~_7HChYT>0g20WqTkdM+#q8Yf>b`U zra|W9(nfk|GOIwm zM4zODo6jm7eNN-Zp}fvs6D3^$>A-^-twNw!vJehDeCTNqrPdK_ib?thjsoc_@LRfo zNMuuwF!v+lD4>NbaTp{l&&?&Py}U5@f-@GAd?$|Pxig~19^C0Rg#YI?zxK%E_|g~i zV?l9Ak=qVTm%a=$BT8r-|GDudb;|0vU!wVoQ}uhd{51;t;o-OJw3IDox~?-2S}6#k zI-L1pKP22UUiz-zXJmQOPl=5z*2fI&Df3R!Ra=_@n=yIJVO(=lkes1-WlCPSGmQkV zqId5g2XuLdg}VgYgMH++0oTB@5H#M#?6}?|X&f?(XiHut9d_EJT@9 z9am|d*hQr)i`FPD>L@1IiG$F#($MEsXOoTmaM5wBvoP%BBlgON2em9D?SJEM0()gC z7%*lP*~VlgqWn>P0=j0iPcH1Yx*t|LQ#pId288>EJK8|`)Mj&sWR<%hG5lqBqg_^L z_EJlQu^+9ory~M3mGqIUz2gfvWcg4kWZfDaKO<9iWW9ZQK%I7Xm?l$|i`CR5jn06; zSsz?>qc+}JNV8a)A0e1gTa&?39u6=xNBCL49kG!M%u~fWmJ>QnGw$6>j8n%8gFgUn zXmXK6g_xG09)yPh#UIDTp6>lkD&WS$LP*ES@eY0{R6Cc9f5qj?h6xr3S~9PSkS;-E zfd}4kNuZxCCIcrugR2sdyr>D8Ql3A2d^e!Urb~B9N%_!yGbxZMePNSTlD$nTtEq?1Sk^*>?oe|A(bMU;mq5>Y%WP{cj5RarvkdjHzSY}Wy+ZRk zwPk2v+<3SQizy6kM>?Rrr2s}9=MdQ3g6l76vnIwyPUqtc2vYpZns#CE|_;^?$8X!~5Mi*{EqrcYU zS?w9QC~KJ2;v6gzKhpD)vgwlcr87`mUarly_qsMl-LkW&>X0I^c02-74}?By7I8zy z*VHQwRh+qaiP`&EydJxsc9Dk7S8ZUWvT}%qeFIT!`eF0G68-n2wTS$$7kpoyo~@^w zx03CnOlHf6ooKvhLAB*v_ z8Nyj_AtO@O_>xg*X*18_a2wbUwR!L?sblfnj{^4 z>w9FJR**ph`gREroBE~LhF-*g^K+Cr3llC_0cR^oZ_ry-(Y(DhlM>55TtR(D+tIZa zV3uLJP6BzaPZBWJPnZE^sROW1B&HJQc`cvazpTVLgZ-Y4xKx@ys2UlaZ(fhKy)>G_ zt+&)~^}1tH1TZ?1e<8oS%8~Z>a!*@MacT+8_A_zd%1)SE5K2ifBHDW^JSRv*9=m;Z zuwVb}98~*eor%0iQveWsJ-mVr*yKp%UjkPg1DySzq9$Q_!lW20*2GVn zm9lo_p!qmtGDb9aeT@WZ^aaiH@=*udRSJoO3RJ-`KPs*^Ns6Reouc&`A1t&XPKqFk zyk9Mhw1d(}$x#C2AIMYjA-Ka{Q$^6sS!e|McnT$=1Ud`9HsZ2Q2L_R(Vu+7xh%$PH z67Z``jq*Yal^bd@>FCvuUm7_+7{l%Y4_L@;2n zbwXJXz}2s8bDV^Tm8_e_LdayJ0Vxa3znHWvw9TJt;nM2FZ@bGkjJ|DuXBT0LYAjy4 zWlF&CE+9`19;AUN?4`&ji>g>tj9z0+Kdgq)XlsVH7%XKLD78Wek-;6sy)J+^(p*cU z{-9W>9<>d1nZ6lcI!rs_nGCKb`|B4QYK%@@!x%+iI{-0U@VLVyS4&3h7fgYPfJ(L_ zhQN3VGQpVgXo0Eh#rG(5`az^;oyC%M6BLd^b3!}1y<0BsHL*#3T|$J`eE$sQ;Ycq0 zx*r!LwGiU)@Dw5&&pVr`X0Y~oxn2^d;YwU=hK?6T+UE8JEI&E-m!T(Es%Hr$x*@ZW z$MCoUnw_#TTmf*5MOE(|kEPKL*YYt{-bf2jE7xdE)C}%C$+b1oN*B3QZ?cQrI;OmB z=)LtfLy40vd){s8dbg1V8hNacT>T|gf&|Jtysv?ZU%o26Dw6hS^jM&VTjb%X{LT+# zr%dl9XAm#^M`XZotP6Rf)7~km+nC_Q6FOPl(M~o}ol^Sv>biyTZa4Dr53hw>52J*yEd~f28<)%U@9J89$AT#6#sZDib59W%~fIon}5M(652% z*$&I^-*>|(X(;t{(GC@LBV;yUDJ3h_(rKt;N=*!FB1p-+aqj+;P7$u1cN3 zTor!~H$is!lX@z)$O@ZqA-!b?9&0D7zYtpL-yN5xNH?c zUm&AJgyYFpF$GXuba~Zp+?0!)9|VDgpE{S?O+#=M70FkLY8dUMoS5rS)U}en$Jmx; z%nq1FxaPMG9*IKZQ*-sz&Pp)HL)aC=`qYxzG90u~oW_g-UI|D7UmwASD7c@@PQ>H? z8aN%cm#P!7-fDjQJ-|@fWpke>+WU5(9u`~Q>L&Fz_tf9L<)dme#MO9oRmDMeM~5PG zBO-~`<7PVy2)f2;fPSE9V4}7Hju$fl80dW*be@R6UsrT2^={(|0ae|Iobzgm>)s|F zHabeloEA#^dni4j{}|3`NW4`zMDa5Od6T$BXd6AfR4$}CTcck>_#Xfm$*x9SGHYUm zp07R%e)~=Y*zz1IBK&?J7s;qIeID=(BH~(BC#pm3QOfFoJIi$z^&cgUL}ntj)3SsN zSMVU}eYIjkp%7SKkjR*1D7 z28j*HY?q=K=eMr%VAXFf%w{I#W^{zcgr_xZ-~H(WC4c^eeLRI$dSP zbJ?4sNFH4!nG0~^%;-P!$J zGf|lAJgi~5+%}!~@j8@rnjfoOK$1ae0l_dt>a6-?N0XjslKCh!;@lR!cYcn=RFXsi zi_Yx$B(#JS{k^1Vwq(VJZStbnTmDdr1Q~7{&@aB^mZC`@ktznDDI&zNPcRr8&W7gb z=Wn${OgkR10$Cd?6PGE6SgFu*GIDO@;OHyoXvwyz^2dn^*u3T zi19X3OV^!0m^~ol643R09wJoc5vkO4LjIIlTIv6KFYx+Q>CF&}`UX9GlG|6+_u@7> zKs#66SBJYy*=)uh&pC^5%$@)oRbD*L(5+w@`zHEg8q9#h-(Aq<%PQsD`GuV7y<;Yl zFB(x53CkUnb8Bng3rjQoC~w%9heuv z%2Y)nB(W?anp~K-7SHq&mBsm!2)2SUMQ80&-3J~${i#BhjkvZQU_JI~mT$9mhifyT zJ*r_L;`|Sq+7fgbiYdZV`iVhTZ%=^O8PeTF@g)1zxZd{3Dbk%SMbGQwhFDt)>h-+5 zsQ=^csV!csKlRAL>s_MbeP) zVEu6k2xs;Pp|Md2zv4dbLZsuep1bArv1q*oT8S(6TF9%RhJNmGi0?F3@LMbKzAEC%ud9Ork|htgPKUJAkRzdDjT6=zsezV{7V&k)1#k z%45qYCNiI=ozGdStrJiaAx-gjYAwwdkKr8~_^*!Jf5AX48Tz8VSiOmK2VQ)5tq#ZT zxmZ-W6j*^ayZk2`n%LQCYwryJmCgk-SZ5TaZjDoAAB~MKeO)o4Mn$w-@T$VSm15?_pLWb)ty@njTcS@;XHE9~GimWhjPtaOKno%@T95NXjQrzi@~kjakYipz zL(dvZmR&e|+f0b#*GrJTjlE2}>%>r0cL^QE9_^BR(yg#$xdV`r{! zY4bKmYGY%(YZHl{(dT>@=}freajXOI%E}iww&6+9^PTqo>HH!WstNf@0e7a4k2V@^JT2X>x9DGD2ryYozf8@&_D`$1>>GzG z7g}D{W~d_i-9=2CY*;s$eT zo5$vuo+uwMNE^{~kIfVpV{Zzw=((61B0CoeA}P>bFOYuBE8yToFfNNskkq7oc(CP= z%}wd^zq_y|k8?|Am!+w)C*dAOu9)X5pVG-!f7Eqli~fvvcW z49o~zPELN1%rD9PVN{6Nm{HoUhvr=!!i-B1JRT<&cxHWPrQ+|xt2HAs1aflD_HsIi zH$PJJaAx1TCHNS9rF8h8bMEDUTQx+l;uy$un(7I+R%+hr@=#iQ{=vKpRNNg_WjX0T z-#(-=wWJzOqVtFABe}Ih#f&jEQHZq7*9(VbQSWq%e4Lyr^+^4KOTD(-eG!368#|g7 zE?yLTkF5O~J@Do8LC{bA$qr$Ne0OIh$#2u__laKaBL`p%nH_IOk?3^;#8mR=luykm zB<#oU?rK9CnF*p(?RV?TBfU5|c-U6RaeNz?1ABShtX)9B&?tLY&yZ9 zAnyO?PZ@u^Xt<0Y+^*IkC?Z%me%L{!w#gQKHF?3R4Lub1r35`g|BAFW@2B)XEv_g7 z#jatgv3R-nbx-znI)L{Ysd)b6`UU^g{G)VMY5L>2#aSdON{9LXt!M4W2z27Ckyohm zJORnHi(d9T0g(K-IeBLES?TF!wcdJ`euFAX|Er@he-{w4<2b?{1jkrxcNrd(EKYKQN`^lKe#ViI-hzy6T> z6nD99T4kP@`;)$*jU%QU)Aano7Q)|TaLtra*X`EWDl(|_VS>-T*h+ufB?h&7FGym|!Q$GXgS@)9Gm=@L@ z=DLyIe0(<7lmEZc4@z0|f9s&qP<~KeQ4ibV6tXu@%#qR&BQD&>or&#O2<=i^(zm5l zB|LZ=ON$8HI{d{7DFwfruAw{)-{x4=sRei?h&;}ir95FjrnmZwjC@M_A?AAv_j(ar zEDk9mRZD<3*e%&E#U2l#fwHR!ceVSTJVBbzYD@Ew0uI00Vd>DAc{6qL4A2%+4R1hd z2rbW4;&Im_LITRF^D72vvXsz(aP%juyOz1=HrN{T4YH+(=M0`vREs9>qnGZ==|S6c zD`ofhh?=3moiS*1FzVnIyX@!%tvb@_pVSk8JrcR4vfIPc9um#@&GYOJXAs?E=iuh^1)Ai(2UDz|>khiS1@9)-Obb!AEUiqwj9D{E*-sFH{FfZXRG#ycWO>oA#Inu3!I z3bkDWG*n~<#Q-OYhq`za)Vp36`jwU=2ip$+e2vg>6Hg&NSCV`YO6h}5r9nx`E}xsJ zD(O6;Z(^4mKa?oOpa1m^${YjhX|*m<@i*A0htXUw1dH2bbS**AQ4(rG9}!v#tO1OdDbnFq`t(JN{BzN+0?Hs6B0r`KNK8P-`(uAb5y~uxYj%T z>w?^e{M9bNcpi7%KRtiI?|V&shE! z^^4tam@Q!TyVLA~x&Gh0ca1=maQt+?IH&MhdL9tmfExvE9lY+l_QJ@p3=}n+uR6U` zhX|4ni~k-%HeIKaU9|g%`%pfoK=Iz=7Vmt+dQcDKOwuO)%01(0k*vTLZw&d%?>?2F zwYR2>6=+%9|`9;f;<*r|ZI9&N_gb9YqLh1HCO-DZ<1`)7#aknt`m zYar6}O&Sa8{mjd+1c@pua%NlofW)$rXp77o8mcukPE2^C&Kn z;)I&rIa`mKA#=_e)44rTe?A`5W$&!Jl+mv-nwCkJbr)`U&coA{lIZFJme+A?ShI#D zTrX#)2M>DJ40sA8Xt|NbGuNb+(Md^H)tV&wos4ZOF`j$O@x(b+C1+3arT)5)etp>` z+VJ!UO2U5^$^XbO6WA`TXS`thwMt13$c4JPvyr;wGH)jsFt|(|5@$9&u1JG~uDxkf zGOd9p8X-BRGy9>Hgs34n6`vUn|0Oox4l#qkf8A>w@s5+CC;yNO!!QOPM2ANX^gpxP5tCg`ESpSIfEKm+h*Bqj5Jjl|p)gnWS zXswVlDd}BhpCyq_1{m2JsW^ta^%G7T_B=C6tX4_T(%j9~s;D3wf18igJso_k#^>Fk zJEMeWw_968t^Mb_PiZcYlk1$!#O^JX3&s%5l2$aC*zkRcx`k26x@lh4Cy|F{Vf2G~ zSMZaEG}eb54+gA$G`yyV*$;qQE$ETyJPXe=ufT#EXObbo>^i3OJei^UbNgFRcJs5o zCZRPU5%WHUm>Wn1khph&EhylEtjqV6cFJ#>ZS@OA>IT>C`C`kRqu0}k-Fo20DYBC$ z<$r~4rgC#4s_WZ&&b+`W(>(%D4}`rtrIFUT6AtX$v;CAjZ`njYC45vhsMoCPi{Kr7 z%lpZI1N6C=Dpx^E)Co>=bz^eRzs z+GVest`9JuBZoKZdcaOe5aL~ppciYH=qgrI$dU|R(1(xcV^+v9pNTigyhUY=|MjJ) zwK}#lzi*J+{~Kih-M?beu>71a*GNm~DQ!U;J=?F9oY-q=DCfqaeiwh_MPHBC2wqlX zCygEj{U0Wtji>%=^@n*fAw+@7NxhAXYazW@EFadQaf}U%z#;^;i>>dS8QJ!>abG@+>&jrhM(#f4dYZ{JN2| zB9_xZgT!rHka$erkjF>{{OplIs~_V=o|*~Q_xft?9mp629ZaZ zHJ$I1nk*+5Gw@EV3bX9}rV-#(N-zfN8E<&$P2cdTHpf4$1nhYwhxCXJ?VFSaR9!p1aYTKtNtN;hdvyUelDM+A~&_FDY6S9hH@DP6zyD zEaj^|Bkq}*u~wt=0YK8BnxE|j3KthIw0)IvV5K-||Iqtym`)JVKe;5$9nqaT6<1dL z>GNr+KZgHjJ3387Vs)yl1F3B{)wo;vWbJbs)6OALIZQ~W+~E7p3V%t>gpRRIrXYju z!lG2rb+}VHz}kw1`NCFlMMI09R6=R*EfR=D`=#=7+e4|B>pCZwtw}$)n}^gS`YK2c z!r5{#-YELm+Z;P@RZn?mHRPFb4SWIL16kYJaug?fIrC4<_#bcnFV04+OFcBO=$;5b zHcx(n1#)E48Rr{(lU)z zG#~(Jg+9-@NHtldL+BDRX;KE@f~evGCh`-WY2IBBWdxMeWE_;6sL0R$miV@uoaE7q z8d8INVq2s)_XEw9RiraKqUdq{dnbPgkNUst@1d63n*&qPwIl{;PSMHQBT_p_n<>Kg z={#Lm=Sih*=_IL|_Sb%U0s2TvbuH`MoxqV5Vk}Hk4lEXDODhSy_DeR_&94e&x3fOU zStVO_4N6v`uEj<<;hQRzQ3jBAQDx(up>4G?$5W|C02oEgOTS}R?>{tUzpo!#nOQ>R~+D?nr&AD6yUG6|++V|VWzq+3rk$e(eUy%YV^*EW< zV#XF0L(JtTyYJ>P2TH@Y&sK0$r}Wd>HR%EdLN%N1lCr$@GlG1)*7%jwW3Kmesd*Wt2-6R4FD>H|I(CEp zF46qf?*zols#UdmZFqY;xTLSF84pUAlue2WwflG|X7o5VA+^Y(IFZSVigk2vP5M8) z0d{BB9$lLDF4=MItCoAa=`<|Vampi3MU#VsT?5VAu0sG&8}d8Zpay@{cd<`C`Shn= ztIO9|QkRD2!E+2~_ZOs&ft=)g?k};0oN|~93Rm>YSBdS+B zpC$-kXVXN`Axy6=RIEJY9Q3CKRh*DTy`PAK5k@lfQ=GIF#bwL4yO{kdVWNk%OQ2|7$iy=hb0e zYIX3~MrONO_om7N$kfv-r8Wk-4l(KvNgB!Qi zIEMJR>xly8OS<%#Xhtagx6*JRR)`d;EM66T8&4)TT*a?bCu?*k!ox>8~ z&EKd8SIAtxgA7AF(H2V$0T+f_$uIR1!Z}WLPj&c9B0+%MA9pO3ZAY=FidU+x$2*1T z-^6tA)jKp#QOcV|!#_T~Ituge%KQh2;5*xdS4Z6(7T|P`H<8*nZk=|%P5jIFRE$YC zE}acJ2vo3LlU~r!2KDQ!!c#jA(H{*OIHXZe9C<3R!BMt)SAbJ3FeI?Nw@$0biansP9qgG>MgRPwcZX&n*QodZc2juHq%|( z%gUlKoN`?&{ETpJcs`gtw~_zH&@dRHz+peVOv!v>ftZZ@I$$UP9fxCQ`YkcLZ*5%K zHt-$0lglI6bkm7{${;=KX{@lLZ5%Xy`ON13VDVhv{c;X^In0s`#25o-}kLS0-@NQx45s&wgP(Aa5by}8l2>k!5`x8x|ce< zx@XW!km-t0^grRH30gt4UlkH(EPd75NFUB1lUqQ+6)6Y8fXeY%7mUKpZVNpDbjl>K31i>uUE-G~M^Ud)D!(0d znYu?FIQ0%3+TA`yy8@R%C7<*AWo6dB95zNjzRx{x{=&;~;u}r5Pjy_~@)s8H{(Itc zb}_>CR%r_dc&|`9NTU7fvJe0DH;FoNEraY#thEq3OY0v9(K{3;>tE;%~=Q{>5k4MP&r)?UagI)$IQUAea z%Jr}1608697LKbTBa*v{i}z={H37y6Z>FTYsI^{77tGCJ96|1HvmXDSBFZx1+jsB6 zk_u$tCkMGT_33wiq*2?LF_003ki3e3t+NjZ+jdQGgA2YZy+@}rzRrJat?tnPTMLCm z(21HGzl-7Ffbc7SS7-j{SheVN);f7&#j_9;QIEr;nmrL%=Lq^!Z8=rkrfIwN=(uWG zH$hl#OQG&pGlk8~6{hcU6+ho*XXXJPT1K1LqrcB)-Wr5$r~&6Hy&;02ZEoh0^pXb3 z)DLD*f2!&|bp7&2SkpESJkm3Zt3%!)+tD7L+F!mY{d0f9p^j}HuEOe9btb9Ppv7Hd zsLz`8-T8G|jVewR5zI@)xy1T)B!Uks8@1CUr*3>ug(X&x0edVB9$EWkZk0oHQv%K`HsXH9} zm(Xw7Q<=;{wDj}%k-WkBq2Jv7?ry$%Inw71VK}S$OmJZR3$0Pck<8PN-BS42Gq()Q zQdTzZBdot2CHD*sa$2^o;4@TIQqsp1D|0p32-a!97TtZX9to6{E*<<5cSfTPj2j)k z^s+lYp!ur8S5TT8!j=bjP`)d4C;`>f`65!W{l;4T z)zLF|*8J`!3g%aL7e6X5H^NmxQnwy1D9G#%px(o8jvXfXdIz{eCEBO~Xqo){k#2?szV+h;s?aauI@qzgVBoU%@OYKm^rfaZREj3D<)6DLIp83Nlb5d-2 zHo*8Il8%w5WYmq*#bIWvYEBzrmvTgMKSU3bmO#Gb7mzY+KJMho<+bh=WCk+kWBR~N zkwKab(SQ5vRF@V?jS?w7^tjeIFl9aX9!*)c_&Bu{wOUHkaZN;zDUu28qIzEXZlw@G z*P&@q{t}I%=PeL#LFxRP<^#I1FKdy8pHeT?1!KE5neWA|`(?hhu@*c^f3v>{H|gN& zMKb3l!&|o_$TrqdV2F8~;7QIiDfdgH(gjt0<1iZMkhs2ytDx zM~xgys5{8S)R;y9vVu&u

q?xL&xC;KxNAi43o#b0HCu%?ufGH@;45NZI0-^ILID zdQ5zxhZhOfp|NG*jj-G-{qzqH!h)#;Vbq)5H`EbBS|wvDB&=w5;%wV8BH`A@Y5XC~ z2aXM+mdP$|^z2)jgF6zD6u(w<1FY0$Kd*ht*~ro#C(nFHCjLD0yI~iNDyAPaW6{)t z8aEs`_RYwd+Hj$C|+Pc?I5ded_kFD1@v$_X* z&<$uxUDVy6BsH1G20%yu>=)R?H2*%7;N8E*1-qxaWVxzF^7!O&1!`A7eg)-iN=|c% z1PhPx2cKshi!9}C@?yMB3jKieqMtBRU+m0ZvVWXm5|6DPc+7fiBT*Z4D?-D#CRP3h zhBk}~L;!yk3*wZeEdB8604JCkSlzO4AK3Sb^4C&_=Q8p2;nV$dr~kQ#iy*z<`iUZO zDO}+Dh{ZUId0hlfeYB6A2=7UDUa4^r!rk@WUZ?-Kgsx#oI1r`x)q;4-u@rj~h#&a> z9g1|JSqt?dy`((Nl>YX9!l<@%$T8B=DTP?{=C&!+mVFSaj z`p4awZR%S}i?eO}hqjC3bXrY58d6&M-Rue^E{_(J54+~>?P|_nqcY1`sQ?%+Rvf}{ zALi_?;H&Dc`*EDpipuTw&c0U`NT(g(MoITz7nT+h?~~TyiORZt zf+Xp`srmTodcopmKWvr~4Z72p!M_;>Aox=;Q-ucUHZxyL1pKG28kk6Dy$Xof4@DB3 zW(;a}@$MRrx?Pkb2tF370gpKw{%l`O>dEWk{HRFkGj&Ky`t>E|jcsx3ZG8EFocZ)N z+|8w9%6a&+$-tCitE&ZMJysyk%IG%I}2^sa$^`GL8YB|D-WJiJ04SS&9F z^A2cL82F{A^M1RJyV2&pE}!#2@e1%#8+S{Y-R0wky1(~!(>FT2pH7)N0Nuws%^x`q zhlB&VUrtXO6MbHGr_tVA3dmyD1eoeMAKPREfuF)ojvulsQKJ+_#2BiN5$@n~y?v>0 z(`s`o&3O-2uN?HR#t+QG3n$Xp*>T>~WjZ@S3N^vg_uAk&7-QqZB87G3f61qmM^z3? zgw~8IHP$F7i_`NcoMi9+JgE}=%87{2#?Po;Bx4)vBCI2!PgT1|mZ>K}s2%X|+6-n@ zO(9?OeC4b^7JYEPy;d@3pH1ui{WgV@klV4PfKU8qiF!4F4Ej8*azxPl^dbHI`z0*4`S&CPlBLE*sh4EDL|Nqux7>Gi&f zmc_o&Q4({zA1vPsb)NC_3J}d<-sgJ3gb469CZmzP#XJ3BG(hB7Ar=%#Q^r5?`4bZ- z-&t;?m%h56R2zBUsF$NoVmv!`doKj{6yG4xe}oqgLv_`_?$Ph@X0&n^>4Bg7#@mkm zJtAUN0kVKHuJ$Kg$F)qhpd`rKk*#4?|x}| zY}fDSUmwo@$c&N+VUtXuJtLMEJ%pe8S(LPTc6Ra zuxs(F^FMy=keplbO-&a-Yuc`)K!8gQfhVBDa@PRo%d~xNb#xrV`yqbrV^j`Pt-ZiO zSt!c`5{tg!hf`jjM!9Ebb6C?tf|$kn|7-6%qni4*eRl{|B2{__Rf-g8ictti5mclp zf)oKkKoRLp2?P}g9h531fKrtvy@%cj2+~A41O(~5-i`lr?l|M!H^zJK`}>ltF|w2F zHRt-3IahXedh)+_?n$9W2|^hm5#KaOCeGeJoFI!08? zUEhw%zWr>1BX0P}Q%EIHu0M-4YT7fQ(ZR^^`3$FLLL|$e2I67nYpaRRX{zPPB{<~! zVLxv!PST$e1Dh$|+!nkC+-J$)uD?o{h3S?gJaa0_;>oFubP7YRu!WVid1Iv4_|OiwhL~&lc$c(fX_jwNZfj{b#h~&{2mNOtBoK*w1(%4=UP}{F6Wwh zR?p^9x3$C=0-+ZLsAF(HT}MZiwu{f)9QbHuh2;3 zuxUhDKghEZhqx`@o#C5-If{)$*Ggh z)9BoLqjr%565KBl{B0zr&WqT>NAHVJ+1UTl1GiJ(%QW?&Io)lQRVX6lyU({`6;EeH zVi6yq3y(-5SweI(G>a-u^-9R~xQsZjxj(q1kyU`Ih#`MN6ZX#iAmB=q%4%`c&ri=@ zpXT-C1M(Xk8%ruEU3NL{dRW2i=pO4cI>mW1LbA;F%LkIZ{O5goOi*lfp&wHOLbX_p z-mGP+|I7^2A3x8+I;VJ=JlzqwG)|R{V90Ii|8mapJ#2_(iz>6rmM@r&;M+j770aybGVeGaj1k-=6B69lHU){|gA>rsxU|ApM!!Bn9{FdKsV^#GWn(u%dlcHSx5C6SCe-fdWvgfO5NIuf=)~+k~W4~QE5?*y`)_k z+iM>qoY~#jpJ=d#FJ5VFZQ}HidhvPi#byuJEnM!+wI(ftc+I|IP8g-{yag&L4X%9Q zQ~pc4X+b$kFIU?SgDxT+m=VDni`bP_-2>i{NMPDlVk}s3-ln>ar z*(k!*S4+ckx}8uYU(I%mf&xZP5gUOTbsLhIzC6QZ>@rf)tDdPC@A^NHrUwYVmbdVl zp?QH3vVOjB4rpEdU|%AM8^$FJTBWb>s7NYSt92ACLNEfR4Aj*wQqj&o~@?C&jl zv!~9r!xF?QS*IA# zYJ&*dRZtM>>U#WJsE*mEDBk+DB zdz9sp7HFxPEQ}WQz=umN>jm(k9r`L%;jK)m7yE`5=638DI+dLCfu9u})5;e9*Rtle zeY*?_Y9p{fOrl5@E9{BTBNp9;0~c6TRSK-uVnIby`SofLSGn>VN%<(I{!rTHQebL>dOv!74Wg5y%itqZRQp0%2b2J`1c-Ws*G`10mu3gV1+`YnGAT6) z{)kwWw_{7s#<2~ejr=1)xBlBrLt}YL*mM5a{bl4$qtJZ`Ms3G8nE{SXwX$@V;R19j zO^9cg2L%tF>4bMYy?^~{2srI^9ong7YZ4hxZVLY)JgXsJ;n8*7p|DYJRqv#!_p%nx za?`u1$e9srVO6m73-quncOB7W7Cj46HI)w*9l8Y^+_(>#OkQDL2;EY}P4&vcOeh_q z-%`nZDnNdce%59Yr*dtVE?abLT|{kSyNxxaonEqUC*7IZByDepm%k5=pLs~{y+VNj zfzCFkl2Vh-vW^s{=$+G;tAoxaj7z>&B)iySqa)7wXk^t#?63!ZOmlNK%dQS@ttdGj zC(VpH??8vCg<&1{zVBugCVH^jOGWn>zJ&{qvzMDZoR}Y-mw7-Zz-m~gIA4M}*}~?k zxiT`3@QaROt_y11da&((Vaik1j}=SaqqavUk!K5kr+$T2?!y}L6E)kXQM`mqdY+K~ z4JVowox4Rekt7mrHiv_zlLzl2JcGmH0=B-9Saw2_!)=r&eUqGN#~j;OgRkzH=Qbk^ zyGVt8*qG5N-=aiFkh@;(a`_w|Z%Je3J`%rcKhYhotLouC?(O&-qB#$V`rw77&|U%k zLCR{=jPfb965lHhlH>QcQu2h$btTQ+M-I#fBY3Z@hsZ}Tvdw&qBeSDaFCxSHSx!&PB^FAh1u1v_d^b*!hs-oxYq|d|KNJmPbI|h}l+G1`wtt>VayHa2 zFdnlsTYRP1Ej@3NqHEL3!rX&*g$PUTN^rb`SJYEQv#VK5(G_0*W^e$Tv7vWf52=5>z1lBNqiBzc!bprs^!k&cz#J#S5tjZ3W>G4%$FB* zE-NCwp-GIbpy3ZeIm1WRxlu}>lCI#olS4E#S0hwnm-Cih^LZt)@88fKra-g?4aodO z-CritQG)A$7i`N9#`>y%q=WkaE8qwTO(iwd)29r~h}P5NOg+?fla+uo2;V>X#WtKX z&E)mcx>UmBBiDcwFo4{5?EpVwG4rps`jF=Ylq6Bxy+VE*qthCy6P!6G?l`2I!%qT?o z)3%HO#z>#dqIaLvmf=Z?-fooic~Su$&r2STuBvqnaH`Un*VF5;xs>xq1&o=OH?Dl1 zUA&nurm<7dhZpqMHl()jNDzfaW*(t*sa#(`)gmEAYO{2GyTm_AO<7KB#!@dxx|1uD z?=S4tfz6AIx4E3UloBJ_Qhh+rbxUZmd_Nw;>J`Z>g#LU%GmI)Duh&(~kxX||6q7EH z6kqyE#5$YBB2CwVxImr6w{Xg3bWML-zJ;o~-qUXxIo2dsuR0@{lilxJWi!>nG@7T} zfzK-4x|2OIu>qOnM_@?Xt@A(dkR&xh*HARe<@?|GPUL}AX}xaAa_P&GMP1O47+Or*2=n0Ml!7DoJH2<*Ir~X7assk1i-daWbG|M8=)!z7b?bBBZ;@m41@3T1Yxo+yA*V zOyB3q`ze3uQoxIr1=jgKwLt4_N;|CjpxG?kW_!3n?cjZ$hS~rtzg5WdVE>< zLid^NXb3RtIz2K)&Fs!kKn&{d4@?nVoB#$D?lwAK&1LF{?{t^1hTVPS`KO+?Lirr> zikh~`E2c7g4`tHbx9Sz*X<6>Q7+7?kULBj2n;JrfT{Np$$Z{L7E1wwU_`ZRB zf{-d3x?}U#C05YP76@D__On471KQ~F> z+OYQ7VXKoqUB?dL(Bl-oTHTPS_g)8Z#cTpt3uRCj4BTVv%xf;svoRfG9UxcSS!@6P zKwjs&_~vUHOMh>bH=D-2Z{;wu_ktQplLnS9 zTR(fu5pQqbJDj#t&w?x8f1>pCS^n4#>0>T><&@kJxWDdLZ8D0)OWbPV`Plu?`rtrx zq~WKr%cvkTV`Q z8M%&=sNkW}Rh7Z14)7w1O#v(Z7PrudNzY0I-=8@ni%BGW05ipxL==c+W2T~Kj{XF{ zAyokL{TbHR#Umxe?faZ~uS=2ULQs(6)kyslVPB6)MuFmYJ;a-~EXCH3A;@}14yi`z zPhIElC#5zkP;je^A|=|!w75w!-bhlJsC_vMd<_h)P^Mq&UsAPvOoFy5J~o3zn`hR# zKRL%5eyc4$CDraX1&4I?iC^NiJWd_`D>1(0d8zCZy(te9NcjW&c5zoI*4i&GSs!no z>;fm7(34|RuViZy+N0OJrQcwkvlaV?;Uf~oOe{(6I<(Xof^T4e{XjTAR@kE7&dk(8N?!A*tk+Y6< z2K=1?nvyTqjH7y8a7c-gy%I!xG(#AxmPsYEg_X@g1LlNpBT8} z^ph`%&Uqn{wQ9cdPiVOLKaQ|kIE8>R#`;^w8Stf;yUMLMIE-XDkh?>J*O3-{WungJ zrjhTMtgITd*j~>}1Q70(ClyKaxNA9Rv@M@~Pm2MUWSr#1u`#=XlEMZ*VXAEEtcL>X z^|Y_oTG$7|M&&aT7a%w0W+2=F4$FJHFIOkitqJvqSVz@;H|XfSg}X1p=YfN;vPoC+ zw_y0--l@Wo>b7(NNQ{Fhh4u~E3k&Ze{NeaFM)r)3*Wm4t-mkMBG#H`l;{8?ClH{mf zmxKf877_?Zq;UoUDSQX?6&vM_CZZaVm|5s*W{Uawkx`1X)d@hUxI_YJb@9-(x=1K@(0wHu`B{F+lD4!wky%!%FQ|+U1>u#K`Khh@r$MnQRl7(xj(vchN;(F#QxjA60a7O=m z0B)>W0YCb+gfw*aO|;kN+=tyN;QzE4lycts)Q8^~n!&Bi=-;9#DJp+u9(n^xrh~xS zf9YCH#Lel8=X1?KCe>wsT(ONzYQ9O?x-)s0LC-ZNkEc$M7N|^KSqGlB9nMH&9Ld?e z-F-$0rr|zEGd>>22sdWVM9IBhA_>E*awwF+^!C!OE4hOq62S3pl;2vG;|)+gkl(v; zcs|+4l#R07J-K(?8IJII=KAKM)~3QiVqzWQ)T33Q>}q|>=a$Q*EPIDb?(0YUOrnSy z_+AxmgNTdn-5hY)5l)5}BW1fUql$u@KhRGlgmO9o$JKJ=gu`A>%mdcD+4%`KsO8Ee zFLn*G!6*FMe%_yV_B?rY^og@hGQn(wd~D2Ux-seEt>{L-=mQ;V;5`)YPE8S>X$yGl zPrpJbaGIla9ccisB8Gq`7`$byIW3~N4&_LGuSwD4$ISL#|MioRAN0yRlkSWxztZF51bIH$`BmXG;}$?C%iV#ogDs@4MLwRMBm*T zuW|=RKfVxVd}_DN3kh{c^Lj`5W%(?JNA0qC)A{4VyZfK=?WSI@{$g0G2wAOhuNo%e zYQA0EIg-n|+??-5+?yPqE`kB+b>rXj>2Yu27@+5MLUwUFN>ZsQ(>H`r8(W{T8`^jW zZDyI*d0o&2S6zX`vnG31)7I8m#`b`bw z4Cljm4jy=;r@Oh0{;!#87PbWsdfB&>)QAV^#Q5PV3N~CRH809Jb*Zv&0=s9KN+6aF z?8BnAq`2CN)|s0&RRE4*Uf9C(9a-w7L`Y&2Gy?CrDprFf$nn$T{=7}c5{mOwyuS9j z=7v1&v9=zO*8@YbNb5{WYxeJ{=m6BUKUL^)$Kru|DvC{+fl@^0#dz1ID$q3Ey}XIM z{LX8~sDda+`h5H#C7CX#;U7!ga~K^e`S`S8jM!o5#|6&)M@e>@tBDckOaKYWs3@{+ z-`F^Ey`uWkOwq;J&5jmURHzRhMepuAZKiw(NJa2olmiY5)HVLOiZJ;s{!P-F)u>+W z`7rBEGc_FJ$Ee2G;{Y z&bkAFPk|KR&9x|hFt$OWCaZV-)~3PmUPS%-L3N19vS1Nh2un6JDQ#+N`<@0gin{pu5%|3$uOzWpOPtYG2m0+raW-fu6u zLB#Vy!`A`vya#Q-c#TQe<_Xv|J6fKpd4h{gj-Nt9aFCVk=VmCArEi@=1@t!t~&pWwFt-G z;rRG@pu=%I3M#aldUos_(18{@>wPT7vrYdxe!|rOiNX<-+Q9cp5kMj75u)Js-SmEH z5yFKwSaE)u+rU9Wbau77GM+@h1A>j$!y8zoA+nJ^u{i{8;hVNwD?#zX<17?s-%! zrIPZ?lW%&)FVEI}@##v{rq?T z_tZ88<{*^k{}tfF;D=4tk=)ZoMRj!R&(gYxMU)_?DlT~caTHT544*v*oEJQo`)d?U`iIumc$CZBI8SnbgwLdl-%d`J4qP1ju zqRViQc!k0t1_?l9{0>7a8I4y_hAc|f}-W*oWpb^=04(V{eW>h zE3dS0P@yw8r=vpYB%e9k1(}ZHSPr+47+suS1o&cvhj$c(gB7?%n@0U_Xr67@p26}j zrvGkaDkA~kC58>Kd3%QDKyh$+asNj~{sY|nXE_0nW1Bl$?r2l+d(Mg+tqGQtfwPbD zG8qF$X9?LxLxRwxxU)N_>)ZvGn%nEg{Q;Z-N|Jpd8;~6L2?mG0g=TTW1N_1!cgZ<-r(;D=r zVWO$e68lMOLY?@|e!snOy=m=zZ`8!tDE?G#!?{g9=vNu68wB2gz zqq)2f+Bk3uDp>Id9uggJUyAEDwf2fK8q$IO)=P9Y`t9`%_DF~d-SZK8tr3nPHMg=~ zRP~xynoayi?_zk?T$F}Nq+*b`B)%F5&i^bif8l20mLN1;G|^5M#A}I_Jxhv(>pAz; zlws?|rzoOd1i@Qm_sE83GUTi~5UYQ+#bftj1tGfR-0FYI+dT*_cSL>GOFXY_&-iil z`pDnpEOsC|A#fRG9}iYOC6|$Tgkv*5PDo|r%)`(jGfz21wtXWj#Fr9#_uJ$ZHoK5? ztTF)eUx)%!4X|~Pn$OzO%5va*r!Oh(gEtnSGCaFS0EE(5{~r$%>;aIV-k%Y*rab_n zh}v3*?IZe!-j%hpd{^DOs0^BERWD|9QD;<@Gd(WJlh4@%h23+x?SDoLpQFra3^hFN zI;MjF`gU+WW|+)_m3DG_X-*~9-o&`ksBDGhuzITtW>3B6wch~qIi32ovFYi?XpeT$ zUha3N5Z|t-zD~bhaqWw$S6*@gR$ie4dhN#*Oe0)T{leYu7H&thn{eM#S}ByBpmKFQ zwaHK@n(e(7^MTjPyGew#q5s9RWFs+x2~Z)PN;ue%_zSCli?tS%egTx}CL)-NXXU0~ zo;yKf*!Q$7kQa5B1WOfC^7rVcr2laBVWxvSZ4f%<@x1e6%Khas&>Vs)c8P*p(d94h z^an3h3p$|mhcbBo(w*#Ix{KVbDCeDV_S9>!zS{80tj5oj>JfJj>g z!wsJM7CG2nF&JdZ(DRF6s2sGonp03_qxyfLL?0N;=EXJvAeQl?ca#XC1x4&_7RbEV9-fMw4ET$K$3-On-^&RD46#+mbXT#OQb4MgMP9@5Fk%M3Zri{c2RGlxR$ zdRzmV3-`Km{pC#x)5>>T)u5%UJ8cj+c{u4+yP0mie!Q!2X=lGN9~Drye;X;kd*jT6 z_^d@@2&!JEZ^JuRhdN`Ml5r@Ch&NnL!0X)BorW2(%H3j0nPvLhdj1jp3L10xf(vZE z2Xiae{2Ko&ZclA$sV^(vTX|2v9_e)^13{n(lEc*2y{7uHZNxIPHh=`igIUSC(z@qBcPzQ%W1di|VgrSYLdXXZsW+kQ<#V*_Eas zz~@Xb$rJ@!^we5!>*WwT?w8Xmzq4Zizp}ehF6NYdexJJbUwqY6^@>r7n)ZtTRlca7 zf7zX?GcF)kc@84y3&$srJQzA7(?hF&$dq!=*d$^4itkco>GhVSzorsPXpWAg^xNI| ztv*|8Pqhy!^S}^*=z-Fu5;H`n8TnMa*xUA&4~3>baBuG8+l*sfH5a^Qley*~iPON^ zGdYZIjxFI#ZaqO1%F}{^M}%B3W!VJoplRN%=z}lq{1fL_w!l4>f@NN>G#yuW&o(GP znw6IXtjhV0(Y@1U9OKzo(c+3Qu)>-tB$rVGvD<-No3>r~+T@lx6b&}4Pyb{^L` z*2Vok_&pD^H?9NM&NMhU_qY5zT8niLM(2IiQpqaIrIRlsLZS|gt0WjJRtY#$`qyWv zeh7MroF&9Jtk%zVZ7bsKd9Rntvb?BA3!4>UuBb=;9~0l9tU+mhN~4JRKV}Fd$2rL4 z=URZ_!4ODO8dGy{MM)D@C6_57XHS1eP6=9Gd!A?&gQSFc<@exf*;_o~E zX*K?q5C7pMNb~+uqxDCqP-Z2#ReDxmkUTJJ+xzcYO!uqA6RhdKVF|vy$D=djm}b zeDQE|g<1TGfEKivb&pc4G#+TUj{U34W0}|Ymq#3r{_Hc9?Q&FmAJ>8mbQ^E_3&#O? z91e=V{G+q9`~s%iVT1Ot@!8=xJTHYs^b;wSI$l*He15l{KDYPvDfc#Y1{kC){y@gm zn3J)@ugt0{QTtIVlhIaKj09jzIo9T*G{6FKo5f1PJaH9D?iO?h@RVh2ZY)?iO4YcL);PIeh=Q=hoCz zPfbnLRCm`ak96dBB^gv?B4hvnfGQ^|sR{r zvpDJF4U(g*jtc;Qg8knO1;_*u0086wIZ1JK&(*)3D~Z%v&P9)Jv7OC&Vr0jQlL9r*;y zzTlTxB#@Uw8(Rj!B^N}CVP#Wi(&d9p^Hp_f6O7wH^y(G#Y_ILFFEhm?@#@fK&lSEj>PbnlPoO?Xa^FyjZS|_ zb@Cv9WC)W=9@0`j##Tw}c5e^VwgZ{b^#(D1hz#okoXC5)va(Q@p%vxJT(u~yvE+;f zhlhliwJU0>NdzMT=C|HSOw7LE823m1_+BB8Hu_>Wb5*#&1<+SpdJM*Ngia)j8S+j4 z065q{=(%}9Q$SDzIV|er^lS(_j0$BBu5QnyO#>}`E0pAE5dsds6_vWSFrtT-ZHu5S zzasH=V95-?qq-c~mOqJ6%lAi!6K`=T78)Zkn&63Mx% zN?untt=l?gL|Yeh5Z3Mecol&oskB2>$QBw!963nS^c?wCUnro5G6Ey641^@&=~eH4 z|Gs%jet81jQ{4e1jAykZH6ZbPwkc|cPb40KWT0bP#G&T%6gI}mT;><^`Rw-6_`fF6 zy{zUl`Q7Z@go=`F^=E~?-)-|?yli;K_XL;nF<%WGR|X2^^#KWG9YO>Y;V?26g*Blp zKEp`NfTwNC8fas-5z%HHaeZ`tEv6SCktuClw{Eu~Q$ceTQ{A+hmYZx_RcDEi)Nk?g zk;9C+cSpnGwT|NS!X+DjvdknR&BY7}pyK8fgKZ9+#B2)+nQ3Qdu3^ulkJ~aql*gCC z6$;u8l(d(uCg)Rt7lWN(hT)XJ*Je(C4)He364RMHVw4n{16W7En!>V9K?E(PYJ`r9 zMZ_fyiE&f6tvx8xdbOW(B4YY$t7r_E{r(IEZe@P zVvLg{VPt8vfe}W-pcfGlUU863AmGSf;v z_y2et^uN6vk_iJpmSpG8#dK_QwFN2Z6Y2Q-N$}yz-O~9VjaDq}*Pd$vl4t!!8>tt0 zljfs$DN(ZJrH6fQ8Ax`P+ob|}^%d;d*d=+G3y4k^`%CZ1);40VI*n|)sa{RSl{$5< zbt*|2Fwrzl`Exwv!MA-y55`*GO`GNP&Cg*-h`)LWB6vM-bx`q#162CCuIt_yOw3E- zQX^uCYEXQB5*Nj3K-D31+ed3Sx*nAtGPz+?D*QWQkWh&Kq1iivuW;kt& zw*^~@4!1@h=U1IRoiw4}jXYkWH5E+RToPUWDss%fQCvJS5s5SoJz7Kr!b^WA_7*Ap zz?$I#F!V@<;hFGI6``#1V{TXA39>qhZn zcYB|7wEKQ6-{+rLk4G}sU+RMXAsp>8>8=9h{T?lNn zfNcuqIeFePdjn72{&6Y_ieichP&Eu$wK;*i?Q6>fUOt8nXh6(n2?2JBJwR{ z|CC7_+q^>jV(cW0dw<0ygz%dCH@}E6|CU5wcum#N%u9Rql!-lPz4n(-<)jtmCl~Iz zWF#CF6IgDfss0ShUY6Y69dX%Rp{rKdjBUX9mm?MqjPcBvx&CUW)JT}%yT7I{Pe@T1 z1U4FIo{Oj4fxQ1NZPBfUnQpE~cb^FF{&JjN(~)?YO71XeLS-X*oyN#qT-|gy{~Ns* zkFDvU_GFZZ79+8Wg$kjMXN`Z^I-WfJ{89&He7j}AKey824+1*ZWAr4|J8>{5S5H51 z9;L~Eg?+<*HD;HvHxAt*3Xzb#edOVXd7@}yG)Ve(DzOVEqf|45pW~9_=sHG^TEsYv zqM@jDrSDh5NC$eqFab1PZ$TtQF6!S;U~}0ZSRj{|qy>hoMYZjWMu2ooLh=4Q(91Xb zA>0hrm&0wUd@jqe?pr+Z)M!vE!+C41?`L+m)H#7UH!L|(c`EAhQcd#TlI~(wQI$&g z+fQEGj-XZ@yf*G2TrG2(Ok981(~*18Fs*;P%y>csbZGG#I~^c?;YWVVfc=<=+&nmA zcu&X2qtC3}cZ!RPIzqMJw;|l&XNMY}!|uz6N3J%;)-TsR9eEbK5XSOq9m+_@vWvIdT^g7kYeLAk>}astnX_SQrl4}w^vmEqnah!`*dOeW z%C7OJS}2M{I!fvi_2X9$GSNdJ(5CkV=KHyKj^mNCZT5ry>C5Eq;q9{{>C}ZERgTM1 zCNT|YZU?l~t6gbdu_YunG@_Zx7%hl3rcE+3-_;D;u((ifP>9sl7%*qE(t@qHw^3hl zWRLVs8XjI6T64+tx9zy{evPg<{{gOJvRg%l4b*U{c~AY;sP^}eLne|;XWp;E1PdG^ zs$a3`^{#z#yk#i)?jC=_p0bpb_O)rd<3Jok>WM?@L7GKH%$VE&m#O~IK3OY7D|ga1 zMmnyUA)eS3_(OF67~w~ZNpTKU zg59U-flba^NsaC8rPe<%_Q9uQuPhrx?!tBECvn&#jt7evfg4sjAU#x^3W0D37kFp9Zsxj?)tK z#hU*DAp>}(dzv$yj!>_C3=WX^zM@5uux?L!IC7m=D*xFH85rUkiD+u$Fc99_;OiRQ z?|g;~oFwS9!$KTRCQY_(yTJZX_2s5dTJuJ~e$k)gffYXU;#H zGBp7Y=F&P=)^1Ja+9@CuaG=g2T|5UQ%m*G$0 zeQx-JUhJKe3Kv7p)#f74^}l37Mu;Ki>Sv4+A&02Eb%WHE+f?b)P|X`ebS_1yJbu`{ z5r0V~8!0ph5(e@LYmPYJ%TT#%d2uJZ9zniN`kbG6^Oa+3j4`}r`lBN1!{{CmBFu>^ zdHD5ac*=a2`QrnlYNBS!efgu*3#g+m5(v`}8cwp=U?i!OT|q9~5-6e!P1z_d$XI9; zps8SBS(CNc($LP7>pM%T$pf9Jcp5Rz5nP^bV011CY1g2uTh6$*md{yic*ph7*RJQJ z?gN=x=PMt}197OV8U?TW*!P652bT<_LdC}ioRDtL1FWleVgMz;~nUE^{O50k?5)|j?l$7kPBH2P#}I7<(u~aZSV;&=ls#QVKZf#CHu`Qu+-gr9Hn7cdoJCn3 z!w3oUyVZFG@Zq2%hbA5(z^mOo741|8R@`Jl`mhL2#~&zv6Pf##;?q6>@UI7~ zQ4cH@!lzf`Inp&+{Er4-#xh^&rtvpg`SK|z0;EiPk2CECB-}5bUX_*Z`_8`pWDAN11=hAp1?XsR=(6sLDoK?Tc*S*5+$#S5*3ynzLjE> zLav;6YKO2e$ox|(<_-ARE_$M(!^U7ZqZrJ>F%ID3+m5k_R z;>{&MX3lk{s3-Z>{AZnAs-pksnWodMFi^1>z%8U!O4nsuA7BuQwezMTS|ndj@?iDG zcR%}8@xXVsVD*p21q&RyNu`Fyllk{q^*#LYA6`t6xo3MY)^_`bBZ_WCj!VA#>_6C8 z3GsQarZ8>^a45*{qbqCA@07=xu8IoP;`sOUFZ3Va&39oEQAi*j--dNNX>O|wybHFj zwYyQDo?KObxFbe*yFy^=p7Oqb{#YAHcBEx?Qp1}Hl0>FHYaUkG-?pZCTzxt)UWGMy zU0ma6zCS#nb<q?Qw5`+XLK&pwNq2PwRG@2sV$A9G6E1S zBYl+AKmUab`0VZUUR;u{^&qa`wYxCy7@kDzqHyj%_vwpD$4h#Bl8ICq;ek*(v0}>c zOk{vY;vsu85-|)51sbBW?8z0o<@uO3?g8G2@>|%W=hk{O6>XC#7b%hjYyYv9Ox3w) z?q@Wgt5G`Uah@g77mgU>4d3ga@!fCBTcayhl}?V6Z1RaLo^O9VS{OeCF~H zsoqTz_9sfzT6GDi2G&jfKNOl&S+ zT#L*bhtvb|c(+%8>_!Ivw)DD#C-6U(MGgG+AOjNd5?x6neYxz%o}(r?91^@9keSAJ z#Y|HN&y`4ek0 zp(s$fkoUXgczh&NRkdLUGe&+h$1ule^ve<))C)Ih4=_gJo`#{QECW-!=)IgqL(Avq zRnSjNG?UDxt?e7E0cy6Qr?nn0-Q!`TW?YIRMIhk{^VaZ(NM}7tdM|-YD)-rPWMApc0~XG_kmW!a~7w z;zJ-dN%7ER1ahAyYz{1^#CQjnrWjNe7WkksbPhU*Mn*&Lrt&>^`rf;a!0d(8qMfX_p%HAjeN+2KLo z(tr)fGIv~0HY7GZ$&N1lck{6hLi}dl?2t$>OOX&L)UW`DN_ho3D+xvUa{D^;fBEO} zXr)y?;1fX_w$Ihyu)&nV0m^c?vg}jynJjjRp6tttv-f^;r7d-AUbD0)DSzG-YC1Vb{$mGwsv;>HVLiy?6>W- zg&NweKsoRw<|s-F$5-LrcJt4pDOO`RavpKvy2!NF?A5S;qpYxiq`Gppnu>w3r(8G z0cj7COk#H3_b&~Xi?uEw!S}tijj@gPfvSM^LSConnsN&{6C_&XR^Ub^@o+r&TF=Pe zmd&k6rrf>+XZd&`@#m}~Q(rYB-}qK5#-v{eHi+wV4|~rx#yIJS}?T`gF8fX zudD!v4_EyQsbi$$imv-tL`a?87oir9bd^A|_x<;z9@O62K<>h5@?oX)8K;KA(Qpco z(%=_R2m(GfpY2RhE;>4@!slirk41AS z4W00`#Oli@%mySh;e@^JaTw1GxAPsS7QyYl8M9WN$vJ(g`i4JwRW)bwA#bJsCDNtdQa1(M0;MaMqQ9M;Fl0oPO&i!<+d=D1p zZ7HgRPhC2^G)3fyc4K$>(0`)WwP~sJivDC`_1n(r0)G;mKLs67+=+SXy6iSfV^w5g zQ4{|Ia^k6GxBkOWk3uo_EWH=XRUpq?qRfavGfzx}Wit`iQI_UA;>UNfJjpJ~9$sSN z2x>AXVU#S$fdbzgB*8UoS=25G1+ak-a>s!D?YhNRszytB*?XwvjIyKR&o<2V-&R}F zy{`a^qId_G4nzmo5WaMUlXade)Uyp~r)yUrVORtC-ByY{1!YnMMUJ zDji6Mw}ta+B4BUaI0knK_E{+L4}V7>`rc0xbnJW9FX5&6CqnHyh>AgVS-Tbu8#>eZ zT}d6HM%REYD^fA+4SuBzBE6oYtyLQPUw3C0`g%s?Td z`ittqP{hE?WDY%ZzTa{}ZAWrBcc&?Cgp%RWrPp__FvSb}=!eH{v#ENYiWaeQxmW)E zUW#W+M_{MSwgr?c zLlB0i3LYIc=;8I@1J9&WV;$Aqb%|4IG=8bDh)3-Wb@3^;zZo>mVK7Q<>`Fj|AQ>yN z%-x|9P{(+Or(VeL8pg9XX1`0y5_)^OGw`xIT{DxI!@0lDKyBxWH%Qx#{YXvTfKMtY zT#g8|LQtOCS`gYtDaTmns<%c(H-FgLVW;`Z8AYVHr+aQTn5W%{KS@Ftsl964_-TD3 zG#D|k_?|o}%K2{wO9sN%MAk~m<;R#x%c<}wA&&^@9Pz>n(hyFbqN1Cu{qYHy2d&#f zGXFs!07!{8j<;fMhW=_n=o)%Dr;5f2l(+e*|5mX;5ruGhbqX1Ux%_6pLhXCm#@To? zNNg5GoZ4$%ew0r?syW4VPUyJ`Yp+Mw^DkB#Lp}A!3MmsVgjRVS!!N22;;xnbZMRY+ z;MehBE3AOZlnk+(*4=q;m=2;~M)w9&J3M(h-To7Z5y~zzz$h^&;rooU6s6m30~l*( z5KEhSQY`dmwuNO8MP_M-9MfI4V-?=+j|3W}?@$cYAH<&OEHMQoeS(t`S2c4`U`%pSi3)$#IQoG)Ik8+d4M%ouX2@>mL^d@00n`;@N$CRroB8|z)4 zi*z^Lvm;ObY0_UgAZL!;*87?`oo}zc42hHPsoQ7*G=E7KriZVr%?h!%$WhJRPfczS zRD}|otHD@sRY03`8>%~pa<>m^@0HyMy;E}N_2Q*xgTLqgW}V60-ax64ab1_Hm{pCj zUwf3H!;RZuK3da`AvghzIb==9pa&0uw-?W$)#az+WVags*~4;_IBU;#9gk@pz-bM) zel4FxJD{1Gu;k<;@CtZa(Au7VR|m9=qmx6El0Kh>VFX%lc<&;plz1rx$X(&IG9Ipd zun54qfsYPz7wh$fTQuOXIK}Y1_ViL>B&8mXF?#`CxXJLz&LNvz4LIpcuJD%YYrfx;V7dJDTD??Yp@I0MKaIwi8&EA=y+jSUZ>D2qK} zUvzb_X|<>T6Hdzlnj#DA`(ovaVYw4#za^K-Wi)!hPJ#yExy_NbXNW8ngrzt+g0l#$ zqy|Sxm@IeIQ-;ze(YKhIAGf()0DiZBaPKuDQ^7yk?zWbk?OsoFgm!a$UripL=;DpN zyT)M7%dgsv+Wil&{a-7~bN=}}&Y!*;koFuPTppc>X+zm371=e>-%F+g{$$K)m+!4d zpLfpxHe}*_Z4gSXe zGi>Cz#K7n>&Ki~%X@WCtT*dq2J57&l@#Y4Ri%#ICpsT!31h7%c+d|ZSf$~PoLNSGc ze21hc((&-kL_WGYVRKqTOVVO0LHwt*Hl?BhC4Fr0?D)w1irLC>CNtGqVg5$EGzPdH zjWQ_dQOVG2hDd~_YPN3SJ9Vu(_SBc(2@eriLPmzqP(Htf0z_YxH~o7tk1PcrUzX6p z5c|9cWr4>Rhwl6FmmL4Mx9roGTLfjlqWYPpsqP0lqwZjYU(%V1xyt4Q*5a}mN}tw# zwOx^yG#Fk}Ym9!;l>202x*DneIom=&t~;ed4mJHwxnLjqlk^Fkk7CZ*udACivl&Ae zA+vre9P#Kc`YU0B7ReL3nwx8v36%rOUr<(cPoD2>vvMZoE?yT^y??6)3pzW?H10xM zqY9PwRO0AV(p}QQqUd-r?{8aGYJ9C};{l@$mrE(VMgBb?@wSY?J&sLs@RT>l5&1yn zF+alHM<)tAR-pQ5r*z2{`*cjH7zA=4F>J)>Tk+kAG(8^)p4@PC^l)_YNq(_48lh%> zE0Tw#40Z<0$9NDzIQz`{Tcgs?S3tSotD`%tei<=&ptOBq!=$qArL~TSC9#UQujz?7 zMxN5hS;4x}jtw-Wxx#_DqxdAOw$_^4-Ke~o$5bzi9e?v(o|*fvK$>j7#e`Gl;zC_t z9n<&(Rr8ezDPe?$8?evQHPGCCEhadD*x5{T8)_$Ttqlfj>gi@xaz!h?X3{I43C2um+|0i?@1T|Fn;_NZ=%y_1Mx%9t1S}t##fr|b`=V!*2ic` zLbzlE`G^Rte8e{^X^-x!bNpInb{V=9k^Nq*5rVX5c0pHXI61_wv{NQuOM9{vhDu$vDEHODarAP25%kGtVNEAZES=v#jDp2JLSR zq*);;T^DT4XgwDAz8&kbx`T_sbN+jZ5bi_dxW5r0cr!Z%#0%`37U@J=?kx`Z4nx&JjIbKn( z#s!Z%6Wy~_PZ$=RPsRO^$M8rM7?Q;gwWagKU%JoC3 zlsF787f1+2Unu_~oqCX)+kusp0&znGND5KOD)%=@kwB#4VM?))A!&~m9ZXB~fBX3( z1ETW(yZ}BTSDrMdkUk^k>WXg5HKthcPIOCh%66>?EZ8fZ8xeJ z=tMk_5n$nUmG$+40jn*Yi(nvCv4JR)QfJ9yS^&C}=k4PC&Xo1AOD(;h@0aTwjajz; z_+Bcs@bx}^e5biqNMtNcr+-?1kmy57v$HxuW;F|8NS_@UR(@un+24YY7uIze(X~t= z^k~mBgiEPwK-0eow%xt!o2Qrm1*I`AxkR=OG;t&os0j##chkDg_{z;^z4o(f-2;AO zF{0YVwc3CS>yy&BKzNGoN(gpEaP|`uPH+uUe=>XZm4G~TlH0?T1e1!lg@_(5cVC$d z*j%wC&DJTfI58I_6O?cOt`r=_7J9uBqI+Fk=J<8p29QhYD)s9Ex^w&Op2pYR;ZYR8 z=P!&_DtdTV8A$1_&%hc&h=R+98fkMV-pxm3fvHN{3x_8 z*-AO-oq9Y-Hps)BIz1f~tEL7(KIV9(Byx;!i3|!ozl3QKpo4->gB_#J4su{lM}BA* zs6;HKB1;7rIHVAIvMUO+6mwg`dQl$_%HPtKF`GIvH|NxB;RGWo{tY21$bimJg}32& zhku?BPQk&!9EH{A!&Y*ZXU}qSccW^6E56oMORjr8_AbSOEN7BDqW)6rU8F{kqKH2b zzpiybrcCD0{1z&W<*y$4^`cQ4p8I|R?4{#mTYj(Y7cKh*1L(`U!Ue!MUW*W&GG%98 z$;r#Uym2g${7#H%TT4=Gj~7EwQRvH#ekr~*uScS;^S6<#hv^jhg;_M9`(b1JqpWOu zJ6w_ZJv@BK6R!?JFWy1{9~HT>T)@B{@+%X$z?GD@aKXAG{d#I2u9EkG6Q0zVKOD>~ zido!@roB+vtD%<1r-^<}#-;X{-V1cx6a)ItLY@| za{XVfbkjE?#%C_z-2H+2a*pP@eyX!sChz0I=?E6ZQj=`r%|IJE+hD`gW2A^arxVz| z;N3vlK-oi!&%n&I1C>HZEbO8PuBb#S#$=@8_NQ?uM%F-=y@T;W_`h!Deua6n+5b05 z6)gI%xSij?lt3k^#V&w#O+OED!dLRb+P|FMi|(B8FHr2$w-r~ZzC16>3G>|BSEGgu z#)x`eD8Ai3lcm;w5Assw@zxMPB9f17uhM;59HkSa=zibGdO5xDOSk*;14h2F=LeI2 z{&L{{_X2Zx`MpL#)LoAa-;v*R_yDZ;BjI+ekgpfZ1Q8CqZP)j+%u)hUd$OXFbHX;) zszQ-XnCaBs1cu;H-4}$Fnkb@zGMac*xh=I5obJCXfsUM)9x97{3ULOf*GN^!RKscQ zf|i)NJwU~@T`5kK7Q%OO(w^=L(f2(Rh=Nh;q?z!NBwOUHNmf6LC7*`K=>Iv!ke z+!wBBCdUj~E@*zQ+2IilKaLuSq_Vk*D~%fw0Cw#~Te-28<6GSDl?>gFw=(;6Nm*{Y zjp4saZJ?sE5GXQlHd}e@r-B!1ym_*%7%%X7>U}iV&0^FN8`BaAO>yqWD zu%A1!-j)5v-u*G5w#v1jeMm`r#`zyRM*csVgt;FjvYI9nZ#NES{Gsx1v$f?p%YJ!^ z9QEG0wGd%*Pd;VL)Ml*)zCi|>azOBWFTlJE%g6{fKTgq#OUx&z98HaE;T#=|17o6&um0W2ubmcfQwV)#ip+>I1#A^Eudzx$38(S}DFJ<@ky0cKlW{)U;E(z0 z5Wl)%JU~7|cWdwZfAqVOXu!xZU%nD$rDC@_C(QnFwQ9#JHTeoJ-ZzKBj$=H1`jEYY z$s2*z*HO%6S&7|RP1HdU6x%| zy>4Jy{kfly?S;1R=GVJOvG?QP;+Lm*BS!#ZkW3-=OYu~kcx0POFAxjL&y-mI~ z=LLLEKvvyX+0TQ#bmGVi-;WZNM9VUOtvx{XQo>{X7-SoaO7k>;oUhE>dJxM<4*GZo zASW2%lFeV~`J~(w@k&Q1AkFP+#q&R&Bij!Ec2!6D?KT?OIQx$vW>5uvRS5SUVpVC` zq!OS#5(itPY{Y+_nO}n3Gronp%zpu;CTR<^RvFr&_TEkC4{txuovU~8y6|)9t-N5u z^SV78b|P%ho}#IHI*P;a8VSC+3);2-t_^tiVX}ZFeOXWjUoko8Te#1i)HnPcmVv7- zLA}V*Aky>7*);goo4fkfPFzRD!=r6eBI^^i-MV;x^Vf9@(-_eOzi3fS=SZAPARog+ ziGqZshJ6D5pwwz0TDq&1Z`0S|eRLXl?N0+e@G+>4pMhdSs4;umxp$J-+_#bg8OM25wAI#|7J7b>gF^pZ&Lkac0gRfeS5W{ucbj@^>b`RJe^S#W zk|sW}7HLk2t(>pLiZ^j-%r?r5wTm$-EW6@p%?<22?fd{^O~9ftS~)z6B?4G=|5!xZ zzx2}aeX!^Et$c+#!zFU^dMM5|QQl3QxKb#~Op0poQ^;ULSF;2nVp|Ifj);aiTU>o|@IDJ0I1NI%oQ)If zAd<=bX#Fd7RZrPzGgPyi&8FKFh3C#9c4jQSr|9p&v#T)P>mbmb)9Jk4#yzp|alurs z!U=$vR}Uv}*;d}+?{4`|5A>!TgbJ@{69=kEuF5HF0kxA^EZEV!wUe95Ys}s$l=(FV znYGLwGIG#TZEpWN24rrVHK9k-bG4o`jX+ivf(K~>HNm(hPFSjxtBJXG6!#Phc zm630^-g6)QM!nABIB7`CI){wLhgc_VW{X;XDUldGpvo_HH$0bHUpjw@GPc7M98ls| zU)4MWO7yi^(be@+pxI!DrYP)fi?-(FHG|65QzVnit8MA5$HEMa}$pf5N9Jx0@fGB4{J!GJy+6Lx<%M%|?0YH`|JSKy~t` z2bT{WdD27lML$mL!vDobwDYYhX`0OE+V1VeL8Q$kyZiOw(eexQ>l@$Z(+3#L8k}3# zw7HZC^b%n-Z@NOEH++G(Ra^4qDkzXAn-tUWLZrbUhmEXRy7#`u^aP(85Dr>IM z53ZFOC8bSrG#yW@czwVGwv5^p;lQthYxhzbvEd|=?Ne%m)g^0SsvZ!wB9XK zSeW?R>0HUHonVR$SFIHG%dW=iv3@ZbbF9#nc9epq61PWdZM;J_iPZe^a|ipEU$kx4 zsAxp(?1vs*cNlB}7ak&hO24>I#~L0hn=gt{FiYF!i(*uYw(4pxuBfMT8-U4$)SlxT z6DX4Vc$Z06P7##iKS?7nyU-1MPfyYlj})Jnt?4N{0bxX{U!bd44?7GGn1x0A2f5D* z%Hng_^!@(hCMm?X4$+}EK9DP}k_Z{FBk@07X^()BjY^qjD7U#n&OtxjEAB6tJCYZN zN^y?2yJ*>d&ewkJNBhOS#c`!TR#)R^1chgo(rpSF@~D>2Y-Y8uN@Dc=_3qP7%YO;s zi4i1bL-LWDS=!b?+;g5~<}$G5G=-kpzl1)Iek)-f?VQl?JF8^Ub!ew)6^J0dPM-6p zKXFcq9Vc(z9dkH?8vFWtLRa1WOu`fSR|QGHfIM!g4zj_`kTs-9q<^k)1Y*t7N%@1? zedl}>Ed>j?G0aPV(czoeo46mqU)TTbkLVAKhgpZW>AjD=l*uh#I@GG0S{DMak#+JEFfz?FFXFWANqDoBMmn}eW;y1n-wS{6^|M^ z9_x?+PmtjIkE86t*ddL^xMdn<90*%S(<(v55mR}1ejX}-$Y(1b)u@|h`^P)~ue#s< zo0N`6He!f%W(0d5SC2hS)OOahcJ>>Rr~N~o#;Jp;oqbtvY+-uc5hFS;kTXa=(chW% zcj_Uah0n}(Zqd?XoOuShSs;sJFu;1pN5nLLK*Fo_}d;CgV@V1 zY(V=9z%VpvnvTw!XG+530Sbhdubim4$kVK(u4YRnH=iK{GiKqQ@7A{;Q8`)8>Thoi z-BR38C+LN|q;NGenfOv)yKj~Q*V6^1%jEKDk`%c5ZhpzxzK>jDp`f(FTlIGXN{`Gw zq@HItM;JazmsXzScsl!WIaZ2m;2d1Z;yiak8ET@ zz+*SR-LvxUVVLC?04Zs42P#d%lRK!)uJ~Jmd>iJ}GuftmEMKzGfKl#|Mce9)`<4uT zDMR;)w9oTNkB5j4eBLv22Z)w>l#INN+Db>&Rc^aB8Pb$Qn?7uKX9Bl)J3H^8X#Cwq ztVDWmV2g+$%qB7cy7})jnV0n~N`trOA5S0O9WAo;U3nMq#>!_s7GW%@+WrAV=NR2h zA+!|QsJk^)3nr(ErnU%(GoH=SFk<&-six7;tXb}G?@8g(jeB%#g!R8Y#S_T=NEtI_ zXOkfB;VBz-xkthhM^ovq=^B_CO8CKZHU38j??U2Rmez103Zj=OH+0XRL<7=1u7Il6 z$KzEl#bjbgUJ$iEP1k(;APg8?$+=FiDE3YxgW0I`eAx~sSzrL>5YV`3wkX4)`#INU z1+tga*XCt{X8tM#Z7Fw`P&YT0Na=O?!u@d9?vQJeu2XkFDe#t5;Af(P-#{lJoWRnr zVyEVDWT3scwRR!W^D~#4m~B+}QQ#13o==rmSTXjTC#?JnR8{Y!4T;w=Rw}4-Y4L^$ zC&X6Ii8!PQl-_{kr_Qluwxa18oNn{0#4IvD?*^}Z$RnRo!R%nSal`(lRV7W~<3I*| zsRBVyefCxMnM9>(NxAXqxo1QS=oEu8M8Gs=52_-y^If*|K^dHV-q!qngbN4t0H=wz zG5Wt8eT?+*0r&P1E?G#}TEyhh%i-;`Uv+>pH0VtR}j>f7>8yI-C8Nw7_jXop?5cfUmVUw?eyarE=> z&Am_B0EQuUGD2?j zq7%v#!Eo!f@}_S)$cJ~#CTcYw;^{L@&WOG8jR_760ks}w??N6btGfs1Z&T-L8pn~v zml6pab_ghJpUGQv5bBYKOaJLzh>Yp#$cKDIBeAYg^SodDp*W!@%|@Y&@5O8A+XIW7eGE~8Ms|wy6+m)@=R9A;!6A0Tt5f>qsS{UuCse%1x-(lp zz%Y+6I$4BH>Bq6VzRFPp(d-<2MRSAL_~a@9>?x6}0<&52w0J7H=3k+sRZeo9E{~{; zmdW$ARZzL*J;g`>D5MHGL=llMPK~KMjD)_fO7kqePeh0yi_SDOW^hhqV*JWZ8{U>_ zZhpxH>ciO3!{i9-<>l-5KVqB!lR4Tl`#d9zH3e-Glx8-6yJ`jom~8sobI;w?3>1+Ic8a`qkLF8c0>kz&o`BKPktuaM`VMaCF`r>@` zr>$a3Jcn+o>2LlYJa1wAt(5=2)+X&Q@I$ZfBRCSR$dD@N`tp5ZLVe{dYcgc9L@4?D z25V>fj9V(H?r!>vggWzT&!m~_d5S00(-b-^sl$~G6IEx}YmzMH%UR|@!v-@P$;2#D zaRXcynRo~LtCk`8PJt{#MyPJ3qLApjZbpb+kXa?q)M-zlhWEm8ZLCz%t1qf^&nVf; z)!KxCHc17AqjYeSegRH}cAM z=)AoL0q3Tx%6U->!MwF za0a)`Pdz_@q}?&4tv5By?y+T)g%^Ak9pr>nF*2dG!mT~fW}6na33YU*=U3&0uJg*2 z_|OCUP*`=JFp6yBoCQ1*b#t2b5rQ-laTWqLib3DFRrPljXTPjx%l#&c37Q4oaw_aAAo169)3R+L_72amT`uws>c&0ZmG zO(R0y-mu^+SRGZSpLwHrrsmZ&Kmic|#!-@Ob1Sneo)i@vjkk*Pp$p3^rV#@bzDS!8 zlg8=fH?OrqOG!dHp=M25ta?)V4)@4t)Cp2q6z-|dD+-s$>|=^nRwB6&ZUC?J6vgn7rLTyTn5J{xFLypTw+zBt(X^yCtqIKcjpIsc)HNQQRvuF61?Wm0*;~Jd}m)Jk={~i zJKKMVRrp_{!$B;Q31XH4Sk-u-;f&VXF_3YtY%PVIflfF@9%w{m-SBg8gwXyWYm50x zBk-k}p?Y8YQ{_*}m29dyp*!(JFMc;MFNL%UQ;Mr zENii=Aj{2KI>ct+nT!fnTJ7y0xq8&m35bhT&aB2ZmI^A?}F) zYH_BM8=EQlGJ)b$B7bpyl$w~&lO9|%Qx$zCs(2sAU5*qpGVzKmU}T4iaP*gqcb44HhHm%aWZQZD$l-kd1Ge~FY9Oy2@Kv#p9q}gX>Nby|wkQB}A{Rv9#PG3KWv37@Z#^2V(-D zuNSh7Fj>En!VF(`Yjr}q(W=0H9h{x6_w$G4@;NBH+8 zBfodDj;W7xPw&Z8Gyhp9J|vNVNrfI{_Nx)O`r7O=#+%rtwr5D8I)7y!??L7T+LsQo zjTQSv6EKh6)g7nZrp+xQ6z@1wr8A}BFZhd8V`#p@SiW&`F`TVdf!Lq9MueFUZ`YYu zI(KW|tZkfivxAF}y7iir^(Zb>q4NnIFXXh8zDe>_&WF=seid4d)6+f-Q@C7X};BkTBogn>}caygnZS{mV`^o@3XoT=O|F z$Vt$4YAK>zd39Glw5?$$yirQJM>? z9wiLX&F4#~L{@0GyhMAzoLI-WHqyn{V5xYXMc`Q zkxJz>2GtKJ6U0kft)d}^h}DaL-O;ul$S*rz{=pda!fcU0l2oInOW}P9M5wW1UT2@m z=Z5=935|=4IM&lQ*IfB~-GYM@Mw1%N?NVmto%AYFRvAdvpGmPSK*XKEc@gvfyZ}Fb zY!pXAdj*}EDnF4@rNRq5RTcLlQsmhS?jT4r?){#v(@hW&)_>wfj>NQbgk@YJ?~=BV)Qy!GT5lOo+NEFpng+p%(pQs&4HkMsrz&4pnQ23Zngt%MLI8OGQt)F9ci zOUS-u8;mXc@+rGAvPZT^*+~dx>_YZ3B-!_d@6qRZp4apIp5H&;|G)pt@|ydcbI*NU z@8!DAnK?SSo7@6@sBC(Lme=-0VpeOX%5r8i5voQlMll_nNjfh!^>lp3#;Zf0{)*|X zF^_@wA3D%DJvnsM35k4K{R2~wki+CNrIUaY6*j53@f{LD=e5ZAmY7PRPUh~zPdL=THpT0M|#dsji`Jl5pkUC2}ScUcBsxDZQGgvC}>EH?*zpL7>R z)SicJi_GG!_ zkJ>cDCoO3|%lk_@0q7fkt$q zvKFUjQV#0$bBucTfcDsB0>&0TNwj$n*jeL49;=4ky!%*b%{4kYKP?bu9lOXMP{%TB z*V~c*6aSX)?h+&?hn@9#o7becXKyPDb$35!cs$c{_%ix2Jj}y8t0p{itE=BYP8V*M z6Twi8vyW9fBiPjFK705CDt&kzU-%v1--uGE8h^d_ED5@3mABID@bP+p^$s4c@vJ}3 zL|Uq9T3+<98%c%-V|6A1L$JYC4H&goj)rZDz=1@|;dVlkdR%*=+5FwS(kf#@{6$AzAGL(OTit$6_6kZmO~fFJpn~6nECG>R3CG3x~$jor#b;EOt&g ztg5_%ey2OwU)DK~f6dEY@=<8Nn({oiv@e@SBsOFTsdVFOTM?L=RJZL)Dh)WOxd%0J zYnZzG&OdMp=>9&KqOeNSZN(zT;;F?rBq=TQ)Ca+|h@(sj*P))u&mSzBg$78aRo7Qu zVKN1TnYG!dG@L48qXqnWPV1a;)!`GQXP~;6lOtvQiH#F%!fm! z>YuM}9^`l3@c=S&Av*U5r9j)}P$kA9DqoQOIicL84Hog<^=tA7w9=git?DLhY@` z+@sNG^@WwPI*wX?2?}JT3Sc;M%K3-vqMdjdU4yr)nRPuy$N)Q=Orv6Zn0jtu)c{B3 z8^LI}cs28tyAZ7&dn&8QG`(t5RNmNbuez3SDC0FHh?d5!Q}Q`UIn#_orMr4|VeE|6 zx4-fF`3qGC(<+p}-_c0h%p@z8(jgZ+x#GVo9q8rr7rh_1^_32lq7Ll`NX-7?L#1oL zZCO~0;>MU})l4ns;yUokdn?q_aI|1BJmf9+ts9(nEEoEsU*l<+dW~3A-C}=fj+qu# zOl?k4`6>6S{`Fw(&XO>zj;zMg*}h**#o4Fs7(e`(KyRlQ>l{u4doIif;q$TD@rMn% z@R-=r=zblwlYIFqCCalmWrQz8I(RvNf^T?*PuNdbIzwtXFN2cLNn%I6zH&AsLPub> zZ?3K*TVL;f`}scgm2)96+W9Z8=NDO?5(5la>_S6gIC|MBoh$}71R8rvI(L1yG%p0~ zX$nb}Wb8d2JY`}%N>X=-Yj34%Tc^ogq8urmIe^f-he~fFfkf;^dbu$hfq9ui#bQ{R zZbX}rYDI9=Symm59{~7r-bfnqCYR}Iyr_a0Q~9V@{o+&OpwUyPsGe<4qLK^0bKY=S zkNI-r3lU?#=yQyP#6oMD)&a2^U1e3;6;{V=(aNyX*q-}LYfH(~e&b3j_fm5{;>F~0 zHW!ySANA%6(>eM@3#+?eO^HI1OPAlMO?vj_E4m_tg*60(TkJxM@HMs^d7nb)Iq<;= zOG2fzVTz~9C7GTuSH7DrVbsH4Sw4MnOUg!a+=hM?DUiuo;RJJvjC72qFrCOj>e;1U zqEm;4b>#fi7k3J^w9js6_cXM^(CzUD=o{II{Gh)3a_OmVVDmn-jIgvejA~l=e`)ccbK8;E7^QAGt_E%5JMyEwSZo^wAi5hs>6^@$}U90iT?+z z(@aB1nv@+ET*_JP6}q&;W-_4zA4IX(M3t54#633T5)ntnF@`8R>T8#wi70eQzQ8-f9)djXUK@CtenM4{3Gf z?E5gbyMmVRm=`tLPl3e?0wg*L4$tIZMf};mZ0F)9`Wg-9sa)nHVSeo-j6)*qvA!=}rtn|o2uizY)* zP2#SMyKtWh588NHn~nO7N0PhN^nngUX5i8zBYJJ(8SRnxM1%zDdaz4MS_YHU5d4l| z(aVTdx|J`=^#K++IvEH>sD=^T<3$3izX+G*2n)q{wsy*gi|02I9^cXlXUD&1B&!#` zO-~bGyIw=Qh)!36g)*X3o*x&W@Nb*G&#dJ&2Q8mEJ_=j_+;3t65WJ(LJfy-P%C5K| zs?I?|kkTX|_E3JU4%Aapa!c zA$g1YMu5(8afjS6yZx2Q>AZQ_RQDaSK<*aT3dgf5b6{$AP7mVDU`d(eb}E+Dq+a1= z@Qer!h`zQfJKL0#OFzQL?NomI0@2R>YWO35Rt+Im3$0)&KWQv;tpL5Vm~dE!m877( z)fc}{whWcE^|XS;qS|)Z!f?rpqf~nv3CB0(M_dk|M;p`4+on8}O|Qii#JUR0X%m+> ztC1~5Lra;@n>wv&>>AHaW$9M%@{3Da^c@by-3t*!$y_)z(Nh_@DSK>{k!FD5KksM| z4rH2*HWt3Ym9jX(Vb^Y~{ncB*pUT7m;pPZ`ft2OfmQC%B@6QayX5)cz*>W6ZPOf$m zEN8=hfp9vKmQ!3(mU(!-v~Gh-{IMC4CP~)4l1Q8~zr8G4h+7->T`i?`YIS;Z$?Gc{~jv)LOz)r{zL&=w*ycwyg7Ku=Y(!(7vr9F)ylBE;ZGg zJn9;Xt*<-)y%|YS<%e-!s999g-GTO0cYq^28u(O+1Vn8Sm&S<+H~PSTZvh^6dI0vz zZrFRp0~-ZU^4=Tam*z~78HO;i?Q1Ft_QruVQuKPEa8|rI@qzSDeyN(b;vDo6^zmzs zlh=D84axiDqtU&rCGeuzZ%=RsbwDi!+XJD4$Bm3xBn^~ehn=iqy9I4Zm516#yCGo; zhHk0OQ;7=vcV9F=LS*0kHk&v{qnG$?nFKT>2-0T2mNwU?&%+o89+a?KizMmRs0Rmp zM&fC=9^@uPPbsUaS{7X<0ZK!zi+s7%BZHYCnxXE?jPTN}D^6RA#irTG!3lf;hy%)f zmEtzQ5c^bILS+#W&@skd>E;X_kIlBmGjKVYA!a5pFQ?z{YX68ZsF~}%kN+$jd{((- zvW?oHro-M^Ltzmaz0TM=w$0Hn0MCEnPUNGmYrS172dI#^9gh3SQ1B0VkgvAcS(01~ zvWLS0V^-FY3g+u<_F0Ovh6q4i-cIBE0P=$lqD3wRDi~+v(&rXc9m-g#k^eSI`e*!i zV6pVuIug+F)XH=5&1ZR)JL*)-&_@F3tfav;lB5X>gsBLt4Nx&GM-CS1B6tneQNXc_ z2cRM3DWNbZ=EO_wDOSMc_mZZVLE9#nT{j?DZ{%6xlH}MKX6Mf`3BAk;L+o`m{pZNL zqOn3FXDO5Ry19R>8BQAb%!E0=#ouR&==2NnXT#6_c0Q7kj zi#OSo!i=jER@$fKO{`?jGB?=rXSo9ll{@nTGX~zfqjz!DBb0GkoceQ>uZ?Z^ z$Mw~6on`gzzIm{(c}S`!zq=wB*YRd0PVekTIa=;e=fLn~U(AvE@S-(UQu-%NdMF*OtZc|8MvICJ)m`CJh>e~Hn{ z@AL6**?}PYV>X49lYp%S$v5nl zR?Yw~ijO7|%H~|0C%bm`V>naS1{rwnAO23gZua3AcU!2bTATt z_WEDevG)jQfW=^;+=SZitp&T`ZSDbr_L-}>ah5+ArpdXdZf_Yw#ib=3kS$g1|pa^5=#Ek86zB<)~JKNHyRVWizPt!uh3du5j;Bzob4k5d%KWz_9CXsUih_AKtt>vq+a5lp7 z1ar#r5g7Cd@@5`Vkr=}G{U#3)@-As2;pM?kYw6YAQYLM=UVqkLv0HO$00K|7GEf!u zMHZTXoj|b>E)2R&re7Dq{I&G^E9nO@<4G2&&G#7T$>v0|P;R-RGSq1ZPV74VsSkjZ zUNv$u!lj5+?EMsd$VSjHs@StDnCD>dIq=Z-CJt|B4DSf4uTipv33{B^%$c(lGZAsN z>*?OX?VZq*wGp6?rs}aw+Bryv)R>v*girhHJEt*As*DvEN z^TEp`9+uf;QD+7!juDsu#6fr9HFb;lpV%AQ&Nnb{66dPk+8N>W5oj{XgfnaY zb$ojvZFGCY=8^Ad?3}AkF0FB3E3yQr=M3%i0qW-|m|7xsH^D6UHIe|cWm2v!71$TgW9+sG}S%6e%Vko^t zI@Ct+PXCd5u0c1Qzh4uH+fR@!=?lPy+f)+t0#7>n3)yn^J0R^kb-jjquibVZV{jeb(Ah_D;5?TyUx(qEIhOdZn1b6ZX^_{4 zH`fO`7)k0Eeq98A#xO;geWS_gBktm6X`Q%Z?N0}T?n&Ctyn?YXnMHAPa$ zezm@z(<<5;LZSyQ4pZ%oxon(52W<=>j+Wjgybd_}2}@n8O4vNyEWErj!*ljv^C^$X zhY6mbtd&ht&>qFntbsT9VYg}nxr;=HsrNa2dU>OKv?TS*FT%y)sZB}VZpr2D^a4CZ9`BP%r*L?@WgwA$YnO2 z`jS4=H~~)N1k(b_L1vQ~Gb94$(@t$2>OS98^$D>4A4s1=Ko824)!(D(uY&pZM#%@$LCv)QXYa4rUL%(t2XGKqxBRYoIKr4dbMt{ic*xa&pkg-~SDN6J; zlh}8il84=DX`n5VGi~NY;ccHn-*qW?f}m?Dt^X5CT+57ylXaLk`yYUMpT(7F3A6El z7YrVnWa*2HlHpGiz+(m=W|q7l(vf2Rd>e^4G;POWYLf%zt00^ct@VzLv zWy8f5r+Q{60|tC!Hbro9yZ27z*sL4n=gPbKRZX#xqV1FoAB^3ipTplC=?g0l#kgVENw8qESX9vkPH7A(f27$JP0^(0r z!!`x_@nYS-VEZ2c{o`Sipcc|%0z6%iXZ8qQ!lDuipnj5I%fFBBwCz>t{WmbT^z$?w zs=EWWN#I$Kx-Br{1ODtFz!W5pCNYH_xBL@NOk1!#JWBO($Fd>lJj~TkxBREp{LcNz zm308YWa?nw!Nw$!|3+!eeoj?ch$SeQpaEq59SU z0hxdA(0t+P!=ppa%X2{u$3`_obMm6_(XWx`pza?mc>P}aJPqo8;b{3>P*CDDfyZ?0 zeW}0y7$(Sfp6WL_Vt;g5zA2FPIAZqQ(MH7Oib;8}`<06XX#1(qD!j$CiL1(9kd1&M zF@+}VeHr=P+5=|ak4nKyXidZnodfZ zfo=0PBmnFGUa>BM*^H0S{?@A8V4oIw^WGrSr(D$#t*z6UIrsR;WP-gCIl8?BT>k@=l%t>VzBni~Ovk1891YH*vM8wh0}kclR4M6NUmLT9uf5xTsKk&j%>Y-#Uezhcx)h{tcF?=C_2E z&F=71&JusXA|JFP-YkE{d+mr6<49ojKf^l#x`7kzqX%x0v{R|nR3T?5>PD<| zS<_05*>ZZo#^uz{%f1JLlpwtof9Ip%660j!>G3p)c=NsX7ic|c@WwS!Fd&V+&lBQQ z9M0R#4uCS%;JwS6xwz5MOSw8d*0ba5Ya4R!Z#U^3xGOk8`mw;cD$eLKE_p9&x$3I0 zA+F2?Ygl#|L+W(gO#s{F*dGV`ZohLiGb_YSGqkWP^oxn|P!ubkT5a=_uaTfqiuDmM zUw^;APC!4Kod(^B#mEhR`{PgJ#|trMO(OT&SL9AXztI5(#JIVhGX>JuUokeolFUdz zwjfV~S;VcU*EIUQ)AU;=Ls`wfaPX=9y)n@^LcNELM@~8k!fOloczIvV;<@_;$tDED zd%lKRXzdD(`C#JKma52Z?7VRC8~vbDz9FnEGfffsVZ2#UM7f zk|0mq+254ML5|l-aDKnAX0?%T<@cYp+MaO<+E6{(_S-%^K?WH;q-q)2^6Jf(dq%%E zrh;)4-*6Ns{x`c$*Qo_ZXjJW)t8zyVO*FQF#;)~A#6taR^w2jkLAHNrpY(~vTwJav zX`4=eooxABe>jFIH%XfbpeBsgT=XIBGHf1txY1tc5y|2dUi)tZo){BQl#9x)s<07i z=3jgggJOezed1*Mr#;-zehMA*O{oKjGxVT30*K<}S2ZFS%`=9$9ky#R#3B(xoXo%5 z|I^$pLgf@&X#BX}D-n8X%^A-dUHryaC;AJZ_*u)y%; zpgGYs^*=HGL{LAMd_f_TW8gh}cbb8B)V9^L5v&PnPRJ6CAIyZ>$wbs`Rs^dJw;e>n z0C8Q;Y*NO))#&Y833ur^5#D4l7R8>j5FFfpVBxFSC zHdt*efzr5}FhnI?1@``ilTUho|KTi7tiLh}kK^fvh$GLO*u7p!SR&Rd|L@v>y{Kho z{oky`$zUMl~+ zT#cK^g=glve})=LaeaOl^2i~aF}wQqVI^xven+cS_|pB@-v0JGojw#G%n6SUC;YDt zDbCMd4m*{04fx%7*)kbADp3Yk!H~u$6?51A( zMdWPo_cy1;KRZ9Ox|0eAoF`>JG@ecFjo07{iyWyd9IcXhFm4;EDQA*kwI2xKb zcCLBf{BvneCUjp*o%DxU)5TK5Zw;}*EV5b06R%`tI}x_b{xX{fOB~yW@~g;d3Vkk7 z@?_@l#yp7|7;%AS=Dw5VVtjK!^z$Q$>^^~&FF7vN_-ifUEpbc7d_Q7NIx&MsTtYB` s(@`q?f899$e^39rCCFJVJ(B-kgLS*b70C