From ab61101ab64a58d4a5367d000e44446ca92353c4 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Tue, 20 Jun 2023 20:36:33 +0700 Subject: [PATCH] Pull and push modes now can be independently configured --- .../mc/otm/datagen/lang/English.kt | 3 + .../mc/otm/datagen/lang/Russian.kt | 3 + .../mc/otm/capability/FlowDirection.kt | 4 +- .../mc/otm/client/render/Widgets18.kt | 134 +++++++++++------- .../otm/client/screen/panels/EditablePanel.kt | 20 +++ .../client/screen/panels/button/Buttons.kt | 129 ++++++++++------- .../mc/otm/matter/MatterManager.kt | 2 +- .../otm/menu/input/EnergyConfigPlayerInput.kt | 21 +-- .../otm/menu/input/FluidConfigPlayerInput.kt | 21 +-- .../otm/menu/input/ItemConfigPlayerInput.kt | 22 +-- .../textures/gui/widgets/redstone.png | Bin 713 -> 0 bytes .../textures/gui/widgets/redstone.xcf | Bin 4764 -> 0 bytes .../textures/gui/widgets/side_controls.png | Bin 2050 -> 2631 bytes .../textures/gui/widgets/side_controls.xcf | Bin 37629 -> 70796 bytes 14 files changed, 203 insertions(+), 156 deletions(-) delete mode 100644 src/main/resources/assets/overdrive_that_matters/textures/gui/widgets/redstone.png delete mode 100644 src/main/resources/assets/overdrive_that_matters/textures/gui/widgets/redstone.xcf diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt index 2f178dfb4..efaf4c0c7 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt @@ -661,6 +661,9 @@ private fun gui(provider: MatteryLanguageProvider) { gui("sides.energy_config", "Energy Configuration") gui("sides.fluid_config", "Fluid Configuration") + gui("sides.pull_help", "Hold Shift to cycle pull mode") + gui("sides.push_help", "Hold Ctrl to cycle push mode") + gui("sides.top", "Top") gui("sides.bottom", "Bottom") gui("sides.front", "Front") diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt index c450a4a45..ad0fc506c 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt @@ -666,6 +666,9 @@ private fun gui(provider: MatteryLanguageProvider) { gui("sides.energy_config", "Настройка энергии") gui("sides.fluid_config", "Настройка жидкости") + gui("sides.pull_help", "Удерживайте Shift для настройки режима забора") + gui("sides.push_help", "Удерживайте Ctrl для настройки режима выталкивания") + gui("sides.top", "Верхняя сторона") gui("sides.bottom", "Нижняя сторона") gui("sides.front", "Передняя сторона") diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/FlowDirection.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/FlowDirection.kt index 4e72ceb3a..ae15a5428 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/FlowDirection.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/FlowDirection.kt @@ -68,14 +68,14 @@ enum class FlowDirection(val input: Boolean, val output: Boolean, val translatio get() = TranslatableComponent(translationKey) /** - * Subtype test (returns true if we can assign [t] to this, e.g. we can assign [BI_DIRECTIONAL] to [INPUT]) + * Subtype test (returns true if we can assign [t] to this, for example if we can assign [BI_DIRECTIONAL] to [INPUT]) */ override fun test(t: FlowDirection): Boolean { return t === this || (!input || t.input) && (!output || t.output) } /** - * Subtype test (returns true if we can assign [value] to this, e.g. we can assign [BI_DIRECTIONAL] to [INPUT]) + * Subtype test (returns true if we can assign [value] to this, for example if we can assign [BI_DIRECTIONAL] to [INPUT]) */ fun isSubtype(value: FlowDirection) = test(value) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Widgets18.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Widgets18.kt index a34697f1c..3e03f8ed5 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Widgets18.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Widgets18.kt @@ -59,40 +59,99 @@ object Widgets18 { val PATTERN_SLOT_BACKGROUND = slotBgGrid.next() val MATTER_CAPACITOR_SLOT_BACKGROUND = slotBgGrid.next() - private val redstoneGrid = WidgetLocation.REDSTONE_CONTROLS.grid(rows = 1, columns = 3) + private val controlsGrid = WidgetLocation.SIDE_CONTROLS.grid(rows = 7, columns = 9) - val REDSTONE_IGNORED = redstoneGrid.next() - val REDSTONE_LOW = redstoneGrid.next() - val REDSTONE_HIGH = redstoneGrid.next() + val BATTERY_ONLY = controlsGrid.next() + val ITEMS_CONFIGURATION = controlsGrid.next() + val ENERGY_CONFIGURATION = controlsGrid.next() + val FLUID_CONFIGURATION = controlsGrid.next() - private val controlsGrid = WidgetLocation.SIDE_CONTROLS.grid(rows = 4, columns = 8) + val REDSTONE_IGNORED = controlsGrid.next() + val REDSTONE_LOW = controlsGrid.next() + val REDSTONE_HIGH = controlsGrid.next() - val PULL = controlsGrid.next() - val PUSH = controlsGrid.next() - val PULL_DISABLED = controlsGrid.next() - val PUSH_DISABLED = controlsGrid.next() - - private fun controls() = immutableMap { - put(FlowDirection.NONE, controlsGrid.next()) - put(FlowDirection.INPUT, controlsGrid.next()) - put(FlowDirection.OUTPUT, controlsGrid.next()) - put(FlowDirection.BI_DIRECTIONAL, controlsGrid.next()) + init { + controlsGrid.jump() } - private fun controls2(input: Map) = immutableMap { - put(MatteryDeviceBlockEntity.ItemHandlerMode.DISABLED, input[FlowDirection.NONE]!!) - put(MatteryDeviceBlockEntity.ItemHandlerMode.INPUT, input[FlowDirection.INPUT]!!) - put(MatteryDeviceBlockEntity.ItemHandlerMode.OUTPUT, input[FlowDirection.OUTPUT]!!) - put(MatteryDeviceBlockEntity.ItemHandlerMode.INPUT_OUTPUT, input[FlowDirection.BI_DIRECTIONAL]!!) - put(MatteryDeviceBlockEntity.ItemHandlerMode.BATTERY, BATTERY_ONLY) + class SideControls { + val disabled = controlsGrid.next() + val input = controlsGrid.next() + val pull = controlsGrid.next() + val output = controlsGrid.next() + val push = controlsGrid.next() + val inputOutput = controlsGrid.next() + val pullOutput = controlsGrid.next() + val inputPush = controlsGrid.next() + val pullPush = controlsGrid.next() + + val flow = immutableMap { + put(FlowDirection.NONE, disabled) + put(FlowDirection.INPUT, input) + put(FlowDirection.OUTPUT, output) + put(FlowDirection.BI_DIRECTIONAL, inputOutput) + } + + val flowPush = immutableMap { + put(FlowDirection.NONE, disabled) + put(FlowDirection.INPUT, input) + put(FlowDirection.OUTPUT, push) + put(FlowDirection.BI_DIRECTIONAL, inputPush) + } + + val flowPull = immutableMap { + put(FlowDirection.NONE, disabled) + put(FlowDirection.INPUT, pull) + put(FlowDirection.OUTPUT, output) + put(FlowDirection.BI_DIRECTIONAL, pullOutput) + } + + val flowPullPush = immutableMap { + put(FlowDirection.NONE, disabled) + put(FlowDirection.INPUT, pull) + put(FlowDirection.OUTPUT, push) + put(FlowDirection.BI_DIRECTIONAL, pullPush) + } + + val items = immutableMap { + put(MatteryDeviceBlockEntity.ItemHandlerMode.DISABLED, disabled) + put(MatteryDeviceBlockEntity.ItemHandlerMode.INPUT, input) + put(MatteryDeviceBlockEntity.ItemHandlerMode.OUTPUT, output) + put(MatteryDeviceBlockEntity.ItemHandlerMode.INPUT_OUTPUT, inputOutput) + put(MatteryDeviceBlockEntity.ItemHandlerMode.BATTERY, BATTERY_ONLY) + } + + val itemsPush = immutableMap { + put(MatteryDeviceBlockEntity.ItemHandlerMode.DISABLED, disabled) + put(MatteryDeviceBlockEntity.ItemHandlerMode.INPUT, input) + put(MatteryDeviceBlockEntity.ItemHandlerMode.OUTPUT, push) + put(MatteryDeviceBlockEntity.ItemHandlerMode.INPUT_OUTPUT, inputPush) + put(MatteryDeviceBlockEntity.ItemHandlerMode.BATTERY, BATTERY_ONLY) + } + + val itemsPull = immutableMap { + put(MatteryDeviceBlockEntity.ItemHandlerMode.DISABLED, disabled) + put(MatteryDeviceBlockEntity.ItemHandlerMode.INPUT, pull) + put(MatteryDeviceBlockEntity.ItemHandlerMode.OUTPUT, output) + put(MatteryDeviceBlockEntity.ItemHandlerMode.INPUT_OUTPUT, pullOutput) + put(MatteryDeviceBlockEntity.ItemHandlerMode.BATTERY, BATTERY_ONLY) + } + + val itemsPullPush = immutableMap { + put(MatteryDeviceBlockEntity.ItemHandlerMode.DISABLED, disabled) + put(MatteryDeviceBlockEntity.ItemHandlerMode.INPUT, pull) + put(MatteryDeviceBlockEntity.ItemHandlerMode.OUTPUT, push) + put(MatteryDeviceBlockEntity.ItemHandlerMode.INPUT_OUTPUT, pullPush) + put(MatteryDeviceBlockEntity.ItemHandlerMode.BATTERY, BATTERY_ONLY) + } } - val LEFT_CONTROLS = controls() - val RIGHT_CONTROLS = controls() - val TOP_CONTROLS = controls() - val BOTTOM_CONTROLS = controls() - val FRONT_CONTROLS = controls() - val BACK_CONTROLS = controls() + val LEFT_CONTROLS = SideControls() + val RIGHT_CONTROLS = SideControls() + val TOP_CONTROLS = SideControls() + val BOTTOM_CONTROLS = SideControls() + val FRONT_CONTROLS = SideControls() + val BACK_CONTROLS = SideControls() val CONTROLS = immutableMap { put(RelativeSide.BOTTOM, BOTTOM_CONTROLS) @@ -102,25 +161,4 @@ object Widgets18 { put(RelativeSide.FRONT, FRONT_CONTROLS) put(RelativeSide.BACK, BACK_CONTROLS) } - - val BATTERY_ONLY = controlsGrid.next() - val ITEMS_CONFIGURATION = controlsGrid.next() - val ENERGY_CONFIGURATION = controlsGrid.next() - val FLUID_CONFIGURATION = controlsGrid.next() - - val LEFT_CONTROLS_ITEMS = controls2(LEFT_CONTROLS) - val RIGHT_CONTROLS_ITEMS = controls2(RIGHT_CONTROLS) - val TOP_CONTROLS_ITEMS = controls2(TOP_CONTROLS) - val BOTTOM_CONTROLS_ITEMS = controls2(BOTTOM_CONTROLS) - val FRONT_CONTROLS_ITEMS = controls2(FRONT_CONTROLS) - val BACK_CONTROLS_ITEMS = controls2(BACK_CONTROLS) - - val ITEMS_CONTROLS = immutableMap { - put(RelativeSide.BOTTOM, BOTTOM_CONTROLS_ITEMS) - put(RelativeSide.TOP, TOP_CONTROLS_ITEMS) - put(RelativeSide.LEFT, LEFT_CONTROLS_ITEMS) - put(RelativeSide.RIGHT, RIGHT_CONTROLS_ITEMS) - put(RelativeSide.FRONT, FRONT_CONTROLS_ITEMS) - put(RelativeSide.BACK, BACK_CONTROLS_ITEMS) - } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EditablePanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EditablePanel.kt index c322ffbc0..a0ca9d7c8 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EditablePanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EditablePanel.kt @@ -391,6 +391,26 @@ open class EditablePanel @JvmOverloads constructor( field = value } + fun prependTooltip(text: Component) { + if (tooltip == null && tooltipList == null) { + tooltip = text + } else if (tooltip != null) { + tooltipList = listOf(text, tooltip!!) + } else { + tooltipList = tooltipList!!.toMutableList().also { it.add(0, text) } + } + } + + fun appendTooltip(text: Component) { + if (tooltip == null && tooltipList == null) { + tooltip = text + } else if (tooltip != null) { + tooltipList = listOf(text, tooltip!!) + } else { + tooltipList = tooltipList!!.toMutableList().also { it.add(text) } + } + } + var blockingWindow: EditablePanel<*>? = null get() { if (field?.isRemoved != true) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/Buttons.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/Buttons.kt index d89dbc847..7db124cc0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/Buttons.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/Buttons.kt @@ -1,14 +1,20 @@ package ru.dbotthepony.mc.otm.client.screen.panels.button import com.mojang.blaze3d.platform.InputConstants +import net.minecraft.ChatFormatting +import net.minecraft.client.gui.GuiGraphics import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting import ru.dbotthepony.mc.otm.capability.FlowDirection +import ru.dbotthepony.mc.otm.client.isCtrlDown +import ru.dbotthepony.mc.otm.client.isShiftDown import ru.dbotthepony.mc.otm.client.minecraft +import ru.dbotthepony.mc.otm.client.render.AbstractMatterySprite import ru.dbotthepony.mc.otm.client.render.Widgets18 import ru.dbotthepony.mc.otm.client.screen.MatteryScreen import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel +import ru.dbotthepony.mc.otm.core.GetterSetter import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.math.RelativeSide import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback @@ -42,11 +48,64 @@ private fun > makeRedstoneSettingButton( } } +private class PullPushButton, T : Enum>( + screen: S, + parent: EditablePanel<*>?, + x: Float = 0f, + y: Float = 0f, + enum: Class, + prop: GetterSetter, + defaultValue: T, + val pullProp: BooleanInputWithFeedback, + val pushProp: BooleanInputWithFeedback +) : LargeEnumRectangleButtonPanel(screen, parent, x = x, y = y, enum = enum, prop = prop, defaultValue = defaultValue) { + init { + if (pullProp.test(minecraft.player) && pushProp.test(minecraft.player)) { + tooltipList = listOf(TranslatableComponent("otm.gui.sides.pull_help").withStyle(ChatFormatting.GRAY), TranslatableComponent("otm.gui.sides.push_help").withStyle(ChatFormatting.GRAY)) + } else if (pullProp.test(minecraft.player)) { + tooltip = TranslatableComponent("otm.gui.sides.pull_help").withStyle(ChatFormatting.GRAY) + } else if (pushProp.test(minecraft.player)) { + tooltip = TranslatableComponent("otm.gui.sides.push_help").withStyle(ChatFormatting.GRAY) + } + } + + data class State>(val pull: Boolean, val push: Boolean, val value: T) + private val sprites = HashMap, AbstractMatterySprite>() + + fun addSprite(pull: Boolean, push: Boolean, value: T, sprite: AbstractMatterySprite) { + sprites[State(pull, push, value)] = sprite + } + + override fun innerRender(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float) { + super.innerRender(graphics, mouseX, mouseY, partialTick) + sprites[State(pullProp.value, pushProp.value, prop.get())]?.render(graphics, 0f, 0f, width, height) + } + + override fun onClick(mouseButton: Int) { + if (mouseButton != InputConstants.MOUSE_BUTTON_MIDDLE && minecraft.window.isShiftDown) { + if (pullProp.test(minecraft.player)) { + pullProp.switchValue() + } + } else if (mouseButton != InputConstants.MOUSE_BUTTON_MIDDLE && minecraft.window.isCtrlDown) { + if (pushProp.test(minecraft.player)) { + pushProp.switchValue() + } + } else { + super.onClick(mouseButton) + } + } +} + private fun > makeItemModeButton(screen: S, parent: FramePanel, input: ItemConfigPlayerInput.Piece, side: RelativeSide): LargeEnumRectangleButtonPanel { - val button = LargeEnumRectangleButtonPanel(screen, parent, enum = MatteryDeviceBlockEntity.ItemHandlerMode::class.java, prop = input.input, defaultValue = input.default) + val button = PullPushButton(screen, parent, enum = MatteryDeviceBlockEntity.ItemHandlerMode::class.java, prop = input.input, defaultValue = input.default, pullProp = input.pull, pushProp = input.push) + val widgets = Widgets18.CONTROLS[side]!! for (v in MatteryDeviceBlockEntity.ItemHandlerMode.values()) { - button.add(v, skinElement = Widgets18.ITEMS_CONTROLS[side]!![v]!!, tooltip = TranslatableComponent(v.translationKey)) + button.add(v, tooltip = TranslatableComponent(v.translationKey)) + button.addSprite(false, false, v, widgets.items[v]!!) + button.addSprite(true, false, v, widgets.itemsPull[v]!!) + button.addSprite(false, true, v, widgets.itemsPush[v]!!) + button.addSprite(true, true, v, widgets.itemsPullPush[v]!!) } button.finish() @@ -56,10 +115,15 @@ private fun > makeItemModeButton(screen: S, parent: FramePa } private fun > makeEnergyModeButton(screen: S, parent: FramePanel, input: EnergyConfigPlayerInput.Piece, side: RelativeSide): LargeEnumRectangleButtonPanel { - val button = LargeEnumRectangleButtonPanel(screen, parent, enum = FlowDirection::class.java, prop = input.input, defaultValue = input.default) + val button = PullPushButton(screen, parent, enum = FlowDirection::class.java, prop = input.input, defaultValue = input.default, pullProp = input.pull, pushProp = input.push) + val widgets = Widgets18.CONTROLS[side]!! for (v in FlowDirection.values()) { - button.add(v, skinElement = Widgets18.CONTROLS[side]!![v]!!, tooltip = TranslatableComponent(v.translationKey)) + button.add(v, tooltip = TranslatableComponent(v.translationKey)) + button.addSprite(false, false, v, widgets.flow[v]!!) + button.addSprite(true, false, v, widgets.flowPull[v]!!) + button.addSprite(false, true, v, widgets.flowPush[v]!!) + button.addSprite(true, true, v, widgets.flowPullPush[v]!!) } button.finish() @@ -68,10 +132,15 @@ private fun > makeEnergyModeButton(screen: S, parent: Frame } private fun > makeFluidModeButton(screen: S, parent: FramePanel, input: FluidConfigPlayerInput.Piece, side: RelativeSide): LargeEnumRectangleButtonPanel { - val button = LargeEnumRectangleButtonPanel(screen, parent, enum = FlowDirection::class.java, prop = input.input, defaultValue = input.default) + val button = PullPushButton(screen, parent, enum = FlowDirection::class.java, prop = input.input, defaultValue = input.default, pullProp = input.pull, pushProp = input.push) + val widgets = Widgets18.CONTROLS[side]!! for (v in FlowDirection.values()) { - button.add(v, skinElement = Widgets18.CONTROLS[side]!![v]!!, tooltip = TranslatableComponent(v.translationKey)) + button.add(v, tooltip = TranslatableComponent(v.translationKey)) + button.addSprite(false, false, v, widgets.flow[v]!!) + button.addSprite(true, false, v, widgets.flowPull[v]!!) + button.addSprite(false, true, v, widgets.flowPush[v]!!) + button.addSprite(true, true, v, widgets.flowPullPush[v]!!) } button.finish() @@ -87,12 +156,12 @@ private fun moveButtons( top: EditablePanel<*>, bottom: EditablePanel<*>, ) { - top.tooltip = TranslatableComponent("otm.gui.sides.top") - bottom.tooltip = TranslatableComponent("otm.gui.sides.bottom") - back.tooltip = TranslatableComponent("otm.gui.sides.back") - front.tooltip = TranslatableComponent("otm.gui.sides.front") - left.tooltip = TranslatableComponent("otm.gui.sides.left") - right.tooltip = TranslatableComponent("otm.gui.sides.right") + top.prependTooltip(TranslatableComponent("otm.gui.sides.top")) + bottom.prependTooltip(TranslatableComponent("otm.gui.sides.bottom")) + back.prependTooltip(TranslatableComponent("otm.gui.sides.back")) + front.prependTooltip(TranslatableComponent("otm.gui.sides.front")) + left.prependTooltip(TranslatableComponent("otm.gui.sides.left")) + right.prependTooltip(TranslatableComponent("otm.gui.sides.right")) top.x = 30f top.y = 14f @@ -113,39 +182,6 @@ private fun moveButtons( back.y = 14f + 42f } -@Suppress("name_shadowing") -private fun pullPush(frame: FramePanel<*>, pull: BooleanInputWithFeedback, push: BooleanInputWithFeedback) { - if (pull.test(minecraft.player)) { - val pull = LargeBooleanRectangleButtonPanel( - frame.screen, - frame, - skinElementActive = Widgets18.PULL, - skinElementInactive = Widgets18.PULL_DISABLED, - prop = pull, - ) - - pull.tooltip = TranslatableComponent("otm.gui.side_mode.pull") - - pull.x = 30f - 20f - pull.y = 14f - } - - if (push.test(minecraft.player)) { - val push = LargeBooleanRectangleButtonPanel( - frame.screen, - frame, - skinElementActive = Widgets18.PUSH, - skinElementInactive = Widgets18.PUSH_DISABLED, - prop = push, - ) - - push.tooltip = TranslatableComponent("otm.gui.side_mode.push") - - push.x = 30f + 20f - push.y = 14f - } -} - private fun > makeItemHandlerControlPanel( screen: S, inputs: ItemConfigPlayerInput @@ -167,7 +203,6 @@ private fun > makeItemHandlerControlPanel( val top = makeItemModeButton(screen, frame, inputs.pieces[RelativeSide.TOP]!!, RelativeSide.TOP) val bottom = makeItemModeButton(screen, frame, inputs.pieces[RelativeSide.BOTTOM]!!, RelativeSide.BOTTOM) - pullPush(frame, inputs.pull, inputs.push) moveButtons(front, back, left, right, top, bottom) screen.addPanel(frame) frame.requestFocus() @@ -196,7 +231,6 @@ private fun > makeEnergyConfigPanel( val top = makeEnergyModeButton(screen, frame, inputs.pieces[RelativeSide.TOP]!!, RelativeSide.TOP).also { it.predicate = Predicate { inputs.possibleModes.isSupertype(it) } } val bottom = makeEnergyModeButton(screen, frame, inputs.pieces[RelativeSide.BOTTOM]!!, RelativeSide.BOTTOM).also { it.predicate = Predicate { inputs.possibleModes.isSupertype(it) } } - pullPush(frame, inputs.pull, inputs.push) moveButtons(front, back, left, right, top, bottom) screen.addPanel(frame) frame.requestFocus() @@ -225,7 +259,6 @@ private fun > makeFluidConfigPanel( val top = makeFluidModeButton(screen, frame, inputs.pieces[RelativeSide.TOP]!!, RelativeSide.TOP).also { it.predicate = Predicate { inputs.possibleModes.isSupertype(it) } } val bottom = makeFluidModeButton(screen, frame, inputs.pieces[RelativeSide.BOTTOM]!!, RelativeSide.BOTTOM).also { it.predicate = Predicate { inputs.possibleModes.isSupertype(it) } } - pullPush(frame, inputs.pull, inputs.push) moveButtons(front, back, left, right, top, bottom) screen.addPanel(frame) frame.requestFocus() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/matter/MatterManager.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/matter/MatterManager.kt index 95c511b37..ea34a8d46 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/matter/MatterManager.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/matter/MatterManager.kt @@ -1686,7 +1686,7 @@ object MatterManager { fun onServerStarted(event: ServerStartedEvent) { check(Resolver.ready) { "Recipe resolver is not ready somehow" } check(Registry.ready) { "Matter registry is not ready somehow" } - finishUpIfRequiredAndPossible(event.server ?: throw NullPointerException("what.")) + finishUpIfRequiredAndPossible(event.server) } fun get(value: Item): IMatterValue { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/EnergyConfigPlayerInput.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/EnergyConfigPlayerInput.kt index 2abbbbf96..3525c023f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/EnergyConfigPlayerInput.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/EnergyConfigPlayerInput.kt @@ -21,8 +21,8 @@ class EnergyConfigPlayerInput(val menu: MatteryMenu, config: MatteryDeviceBlockE var default by menu.mSynchronizer.enum(FlowDirection.NONE) init { - pull.filter { allowPull } - push.filter { allowPush } + pull.filter { allowPull && possibleModes.isSupertype(FlowDirection.INPUT) } + push.filter { allowPush && possibleModes.isSupertype(FlowDirection.OUTPUT) } } fun with(config: MatteryDeviceBlockEntity.ConfigurableEnergy<*>.Piece, parent: MatteryDeviceBlockEntity.ConfigurableEnergy<*>) { @@ -34,17 +34,6 @@ class EnergyConfigPlayerInput(val menu: MatteryMenu, config: MatteryDeviceBlockE val pieces = immutableMap { for (side in RelativeSide.values()) put(side, Piece(side)) } - // TODO - val pull = BooleanInputWithFeedback(menu) - - // TODO - val push = BooleanInputWithFeedback(menu) - - init { - pull.filter { allowPull } - push.filter { allowPush } - } - fun with(config: MatteryDeviceBlockEntity.ConfigurableEnergy<*>) { possibleModes = config.possibleModes @@ -52,12 +41,6 @@ class EnergyConfigPlayerInput(val menu: MatteryMenu, config: MatteryDeviceBlockE pieces[side]!!.with(v, config) pieces[side]!!.default = config.defaults[side]!! } - - pull.withSupplier { pieces.values.all { it.pull.value } } - push.withSupplier { pieces.values.all { it.push.value } } - - pull.withConsumer { v -> pieces.values.forEach { it.pull.input.invoke(v) } } - push.withConsumer { v -> pieces.values.forEach { it.push.input.invoke(v) } } } init { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/FluidConfigPlayerInput.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/FluidConfigPlayerInput.kt index aa0afad4e..b7c33511e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/FluidConfigPlayerInput.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/FluidConfigPlayerInput.kt @@ -21,8 +21,8 @@ class FluidConfigPlayerInput(val menu: MatteryMenu, config: MatteryDeviceBlockEn var default by menu.mSynchronizer.enum(FlowDirection.NONE) init { - pull.filter { allowPull } - push.filter { allowPush } + pull.filter { allowPull && possibleModes.isSupertype(FlowDirection.INPUT) } + push.filter { allowPush && possibleModes.isSupertype(FlowDirection.OUTPUT) } } fun with(config: MatteryDeviceBlockEntity.ConfigurableFluidHandler<*>.Piece, parent: MatteryDeviceBlockEntity.ConfigurableFluidHandler<*>) { @@ -34,17 +34,6 @@ class FluidConfigPlayerInput(val menu: MatteryMenu, config: MatteryDeviceBlockEn val pieces = immutableMap { for (side in RelativeSide.values()) put(side, Piece(side)) } - // TODO - val pull = BooleanInputWithFeedback(menu) - - // TODO - val push = BooleanInputWithFeedback(menu) - - init { - pull.filter { allowPull } - push.filter { allowPush } - } - fun with(config: MatteryDeviceBlockEntity.ConfigurableFluidHandler<*>) { possibleModes = config.possibleModes @@ -52,12 +41,6 @@ class FluidConfigPlayerInput(val menu: MatteryMenu, config: MatteryDeviceBlockEn pieces[side]!!.with(v, config) pieces[side]!!.default = config.defaults[side]!! } - - pull.withSupplier { pieces.values.all { it.pull.value } } - push.withSupplier { pieces.values.all { it.push.value } } - - pull.withConsumer { v -> pieces.values.forEach { it.pull.input.invoke(v) } } - push.withConsumer { v -> pieces.values.forEach { it.push.input.invoke(v) } } } init { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/ItemConfigPlayerInput.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/ItemConfigPlayerInput.kt index 3424eb284..8c6216f03 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/ItemConfigPlayerInput.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/ItemConfigPlayerInput.kt @@ -1,6 +1,7 @@ package ru.dbotthepony.mc.otm.menu.input import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity +import ru.dbotthepony.mc.otm.capability.FlowDirection import ru.dbotthepony.mc.otm.core.immutableMap import ru.dbotthepony.mc.otm.core.math.RelativeSide import ru.dbotthepony.mc.otm.menu.MatteryMenu @@ -22,8 +23,8 @@ class ItemConfigPlayerInput(val menu: MatteryMenu, config: MatteryDeviceBlockEnt var default by menu.mSynchronizer.enum(MatteryDeviceBlockEntity.ItemHandlerMode.DISABLED) init { - pull.filter { allowPull } - push.filter { allowPush } + pull.filter { allowPull && isAllowed(MatteryDeviceBlockEntity.ItemHandlerMode.INPUT) } + push.filter { allowPush && isAllowed(MatteryDeviceBlockEntity.ItemHandlerMode.OUTPUT) } } fun with(config: MatteryDeviceBlockEntity.ConfigurableItemHandler.Piece) { @@ -35,17 +36,6 @@ class ItemConfigPlayerInput(val menu: MatteryMenu, config: MatteryDeviceBlockEnt val pieces = immutableMap { for (side in RelativeSide.values()) put(side, Piece(side)) } - // TODO - val pull = BooleanInputWithFeedback(menu) - - // TODO - val push = BooleanInputWithFeedback(menu) - - init { - pull.filter { allowPull } - push.filter { allowPush } - } - fun with(config: MatteryDeviceBlockEntity.ConfigurableItemHandler) { for ((f, v) in allowedFlags) { f.boolean = v in config.possibleViews @@ -55,12 +45,6 @@ class ItemConfigPlayerInput(val menu: MatteryMenu, config: MatteryDeviceBlockEnt pieces[side]!!.with(v) pieces[side]!!.default = config.defaults[side]!! } - - pull.withSupplier { pieces.values.all { it.pull.value } } - push.withSupplier { pieces.values.all { it.push.value } } - - pull.withConsumer { v -> pieces.values.forEach { it.pull.input.invoke(v) } } - push.withConsumer { v -> pieces.values.forEach { it.push.input.invoke(v) } } } init { diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets/redstone.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets/redstone.png deleted file mode 100644 index 25899a087574c82adaee823065459db4e5ee89c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 713 zcmV;)0yh1LP)4Tx04UFukv&MmP!xqvQ$>+V2Rn#}WQa}{L`57Wibb$c+6t{Yn7s54nlvOS zE{=k0!NH%!s)LKOt`4q(Aov5~>f)s6A|>9J6k3D|UUf6M;+ajy zXOi*FVmSBXL5wX~)VPnKpk7L>+T_rIKP;p3I@Jrmk zjCUiO<7;zsKW48)9)PBWV0TsT)3o1VUpdRVy5nYzST;7F{$1At70;t2A*OOL1Jq2DdBc z8BjoZhNx!26L`gvS765;p_G&+y8Qlk<|dP3m8zAhz_rfI`MmecIrl$zl2*HOFTTIN z8GpODv}70`L-S%7KR{QZAmAcp3Az?a(B(B~`W8+i#_Lc7y$ijW@``)|`U5JrSZrav z+vzlS`pCvjduzA3)^BdagLZ!_zWw=^U&&H&uIZZN0tIikB9V9$b)8Vd0yd zc0X?KtZy}Yis)``_L}|J`Dgfqz38l*Gb4DI2>I*DefrnrKJ$HYFRv!|E1xF!tGVQU z;aWiwsd95$?bgY>z8Vf}~eeG3B|L_cHuD8D4FczeWss zekQ}uX83Z3zXGrIK7h2|6r^~~FP)$3nt03L{(gq{n@IaEGs2%Tg0Dh4SNO{W8>;X( zudf`IO>me`DKaOA#vDe7Ib%h`9DHbw4~-0F7$OFkrp%v16jEb8!Z_q7xhM+^X1p!* z*vV!%WuCYg=FqfmuE^wuT25J%P35psgR7B`Bl4*kQ^TP~E}|-dHS(z$8BCSAYUEQR zANpF88uJmxDnH5O;~30%Tj;TqO_h9H40C8&Hy8O-wVbjbpW3C%$C8<)K8~mlyTp>P zr8X%Amikz2buK)cr9PJWNFg=4qr~WB>Vr-OSuFI}$%dFGE=F@uA2%2Eamy(S>Vw^( z&Lgk9-5p$7;OVXWGQbmnGo$cfMtBN%h1(Nss0w$yJ^`MfM0p(mtqC3K1cxBu1rzKc z@@WdboU=R{dhj{pu?L^5wD$~vK%H0*z{puOqW~yN0M^5yRyzf=CG$im&j3--!rOt7 z{2U4e4;XwGZZ%c}kg^0|KdfrCQ@~7q zLVX69mpDHMR6&oYabTr>4xvITPvrOnRw44K1Ezo`%OeLoffbSZi4jI+b?{9AOZ_l= zz)~x>npTu2^#iQBhxU|s>gVQ7fvdww2bVB0ztQfk-Q8|(TtKhBWi&3+@u|aK^rFY- zoF3?W6n{VGjju?0e3m5p;cdtz9oKHq%W=`1jExyj89U}BJkFcrv5~?!amxIa2)vXN z#t?x{0`FTW6CMx~j0+|=j`$w<&(3YBiFO(_VIx|$|Ji{gk($V=^9H@!nke_JR9XYo^@**csiT&JiybD zJP!{3;puEu+c0lK44=1}R^%HYZt<6m440{K`oMmf#_3&}8FOD`1$Y%9ZQNXIf=w<% zuUF$rHdwY?!{w6AEk`yQ$h(X-DFv3+$pEBHQwamP_}4 z>ULfabUrHebN=kv({5M3o?t^&>3ID_m`0;u5ROWN0+4+kuttrb9yUt#0!@1!$WHQq zCUE^Xg0j9$trTcq2DnfCKVd#?n`@5W#;I;TcG~3PZAkNSt98S!G(TQ(X@`_`>m d^bKC4dZ$M9Y2Tt}=>6YzAkY*caG9u9&EHSXR#*T4 diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets/side_controls.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets/side_controls.png index b9553b67fcfaa477c3745da08c68d80db3bd8028..23f14bebe429fc7a8ec2139feced02e13080f676 100644 GIT binary patch delta 2595 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 delta 2010 zcmV<02POE&6oL>TiBL{Q4GJ0x0000DNk~Le0001x0000;2nGNE02wQM`jH_Ve^3;K zPg6@pDh_rK5zJ7X+C@biOBIV?p|llRbufA9A2ex5Qd}Gb*MfsTi&X~~XI&j!1wrr! z#MQ+~(M3wUFDbN$@xkSNocGS*zWV^7Rb#5z7Y9_$GBU}8m@lk~!B+$@P8CH^Vy2$T zF6Q95zV6}U`(2D@dEfhU4Jt*Ge*r#`IL>s#BHkdL-L!Ph`@~^Zkrd){;;2Cl5?YXf{|kZb*PXWKlmT~f1a&bnx1l# zLJ1)7V%r}RKyVjmH*Nd-*tXjzfd3h|(z^b73z+*Pz1h_wN5IfFaBw3XSuNiH2Zz99nX=bC-re6jw}0<+=Jx}k zZ*sW{e|^gU000JJOGiWilez&Ye+3@}HU?q4zlZ<;1^-DzK~#9!?Oicz+)5ChJ@g~e zqzI%4z9xm62QJ*XISf8hJ$V1XadVY%9a6cuNq;W_QaN#EZVqcM5 zyjHY3-^{LbI%z&IHeTImr2RCrv-6=NG8hbo-s05|ByAc6iPp9k+fB7<-vBxY{ zJH9J_5NQ0F0LS>>KUw&3KJ`D&^Dp$p;i-Rdc$#hJ^zey4J$&NZBu|P&Lm&@IASywg zroT6ZkT?<&Nh8lctCbrvd5DM{kit9>(Wn2M%Oy{U=ZjmXjX*?1-#@=~x#S7)_VZ7d zJ6Zoed-mt=k9T)OMD*_VfAMu{C+mFn&6OZeX@4eNMIOmm7m-IYhMUBTqVF2Z=lgi4cF9?6_FUf8wA`Y1)*bdoJnuPPO0*|c$q&Y zAPv$|?S($HDcZ1Oe=ryf27|#cN~{-m$bzzqMcF16o3Z{=_k9orf9+J7$YVXAzb96@Q=KA6 zNQfNbhlFU$PK7W$yg4Cxnm&U%%k^l`o5%HxO8JAV3CH+wP0$5l{mDWmxRkI8Nkd%< ztBgDe0vUO9-p+@aMJS3RNC6sNe;+A;Dl1hQ%i zi>k4Q3tjYce|sxvB;@vty7I@hk<+(DO(z9cjiO|VMZvXisGV4JUw;lQ<2ip)b|!69 z6GK$dNwzXH{%Cw`I(OIpOzIJ*R8AiniJIDLE^9^&U{6^V!PmTGh4ZpN1I zrz<-X>CLeQtKAacQfR@~tllx?DS^*nA9^S}@m@c6Ff2ySma&YNuYta|$}tAE}*EYr-MD zsUA`!mQud;K|!arQ?eQ@CD`hNXb)B-mQud;O+km+DXrKX5{V23gTY`h7)D*j$I9kd zRl+SOx2db#6;4i0R2zQF<GjFil1D=#P7#;Wve1&~`e@g^gs1XM9kohC9%<^*qVW}XIf}&a ze>3X_-!{DKPlB&EZ~V*MGbbHOMV9$|PDDf(7Z)2L51PW*HBfB9jF4w6_?4c{#AAJq zJYkBGj8{_f({Ji`7fBRXfXHyGmR*{%e+@X`kJ=rLUn(aJR<&}7O zXV>X$o2#*;BGD9g_}&h>Kh#I^ESF1%>;*L)Q%S2Wi3$$+UIwJBM!vVAZGWzhcHQ3P zjer02ijMCOsQ!Cwk>@W0ZR%Tzw@Fy_u#tF1;qSf611}|!wkOsWdAKMP8>>RnEFcZi sv63f+P4v4;mElb!Ds9(bFc{jw|9?KV+G)6PX#fBK07*qoM6N<$f?ImX*8l(j diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets/side_controls.xcf b/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets/side_controls.xcf index 119df61fc020d2e69e58d8a153e997de00d0f0b6..1556edefad368ba7a8de5d74c0a2feb9fcabf0c0 100644 GIT binary patch literal 70796 zcmeI53zTJ7S?ABax8B{AC$FfZogsmyZbuT(Aj@7L4vWEMvlP8cM${1qNoZDArKc-6 zx^z(l6S5R4pkf#WVYFsBA&XfZu%ZkZLVPxAGghy06tzSY5g&*+C<5KpXMX?xe%y2J zqq@3o(%cBA`_y;#TuWqP`td*+)z z@cFBB^ZXd@399>E;N!w`q0Eov{vh`yH`Cf{4llm+<{PiM`Pku?6Xo=G?O(q2hmPF1 zZ~2xZhhP4bx&1fYe8VkAZaKDZzri)fZhqNI_g(9M*FA;gmkmh1ZlC`t`3IMezVwE} zOE>Sk?pi`WR13wxHLqGaeCxi$OE0I&XBfKL(bxDI?}fKPoS0{r%+0KfBf0e;u(1N`pa2=IIVAi(c`V}LKaDZm@=3h)*03-FbH8{p#Y z0j~UMfIk}B^SW5ikNt9pUyc2K({u>`)Wrebtug2NnXd})t%m}9`-=m-Z!N%I`c#0w z@^t~e??(cB|8EEQ(1!y2_5T~-Z~aMtzx@{ho)lSg{oX!<;*bAlfPZ>LfPZ#tfPemb z0siGv1N^HW4)CvIJ%1P5`}Z#k@&E9X0siAB1Kj#g0ha&Uu+a>7Z%hPUYfOc9HD;e2 z()Sz-aQ?vnFPRDOvadI+|GA!^`XOGKJ$B>Emv6mg=|*Ll;)bD$lKVlR7P8H=tq&zfLY*DClt+YZey}(Vd zq~y;%RH(4xp-F;GayInFN;B2|xqAz>N-?UZq}uW!AVsLu&#oxZ|7n&2tzwJPn#C7F zv900@DnTu66#ukRtc2{uGz-cmOpIDO%gwtasALjT&e>wiS=?z_LD|a5%T&jI75vXJ zvtmf*);rzi3bQK{F8A}Hxht``AeF)zvHK0MqVhZvpq^mEJ)bUG>N!O=R~lqF?QTpI zElMptd~-!C*(2C9pqIySz8>1WSsmjyRPyY0lPx;z~wbc|rVvLJx{jJ$b|_ zLZyBd26lR(W+~7=;wnKcWyG(9;hmirmra-$nvzDG1eHu;%E^d3OYex&Cd&^M{LeA7 zVrVG0-sv`1ow<_HqTJ7i=3W__TN!Z@8(>A{#m+0(aL?n2Q)Kf>M*P5OcY_h9)Y8Mp zh(|A%CO!lU#fU-osP-&Cb z!gGjo`xF(TLy0a*xoW8h9@nlGz$|5I9U_f_8&o2w_z>Pxv_ODb)g-M|Ud?+e#e1a^ zFNt>pc-hopZ#$8;d}1cL2!a%8oYXjDwYtf1io<3-3m+<(@Qfn>oJ&F zUv6AKUU!H&cx%>tH3`22X%QGUg!h=o%3`wIf{(;+(~-{xLF$BkyEkJ5Urv@XZf&|J z^Znves~hj%xc}5^HhyX2y{F!&52ndLD5bdMP4PiMsL&mG@RD~a zGF~Z-;3dD2A`cX;rFrhX#l+GcNPe!ETAKAeYu=o5oZ`d1$N46fuEDan@NZrN8C(QO zNfg)bS(98nF66n0cRYbl{g?ckI(+Mmi_1d7I8laLsB5>Bp($bIx{O&vzEbZaWnA`K zIi*WAL|yig6n}LwkBrsbSZWrncVZUwJWnn$1tBg$(%;F%9{V8;>p0PRBD3An z`bDXL03UmIC7k*nY5lS98IVTQV}B>bKckpG2*wZ2ZZv>r53WqHK6`eB=Q9UaRyHP9 zP8SOW5X$7fGA zfM<`dOua$%^L*y`%F0Pqc(O>r;|d-h96WmTxavP%9Od2e_@0wx1x_EIAWZ$oPx_xi z)PLOdpQQeivv)LrXHTw7{b$wB^O=(?D|e{EJBk!c&55bC;L)QeRsYH2D5>SiJ$IB9 zIDK-0F!i6j!~Ybb{*$ghQh(_w2=!_@5RLZp2_-I?$NbpKq-3g;$?KJQQH3~S&&JPh z{L03CnCUjp|BceQ#*I0S(5787M?-6iU&9?4fTw&t;RE@xi}Naf*7l z1!JA9MdoXys3pw!1ak^=Oj4NNQGdCNXzc(yK-$`(yjDzWER%<{MknM|+LY^J+Ok}_ zHl8}F14!yLadXr+*O@9NXkCN2nOdBBJ4@g7K7TuyG$-bGQt$cOxuiIIqEN({*#@iY+=8*rRvYY+qLzSN!JGniNdaTj zU#^4IHQ*YMwzep*71J8)%5{Ou_0qNRw5B?Mq)rnzM}2c^V3*c4h?}X! zskgKAUGMXE4eTD8<4L{e?;6-WR4C%ideH`yYhbtChusA*t96itI(8Qp^k%zM*{y{d zb{8txEsfoU8g>^d*e#9Sg$i~TB6ee)73`8??BrGZ_=BBx9>*>Gm>8GE8zyGtl%ha5@itXCUZWm3QYo`O5f_2@~QuEtUQm@8qHi! zoZdaFm8p!Xgfd>4U|Gi~N~p?^^;A~@g51n1oHmk#C?gB~wI@D@aOi>&Lm=BmY)Q5uM}^D!C#A*qLrI;NPKXab zX)H5ULq<+-N;c}LNo*4dHz`@=f+dYqtR-Wt%Fms>$UbOgGggi4Z7iN$Rum$zM4+YQ zhQ*_jy8@ENxC#c;B6ni3Dj*qF3B^rr3rFS+yU;A*UbK?xr{BLW(Tr`DUk4EBb_l9Y?ckHU|4#Fk)T(&C@zHPr&v+UjPB z$d?GDwl)}SS1{NHgNOxV5DGR1$=h0p7+fgJg@{3E5@ek*xX>sY3lW3TAPdGIu}vhE zyXS(9K{19p8msa%E6hfbH5G$LxnOWX*fP&X43caNI=L(8A_hryVGCfeBIv+|1ew%@ z1sWLa4b#Jj!6@Kr7>q)$hC#$S7?kMA7+kIJ`4cLl?Qs>6_Lzz&dt4nTMNZ8jx9VXn(MeXN8$!?Rk(jN@tRT1UES@Vlkc0*T zsa$Mr21(W0gcLR*4U4K7#8MDWw2(I}h{zw_4&o?;Bw2#sQL!++vMAExhPXz@_TXj~ zGQ>4Isz@TH+??&82mE}tvpGWoMr4*M(^;BK6;oM?z#EI-puV&-`yv|3c55|Id~21y ztOhclT%|9oK}^sW-Y`LvKfG<~iy;%RMS!FN?58Y>G~*N3ShMxDn%SMW=9(%JvzM#0 zYxKp>XV+F|NWf&v{5_rdn!aRy7SF3MG8fIku&9j0z{O(E*bn$>UcwGGoR{n&pWX>< zsb{y|?5ConsU2mOBSuRVvx&*{A_`LlQ7LLwPiM>a43V@sa};fkoa8n~4hn64UZgj~ zfK3A0YBKTA=%=EOw3?G=C zb~vYXUgYPqYv!QH+%USb!qjUN#j_Y$&`eA_oIpF;*c`kF^D^h69c{HEFfPWanU*$~ zVJFP2^YB?<(!`DMnDnBB3M>jkGC^q(GYflCqgc>2673q9pSVWmA)&_okpD%n++Nsi z4pvL-Ad%l?uf$ejr(pV`E_qL^SeD|DyagfFcr0x3?v4AlXAET=C&qX+?HPqJ#0BDjQMjOIef}D`8K$d;3$BUFh)zyv1g?2ydcjj^J{eTEn`0`Ejcfdz;~85M;Cno7bCovxyovznOWrE}^CP3AC} zPPa9Wlvzb%Ja?2?MWvoGdgg<4pCJZq!8=h~V8St{iQ2*e&C1}6wXU|9v#yxqrR^03 z1xrA?F`AOa#&{YQ8{^4WY)ly&Bb!JQUfyv#G!+Uc2@zE3NrJ&?Jj%v?LCrEQhIx#o6dA*p=L7F2pLih^O(Tk0b+DY&RQP3{xwnktVI1-r4hdVSc)_S?^38o3Pz$w3P$uJzmVeLFZ<<#D0r9h zJ5n&hJ5n%G-qJFQ?Os}=Z@U)Nu{Pv%tPO!4WOMjS-+K7v5ut3P@{uD0q_XIFoM`$g z+A|7Gi#99QGppf5w~?lw`L&gdDUGOSJ};eNsFduY@vI*~?M z!O1ilCI1Dp^QA_#xD=bh3QulIR11$jdw(xJYj557>5Y5#J@Fev300e48w}&bE^6N> z>|(!u6%wvzA5Bld9(H;58wR8i_3Zza;;$>p6BpxN#WMAdZKU1n>)UF z^U#QIvXI{E+rE8R3-8`+O1RN_`r|l&^jeM~J#gx-Q+ICM&#{OH2T+c7w*ECyPCQ4R z#{N0m_`g5rw^A-(!W@s!`ACXq3kJ(Wb49r>$|A9wB60JC=YdMs>LMj*1DVqkaEtfz z?hp^$=T`N9LQT~F&t2p_u5bUY2wxVU|E9bIp8L}w{#$Mi@CC04P>0L!fM`XSB?2#a z;9ds#VkY8;x~JxSdx_#=yle^i+sXtN+~RZ$i+lLpa-5Si`P#}17bIu&xn>pVJntWTS_yH+}ye@WHZ!nhQh~|J~)lsep7F0=|vv4 zt?Xed|KH$YTaS~k@r?2>X4Ip_XlX`ZMD4Mj4Ckt-3rM%h}e=s1?#(s(H z5017V(YAK;5J;>z*@8qH7>bt_Bo7Lp-D|hjK_YII^1ssZrJO!BaS$YDbgc!6cI5?$ zDhbEgZk?>s;4BLgnTI!UK`Yr0Xy8aIUYElrNc7f&Qfa$Wfy{RG=9K#2H_7cZy`>c; zInshK`;l>=E<4iJH^D(Js+eFc%br6VmEql#0pbv@mr>!Hg z>r2~%L~J%A(O$G$3pFINQ)eXFgBCZEE)rcs4T-VNj6{}d8+f7V%&(5k^dQlxwB4ya zNOT&=b6O7)qi^hV_Ll{TmAH(=h3HZxga#xgAL9xV7eJu=K{FCxPlIq>g(U3m@&voX z1lO3VJDJX5Pgh*Z?R{`S)I(R;3DA!*Re^v z%T{oaaKf%pa)%Y1CSN@aac8$O;Q}JfZBo0!S@4K}=oEW9%y?ViS$nFIuY;<^`!zVk z&Ie~$oV1s5LbNk1q~m=-JlzmG!4Vczcz=+A7yIX;qBy99K?}mCfdg$_bSW<=aT>5D zxReG;oCd53t|`K-)Mn4u-mrux=&+!Yqd)Dli24fJ0WvI`R*JgOgyC=kkN;fva`dn$;~ zJ}8J-00{_^Ng#p(w^R@T`%fc4rh!fGi_*|qQFN{^91$TQR}&%18xbLXtqBmNMMOwe z*8~V1ulb$!h9e>@Fd`x>Dk35*BQhd-Sg7kr4?CJk<++M(G*2%B5e+Z;<;c3IB4!9nG1S$81~H?iWq|OEdA2+y%LCJ- zvG^?Y#Vpg1?q8)cv~z2HLylsux8{l+Ta<_w)H9T zhW+eQU&M@I38uxYL{8nYAL2+FH!m*a2+_QEutE>gJ7?MpYQGI1k&s&KbsQTzj&XAq zW>shmYa?rxh0@?7H&dQ%lR%qU^r3XPKnp`|Gtabn!EKiFTKieWA?Q=|zEiJL(5h-P zFVH}T6aA}3r6-zC-lhpET`DlCb$NPA@qL@@_?>v2J|-`qcDK{?Zdw`Ayk6Hh&F|kt zdq$X4HS#e-_pEr~j|b?#X$~JJQZM|)0ck|N@WB+nKT8kBE=mqY#Zm()iNt6{X#t5v zNin5Ui%ClGnl~sU9UwHkN`q7gazOIHGC&VXOdd(ok_Nb(iu)UjUscc!NH(%%;qn+Ae1|#Q$ zQzdP>E~gR_O6T-j;7$>}R#(H~11GUmXW3GX;=Wj8-kXRumZ`?C<@G@>r%B%=UP?Ta zbcVv>Rq@MHHJoYewZ3p!cC|~s*ve7m3gsFnu6Q-=8HFp7f4cg~)%mXm;ZMR$qs?H1%RUAz) zTZF$so6!VoGV_A9*!l88)KpX&HI%DFGs&eQ+(8MsDin~bvhqBsNTOgI|Mezftj_P577gf){r!+FY=nqo?kp+AoXQ(TT5Ff#}&yz|)k&uWCZ&?*&&SlkzmxI9K^Wv@uTlLvE%c z@IxchvN~E6-}kWq{kMl7zK@mDe5EuZ{$oD>wmTC_n}=bYAw9{tT8kABK;`dVSY!{{ zXl|tGgPcFZlp{UKi8;&~sz%aYNO2EzJa^uc1eL4FLV#%!5$vJfQXdf;XwUF@@i_XJ zjzGS}iA<1wc!@R&)0Idxiu0E|m=b^~jmMY#L5kmg_v1IW$ z$>XbN&j1-0e%NuzF4Y?jjm8{+{!x-9wGv_2{_sM;>l_2a}VqURBK zrT9&CuzTI~j_z|7@R3(;dSE~rQ8#7#zgPHk*pihUtF-9u+s!9ga991Hh#ss^y@?+RdyLi@6u7&rOEFx28TGoWJ|epu{@V~;OC#_~EuZ=NvUh3MyR?sT#?iZU6w0ZtoiqAJs*8?2M#&Kw zKs{L7#MYq6;7;~%WXbMy zdKRqahr85=%{oqQk=obMw_V@QPcZz-sUH=l$MxH;TCb2DB0=+2+*ikEz`1_QsW?rZ zuc_qMJMmh2YkC4Ev_xUH6eo!*(Oy_NH6SlhOL4vLRnf!rN3tz0&(d(h)lTt5~Ktf*pD@t%LZ~r&6a`B*lppd>DccAJZpQ<<6M%<$30rHMrC#bI+Ur85A+F z!TL_DM++wB<3IjbEOTo)bZOaM{-biz3I}8G67^HdE?tb4KgFt4YL}m=pC+B3(ekHQ z87VabzG!nsRv)A*$|*0=clr}EH*L$Thz`l;bi_&V93)=|1WXWiz$cjYHL zxLnpq@rxanN|{5_+}cC>MB#LMt5~Nuf@}05PbNH2BfN7Mu#5D zJJz+Y4uK4f#h?Zc8!bH4+;e;g&jZwD3Ul zXyJ?1SQs!`ef8Hyt1q=ST79XN(dtR-8Lghw+Gy3%>Z7$lZ!}u^L7{2R0r!j+`0!|f z4}bijK3d??qXjPYN#EYls#Tjui!Y+sF&7N`kx|M}aV-1`vp|nghDw8vG%^EV@G63b z{BAE)|L8Ymh0orq3BC0;sIMBA@~FPjPQTrDcGD*8@H_aumK}Zvr|ENl^){q3`Mie9 zWIXzya03r%H2R>@R3>B52N@fF9V(+aRh3{Eo7V)X=nqiRXawyRvsgWm578SwVau?{ z* zx0u`Oi5U4b%a?YQ0TI*}1f-b+`9{)&d=Bw_WJ8TOp!AX;{)yq+xeSQ5;MRdia6^Ad zX}cP?Z_gJml>u3mWCpGaM~2o&)c;paDXhZn5H_Ct?sx;rqOCfb`J?DI-C-8*5-tg&rVO&!kk5Ac8A={WlKK0#GVQ z5RT5eabS((n#zEnbUZ){!VzIqsgzJQ6f{5!4A6pfkdBBrk>QY?paCLIuj+{yr-JGs z$PWW_8~MmHP!KXa_QKY1Ff7Q>E|fPo!!bbb1kZ4W10B(?d!%!Q)u-~tDUBiM(>EFt zwUZI((>EFsrGfuGeWUT%u74Vh=OOsBijfNF@CGqfD}u;Gs}!jcsTR~sV-qY(eF&mj z2A2@kR;A3*W6;W*QPd;)JG5nTGl_S}dm7sUMv*QdAG=en`uXZK@+FFG335#fB(f!{ z1(7or(-O}T*ZS)5DxH-`7PPPVpc4Aa96g3kuc{PC197@WTP9bN$dn9~&H*Y5R3O0_ zyHl;&orY(lC=`E+Hi)tK6NGmy`m*({Pl?glY-!tO9Z*7lnWM*ebv#?e`eJz!LYltN zRQ~&|e>lUvMkd{?F}Q@G`j(ix zw|*_e?8x2zlEb&`^VfaChu5C2_tG-CR&sQW)2@PSQ;zd_vS{H=8X?iLris5rO0_UI!Xm_nz+acpGH{G(+Deg5pc?JK2L#* zJe3IwI&o38ur3#QP9iSyVi=9E;-wK*xN1boaXwGxA{pyJVJ0rB7Bx0pq|eRuagnws z$4M8-U1=09I-58kz&mfNgnPK?&Yv5QM%116r+B!?D?(NdUiE>CyuyPT@M;cfpq3-* zq8-ISz^tTL7irbRy2vXesX8T^dc5jk<=~YK8sSw88lja7na{NxQ5Wqfjz+LrU|pn@ z0qY{K0;KAc=tg*EZ}s5WJB{#6okn<8P9thLqAuD|9F1T`tZA2Lzt%>c>89$GI0k%l z$>F7=ue$a7Z+X?NfSzwR%CH+p*Z)zNsp`H=_kMgE|A!wR;{Wja?EjFMDJ-u>l_X~J zvT0OFW}K8Gs-zvo1!f8>kDj9SjF{&gnlT=b(2FxnSER^y_<+M#) zV5YFT<~bvch)ZfTBEHyVrm##FRg#!VDk(2@WtC(WN_nGl+9obAQ&>UrERIIRWg{99 zUmOEwil3#fxq_s9?s3vcVxSS2NM>sFy6f^vs7E8+_0$1rMBVl8Q#?$BH5c{>ARO&V z$g1;B1T3W8hDv(MHylDNoEJduGP4Rx^=#aEe?qmGN-*5QqBiw;v7P#~ZmVgK7SAi` zDc^8NeH^Q#KHd&1&)SNFE?tW2!$xzAY&F%F)`zt?qWUW7Dc^9Yk6z0qA2anc1>(VkJbAR9x0 zlHV-ftaSBo!J7xo|H=F2?@TZ3heoyL&c}%s*~n)pOD;lkk%E?4oA0KkT-!lt#O_8= z38m>5tb+@YO4oa$5}i<#Ly+887sXKwxXNMW;qcr`db8v!D>3Toc z$9k~qWAVxLF-xF6Z+(%^sXKw8KF={!pBKEU?~MT$%zAn;U|u1!Xq?zUq&f;4Xr5HL z-tweMpob0K^34O%hbA3UUB2b(*%myrUnGKj#zy>UHbyHKW?OR&C z>%B~t_#l`pS<^CEGJ$|BSTZgBmGk zlNV@%8tLb0B_@Rp>PmXbHykqUk~z)0!6!MI(=NjjrZS1U0F%56TU*`{1CtkK$Ltpv zM~%5AS@WD~c#poBed>z?+Nf-Cj%^kr@YB{$hiib2;dxSjuYWq@7aQoLG4eR$ca*^gZ%jQ z5pDfGUa$W@t`VyAQF4+2n}ib(L23ZC)hH>#lq8(XP*1k_czKX7$Qi8wOWrVb(e{ec zboL@iBA~V}6$Xp?g~8EJGz6CxY^Ov1`gPaxieC7WcGXkrAP;_hr&~V>+w1use0Cl! zXBZeK&OU@iHK2B5waDiEBsnTFPKUPIjFT1~uoipIbtp}zE*KXt)B&+y9R`c~8OC1k zc+A@Fp_1$!Z}Hqcd4et4JovCo<#cM0xk6-OdT0 z@z8RL*Vw)3N(7QOc<6^Um%)zzG;Etn$1!!ggBjZ$=*TvL21wf)(m{gAes4w$!Na*v zF-R9w^-Wd(D2=f|?hb+)pMJfQP5^-YtZ$N@6I7YwlBS>7sOlT+w;bkM0dDIc-NW|+ zr2Dg;(Kw{A${W_d!KWC|{`R8v*)BGq8~tYmdJhwTL^39?L(nSY{}GGfnGsCUQj zVH7$*UthSjqN=Mxv%AvB<0^FiT9E{dlFcXfP$W>?fLjnML2R?sveDrOlAT`mf0SB(f; zxSnf-LkJXDQD$A0yVEC{V8sa@tT1UpRFtZ0Y`93L82Y%V3E7Mj7wHtkC|vXz-mhHm z&HkT6CQgZ5^xhjP8B-cj@BQHv4;R`0xq83=0uE;m;36MFfO=x4-914)(na#;_9{Nq z(?JHuGEF^9#&wtgDQutU%9#Ti;X?>i9W(9jiAH$wnnp+$dG=2uVwr9P6V9lMyf9ih zb3h|}2!X0&rrkZ!2pMM-AJ$*NgtSpCa}4;X=M+QD=}v~-IG$n{g_-^-F+zY3ytxui z3=^5@f%^ue5%s_aQ+#5k@D-D+lEPiIzGlNYw^HEoXaep-KSwp|~lSXeWT_4x#XP9so@)6NIR+BCsYZM>fr zQ)6wOzI@T9H~ADppDG#0Qw*bU!DkZ%2l%UhRtYCckE-NXPY*~V>ent$@j;bz&l|`l zlfx8L$!P@W19^XbFmi$PhPXg_BW_nkEqA2anc1>(VkJb z;9n922lyKwuY`NJ;5P@&|H=NF`TS3G-)6E9&Kp3Li)_{~nF!|*o^g}ue zk9V=85#`g@B?_!oOT|}&U3PFmceUsX|HJ9#HMWN-JW8Q-8|$J z!^SfcQ3DfV;>>d6#*p^MKOf=$7?78!jnxqU`@bIGhhtc$7~UW!`x6)OLkj#b`r=pU zN9Rw>!xH>d`r;Kh-(Lh9gJ;O2TrVHzeJV^(IWDL*QhcR;;Nd{(-AQ)2fxvVbAmF>S@g_$Td@o11D;I^*w${ zfqt!Xuc?3Fgr6Ot-|O6K>i@_%VV2&96XLeT39jhI1x`f+aYDLrL3$5P7U*BugA=|$ zJ&zcx;UvdJoK)WnI9UK6Weq0_;G?YJ1ea{+L~-R;u)PD7=#3I8Q5)i|y3;+4k4}1a zo0tzy=Dbiw$x#Y_iWo{z?@8}MxW!KLP=>aW)cYEg6CiYv%bV<}tG90Yp7W}`9D#BB zW6#;XqCM_i?0Ffe;kAKhHi;GQXq#MIwaG2WUWNH?lQPABI_@N1#WmVI%X2*p{VHG1 zuRRa?4X-ygfsz^uOKMQI>m#isO^1LSmc(G1qaQ=E#9E%!Q)iwSYOP3ydYD=z-z+7r zKqkZZ~RT}TD`ES^~97W5VfxmUTxJ(}u>uU5GQ^%K(K#Z_)W?s}L$*YazN zg+9W|ja8teg2Ivtl2oc=c64H&CHchl3XAS3 z+x4l>l7ixR)i0W7vY7k4;6B57xsQ>v>)}c(;m+IxxHk6=+K%H~qj=RxU-M0$YdoVv zE%dc=*TeL=mY+V?c$&WEFnzA^GkwkBODpBj+e&?^yB?;uxlVeU+fHwD-_+X|z(b5H zd}rR>L_3KG*>y3m;>sH!GR5(>ZBE> zO3E;#71lSj!diw_Shu(p9wA!cQKJ$=kPu)sJ)*g zf6`bQ4O!HITRKlI zC)?5m7FPd+nJpzr3_9cs; zCRwARC@e!tDP4*wiBe3Vlv27B=vFk_gTA$$k%Jq>0l|VvCB(0BV`#xPMjqpcak|MVuEsJi3(<0lXg^>h7 zNIYYrHEp^voXgvimPIe6Smc^0Fgqwg;uWK(X=8{|*0&`si%v?h$aEPLx|8|DKcpOldrRd^yE$qY}Nsz*u@UVJfd<&U+OB8%b*bi`%M0&(|rz zb8|}Y904WfIXNYGPO+^jR0&@5gPyRmwkhG^wXm|cR-crTojOj`q>ZIfsOj$#B?S11 zy#7r%QB0(!PrS2|H>DBviC<0e+ej%=~MzMv%} zj8+}>!|h#qL9583((Z^XDxg*}hs*){W^a-{lpt$Laz%4MpwTK1x`igbOj-tN7pa(bEhF94C6x5RXDn zpHczc>r+3_eeP9spZduGX+(YM-W303|C_G=O&{fGiSu6*<>UkFVe~&e==@WZM4vvH zC`#v8(z}Hm*s(t`^VjrMMEk@tKmN1?{R($?+o!|`Al{GpU@IX z>ND~8PPV?A_qn#BXNv;@iRwkl*U@W3i>r{*zz_Xsf^C$0G99uDBrSQoMMzpP2HzQsggk zSJ~{(5N~f5EyZ%nuO@r5=FL<+bxLDjU2IZ;zHZqn2+?_Grm*;HBb^3X$f-hocUx0$=3q>j`Tw3%fBJO7bC!wxsQ@U^gb zyPBV!e|+3Z?V1b9D3@1@AZ6R%jkN3sC;35I*+smL*@uc22mfq)NR=y)kB1zV?laTtLqndNm)@?%wy)FMRdIUY_UP4-dTV~K^wu0->8<&< z(%Z=4xwj5idh7hLw~~8RPZmvjv%?t>goCdO z9uwlS>;r>DwGRv)6XGhKgYS%eHmqA|fjLLJS+rn{7MN3Lfgvq$Jhg}`#0`R4rx7QJ z0|W^NKNniCN(-|83oQ_};~x|JWN3k?eAO*5Rnr1fvv$JB$@jm4ze(~tp#_eo7Ex-} zNIZ)=vj$4kO$*HPyl+Sg%;U7cvVsUeQY5pw4vUo?7AtW?35$`fVipIL5?AWLOqg(H zBE%`qWPyP&>C7;Y>Za#qIG)JaxQQc5SdgR?98~OLVuqj;GXkYR?12d=MdIBA?^62a zW-g@+jw%qeTuwyPayc13N9-#F){(&0(x*z0>x)X*nbXRQiEH^4LRpor#?fPC6uSCY zq6x!B@sUb6(N3VNMo~T4lhXKwiiVzjL05fl1*WUzOjnv-Sx9e7R|w&{TY)KJJ=2vY zBNnvV(iMWV?pEMZ7BXGs&6NvIS4WNrUsbwl5*{acr3Q{dSAU@n=Bv^2v9}mbv=iy7 z^&L51SC&CntyiY_bI7Y`b_Wxiu^hf8zMZ_nWc9aOZMss*@OAM%NmG$m(M+^yC~0${ z*2d?nzhf=DRf%gHeN{#wuDt7J0%=VCR3a2$4{=Q%ACLxdO`b^c=MY+++aYc=e?xd} zLtNVlEfJT5mWT_u4RLKJv_xFlU*!T4SM*h>EuG8A5(AHu(2}ppD0KDbi6#si(^YSS z9=e**x@x*o8gwE6>AU!cZ5-ZUOJZ|)YAEI0}GqH?$66CLOa4TuC#P6C8(wI z;l|al5;SYr+2VVjxEsl^nhw8@EEH8m)Hph-j6zC#0ujW&jk#^~-`sap@>WP`uB!ir zk&?udc3~u*L`uVT-!MXuXc8evG>Mdk>%CzmNGz!YEr+Ot3#Id-qe`Dxl1LgSv2+#f z8HJWUTA>d_%-+{l!iip@Ew%UU1Jd-)FQ@oHwiFEQWlP2p7`8gLb$aTvqbR{kfs_FB zY>m%$?!skBVo9?#&-Zp!!tUmKQ?{Rkq^eXJM=zC8C`o(W-K%lYp#9%SNf-TfH)A%c zprng)^dQ3tI>1QsW|}wBkO*ID?sK#34Zn5cr#J2qqN>C+LwKCTlG-;4F{v-zt8wWS z-9RRoNKBXJ?|+jgi7bfe(ifz6zC>MAF5h_Y)N421xADNKyON8FFj6I(ar93ag>1wI z-K%l=w|4`XG$Pqt?q!mgULl*yZ%^+GGP03DSVERTvWymG8Evc0`s^A?z>e|4y6hV1 PqV3(eM=xPSBm4gY4|(?1 literal 37629 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 z zSb}FWD1v7*$YC|(nRaLSl@4wF;>L84r2xo3!~Y?80$AR@JQ&pd@Djwes!a)Q4?zAd zg@-FJ#v2oN{j7^<-VhQ%LmF=H^7i@u-wyHf$s=~q@H&4y#cTB?b2!L@V|B}mob%~V zw+N>RPXdhSLyi0-VfnS|LJ09s(5l~8khK1UwL5LD~qe2b~hBq=-`PRDUtES&YbW(@h4JbJORuyo?w8vbCdCBVHr;> zR{>90!KB)cDxL^~?&Jya+OKLnfwu8PWfIoL6Kamn)G(e{Sj3Z%FXxG!`O(G`J%2sp z30NX>Vqc-Z791d)s{u!%vnlcu)M*2lLAzi7aE11ogAc5K!+9C{=PW`ob1LMQ@j@By zJPn@Tkl{dep2m1oH|I8?ZiDNtn`h7JRvWba8!5@ zu5~5w(0zjm#2RvbIg zP4}aPN9~Yaj>1MR^afJ$VdpS$O1(>i#dJnU(=9<396fYv^qiOUc)%c&x@9p>64IpX3V8BFT5ek5mm=ygZ$ITralBY+` zBrIQ=h-uE2uf>|EYf_>FCL_}$nv|r8FnLzdME#f0za|QBgv=oQ+o*4FJn#S`Icl!1 zwN7Y1N8TPt&f)*ClHE^Wi&sV;pLD_V*+HxLLmF;BzQx7g_fX-0ba5pSgd?NB4ayne090am zCuxWeEfJ*!0SR&lkA?#)P%Bmc9ZFUoZdG)LCs3Y{PkTl)e23{*oXF4}{T~{4EKazd}zcYt(sJVefs5jh`%~36}ghLF!fZ#Bjt;EBo4$p0{QVgvb7=HGwg>{27x0twq6Vvit{Th z$63wDLYH0*Z)O94G)VT1cD(6Y>%`~ZIpj+!czP*92iLzI$%MwEg|l=4m&^gb*#V24t&<++tow^F26*c9V{Axg{Jh6+ewE3J);LP{jG)Awe763nVuwS;r4lt#n<^%3u4VHz|XsNZFnX71>E@Q%n61jY-~gZCH2 z5%l2aL->y=4s=oXKlKquVzChm2gyk4S8PT?mpl5<7b1U$*gW)9K^#F3WoHu>&1L~^ z_Bu$j87`mcx^z(2Tto>L<~4}sB3wSxb?Kn~OE|YWXx;3g)?J(K*w?y!*Zw^=E(b}1 z^xjq1T4%A>y6oZi;eQKv&<+WD_=g2?1U+(L2){ll9p%s=@&Jd%ta=6}K* z#`Ny#8VR|!lWRM$Xb9Cx@>_kW@nGv$YC= z4D9IojsJ~29YXNAO#hQ6#Buw%D?=W-a|dkg>0t8?*t`Qa?|{uaVDk>^&d15s(~;|O day?G2$I10LxgNJ%S@*?V8Saa_^z4P;{{WHCEs+2K