Repository: DaiYu-233/YMCL.Avalonia Branch: main Commit: 81624f63d1f6 Files: 340 Total size: 2.1 MB Directory structure: gitextract_vk4v6nm4/ ├── .editorconfig ├── .gitattributes ├── .github/ │ └── workflows/ │ └── publish.yml ├── .gitignore ├── .vscode/ │ └── settings.json ├── Assets/ │ ├── Default.isl │ ├── Icon.Border.icns │ ├── Icon.Shadow.Margin.psd │ ├── Icon.Shadow.icns │ ├── Icon.ai │ ├── Icon.psd │ ├── MiSans-Regular.otf │ └── bak/ │ ├── YMCL-App-Icon.psd │ └── YMCL-Icon.icns ├── Directory.Packages.props ├── LICENSE ├── README.en.md ├── README.md ├── YMCL.Main/ │ ├── YMCL/ │ │ ├── App.axaml │ │ ├── App.axaml.cs │ │ ├── FodyWeavers.xml │ │ ├── FodyWeavers.xsd │ │ ├── GlobalUsings.cs │ │ ├── Public/ │ │ │ ├── Assets/ │ │ │ │ └── MiSans-Regular.otf │ │ │ ├── Classes/ │ │ │ │ ├── Data/ │ │ │ │ │ ├── AggregateSearchEntry.cs │ │ │ │ │ ├── FavouriteResourceEntry.cs │ │ │ │ │ ├── JavaEntry.cs │ │ │ │ │ ├── Language.cs │ │ │ │ │ ├── LocalModEntry.cs │ │ │ │ │ ├── LocalResourcePackEntry.cs │ │ │ │ │ ├── LocalSaveEntry.cs │ │ │ │ │ ├── LogItemEntry.cs │ │ │ │ │ ├── MinecraftFolder.cs │ │ │ │ │ ├── ModrinthFile.cs │ │ │ │ │ ├── NewsDataListEntry.cs │ │ │ │ │ ├── NotificationEntry.cs │ │ │ │ │ ├── ResourceFetcher/ │ │ │ │ │ │ ├── CurseForgeResourceEntry.cs │ │ │ │ │ │ ├── CurseForgeResourceFileEntry.cs │ │ │ │ │ │ ├── IResourceEntry.cs │ │ │ │ │ │ ├── IResourceFileEntry.cs │ │ │ │ │ │ ├── ModFileUiEntry.cs │ │ │ │ │ │ └── ModrinthResourceEntry.cs │ │ │ │ │ ├── SearchTabViewItemEntry.cs │ │ │ │ │ └── Update.cs │ │ │ │ ├── Json/ │ │ │ │ │ ├── AfdianSponsor.cs │ │ │ │ │ ├── ModrinchVersionEntry.cs │ │ │ │ │ └── MojangJavaNews.cs │ │ │ │ ├── Netease/ │ │ │ │ │ ├── Availability.cs │ │ │ │ │ ├── DefaultKeyword.cs │ │ │ │ │ ├── Lyric.cs │ │ │ │ │ ├── PlayList.cs │ │ │ │ │ ├── RecordSongEntry.cs │ │ │ │ │ ├── SingleSong.cs │ │ │ │ │ └── SongUrl.cs │ │ │ │ ├── Operate/ │ │ │ │ │ ├── FavouriteMinecraftEntry.cs │ │ │ │ │ ├── MinecraftDataEntry.cs │ │ │ │ │ ├── PluginInfoEntry.cs │ │ │ │ │ ├── RegisteredPage.cs │ │ │ │ │ ├── SubTask.cs │ │ │ │ │ └── TaskEntryOperateButtonEntry.cs │ │ │ │ └── Setting/ │ │ │ │ ├── Account.cs │ │ │ │ ├── ExchangeSettingEntry.cs │ │ │ │ ├── GameSettingEntry.cs │ │ │ │ ├── SettingEntry.cs │ │ │ │ └── UiProperty.cs │ │ │ ├── Const/ │ │ │ │ ├── Data.cs │ │ │ │ ├── Path.cs │ │ │ │ └── String.cs │ │ │ ├── Controls/ │ │ │ │ ├── CourseForgeFileExpander.axaml │ │ │ │ ├── CourseForgeFileExpander.axaml.cs │ │ │ │ ├── Drawers/ │ │ │ │ │ ├── MsgHistory.axaml │ │ │ │ │ └── MsgHistory.axaml.cs │ │ │ │ ├── LogViewer.axaml │ │ │ │ ├── LogViewer.axaml.cs │ │ │ │ ├── ModrinthFileExpander.axaml │ │ │ │ ├── ModrinthFileExpander.axaml.cs │ │ │ │ ├── ScreenshotEntry.axaml │ │ │ │ ├── ScreenshotEntry.axaml.cs │ │ │ │ ├── TaskEntry.axaml │ │ │ │ ├── TaskEntry.axaml.cs │ │ │ │ ├── TextWithIcon.axaml │ │ │ │ ├── TextWithIcon.axaml.cs │ │ │ │ ├── TitleBar.axaml │ │ │ │ └── TitleBar.axaml.cs │ │ │ ├── Enum/ │ │ │ │ ├── GameSpecialFolder.cs │ │ │ │ ├── LogType.cs │ │ │ │ ├── ModLoaderType.cs │ │ │ │ ├── ResourceSource.cs │ │ │ │ ├── ResourceType.cs │ │ │ │ ├── RuntimeInfo.cs │ │ │ │ ├── Setting.cs │ │ │ │ ├── SongType.cs │ │ │ │ └── TaskState.cs │ │ │ ├── Langs/ │ │ │ │ ├── LangHelper.cs │ │ │ │ ├── MainLang.Designer.cs │ │ │ │ ├── MainLang.en-US.resx │ │ │ │ ├── MainLang.ja-JP.resx │ │ │ │ ├── MainLang.resx │ │ │ │ ├── MainLang.ru-RU.resx │ │ │ │ └── MainLang.zh-Hant.resx │ │ │ ├── Module/ │ │ │ │ ├── App/ │ │ │ │ │ ├── AppMethod.cs │ │ │ │ │ ├── Init/ │ │ │ │ │ │ ├── Dispatcher.cs │ │ │ │ │ │ ├── Op/ │ │ │ │ │ │ │ ├── Parser.cs │ │ │ │ │ │ │ └── SubModule/ │ │ │ │ │ │ │ ├── ImportSetting.cs │ │ │ │ │ │ │ └── InstallModPack.cs │ │ │ │ │ │ └── SubModule/ │ │ │ │ │ │ ├── Decision.cs │ │ │ │ │ │ ├── DetectPlatform.cs │ │ │ │ │ │ ├── GetDataFromNetwork/ │ │ │ │ │ │ │ ├── Dispatcher.cs │ │ │ │ │ │ │ ├── InstallPreviewModLoaders.cs │ │ │ │ │ │ │ └── InstallableGames.cs │ │ │ │ │ │ ├── InitConfig.cs │ │ │ │ │ │ ├── InitData.cs │ │ │ │ │ │ ├── InitLang.cs │ │ │ │ │ │ ├── InitPlugin.cs │ │ │ │ │ │ ├── InitUi.cs │ │ │ │ │ │ ├── SettingChanged.cs │ │ │ │ │ │ └── TranslateToken.cs │ │ │ │ │ └── Setting.cs │ │ │ │ ├── Debouncer.cs │ │ │ │ ├── IO/ │ │ │ │ │ ├── Disk/ │ │ │ │ │ │ ├── Getter.cs │ │ │ │ │ │ ├── Opener.cs │ │ │ │ │ │ └── Setter.cs │ │ │ │ │ └── Network/ │ │ │ │ │ ├── CurseForge.cs │ │ │ │ │ ├── DownloadFileWithProgress.cs │ │ │ │ │ ├── Http/ │ │ │ │ │ │ └── Get.cs │ │ │ │ │ ├── Modrinch.cs │ │ │ │ │ ├── NeteaseMusic.cs │ │ │ │ │ └── Update.cs │ │ │ │ ├── Mc/ │ │ │ │ │ ├── Icon.cs │ │ │ │ │ ├── Importer/ │ │ │ │ │ │ ├── jar/ │ │ │ │ │ │ │ └── Main.cs │ │ │ │ │ │ ├── mrpack/ │ │ │ │ │ │ │ ├── Main.cs │ │ │ │ │ │ │ └── ModPack.cs │ │ │ │ │ │ └── zip/ │ │ │ │ │ │ ├── Main.cs │ │ │ │ │ │ ├── ModPack.cs │ │ │ │ │ │ └── Resource.cs │ │ │ │ │ ├── Installer/ │ │ │ │ │ │ ├── Minecraft/ │ │ │ │ │ │ │ ├── CompositeForgeAndOptiFine.cs │ │ │ │ │ │ │ ├── Dispatcher.cs │ │ │ │ │ │ │ ├── Fabric.cs │ │ │ │ │ │ │ ├── Forge.cs │ │ │ │ │ │ │ ├── OptiFine.cs │ │ │ │ │ │ │ ├── Quilt.cs │ │ │ │ │ │ │ └── Vanilla.cs │ │ │ │ │ │ └── ModPack/ │ │ │ │ │ │ ├── CurseForge.cs │ │ │ │ │ │ └── Modrinth.cs │ │ │ │ │ ├── Launcher/ │ │ │ │ │ │ ├── BedRock.cs │ │ │ │ │ │ └── JavaClient.cs │ │ │ │ │ ├── MinecraftSetting.cs │ │ │ │ │ └── Utils.cs │ │ │ │ ├── Op/ │ │ │ │ │ ├── Account.cs │ │ │ │ │ ├── DownloadResource.cs │ │ │ │ │ ├── JavaRuntime.cs │ │ │ │ │ └── MinecraftFolder.cs │ │ │ │ ├── Player.cs │ │ │ │ ├── Ui/ │ │ │ │ │ ├── Animator.cs │ │ │ │ │ ├── Converter/ │ │ │ │ │ │ ├── AccountTypeIsMicrosoftConverter.cs │ │ │ │ │ │ ├── BoolReversalConverter.cs │ │ │ │ │ │ ├── BoolToDoubleConverter.cs │ │ │ │ │ │ ├── BoolToIntConverter.cs │ │ │ │ │ │ ├── BoolToStringConverter.cs │ │ │ │ │ │ ├── CountToUnitConverter.cs │ │ │ │ │ │ ├── DateTimeToStringConverter.cs │ │ │ │ │ │ ├── DoubleToIntByRoundConverter.cs │ │ │ │ │ │ ├── DoubleToPercentageConverter.cs │ │ │ │ │ │ ├── EnumIndexToBoolConverter.cs │ │ │ │ │ │ ├── GameSettingMaxMemConverter.cs │ │ │ │ │ │ ├── ListCountToBoolConverter.cs │ │ │ │ │ │ ├── ListDistinctConverter.cs │ │ │ │ │ │ ├── LogTypeToColorConverter.cs │ │ │ │ │ │ ├── MaxThreadOverSafeConverter.cs │ │ │ │ │ │ ├── MsToTimeConverter.cs │ │ │ │ │ │ ├── NoTaskIsVisibleConverter.cs │ │ │ │ │ │ ├── ReversalBoolConverter.cs │ │ │ │ │ │ ├── SelectedGameIsNotBedrock.cs │ │ │ │ │ │ ├── SpecialControlEnableListConverter.cs │ │ │ │ │ │ ├── TaskStateToColorConverter.cs │ │ │ │ │ │ └── TaskStateToTipConverter.cs │ │ │ │ │ ├── Getter.cs │ │ │ │ │ ├── Setter.cs │ │ │ │ │ ├── Shower.cs │ │ │ │ │ └── Special/ │ │ │ │ │ ├── AggregateSearchUi.cs │ │ │ │ │ ├── AutoInstallUi.cs │ │ │ │ │ ├── DropHandler.cs │ │ │ │ │ └── LaunchUi.cs │ │ │ │ ├── Util/ │ │ │ │ │ ├── Extension/ │ │ │ │ │ │ ├── Extensions.cs │ │ │ │ │ │ └── Number.cs │ │ │ │ │ ├── Permission.cs │ │ │ │ │ ├── Platform/ │ │ │ │ │ │ └── MacOs/ │ │ │ │ │ │ └── WindowHandler.cs │ │ │ │ │ └── VersionComparer.cs │ │ │ │ └── Value/ │ │ │ │ ├── Calculator.cs │ │ │ │ └── Converter.cs │ │ │ ├── Plugin/ │ │ │ │ ├── Helper/ │ │ │ │ │ ├── BuildNavItemContent.cs │ │ │ │ │ └── RegisterPage.cs │ │ │ │ ├── Loader.cs │ │ │ │ └── PluginLoadContext.cs │ │ │ ├── Styles/ │ │ │ │ ├── Dynamic/ │ │ │ │ │ ├── ContentDialog.axaml │ │ │ │ │ ├── NotificationBubble.axaml │ │ │ │ │ ├── NotificationCard.axaml │ │ │ │ │ └── Popup.axaml │ │ │ │ ├── IconPath.axaml │ │ │ │ ├── Style.axaml │ │ │ │ └── Theme.axaml │ │ │ └── Texts/ │ │ │ ├── CustomHomePageDefault.axaml │ │ │ ├── DateTime.txt │ │ │ └── IsAloneProgram.txt │ │ ├── ViewModels/ │ │ │ ├── GameSettingModel.cs │ │ │ ├── InstallPreviewModel.cs │ │ │ ├── LogViewerModel.cs │ │ │ ├── MainViewModel.cs │ │ │ ├── NotifyPropertyModelBase.cs │ │ │ ├── TaskEntryModel.cs │ │ │ └── ViewModelBase.cs │ │ ├── Views/ │ │ │ ├── CrashWindow.axaml │ │ │ ├── CrashWindow.axaml.cs │ │ │ ├── Initialize/ │ │ │ │ ├── InitializeView.axaml │ │ │ │ ├── InitializeView.axaml.cs │ │ │ │ ├── InitializeWindow.axaml │ │ │ │ ├── InitializeWindow.axaml.cs │ │ │ │ └── Pages/ │ │ │ │ ├── Account.axaml │ │ │ │ ├── Account.axaml.cs │ │ │ │ ├── JavaRuntime.axaml │ │ │ │ ├── JavaRuntime.axaml.cs │ │ │ │ ├── Language.axaml │ │ │ │ ├── Language.axaml.cs │ │ │ │ ├── MinecraftFolder.axaml │ │ │ │ └── MinecraftFolder.axaml.cs │ │ │ ├── LogWindow.axaml │ │ │ ├── LogWindow.axaml.cs │ │ │ ├── Main/ │ │ │ │ ├── MainView.axaml │ │ │ │ ├── MainView.axaml.cs │ │ │ │ ├── MainWindow.axaml │ │ │ │ ├── MainWindow.axaml.cs │ │ │ │ └── Pages/ │ │ │ │ ├── About.axaml │ │ │ │ ├── About.axaml.cs │ │ │ │ ├── Download.axaml │ │ │ │ ├── Download.axaml.cs │ │ │ │ ├── DownloadPages/ │ │ │ │ │ ├── AutoInstall.axaml │ │ │ │ │ ├── AutoInstall.axaml.cs │ │ │ │ │ ├── AutoInstallPages/ │ │ │ │ │ │ ├── InstallPreview.axaml │ │ │ │ │ │ ├── InstallPreview.axaml.cs │ │ │ │ │ │ ├── InstallableGames.axaml │ │ │ │ │ │ └── InstallableGames.axaml.cs │ │ │ │ │ ├── CurseForge.axaml │ │ │ │ │ ├── CurseForge.axaml.cs │ │ │ │ │ ├── CurseForgePages/ │ │ │ │ │ │ ├── Fetcher.axaml │ │ │ │ │ │ ├── Fetcher.axaml.cs │ │ │ │ │ │ ├── ModFileResult.axaml │ │ │ │ │ │ ├── ModFileResult.axaml.cs │ │ │ │ │ │ ├── SearchResult.axaml │ │ │ │ │ │ └── SearchResult.axaml.cs │ │ │ │ │ ├── Favourites.axaml │ │ │ │ │ ├── Favourites.axaml.cs │ │ │ │ │ ├── Modrinth.axaml │ │ │ │ │ ├── Modrinth.axaml.cs │ │ │ │ │ └── ModrinthPages/ │ │ │ │ │ ├── Fetcher.axaml │ │ │ │ │ ├── Fetcher.axaml.cs │ │ │ │ │ ├── ModFileResult.axaml │ │ │ │ │ ├── ModFileResult.axaml.cs │ │ │ │ │ ├── SearchResult.axaml │ │ │ │ │ └── SearchResult.axaml.cs │ │ │ │ ├── Launch.axaml │ │ │ │ ├── Launch.axaml.cs │ │ │ │ ├── LaunchPages/ │ │ │ │ │ ├── GameList.axaml │ │ │ │ │ ├── GameList.axaml.cs │ │ │ │ │ ├── GameSetting.axaml │ │ │ │ │ ├── GameSetting.axaml.cs │ │ │ │ │ └── SubPages/ │ │ │ │ │ ├── Mod.axaml │ │ │ │ │ ├── Mod.axaml.cs │ │ │ │ │ ├── OverView.axaml │ │ │ │ │ ├── OverView.axaml.cs │ │ │ │ │ ├── ResourcePack.axaml │ │ │ │ │ ├── ResourcePack.axaml.cs │ │ │ │ │ ├── Save.axaml │ │ │ │ │ ├── Save.axaml.cs │ │ │ │ │ ├── Screenshot.axaml │ │ │ │ │ ├── Screenshot.axaml.cs │ │ │ │ │ ├── Setting.axaml │ │ │ │ │ ├── Setting.axaml.cs │ │ │ │ │ ├── ShaderPack.axaml │ │ │ │ │ └── ShaderPack.axaml.cs │ │ │ │ ├── More.axaml │ │ │ │ ├── More.axaml.cs │ │ │ │ ├── MorePages/ │ │ │ │ │ ├── GameUpdateLog.axaml │ │ │ │ │ ├── GameUpdateLog.axaml.cs │ │ │ │ │ ├── TreasureBox.axaml │ │ │ │ │ └── TreasureBox.axaml.cs │ │ │ │ ├── Music.axaml │ │ │ │ ├── Music.axaml.cs │ │ │ │ ├── MusicPages/ │ │ │ │ │ ├── Lyric.axaml │ │ │ │ │ ├── Lyric.axaml.cs │ │ │ │ │ ├── PlayList.axaml │ │ │ │ │ ├── PlayList.axaml.cs │ │ │ │ │ ├── Search.axaml │ │ │ │ │ └── Search.axaml.cs │ │ │ │ ├── Search.axaml │ │ │ │ ├── Search.axaml.cs │ │ │ │ ├── Setting.axaml │ │ │ │ ├── Setting.axaml.cs │ │ │ │ ├── SettingPages/ │ │ │ │ │ ├── Account.axaml │ │ │ │ │ ├── Account.axaml.cs │ │ │ │ │ ├── Download.axaml │ │ │ │ │ ├── Download.axaml.cs │ │ │ │ │ ├── Launch.axaml │ │ │ │ │ ├── Launch.axaml.cs │ │ │ │ │ ├── Launcher.axaml │ │ │ │ │ ├── Launcher.axaml.cs │ │ │ │ │ ├── Personalize.axaml │ │ │ │ │ ├── Personalize.axaml.cs │ │ │ │ │ ├── Plugin.axaml │ │ │ │ │ └── Plugin.axaml.cs │ │ │ │ ├── Task.axaml │ │ │ │ └── Task.axaml.cs │ │ │ ├── NotificationWindow.axaml │ │ │ └── NotificationWindow.axaml.cs │ │ └── YMCL.csproj │ └── YMCL.Desktop/ │ ├── Icon-Border.icns │ ├── Program.cs │ ├── Properties/ │ │ └── PublishProfiles/ │ │ └── FolderProfile.pubxml │ ├── YMCL.Desktop.csproj │ ├── YMCL.Desktop.desktop │ ├── YMCL.Desktop.metainfo.xml │ ├── YMCL.Desktop.pupnet.conf │ └── app.manifest ├── YMCL.Plugin/ │ ├── YMCL.Plugin.Base/ │ │ ├── IPlugin.cs │ │ └── YMCL.Plugin.Base.csproj │ ├── YMCL.Plugin.Page/ │ │ ├── ExamplePage.axaml │ │ ├── ExamplePage.axaml.cs │ │ ├── Main.cs │ │ └── YMCL.Plugin.Page.csproj │ └── YMCL.Plugin.Simple/ │ ├── Main.cs │ └── YMCL.Plugin.Simple.csproj ├── YMCL.Web/ │ ├── css/ │ │ ├── components.css │ │ ├── google.css │ │ ├── main.css │ │ └── responsive.css │ ├── index.html │ └── js/ │ ├── downloads.js │ └── main.js ├── YMCL.sln ├── YMCL.sln.DotSettings └── crowdin.yml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ root = true [*] charset = utf-8 [*.cs] dotnet_diagnostic.CS8600.severity = none dotnet_diagnostic.CA1416.severity = none dotnet_diagnostic.CS8602.severity = none dotnet_diagnostic.CS8851.severity = none dotnet_diagnostic.CA1822.severity = none dotnet_diagnostic.CA1839.severity = none dotnet_diagnostic.IDE0090.severity = none dotnet_diagnostic.IDE0220.severity = none dotnet_diagnostic.IDE0044.severity = none # CS8601: 引用类型赋值可能为 null。 dotnet_diagnostic.CS8601.severity = none # CS8603: 可能返回 null 引用。 dotnet_diagnostic.CS8603.severity = none # CS8625: 无法将 null 字面量转换为非 null 的引用类型。 dotnet_diagnostic.CS8625.severity = none # CS8618: 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。 dotnet_diagnostic.CS8618.severity = none # IDE1006: 命名样式 dotnet_diagnostic.IDE1006.severity = none # CS8612: 类型中引用类型的为 Null 性与隐式实现的成员不匹配。 dotnet_diagnostic.CS8612.severity = none # CS8767: 参数类型中引用类型的为 Null 性与隐式实现的成员不匹配(可能是由于为 Null 性特性)。 dotnet_diagnostic.CS8767.severity = none # CS0642: 空语句可能有错误 dotnet_diagnostic.CS0642.severity = none # IDE0063: 使用简单的 "using" 语句 dotnet_diagnostic.IDE0063.severity = none ================================================ FILE: .gitattributes ================================================ * text=auto eol=lf charset=utf-8 *.axaml text charset=utf-8 *.cs text charset=utf-8 ================================================ FILE: .github/workflows/publish.yml ================================================ name: Publish on: workflow_dispatch: push: branches: ["main"] env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: true jobs: time: runs-on: ubuntu-latest outputs: v: ${{ steps.date.outputs.time }} y: ${{ steps.date.outputs.y }} md: ${{ steps.date.outputs.md }} hm: ${{ steps.date.outputs.hm }} sv: ${{ steps.date.outputs.sv }} steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Generate Version id: date run: | echo "time=$(TZ='Asia/Shanghai' date +'%Y.%m.%d.%H.%M')" >> $GITHUB_OUTPUT echo "y=$(TZ='Asia/Shanghai' date +'%Y')" >> $GITHUB_OUTPUT echo "md=$(TZ='Asia/Shanghai' date +'%m%d')" >> $GITHUB_OUTPUT echo "hm=$(TZ='Asia/Shanghai' date +'%H%M')" >> $GITHUB_OUTPUT echo "sv=$(TZ='Asia/Shanghai' date +'%Y.%m.%d.%H%M')" >> $GITHUB_OUTPUT - name: Display Version run: | echo "Version: ${{ steps.date.outputs.time }}" linux-appimage: runs-on: ubuntu-22.04 needs: time strategy: matrix: arch: [x64, arm, arm64] steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: "8.0.x" - name: Write Version run: echo "${{ needs.time.outputs.v }}" > ./YMCL.Main/YMCL/Public/Texts/DateTime.txt - name: Install Dependencies run: | dotnet tool install -g KuiperZone.PupNet --version 1.8.0 sudo apt-get update -qq sudo apt-get install -y fuse - name: Build AppImage (${{ matrix.arch }}) run: | cd ./YMCL.Main/YMCL.Desktop ~/.dotnet/tools/pupnet --runtime linux-${{ matrix.arch }} --kind appimage -o YMCL.Desktop.linux.${{ matrix.arch }}.AppImage -y --app-version ${{ needs.time.outputs.y }}.${{ needs.time.outputs.md }}.${{ needs.time.outputs.hm }} - name: Upload Artifacts uses: actions/upload-artifact@v4 with: name: linux-appimage-${{ matrix.arch }} path: YMCL.Main/YMCL.Desktop/Deploy/OUT/* retention-days: 1 linux-macos: runs-on: ubuntu-22.04 needs: time steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: "8.0.x" - name: Write Version run: echo "${{ needs.time.outputs.v }}" > ./YMCL.Main/YMCL/Public/Texts/DateTime.txt - name: Build macOS App (x64) run: | cd ./YMCL.Main/YMCL.Desktop dotnet restore -r osx-x64 dotnet msbuild -t:BundleApp -p:RuntimeIdentifier=osx-x64 -property:Configuration=Release -p:SelfContained=true -p:Version=${{ needs.time.outputs.sv }} cp ./Icon-Border.icns "./bin/Release/net8.0/osx-x64/publish/YMCL.app/Contents/Resources/Icon-Border.icns" cd ./bin/Release/net8.0/osx-x64/publish/ zip -9 -r ../../YMCL.Desktop.osx.mac.x64.app.zip "./YMCL.app" - name: Upload Artifacts uses: actions/upload-artifact@v4 with: name: linux-macos-artifacts path: YMCL.Main/YMCL.Desktop/bin/Release/net8.0/YMCL.Desktop.osx.mac.x64.app.zip retention-days: 1 linux-windows: runs-on: ubuntu-22.04 needs: time steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: "8.0.x" - name: Write Version run: echo "${{ needs.time.outputs.v }}" > ./YMCL.Main/YMCL/Public/Texts/DateTime.txt - name: Build Windows Executables run: | cd ./YMCL.Main/YMCL.Desktop for arch in win-x86 win-x64 win-arm64; do dotnet publish -c Release -r $arch /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true /p:SelfContained=false /p:Version=${{ needs.time.outputs.sv }} mv ./bin/Release/net8.0/$arch/publish/YMCL.Desktop.exe ./bin/Release/net8.0/YMCL.win.${arch#win-}.portable.exe done - name: Upload Artifacts uses: actions/upload-artifact@v4 with: name: linux-windows-artifacts path: YMCL.Main/YMCL.Desktop/bin/Release/net8.0/*.exe retention-days: 1 win: runs-on: windows-latest needs: time strategy: matrix: arch: [x64, x86, arm64] steps: - name: Checkout uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: "8.0.x" - name: Install Inno Setup uses: ConorMacBride/install-package@v1 with: choco: innosetup --version 6.7.0 - name: Apply Chinese Localization run: Copy-Item "./Assets/Default.isl" "C:\Program Files (x86)\Inno Setup 6\Default.isl" -Force - name: Install PupNet run: dotnet tool install -g KuiperZone.PupNet --version 1.8.0 - name: Write Version run: echo "${{ needs.time.outputs.v }}" > ./YMCL.Main/YMCL/Public/Texts/DateTime.txt shell: bash - name: Build Installer (${{ matrix.arch }}) run: | cd ./YMCL.Main/YMCL.Desktop pupnet -r win-${{ matrix.arch }} -k setup -y -o YMCL.Desktop.win.${{ matrix.arch }}.installer.exe --app-version ${{ needs.time.outputs.y }}.${{ needs.time.outputs.md }}.${{ needs.time.outputs.hm }} - name: Upload Artifacts uses: actions/upload-artifact@v4 with: name: win-artifacts-${{ matrix.arch }} path: ./YMCL.Main/YMCL.Desktop/Deploy/OUT/* retention-days: 1 mac: needs: [linux-macos] runs-on: macos-latest steps: - name: Download macOS App uses: actions/download-artifact@v4 with: name: linux-macos-artifacts path: ./YMCL.Release/ - name: Extract macOS App run: unzip -n ./YMCL.Release/YMCL.Desktop.osx.mac.x64.app.zip -d ./app.x64 - name: Create DMG (x64) uses: L-Super/create-dmg-actions@v1.0.3 with: dmg_name: "YMCL.Desktop.osx.mac.x64" src_dir: "./app.x64/YMCL.app" - name: Upload Artifacts uses: actions/upload-artifact@v4 with: name: osx-artifacts path: ./YMCL.Desktop.osx.mac.x64.dmg retention-days: 1 publish: needs: [linux-appimage, linux-macos, linux-windows, win, mac, time] runs-on: ubuntu-latest steps: - name: Generate Release Date id: gdate run: | echo "date=$(date +'%Y-%m-%d.%H-%M-%S')" >> $GITHUB_OUTPUT echo "title=$(date +'%Y.%m.%d.%H.%M')" >> $GITHUB_OUTPUT - name: Download All Artifacts uses: actions/download-artifact@v4 with: path: ./YMCL.Release/ - name: List Release Files run: find ./YMCL.Release/ -type f -name "*.exe" -o -name "*.dmg" -o -name "*.AppImage" -o -name "*.zip" - name: Rename Artifacts (Remove Desktop) run: | cd ./YMCL.Release/ find . -type f \( -name "*.exe" -o -name "*.dmg" -o -name "*.AppImage" -o -name "*.zip" \) | while read file; do newname=$(echo "$file" | sed 's/YMCL\.Desktop\./YMCL./g') if [ "$file" != "$newname" ]; then mv "$file" "$newname" fi done - name: Publish Release uses: marvinpinto/action-automatic-releases@latest with: repo_token: "${{ secrets.TOKEN }}" title: "v${{ needs.time.outputs.v }}" automatic_release_tag: "AutoPublish" prerelease: false files: | YMCL.Release/**/*.exe YMCL.Release/**/*.dmg YMCL.Release/**/*.AppImage YMCL.Release/**/*.zip ================================================ FILE: .gitignore ================================================ bin/ obj/ .vs/* .idea/* *.suo *.bin *.user ================================================ FILE: .vscode/settings.json ================================================ { } ================================================ FILE: Assets/Default.isl ================================================ ; *** Inno Setup 版本 6.5.0+ 中文消息 *** ; ; 要下载此文件的用户贡献翻译,请访问: ; https://jrsoftware.org/files/istrans/ ; ; 注意:翻译此文本时,不要在原本没有句号 (.) 的消息末尾添加句号, ; 因为 Inno Setup 会自动添加句号(添加句号会导致显示两个句号) [LangOptions] ; 以下三个条目非常重要。请务必阅读并理解 ; 帮助文件中的"[LangOptions] 部分"主题。 LanguageName=简体中文 LanguageID=$0804 ; 应尽可能设置 LanguageCodePage,即使此文件是 Unicode ; 对于中文简体,设置为 936(GBK 编码) LanguageCodePage=936 ; 如果您要翻译的语言需要特殊的字体或 ; 大小,请取消注释以下任何条目并相应更改。 ;DialogFontName= ;DialogFontSize=9 ;DialogFontBaseScaleWidth=7 ;DialogFontBaseScaleHeight=15 ;WelcomeFontName=Segoe UI ;WelcomeFontSize=14 [Messages] ; *** 应用程序标题 SetupAppTitle=安装 SetupWindowTitle=安装 - %1 UninstallAppTitle=卸载 UninstallAppFullTitle=%1 卸载 ; *** 杂项常见 InformationTitle=信息 ConfirmTitle=确认 ErrorTitle=错误 ; *** SetupLdr 消息 SetupLdrStartupMessage=这将安装 %1。您想继续吗? LdrCannotCreateTemp=无法创建临时文件。安装已中止 LdrCannotExecTemp=无法在临时目录中执行文件。安装已中止 HelpTextNote= ; *** 启动错误消息 LastErrorMessage=%1。%n%n错误 %2: %3 SetupFileMissing=安装目录中缺少文件 %1。请更正问题或获取程序的新副本。 SetupFileCorrupt=安装文件已损坏。请获取程序的新副本。 SetupFileCorruptOrWrongVer=安装文件已损坏或与此版本的安装程序不兼容。请更正问题或获取程序的新副本。 InvalidParameter=在命令行上传递了无效参数:%n%n%1 SetupAlreadyRunning=安装程序已在运行。 WindowsVersionNotSupported=此程序不支持您的计算机运行的 Windows 版本。 WindowsServicePackRequired=此程序需要 %1 Service Pack %2 或更高版本。 NotOnThisPlatform=此程序不会在 %1 上运行。 OnlyOnThisPlatform=此程序必须在 %1 上运行。 OnlyOnTheseArchitectures=此程序只能安装在为以下处理器架构设计的 Windows 版本上:%n%n%1 WinVersionTooLowError=此程序需要 %1 版本 %2 或更高版本。 WinVersionTooHighError=此程序无法安装在 %1 版本 %2 或更高版本上。 AdminPrivilegesRequired=安装此程序时必须以管理员身份登录。 PowerUserPrivilegesRequired=安装此程序时必须以管理员身份或作为 Power Users 组成员登录。 SetupAppRunningError=安装程序检测到 %1 当前正在运行。%n%n请立即关闭它的所有实例,然后单击"确定"继续,或单击"取消"退出。 UninstallAppRunningError=卸载程序检测到 %1 当前正在运行。%n%n请立即关闭它的所有实例,然后单击"确定"继续,或单击"取消"退出。 ; *** 启动问题 PrivilegesRequiredOverrideTitle=选择安装模式 PrivilegesRequiredOverrideInstruction=选择安装模式 PrivilegesRequiredOverrideText1=%1 可以为所有用户安装(需要管理员权限),或仅为您安装。 PrivilegesRequiredOverrideText2=%1 可以仅为您安装,或为所有用户安装(需要管理员权限)。 PrivilegesRequiredOverrideAllUsers=为 &所有用户安装 PrivilegesRequiredOverrideAllUsersRecommended=为 &所有用户安装(推荐) PrivilegesRequiredOverrideCurrentUser=仅为 &我安装 PrivilegesRequiredOverrideCurrentUserRecommended=仅为 &我安装(推荐) ; *** 杂项错误 ErrorCreatingDir=安装程序无法创建目录"%1" ErrorTooManyFilesInDir=无法在目录"%1"中创建文件,因为它包含太多文件 ; *** 安装常见消息 ExitSetupTitle=退出安装 ExitSetupMessage=安装未完成。如果现在退出,程序将不会被安装。%n%n您可以在另一个时间再次运行安装程序以完成安装。%n%n退出安装? AboutSetupMenuItem=&关于安装(&A)... AboutSetupTitle=关于安装 AboutSetupMessage=%1 版本 %2%n%3%n%n%1 主页:%n%4 AboutSetupNote= TranslatorNote= ; *** 按钮 ButtonBack=< &返回 ButtonNext=&下一步 > ButtonInstall=&安装 ButtonOK=确定 ButtonCancel=取消 ButtonYes=&是 ButtonYesToAll=全部 &是(&A) ButtonNo=&否 ButtonNoToAll=全部 &否(&O) ButtonFinish=&完成 ButtonBrowse=&浏览... ButtonWizardBrowse=浏览(&R)... ButtonNewFolder=&新建文件夹 ; *** "选择语言"对话框消息 SelectLanguageTitle=选择安装语言 SelectLanguageLabel=选择安装期间要使用的语言。 ; *** 常见向导文本 ClickNext=单击"下一步"继续,或单击"取消"退出安装。 BeveledLabel= BrowseDialogTitle=浏览文件夹 BrowseDialogLabel=从下面的列表中选择一个文件夹,然后单击"确定"。 NewFolderName=新建文件夹 ; *** "欢迎"向导页面 WelcomeLabel1=欢迎使用 [name] 安装向导 WelcomeLabel2=这将在您的计算机上安装 [name/ver]。%n%n建议您在继续之前关闭所有其他应用程序。 ; *** "密码"向导页面 WizardPassword=密码 PasswordLabel1=此安装受密码保护。 PasswordLabel3=请提供密码,然后单击"下一步"继续。密码区分大小写。 PasswordEditLabel=&密码: IncorrectPassword=您输入的密码不正确。请重试。 ; *** "许可协议"向导页面 WizardLicense=许可协议 LicenseLabel=请在继续之前阅读以下重要信息。 LicenseLabel3=请阅读以下许可协议。您必须接受此协议的条款才能继续安装。 LicenseAccepted=我 &接受协议(&A) LicenseNotAccepted=我 &不接受协议(&D) ; *** "信息"向导页面 WizardInfoBefore=信息 InfoBeforeLabel=请在继续之前阅读以下重要信息。 InfoBeforeClickLabel=当您准备好继续安装时,单击"下一步"。 WizardInfoAfter=信息 InfoAfterLabel=请在继续之前阅读以下重要信息。 InfoAfterClickLabel=当您准备好继续安装时,单击"下一步"。 ; *** "用户信息"向导页面 WizardUserInfo=用户信息 UserInfoDesc=请输入您的信息。 UserInfoName=&用户名: UserInfoOrg=&组织: UserInfoSerial=&序列号: UserInfoNameRequired=您必须输入名称。 ; *** "选择目标位置"向导页面 WizardSelectDir=选择目标位置 SelectDirDesc=[name] 应该安装在哪里? SelectDirLabel3=安装程序将把 [name] 安装到以下文件夹中。 SelectDirBrowseLabel=要继续,单击"下一步"。如果您想选择其他文件夹,单击"浏览"。 DiskSpaceGBLabel=至少需要 [gb] GB 的可用磁盘空间。 DiskSpaceMBLabel=至少需要 [mb] MB 的可用磁盘空间。 CannotInstallToNetworkDrive=安装程序无法安装到网络驱动器。 CannotInstallToUNCPath=安装程序无法安装到 UNC 路径。 InvalidPath=您必须输入带有驱动器号的完整路径;例如:%n%nC:\APP%n%n或 UNC 路径形式:%n%n\\server\share InvalidDrive=您选择的驱动器或 UNC 共享不存在或无法访问。请选择另一个。 DiskSpaceWarningTitle=磁盘空间不足 DiskSpaceWarning=安装程序需要至少 %1 KB 的可用空间来安装,但所选驱动器只有 %2 KB 可用。%n%n您想继续吗? DirNameTooLong=文件夹名称或路径太长。 InvalidDirName=文件夹名称无效。 BadDirName32=文件夹名称不能包含以下任何字符:%n%n%1 DirExistsTitle=文件夹已存在 DirExists=文件夹:%n%n%1%n%n已存在。您想安装到该文件夹吗? DirDoesntExistTitle=文件夹不存在 DirDoesntExist=文件夹:%n%n%1%n%n不存在。您想创建该文件夹吗? ; *** "选择组件"向导页面 WizardSelectComponents=选择组件 SelectComponentsDesc=应该安装哪些组件? SelectComponentsLabel2=选择要安装的组件;清除不想安装的组件。准备好后单击"下一步"。 FullInstallation=完全安装 ; 如果可能,不要将"Compact"翻译为"最小" CompactInstallation=紧凑安装 CustomInstallation=自定义安装 NoUninstallWarningTitle=组件已存在 NoUninstallWarning=安装程序检测到以下组件已安装在您的计算机上:%n%n%1%n%n取消选择这些组件不会卸载它们。%n%n您想继续吗? ComponentSize1=%1 KB ComponentSize2=%1 MB ComponentsDiskSpaceGBLabel=当前选择需要至少 [gb] GB 的磁盘空间。 ComponentsDiskSpaceMBLabel=当前选择需要至少 [mb] MB 的磁盘空间。 ; *** "选择其他任务"向导页面 WizardSelectTasks=选择其他任务 SelectTasksDesc=应该执行哪些其他任务? SelectTasksLabel2=选择您希望安装程序在安装 [name] 时执行的其他任务,然后单击"下一步"。 ; *** "选择开始菜单文件夹"向导页面 WizardSelectProgramGroup=选择开始菜单文件夹 SelectStartMenuFolderDesc=安装程序应该在哪里放置程序的快捷方式? SelectStartMenuFolderLabel3=安装程序将在以下开始菜单文件夹中创建程序的快捷方式。 SelectStartMenuFolderBrowseLabel=要继续,单击"下一步"。如果您想选择其他文件夹,单击"浏览"。 MustEnterGroupName=您必须输入文件夹名称。 GroupNameTooLong=文件夹名称或路径太长。 InvalidGroupName=文件夹名称无效。 BadGroupName=文件夹名称不能包含以下任何字符:%n%n%1 NoProgramGroupCheck2=&不创建开始菜单文件夹 ; *** "准备安装"向导页面 WizardReady=准备安装 ReadyLabel1=安装程序现在已准备好开始在您的计算机上安装 [name]。 ReadyLabel2a=单击"安装"继续安装,或单击"返回"如果您想查看或更改任何设置。 ReadyLabel2b=单击"安装"继续安装。 ReadyMemoUserInfo=用户信息: ReadyMemoDir=目标位置: ReadyMemoType=安装类型: ReadyMemoComponents=选定的组件: ReadyMemoGroup=开始菜单文件夹: ReadyMemoTasks=其他任务: ; *** TDownloadWizardPage 向导页面和 DownloadTemporaryFile DownloadingLabel2=正在下载文件... ButtonStopDownload=&停止下载 StopDownload=您确定要停止下载吗? ErrorDownloadAborted=下载已中止 ErrorDownloadFailed=下载失败:%1 %2 ErrorDownloadSizeFailed=获取大小失败:%1 %2 ErrorProgress=无效的进度:%1 / %2 ErrorFileSize=无效的文件大小:预期 %1,找到 %2 ; *** TExtractionWizardPage 向导页面和 ExtractArchive ExtractingLabel=正在提取文件... ButtonStopExtraction=&停止提取 StopExtraction=您确定要停止提取吗? ErrorExtractionAborted=提取已中止 ErrorExtractionFailed=提取失败:%1 ; *** 存档提取失败详情 ArchiveIncorrectPassword=密码不正确 ArchiveIsCorrupted=存档已损坏 ArchiveUnsupportedFormat=不支持的存档格式 ; *** "准备安装"向导页面 WizardPreparing=准备安装 PreparingDesc=安装程序正在准备在您的计算机上安装 [name]。 PreviousInstallNotCompleted=之前程序的安装/删除未完成。您需要重新启动计算机以完成该安装。%n%n重新启动计算机后,再次运行安装程序以完成 [name] 的安装。 CannotContinue=安装程序无法继续。请单击"取消"退出。 ApplicationsFound=以下应用程序正在使用需要由安装程序更新的文件。建议您允许安装程序自动关闭这些应用程序。 ApplicationsFound2=以下应用程序正在使用需要由安装程序更新的文件。建议您允许安装程序自动关闭这些应用程序。安装完成后,安装程序将尝试重新启动应用程序。 CloseApplications=&自动关闭应用程序 DontCloseApplications=&不关闭应用程序 ErrorCloseApplications=安装程序无法自动关闭所有应用程序。建议您在继续之前关闭所有使用需要由安装程序更新的文件的应用程序。 PrepareToInstallNeedsRestart=安装程序必须重新启动您的计算机。重新启动计算机后,再次运行安装程序以完成 [name] 的安装。%n%n您想立即重新启动吗? ; *** "安装"向导页面 WizardInstalling=安装 InstallingLabel=请等待安装程序在您的计算机上安装 [name]。 ; *** "安装完成"向导页面 FinishedHeadingLabel=完成 [name] 安装向导 FinishedLabelNoIcons=安装程序已完成在您的计算机上安装 [name]。 FinishedLabel=安装程序已完成在您的计算机上安装 [name]。可以通过选择已安装的快捷方式来启动应用程序。 ClickFinish=单击"完成"退出安装。 FinishedRestartLabel=要完成 [name] 的安装,安装程序必须重新启动您的计算机。您想立即重新启动吗? FinishedRestartMessage=要完成 [name] 的安装,安装程序必须重新启动您的计算机。%n%n您想立即重新启动吗? ShowReadmeCheck=是的,我想查看 README 文件 YesRadio=&是的,立即重新启动计算机 NoRadio=&否,我稍后重新启动计算机 ; 用于例如"运行 MyProg.exe" RunEntryExec=运行 %1 ; 用于例如"查看 Readme.txt" RunEntryShellExec=查看 %1 ; *** "安装程序需要下一张磁盘"内容 ChangeDiskTitle=安装程序需要下一张磁盘 SelectDiskLabel2=请插入磁盘 %1 并单击"确定"。%n%n如果此磁盘上的文件可以在下面显示的文件夹以外的其他文件夹中找到,请输入正确的路径或单击"浏览"。 PathLabel=&路径: FileNotInDir2=文件"%1"无法在"%2"中找到。请插入正确的磁盘或选择另一个文件夹。 SelectDirectoryLabel=请指定下一张磁盘的位置。 ; *** 安装阶段消息 SetupAborted=安装未完成。%n%n请更正问题并再次运行安装程序。 AbortRetryIgnoreSelectAction=选择操作 AbortRetryIgnoreRetry=&重试 AbortRetryIgnoreIgnore=&忽略错误并继续 AbortRetryIgnoreCancel=取消安装 RetryCancelSelectAction=选择操作 RetryCancelRetry=&重试 RetryCancelCancel=取消 ; *** 安装状态消息 StatusClosingApplications=正在关闭应用程序... StatusCreateDirs=正在创建目录... StatusExtractFiles=正在提取文件... StatusDownloadFiles=正在下载文件... StatusCreateIcons=正在创建快捷方式... StatusCreateIniEntries=正在创建 INI 条目... StatusCreateRegistryEntries=正在创建注册表条目... StatusRegisterFiles=正在注册文件... StatusSavingUninstall=正在保存卸载信息... StatusRunProgram=完成安装... StatusRestartingApplications=正在重新启动应用程序... StatusRollback=正在回滚更改... ; *** 杂项错误 ErrorInternal2=内部错误:%1 ErrorFunctionFailedNoCode=%1 失败 ErrorFunctionFailed=%1 失败;代码 %2 ErrorFunctionFailedWithMessage=%1 失败;代码 %2。%n%3 ErrorExecutingProgram=无法执行文件:%n%1 ; *** 注册表错误 ErrorRegOpenKey=打开注册表项时出错:%n%1\%2 ErrorRegCreateKey=创建注册表项时出错:%n%1\%2 ErrorRegWriteKey=写入注册表项时出错:%n%1\%2 ; *** INI 错误 ErrorIniEntry=在文件"%1"中创建 INI 条目时出错。 ; *** 文件复制错误 FileAbortRetryIgnoreSkipNotRecommended=&跳过此文件(不推荐) FileAbortRetryIgnoreIgnoreNotRecommended=&忽略错误并继续(不推荐) SourceIsCorrupted=源文件已损坏 SourceDoesntExist=源文件"%1"不存在 SourceVerificationFailed=源文件验证失败:%1 VerificationSignatureDoesntExist=签名文件"%1"不存在 VerificationSignatureInvalid=签名文件"%1"无效 VerificationKeyNotFound=签名文件"%1"使用未知密钥 VerificationFileNameIncorrect=文件名不正确 VerificationFileTagIncorrect=文件标记不正确 VerificationFileSizeIncorrect=文件大小不正确 VerificationFileHashIncorrect=文件哈希不正确 ExistingFileReadOnly2=无法替换现有文件,因为它被标记为只读。 ExistingFileReadOnlyRetry=&删除只读属性并重试 ExistingFileReadOnlyKeepExisting=&保留现有文件 ErrorReadingExistingDest=尝试读取现有文件时出错: FileExistsSelectAction=选择操作 FileExists2=文件已存在。 FileExistsOverwriteExisting=&覆盖现有文件 FileExistsKeepExisting=&保留现有文件 FileExistsOverwriteOrKeepAll=&对后续冲突执行此操作 ExistingFileNewerSelectAction=选择操作 ExistingFileNewer2=现有文件比安装程序尝试安装的文件更新。 ExistingFileNewerOverwriteExisting=&覆盖现有文件 ExistingFileNewerKeepExisting=&保留现有文件(推荐) ExistingFileNewerOverwriteOrKeepAll=&对后续冲突执行此操作 ErrorChangingAttr=尝试更改现有文件的属性时出错: ErrorCreatingTemp=尝试在目标目录中创建文件时出错: ErrorReadingSource=尝试读取源文件时出错: ErrorCopying=尝试复制文件时出错: ErrorDownloading=尝试下载文件时出错: ErrorExtracting=尝试提取存档时出错: ErrorReplacingExistingFile=尝试替换现有文件时出错: ErrorRestartReplace=RestartReplace 失败: ErrorRenamingTemp=尝试在目标目录中重命名文件时出错: ErrorRegisterServer=无法注册 DLL/OCX:%1 ErrorRegSvr32Failed=RegSvr32 失败,退出代码 %1 ErrorRegisterTypeLib=无法注册类型库:%1 ; *** 卸载显示名称标记 ; 用于例如"我的程序 (32 位)" UninstallDisplayNameMark=%1 (%2) ; 用于例如"我的程序 (32 位,所有用户)" UninstallDisplayNameMarks=%1 (%2, %3) UninstallDisplayNameMark32Bit=32 位 UninstallDisplayNameMark64Bit=64 位 UninstallDisplayNameMarkAllUsers=所有用户 UninstallDisplayNameMarkCurrentUser=当前用户 ; *** 安装后错误 ErrorOpeningReadme=尝试打开 README 文件时出错。 ErrorRestartingComputer=安装程序无法重新启动计算机。请手动执行此操作。 ; *** 卸载程序消息 UninstallNotFound=文件"%1"不存在。无法卸载。 UninstallOpenError=文件"%1"无法打开。无法卸载 UninstallUnsupportedVer=卸载日志文件"%1"的格式不被此版本的卸载程序识别。无法卸载 UninstallUnknownEntry=在卸载日志中遇到未知条目 (%1) ConfirmUninstall=您确定要完全删除 %1 及其所有组件吗? UninstallOnlyOnWin64=此安装只能在 64 位 Windows 上卸载。 OnlyAdminCanUninstall=此安装只能由具有管理员权限的用户卸载。 UninstallStatusLabel=请等待 %1 从您的计算机中删除。 UninstalledAll=%1 已成功从您的计算机中删除。 UninstalledMost=%1 卸载完成。%n%n某些元素无法删除。这些可以手动删除。 UninstalledAndNeedsRestart=要完成 %1 的卸载,必须重新启动您的计算机。%n%n您想立即重新启动吗? UninstallDataCorrupted="%1"文件已损坏。无法卸载 ; *** 卸载阶段消息 ConfirmDeleteSharedFileTitle=删除共享文件? ConfirmDeleteSharedFile2=系统指示以下共享文件不再被任何程序使用。您想让卸载程序删除此共享文件吗?%n%n如果任何程序仍在使用此文件并将其删除,这些程序可能无法正常运行。如果您不确定,请选择"否"。将文件保留在系统上不会造成任何伤害。 SharedFileNameLabel=文件名: SharedFileLocationLabel=位置: WizardUninstalling=卸载状态 StatusUninstalling=正在卸载 %1... ; *** 关闭阻止原因 ShutdownBlockReasonInstallingApp=正在安装 %1。 ShutdownBlockReasonUninstallingApp=正在卸载 %1。 ; 下面的自定义消息不被安装程序本身使用,但如果您在 ; 脚本中使用它们,您需要翻译它们。 [CustomMessages] NameAndVersion=%1 版本 %2 AdditionalIcons=其他快捷方式: CreateDesktopIcon=创建 &桌面快捷方式 CreateQuickLaunchIcon=创建 &快速启动快捷方式 ProgramOnTheWeb=%1 网站 UninstallProgram=卸载 %1 LaunchProgram=启动 %1 AssocFileExtension=&将 %1 与 %2 文件扩展名关联 AssocingFileExtension=正在将 %1 与 %2 文件扩展名关联... AutoStartProgramGroupDescription=启动: AutoStartProgram=自动启动 %1 AddonHostProgramNotFound=在您选择的文件夹中找不到 %1。%n%n您想继续吗? ================================================ FILE: Assets/Icon.ai ================================================ %PDF-1.5 % 1 0 obj <>/OCGs[28 0 R 29 0 R 31 0 R 30 0 R]>>/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <>stream application/pdf Icon Adobe Illustrator 26.2 (Windows) 2025-03-14T22:47:45+09:00 2025-03-14T22:47:46+08:00 2025-03-14T22:47:46+08:00 256 200 JPEG /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAyAEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7 FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F XYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXY q7FXYq7FXYq7FXYq7FXYq7FXYq7FVC9ujbQGYJ6gUjkK0oDtXocsxw4jTRqM3hx4qtC2+u2chCvW Inu24+8ZZLTSHLdxsXaOOWx9KYI6OgdGDIwqrKagg9wRlBBGxc8EEWG8CXYq7FXYq7FXYq7FXYq7 FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FVO4iE0EkR/bUjJQlRBa8sOOJj 3sQYFSVIoQaEZtw8oRWyJsNQms5Pg+KFvtxHp8x4HKsuITHm5el1csR749zJLS8gu4vUhao6Mp2Z T4EZrsmMxNF3+LNHILirZBtdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdiq ySeGP7bhfY9fuwEgNc8sY8yoNqdqDsSfcD+uQ8QNB1uNtNStW6sV+Y/pXCMgTHWYz1pXSWN/sOG+ RrkgQXIjOMuRXYWTsVdirGNYg9K+koKLJ8Y+nr+ObPTyuDzmux8OU+e6Cy5w1SGeaCQSwtwcd+xH gR3GCURIUWzFmljNxZHp2qw3g4EcJ1FWj8R4qe4zXZsBhv0eh02rjlHdLuRuUOU7FXYq7FXYq7FX Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FUFf3pi/dxn95+0fDK5zrYODqtTw+mPNKySxJJqT1Jy h1RN82sVdirsVVku7lPsyGngdx+OSEiG2OonHkUQmqzD7aq34HJDKXIjr5DmLV01WA/aVlP3jJjK HJjroHmKQOutbzRRSxuCyniR3od+h+WZ2jyAkhw+0ZQnESieSTZnupdirYJBDKSrDcMDQg+xGKYy INjmnum62snCC6IWU7LL0Vj2r4E/d+AzBzaat48neaTXifpntL702zEdk7FXYq7FXYq7FXYq7FXY q7FXYq7FXYq7FXYq7FXYq7FVC8uRBFUfbbZB/HIzlQcfUZvDj5pKSWJJNSdycxnSE2bLWKuxV2Ku xV2KuxV2KsS/NO5uLXybc3FvI0U8UsDRyKaMpEq0IOb72agJayIIsES+4uJrSRjJHklXkTz/AG2v QrZ3hEOrovxL0WYDqye/iv8ADpvu0+y5YDxR3x/d73EwagT2PNmGadynYq4gEUPTFUy03WZLekVx WSD9l9yyf81L+P6sxs2nEtxzdnpNeY+mfLvZCjo6B0YMjCqspqCD3BGYBBGxd2CCLDeBLsVdirsV dirsVdirsVdirsVdirsVdirsVdirTuqKWY0UCpOJKJSAFlI7mdp5S56dFHgMxZSsuizZTOVqWBqd irsVdirsVdirsVdirDfzc/5Qa8/4yQ/8nVzoPZj/AB2Pul9xcPX/AN0XgUE80EyTQu0c0bBo5FNG VhuCCM9QlESFHcF0INPavIPn6HXYVsb5lj1aNfksyj9pf8r+ZfpHtxnanZZwHijvjP2O00+o49jz Znmmcp2KuxVF6fqM1m44/FAT8cXz7r4H9f45VlxCY83M0usliNc4/jkyS1uoLqISwtyXoR0IPgR2 Oa6cDE0Xf4ssZi4nZVyDY7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FUs1O65N6Kn4V+37nwynJLo6 vW57PCEBlTgOxV2KuxV2KuxV2KuxV2KsL/N+QL5HuVP7csKj/gw38M6H2Wjetj5CX3OFrz+6LwHP UXQr4J5oJkmhdo5o2DRyKaMrDcEEZGURIUdwUg09n8gfmBHrca6fqLLHqyD4W2VZwO6joHHcfSPb ju1OyjhPHD+7+79js9PqOLY82bZpHLdirsVVLe4ntpfVhbi/QjqrDwYd8jOAkKLbhzyxm4sl0/U4 bxKD4JgKvETUj3B7jNdlwmHueh0+qjlG3PuReUuS7FXYq7FXYq7FXYq7FXYq7FXYq7FUPe3PoRVH 222X+uQnKg4+pzcEfMpMSSanrmO6RrFXYq7FXYq7FXYq7FXYq7FWD/nH/wAoVL/xnh/Wc6P2V/xw f1S4PaH938Xguenuidiq6KWSKRJYnMckZDI6mjBhuCCMEogijySC9m8g/mFDrEaadqTiPVVFEc7L OAOo7B/Efd7cb2p2UcJ44b4/u/Y7PT6ji2PNnGaRy3Yq7FW0Z0dXRiroaqw6g4kWKLKEzE2Nin+m ays5EFxRJ+it0V/6N7fd4DAzafh3HJ3uk1wyemW0vvTTMV2DsVdirsVdirsVdirsVdirsVU7i4ht oJLidxHDEpeRz0CqKk5KEDIgDmWvLljjiZSNRiLLCrDztp2s3TRmtvNyKwxydGWvw0P83iMytf2V lxDi+qPl0/He8dg7fxauZH0y6A9R+vyTfNQ7J2KuxV2KuxV2KuxV2KuxV2KsH/OP/lCpf+M8P6zn R+yv+OD+qXB7Q/u/i8Fz090TsVdiraO8bq6MUdCGVlNCCNwQRgIBFFL2T8vvzBTVkTTNTcJqiCkU p2E4H/G/iO+cf2r2UcR44fR937HZafUcWx5s7zROY7FXYq4gEUPTFU/0bVPVAtZ2rMAfTc/tgdq/ zD/PvmDqMNeocnfaHV8Y4ZfV96a5iOxdirsVdirsVdirsVdirsVea/mb5o9ST9B2j/AhDXrDu3VY /o6n3zpOxtFQ8WXw/W+fe1va/Efy0DsPr9/SPw5l59m/eFZToHne5teNvqPK4t+izdZEHvX7Q/HN Dr+xI5PVj9Mu7of1PRdndvTx+nL6o9/Ufr+9ndrd213As9tIssT9HU1H9hzk8uGWOXDIUXscOaGS IlA3EquVtrsVdirsVdirsVdirsVYP+cjAeS3BNC1xCB7mpP8M6T2UH+GD+qXB7Q/u/i8Fz050TsV dirsVbR3jdXRijoQyspoQRuCCMBAIopew/l9+Yi6pw0vVnC6iNoJzsJvY+D/AK/nnI9q9k+F+8x/ R1Hd+x2Wn1PFtLmz7NA5jsVdirYLAgqSrA1Vh1BG4IxTGRBsc2T6Xfi8t6tQTptKo8ezAeDf2ZrM 2LgPk9LpdQMsL69UZlLkuxV2KuxV2KuxV2KpF5x8xpoektMpBvJqx2qH+am7U8F65ndn6Q58lfwj m6Xt3tQaPAZD+8ltH39/weJySPJI0kjF5HJZ2O5JJqSTnaAACg+QSkZEk7krcLF2Ko3StYv9Mn9W 1k41pzjO6MB2YZjarR488amPj1Dl6TW5NPLigfh0L0LQvNVhqqiMkQXneBj1p3Q9/wBecdr+ysmD f6od/wCt7fs/tfHqNvpn3fq706zVu2dirsVdirsVdirsVYF+dX/KHp/zFxf8RfOn9kv8bP8AUP3h wO0f7v4vCs9LdG7FXYq7FXYq5WZWDKSrKagjYgjARavYPy+/MRNRSPStXkC6gtFt7hjQTdgrf5f6 /nnI9q9knHeTGPR1Hd+z7nZafU8W0ub0DNA5rsVdiqJ067NrdxyVpGTwlFaDixpU1/l65XlhxRIc rRZvDyDuOxZXmqeldirsVdirsVdiqyaaKCF5pWCRRqXkc9AqipJwxiZGhzLDJkjCJlI1Ebl4h5r8 wS65q8l0ai3T4LWM/sxj+LdTnb6HSjBjEevV8d7Z7TlrM5n/AAjaI8v28yk2ZbqXYq7FXYq2CQQQ aEbgjEhINMt0DzzLDxt9UJli2C3I3df9cftD36/POd1/YYl6sWx7unw7vu9z03Z3tBKPpzbj+d1+ Pf8Af72bwXEFxCs0DrJE4qrqag5y2THKB4ZCiHrceSM4iUTYKpkGx2KuxV2KuxVgX51f8oen/MXF /wARfOn9kv8AGz/UP3hwO0f7v4vCs9LdG7FXYq7FXYq7FXAkEEGhHQ4q9c/Lv8xBfCPSNXkpeii2 t0x/vfBHP8/gf2vn15LtbsngvJjHp6ju/Z93udlptTfplzeiZzzmuxVxAIoemKsn0i6NxYoWJMkf 7uQnckr0JPuCDms1EOGXkXpdHm8TGD15FG5S5TsVdirsVdirzz8z/MvFRodq/wATUe9Ydh1SP6ft H6M6HsbR/wCVl8P1vB+13a1D8tA+c/0D9J+DzfOieAdirsVdirsVdirsVTDSNd1DSpeds/7s/bhb dG+jx9xmHq9Dj1AqQ37+rnaLtDLpzcDt3dHoeieZdP1ZOMZ9K5Aq9u5+L5qf2hnG67s3JpzZ3j3/ AI5Pb6DtTFqRQ2n/ADf1d6bZr3ZuxV2KuxVgX51f8oen/MXF/wARfOn9kv8AGz/UP3hwO0f7v4vC s9LdG7FXYq7FXYq7FXYq4Eggg0I6HFXrP5e/mP8AWzHpGsyAXOyWt43+7OwSQn9vwPf59eU7V7I4 LyYx6eo7vd5fc7HT6m/TJ6PnOOc7FUfolyIL0Kxok4CGtPtD7HX5kfTlGphxR9zsOzs3DPhPKX3s lzWu/dirsVdiqWeY9bh0XSZr6ShdRxgjP7cjfZX+J9sydJpjmyCI+Pudd2p2hHSYJZDz6DvPT8dz wy5uZ7q4kuJ3LzTMXkc9SzGpzuIQEQAOQfGc2WWSZnI3KRsqWSa3Yq7FXYq7FXYq7FXYquR3jdXR ijqaqymhBHcEYJRBFHkyjIg2NizHQPPRXjbaruOi3QG/+zA/WM5rX9hX6sP+l/V+p6ns72gqoZv9 N+v9bNI5I5Y1kjYPGwqrqQQR7EZzEomJoii9XGQkLBsLsDJ2KvPfzwJHlO1oet/GD/yJlzqvY/8A xqX/AAs/7qLr+0v7se/9bw/PSHSOxV2KuxV2KuxV2KuxV2KvV/y8/MUXAj0fWpaTii2t452cdkkJ /a8D3+fXle1uyeG8mIbdR+kOx02pv0yek5zbnO37Eg9iNiD4jFQaNhlmn3X1q0jm2DkUkA7MNj9H h7ZqssOGRD1ODL4kBJEZW3OxV2KvIfzH19tR1k2UTf6LYExgDo0v7bfR9nOt7I0vh4+I/VL7uj5Z 7VdpePqPDj9GPb/O6/qYlm2eXdirsVdirsVdirsVdirsVdirsVTTRfMWoaTJ+5bnbk1kt2+yfcfy n3zB1vZ2PUD1bS73Y6DtPLpj6d49R0/Y9D0bzBp+rRVgfjMBWS3b7a/1HuM43W9n5NOfUPT39Ht9 D2li1I9J9XUdUyzBdg88/PD/AJRO0/5j4/8AkzNnV+x/+NS/4Wf91F1/aX92Pf8AreIZ6O6R2Kux V2KuxV2KuxV2KuxV2KvUvy6/MXn6WjazL8eyWd4569hHIT3/AJWzl+1uyavJjHvH6Q7DTan+GT07 OZc9NNAuvTuWtz9mfdf9dRv27qPwzG1ULjfc7TszNUjA9WQZr3duxV2KvnaWR5ZXlc1d2LMfEk1O ehRAAoPg05mRJPMrcLF2KuxV2KuxV2KuxV2KuxV2KuxV2Kr4ppYZFlicxyIaq6mhB9iMjOAkKIsF nCZiQYmiGa6B56STjb6rRH6LdAUU/wCuB0+Y2+Wcxr+wiPVh/wBL+p6zs72gB9GbY/zv1/j5If8A N3TL7VPJ6yafEblbSdLub0/ipCsbqXFOoHMdO2+H2WzRxasiZ4eKJjv32Nvsd5rMZyYrhvW/w73g 2emOhdirsVdirsVdirsVdirsVdirsVeofl9+ZBrFo+tybbJa3zn6AkpP4N9/jnMdq9kc8mIe8fpH 6nP0+p/hk9RDMrBkNHUhkbrRgag0+ecxXe7KMjEgjmGX204nt45gKeooYrUGhPUVHh0zUTjwkh6r HMTiJDqqZFm7FXgevac+nazeWTCghlYJ/qE1Q/SpGd5pcviY4y7w+I9o6U4NRPGf4ZH5dPsQGXuE 7FXYq7FXYq7FXYq7FXYq7FXYq7FXYqi9M0q/1O6W1sYWmmbcgdAPFidgPnlWbPDHHikaDlaTR5dR Pgxx4pfjn3PXvJ/laXRLJo7m5NxLKKNF1hQHchAd9+/6s5DX6uOafFGNefU+99T7D7Hlo8dTlxSP T+Ee78fB5J+bn5VHSpJNe0KD/cW/xXtqm/1did3Qf77P/C/Lp13YPbfigYsp9fQ/zv2/f73X9r9l eH+8xj0dR3fs+55RnVPPuxV2KuxV2KuxV2KuxV2KuxV2KvTfy6/MXh6WjazL8GyWd456dhHIT2/l bOZ7W7Ju8mMe8fpDn6bU/wAMnvGhAjS4q71Mh+gyMRnC6n6z8Puez0H9zH4/ej8ocx2Ksf8ANnlC z1625CkOoRikFzT/AIR6dV/Vmw0OvlgPfDqHR9tdh49bC/pyjlL9B8vueO6jp15p15JaXkZinjNG U9COxB7g9jnX4c0ckRKJsF8o1WlyYMhx5BUghsscd2KuxV2KuxV2KuxV2KuxV2KuxVlXlfyBqOr8 Lm5raaedxIR8cg/yFPb/ACj+OavW9qQxemPqn93vel7H9msuqqc/Ri7+p936/veqaTo2m6Tai2sY RFH+0erMfFmO5Octn1E8suKZt9K0Wgw6aHBijwj7T7yjcpcxbJHHLG0Uqh43BV0YAqykUIIPUHCC QbHNBAIovnj82fytk8v3D6xo8TPocprLGKk2zseh/wCKz+ye3Q9q+g9hdtDUDw8h/ej/AGX7Xju1 uy/BPHAej7v2PNM6V0bsVdirsVdirsVdirsVdirsVdir6y/Lq0ubTyPosNyWab6qjtzNWAk/eBTX +UNTPKe1piWqyGPLi+7Z9B7OgY6eAPd9+7Is1zmuxV2KpP5m8sWGvWfpTjhcRg/V7kD4kJ8fFT3G Zmj1s8ErHLqHU9rdkYtbj4ZbSH0y7v2eTxvWdFv9HvXtL2Pi4+w4+w6/zKe4zsNPqIZo8US+T6/Q ZdLkOPIN/sPmEBl7hOxV2KuxV2KuxV2KuxVEWGn3uoXK21nC0879EUfiT0A9zleXLHHHikaDkabS 5M8xDHEykXp/lb8uLKwCXWqhbq8G6w9YkPyP2z89v15zWt7XlP04/TH7T+p9E7H9lceGp56nk7v4 R+s/Z97NM0r17sVdirsVWTwQ3EEkE6LJDKpSSNhVWVhQgg9iMlGRiQRsQiUQRR5PnD80/wAr5vK9 ydR04NLoVw9FrVmt3bpG57qf2W+g79fRexO2hqY8E9so/wBl5/rDxXanZhwHij/dn7HnudA6d2Ku xV2KuxV2KuxV2KuxVm/5Y/l3feaNWiuJ4mTQ7Zw11OwosnEg+iniW706D6M0nbPa0dNjIB/enkO7 zdp2Z2fLPMEj92Of6n04qqqhVACgUAGwAGeZkvdN4q7FXYq7FUv1zQdP1qyNreJUdYpR9uNv5lOZ Gm1U8MuKP9rgdo9nYtXj4Mg9x6j3PG/MflnUdCu/RuV5wuT6FyoPBx/BvEZ2Gk1kM8bjz6h8n7V7 Jy6PJwz3ieUuh/b5JRmW6t2KuxV2KuxV2Ksl8seRtT1plnkBtdP7zsN3H/Fa9/n0zW63tOGHYeqf d+t6Hsj2dzaupH0Yu/v/AKo/TyeraLoOl6NbehYwhAf7yQ7yOfFm7/qzltRqp5pXMvpmg7Nw6SHD iFd56n3lMMx3OdirsVdirsVdiqleWdre2stpdxLPbTqUlicVVlOxBByePJKEhKJohjOAkCCLBfNn 5oflnceVLz65ZcptDuWIhkNS0LHf0pD/AMRbv889G7F7ZGqjwy2yj7fMfpeJ7U7MOnlxR3xn7PJg eb51LsVdirsVdirsVROnaZqGp3aWen28l1dSfYhiUsx99u3vlWbNDHHimRGI72zHilM8MRZez+SP yFhiMd95qcSyCjLpkLfAD4SyD7XyXb3Ocb2l7Tk3HBsP5x/QP1/J6XRdggerN/pf1vYLa2t7WCO3 tokhgiULFFGoVFUdAqjYDORnMyJMjZL0cYiIoCgqZFk7FXYq7FXYq7FUNqGnWWo2j2l5EJoJPtKf HsQeoI8RlmLNLHLiiaLj6rS488DDIOKJeR+bPJN9ochnircaax+GcD4kr+zIB0+fQ51uh7SjnFHa fd+p8t7a9n8mjPFH1Yu/u/rfr5MZzZPPOxV2Kq1pZ3V5cJb2sTTTuaLGgqTkMmSMBcjQbsGCeWQh AGUj0D0vyv8AlrbWvC71njcXHVbUbxIf8r+c/h885vW9sSl6cew7+v7H0Lsf2Thjqeo9U/5v8I9/ f93vZ0AAAAKAbADNG9mBTsVdirsVdirsVdirsVdiqhf2FnqFnNZXsK3FrcKUmhcVVlOWYssschKJ qQYZMcZxMZCwXzb+Zf5X33lS4a9tOVzoUz0im6vCT0SX9St3+eejdj9tR1Q4ZbZR9vmP1PFdpdly 054hvjP2e9gmb11LsVdirccckjrHGpeRyFVFBJJPQADASALKQL2D07yb+Reu6p6d3rrHS7E0IgoD cuP9U7R/7Lf/ACc5ntD2lxYvTi9cu/8Ah/b8Pm7zR9h5Mm+T0x+39n42e3+XPKmgeXbT6rpNolup /vJftSyHxdz8R/VnFavXZdRLiySv7h7g9Tp9JjwioCk2zEch2KuxV2KuxV2KuxV2KuxVqSNJEaOR Q6OCrIwqCD1BBwgkGwxlESFEWCwLX/ytgnkafR5Vt2Y1NtLX06/5LCpX5UOb3S9tGIrIL8xzeK7S 9j4zJlpzw/0Ty+B5j7WNt+WvmsPxEEbD+YSpT8SDmyHbGn7z8nnz7Ka4GuEf6YJhp/5UatIwN9dR W8fcR1kf/jVfxzHy9uYx9IJ+xz9N7GZ5H95OMR5bn9A+1n+heXNK0S39Kyio7D97O28j/M/wG2aH U6vJmNyPw6Pb9ndlYdHDhxjfqep/HdyTPMV2LsVdirsVdirsVdirsVdirsVdiqncW9vcwSW9xGs0 EqlJYpAGVlOxDKdiDkoTMSCDRCJREhR3Dy/zF/zj/wCXr2V59Hu5NLdjUwMvrw/JQSrr/wAEc6fS e1OaArJET8+R/V9jodR2BjkbgeH7QxZv+cdvMoY8NTsivYn1Qfu4HNoPazD/ADJfZ+twD7PZf50f tRdh/wA4537MDqGsxRr3WCJpCfpdo6fdlOX2th/BjJ95r9bZj9nZfxTHwD0zyl+XXlfyvGrWFsJL 2lHv56PMa9aGlEHsoGc3r+1s+pPrPp/mjl+34u80nZ2LB9I9XeebJs1jnOxV2KuxV2KuxV2Kv//Z uuid:9E3E5C9A8C81DB118734DB58FDDE4BA7 xmp.did:d5f62d1b-7efe-4d05-b1f8-644cb847dfa0 uuid:81d003dd-8fcc-47a2-b243-c3815ba123fd proof:pdf uuid:419d3a9b-55bd-cb4b-8139-14cb80982081 xmp.did:834d4cc7-02d9-4757-a180-d79ec67c6416 uuid:9E3E5C9A8C81DB118734DB58FDDE4BA7 proof:pdf saved xmp.iid:d5f62d1b-7efe-4d05-b1f8-644cb847dfa0 2025-03-14T22:23:46+08:00 Adobe Illustrator 29.3 (Macintosh) / EmbedByReference empty_icon.png empty_icon.png Basic RGB Document AIRobin 1 False False 512.000000 512.000000 Pixels Cyan Magenta Yellow 默认色板组 0 白色 RGB PROCESS 255 255 255 黑色 RGB PROCESS 0 0 0 RGB 红 RGB PROCESS 255 0 0 RGB 黄 RGB PROCESS 255 255 0 RGB 绿 RGB PROCESS 0 255 0 RGB 青 RGB PROCESS 0 255 255 RGB 蓝 RGB PROCESS 0 0 255 RGB 洋红 RGB PROCESS 255 0 255 R=193 G=39 B=45 RGB PROCESS 193 39 45 R=237 G=28 B=36 RGB PROCESS 237 28 36 R=241 G=90 B=36 RGB PROCESS 241 90 36 R=247 G=147 B=30 RGB PROCESS 247 147 30 R=251 G=176 B=59 RGB PROCESS 251 176 59 R=252 G=238 B=33 RGB PROCESS 252 238 33 R=217 G=224 B=33 RGB PROCESS 217 224 33 R=140 G=198 B=63 RGB PROCESS 140 198 63 R=57 G=181 B=74 RGB PROCESS 57 181 74 R=0 G=146 B=69 RGB PROCESS 0 146 69 R=0 G=104 B=55 RGB PROCESS 0 104 55 R=34 G=181 B=115 RGB PROCESS 34 181 115 R=0 G=169 B=157 RGB PROCESS 0 169 157 R=41 G=171 B=226 RGB PROCESS 41 171 226 R=0 G=113 B=188 RGB PROCESS 0 113 188 R=46 G=49 B=146 RGB PROCESS 46 49 146 R=27 G=20 B=100 RGB PROCESS 27 20 100 R=102 G=45 B=145 RGB PROCESS 102 45 145 R=147 G=39 B=143 RGB PROCESS 147 39 143 R=158 G=0 B=93 RGB PROCESS 158 0 93 R=212 G=20 B=90 RGB PROCESS 212 20 90 R=237 G=30 B=121 RGB PROCESS 237 30 121 R=199 G=178 B=153 RGB PROCESS 199 178 153 R=153 G=134 B=117 RGB PROCESS 153 134 117 R=115 G=99 B=87 RGB PROCESS 115 99 87 R=83 G=71 B=65 RGB PROCESS 83 71 65 R=198 G=156 B=109 RGB PROCESS 198 156 109 R=166 G=124 B=82 RGB PROCESS 166 124 82 R=140 G=98 B=57 RGB PROCESS 140 98 57 R=117 G=76 B=36 RGB PROCESS 117 76 36 R=96 G=56 B=19 RGB PROCESS 96 56 19 R=66 G=33 B=11 RGB PROCESS 66 33 11 冷光 1 C=56 M=0 Y=20 K=0 RGB PROCESS 101 200 208 C=51 M=43 Y=0 K=0 RGB PROCESS 131 139 197 C=26 M=41 Y=0 K=0 RGB PROCESS 186 155 201 灰色 1 R=0 G=0 B=0 RGB PROCESS 0 0 0 R=26 G=26 B=26 RGB PROCESS 26 26 26 R=51 G=51 B=51 RGB PROCESS 51 51 51 R=77 G=77 B=77 RGB PROCESS 77 77 77 R=102 G=102 B=102 RGB PROCESS 102 102 102 R=128 G=128 B=128 RGB PROCESS 128 128 128 R=153 G=153 B=153 RGB PROCESS 153 153 153 R=179 G=179 B=179 RGB PROCESS 179 179 179 R=204 G=204 B=204 RGB PROCESS 204 204 204 R=230 G=230 B=230 RGB PROCESS 230 230 230 R=242 G=242 B=242 RGB PROCESS 242 242 242 Adobe PDF library 16.04 endstream endobj 3 0 obj <> endobj 5 0 obj <>/Resources<>/ExtGState<>/Properties<>/XObject<>>>/Thumb 38 0 R/TrimBox[0.0 0.0 512.0 512.0]/Type/Page>> endobj 33 0 obj <>stream HTn1 )㍝Nl "qFRPo̊O|6oN%8ٞ˜ :m_.iokK]YEnұr{>mR)4x iW,'k{4xwS~xU'߰q#W#W^RY -]jp5yOzAkTpdАx#q;OL0 m8Zh4|䇴h1J8` tK36}gV9Wv$T+)Ri9d4ڈ7OAkiA7ba4 v@ !bhS+JA.P\ =( 9Ed2vAVql`!4)5c1 +N @5)aL$"P9TXՂ:s"}\({l4dZT iI䬵-y8A߶,`2<# \F@F+b_PE^0Rd27Ɗ@ 3K Vz!.6AhX8?>J02R{[KLxŪBV=J"BV,Ց<7?*5^@L4"112UT#\f`z"ץD=f#0wB}ލ͊Pׁw̶U Hj-!Ej8Hc|GX}n?ly0Iǎ@Y z^ 9”kΜ& i~Nr^}/r[ endstream endobj 38 0 obj <>stream 8;Z\s40AZ/$q1t$W`8L@VFm2_$rjPF.V:DOkF"OO!mF<&#[:AfKKSt=G-kS\@`>MT (]:');k2jBrl9L8:f;:EIi\G$W(Y[Qgf9FOgucTD.E1QB693*#8_/H&IKCd]\Sf[n e6I8oDo?PKHSG*nWCUpn)*F9ofEo7UD^TKVN4TaL`Ad_1jrH]mUu/$5T6\dpGZFB. 4rHD3'23WNGBc[DJEr70pcI\a!:Tuep endstream endobj 39 0 obj [/Indexed/DeviceRGB 255 40 0 R] endobj 40 0 obj <>stream 8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0 b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup` E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn 6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O( l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> endstream endobj 37 0 obj <>/Subtype/Form>>stream endstream endobj 41 0 obj <> endobj 28 0 obj <> endobj 29 0 obj <> endobj 31 0 obj <> endobj 30 0 obj <> endobj 48 0 obj [/View/Design] endobj 49 0 obj <>>> endobj 46 0 obj [/View/Design] endobj 47 0 obj <>>> endobj 44 0 obj [/View/Design] endobj 45 0 obj <>>> endobj 42 0 obj [/View/Design] endobj 43 0 obj <>>> endobj 35 0 obj <> endobj 36 0 obj <> endobj 34 0 obj [/ICCBased 50 0 R] endobj 50 0 obj <>stream HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 N')].uJr  wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km endstream endobj 7 0 obj <> endobj 22 0 obj <> endobj 23 0 obj <>stream %!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 17.0 %%AI8_CreatorVersion: 26.2.1 %%For: (Administrator) () %%Title: (Icon.ai) %%CreationDate: 3/14/2025 10:47 PM %%Canvassize: 16383 %%BoundingBox: 70 -391 477 -76 %%HiResBoundingBox: 70.1853025442697 -390.731834029115 476.640686035156 -76.9185647838622 %%DocumentProcessColors: Cyan Magenta Yellow %AI5_FileFormat 13.0 %AI12_BuildNumber: 197 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0 0 ([套版色]) %AI3_Cropmarks: 0 -512 512 0 %AI3_TemplateBox: 256.5 -256.5 256.5 -256.5 %AI3_TileBox: -50 -652 562 140 %AI3_DocumentPreview: None %AI5_ArtSize: 14400 14400 %AI5_RulerUnits: 6 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 4 %AI9_OpenToView: -329 139 1.03660278536935 1096 808 18 0 0 46 86 0 0 0 1 1 0 1 1 0 0 %AI5_OpenViewLayers: 6722 %%PageOrigin:-144 -556 %AI7_GridSettings: 72 8 72 8 1 0 0.800000011920929 0.800000011920929 0.800000011920929 0.899999976158142 0.899999976158142 0.899999976158142 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 24 0 obj <>stream %%BoundingBox: 70 -391 477 -76 %%HiResBoundingBox: 70.1853025442697 -390.731834029115 476.640686035156 -76.9185647838622 %AI7_Thumbnail: 128 100 8 %%BeginData: 11361 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFD57FF85AFAF %FD7CFFAF8B618B85AFA9FD7AFFFD048B858BAFFD79FFAF858B858B858B85 %FD79FF8B858B8B8B858B85FD78FF858B858B858B858B85AFFD76FFAF85AF %8B8B8BAF8B8B85AFFD75FFAF8B858B858B858B858B61AFFD5FFFAEFFAFFD %13FF8B8B858B8B8B858B8B8B858BAFFD58FFAEAE8AAE8AAE8AAE8AAEAEFF %AEFD0EFFAF858B858B858B858B858B858BA9FD56FFAEAE8AAFAEAF8AAFAE %AE8AAF8AAFAEFFAFFD0BFFAF8B8BAF8B8B8BAF8B8B8BAF8B8BA9FD52FFAF %AE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAEAEFFAEFD07FF858B85 %8B858B858B858B858B858B85FD51FFAF8AAE8AAFAEAE8AAFAEAE8AAFAEAE %8AAFAEAE8AAFAEAE8AAFAEAFAEFD04FFAF8B8B858B8B8B858B8B8B858B8B %8B85FD4FFFAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE %8AAE8AAE8AAE8AAE848B858B858B858B858B858B858B858B61AFFD4CFFAF %8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8AAF %AEAEAE8B37AF8BAF8B8B8BAF8B8B8BAFFD058BAFFD4BFF8AAE8AAE8AAE8A %AE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE840F37 %8B858B858B858B858B858B858B858B858BFD49FF8AAFAEAE8AAFAEAE8AAF %AEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAE8B0F0F37AF %FD048B858B8B8B858B8B8B858B8B8BAFFD46FFAEAE8AAE8AAE8AAE8AAE8A %AE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE840F0F0F37 %8B858B858B858B858B858B858B858B858BA9FD44FFAEAE8AAFAEAF8AAFAE %AF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAE8B0F %150F0F37AF8B8B8BAF8B8B8BAF8B8B8BAFFD048BAFFD42FFAEAE8AAE8AAE %8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE %8AAE84FD050F378B858B858B858B858B858B858B858B858B85FD41FFAF8A %AFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAE %AE8AAFAEAEAE8B0F0F0F150F0F37AF8B8B858B8B8B858B8B8B858B8B8B85 %8B85FD3FFFAF8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE %8AAE8AAE8AAE8AAE8AAE8AAE8AAE84FD070F378B858B858B858B858B858B %858B858B858B85AFFD3DFFAEAE8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8A %AFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAFAEAF0F150F150F150F0F37 %AF8BAF8B8B8BAF8B8B8BAF8B8B8BAF8B8B85AFFD3BFF8AAE8AAE8AAE8AAE %8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE %8AAE84FD090F378B858B858B858B858B858B858B858B858B61AFFD39FFAE %AE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8A %AFAEAE8AAFAEAE8AAFAE8B0F150F0F0F15FD040F37FD058B858B8B8B858B %8B8B858B8B8B85AFFD37FFAEAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8A %AE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE60FD0C0F8B858B %858B858B858B858B858B858B858B618BA9FD35FFAFAEAF8AAFAEAF8AAFAE %AF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8A %AFAE8B0F150F150F150F150F150F0F37AF8B8B8BAF8B8B8BAF8B8B8BAF8B %8B8BAF8B8BAFFD33FFAF8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE %8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE60FD0E0F8B8B8B85 %8B858B858B858B858B858B858B858B85FD32FF8AAE8AAFAEAE8AAFAEAE8A %AFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAE %AEAE8B0F0F0F150F0F0F150F0F0F150F0F378B8B8B858B8B8B858B8B8B85 %8B8B8B858B8B8B85FD30FF8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8A %AE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE60FD100F8B %858B858B858B858B858B858B858B858B858B85FD2EFFAEAFAEAF8AAFAEAF %8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8AAF %AEAF8AAFAEAFAE8B0F150F150F150F150F150F150F150F0F158B8BAF8B8B %8BAF8B8B8BAF8B8B8BAFFD048B85FD2CFFAFAE8AAE8AAE8AAE8AAE8AAE8A %AE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8A %AE8AAE60FD120F8B858B858B858B858B858B858B858B858B858B85FD2BFF %673DAEAEAFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAE %AE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAE8B0F150F0F0F150F0F0F150F0F0F %15FD040F15FD058B858B8B8B858B8B8B858B8B8B858B85FD29FF8B151B1B %8AAEAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8A %AE8AAE8AAE8AAE8AAE8AAE8AAE60FD140F8B858B858B858B858B858B858B %858B858B858B85FD28FFFD051B67AEAE8AAFAEAF8AAFAEAF8AAFAEAF8AAF %AEAF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAE8B0F150F15 %0F150F150F150F150F150F150F150F0F0FFD048BAF8B8B8BAF8B8B8BAF8B %8B8BAF8B8BA9FD26FF3DFD061B438AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE %8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE60FD160F8B8B %8B858B858B858B858B858B858B858B858BA9FD24FF61FD091B66AEAEAFAE %AE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8A %AFAEAEAE8B0F0F0F150F0F0F150F0F0F150F0F0F150F0F0F150F0F0F8B8B %8B858B8B8B858B8B8B858B8B8B858B8B8BFD23FFA9FD0B1B3C8AAEAE8AAE %8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE %8AAE60FD180F858B8B858B858B858B858B858B858B858B858BFD22FF431B %FB1B1B1BFB1B1B1BFB1B1B1B8BAEAE8AAFAEAF8AAFAEAF8AAFAEAF8AAFAE %AF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAFAE850F150F150F150F150F150F %150F150F150F150F150F150F150F8B8BAF8B8B8BAF8B8B8BAF8B8B8BAF8B %8B85FD21FF8BFD0F1B438AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE %8AAE8AAE8AAE8AAE8AAE8AAE8AAE60FD1A0F85858B858B858B858B858B85 %8B858B858B85FD20FFFD111B3D66AEAEAFAEAE8AAFAEAE8AAFAEAE8AAFAE %AE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAE850F150F0F0F150F0F0F150F0F0F %150F0F0F150F0F0F15FD050FFD058B858B8B8B858B8B8B858B8B8BA9FD1E %FF3DFD131B3CAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8A %AE8AAE8AAE8AAE60FD1C0F61858B858B858B858B858B858B858B858BFD1D %FF8B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1B8BAEAE8AAFAE %AF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAF8AAFAE850F150F150F %150F150F150F150F150F150F150F150F150F150F150F0F0FFD048BAF8B8B %8BAF8B8B8BAF8B8B85FD1CFFAFFD181B678AAE8AAE8AAE8AAE8AAE8AAE8A %AE8AAE8AAE8AAE8AAE8AAE8AAE8AAE60FD1E0F858B8B858B858B858B858B %858B858B85FD1BFF67FD191B438AAEAEAFAEAE8AAFAEAE8AAFAEAE8AAFAE %AE8AAFAEAE8AAFAEAEAE850F0F0F150F0F0F150F0F0F150F0F0F150F0F0F %150F0F0F150F0F0F150F0F0F858B8B858B8B8B858B8B8B858B8B8BFD1AFF %8BFD1C1B3CAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE %5AFD200F858B8B858B858B858B858B858B85AFFD19FF1B1B1BFB1B1B1BFB %1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1B8BAEAE8AAFAEAF %8AAFAEAF8AAFAEAF8AAFAEAF8AAFAEAFAE850F150F150F150F150F150F15 %0F150F150F150F150F150F150F150F150F150F150F858BAF8B8B8BAF8B8B %8BAF8B8B85FD18FF3DFD201B678AAE8AAE8AAE8AAE8AAE8AAE8AAE8AAE8A %AE8AAE8AAE60FD220F61858B858B858B858B858B858BA9FD16FFAFFD221B %438AAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAEAE8AAFAE850F150F0F0F150F %0F0F150F0F0F150F0F0F150F0F0F150F0F0F150F0F0F15FD050F61FD048B %858B8B8B858B8BAFFD15FFAF3DFD221B151B60AE8AAE8AAE8AAE8AAE8AAE %8AAE8AAE8AAE8AAE60FD240F61858B858B858B858B858B85AFFD14FF8B1B %1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1B %FB1B1B1BFB1B1B3DAFAEAE8AAFAEAF8AAFAEAF8AAFAEAF8AAFAE610F150F %150F150F150F150F150F150F150F150F150F150F150F150F150F150F150F %150F0F0F858B8B8BAF8B8B8BAF8B8B85FD13FFAFFD291B67AEAE8AAE8AAE %8AAE8AAE8AAE8AAE8AAE36FD260F618B8B858B858B858B858BA9FD12FF3D %FD2A1B438AAE8AAFAEAE8AAFAEAE8AAFAEAEAE610F0F0F150F0F0F150F0F %0F150F0F0F150F0F0F150F0F0F150F0F0F150F0F0F150F0F0F150F0F0F61 %8B8B858B8B8B858B8BAFFD11FF85FD2B1B151B60AE8AAE8AAE8AAE8AAE8A %AE8AAE36FD280F618B8B858B858B858B85FD11FF431B1B1BFB1B1B1BFB1B %1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1B %FB1B1B1BFB1B1B3DAFAEAF8AAFAEAF8AAFAEAFAE610F150F150F150F150F %150F150F150F150F150F150F150F150F150F150F150F150F150F150F150F %150F618BAF8B8B8BAF8B8BA9FD0FFF8BFD311B8BAEAE8AAE8AAE8AAE8AAE %36FD2A0F61858B858B858B858BA9FD0EFFFD331B678AAE8AAFAEAE8AAFAE %610F150F0F0F150F0F0F150F0F0F150F0F0F150F0F0F150F0F0F150F0F0F %150F0F0F150F0F0F150F0F0F150F618BAF8B8B858B8BAFFD0DFF61FD331B %153D60AE8AAE8AAE8AAE36FD2C0F61858B858B858B85FD0DFF671B1B1BFB %1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B %1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B3CAFAEAF8AAFAE610F15 %0F150F150F150F150F150F150F150F150F150F150F150F150F150F150F15 %0F150F150F150F150F150F150F618B8B8BAF8B8BAFFD0CFFFD391B8BAEAE %8AAE36FD2E0F618B8B858B858BFD0CFFFD3A1B67AEAEAE610F0F0F150F0F %0F150F0F0F150F0F0F150F0F0F150F0F0F150F0F0F150F0F0F150F0F0F15 %0F0F0F150F0F0F150F0F0F618B8B858B85AFFD0BFFFD3A1B153D84AEAE5B %FD2F0F5B858B858B85FD0BFF3D1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1B %FB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B %1B1BFB1B1B1BFB1B1B1BFB1B1B3CFFFF5B0F150F150F150F150F150F150F %150F150F150F150F150F150F150F150F150F150F150F150F150F150F150F %150F150F618BAF8B8BFD0BFF3DFD3C1B3DAFFFFF37FD2F0F37858B85FD0B %FF8BFD3B1B8BFD05FF370F150F0F0F150F0F0F150F0F0F150F0F0F150F0F %0F150F0F0F150F0F0F150F0F0F150F0F0F150F0F0F150F0F0F150F618BAF %FD0BFFA9FD391B3DFD07FFA93709FD2E0F3785FD0CFF8B1B1BFB1B1B1BFB %1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B %1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1B438BFD09FFA9370F150F150F15 %0F150F150F150F150F150F150F150F150F150F150F150F150F150F150F15 %0F150F150F150F150F150F61FD0DFF85FD341B3DA9FD0BFFA937FD2F0FFD %0EFFAF3DFD311B8BFD0EFFA9150F150F150F0F0F150F0F0F150F0F0F150F %0F0F150F0F0F150F0F0F150F0F0F150F0F0F150F0F0F150F0F0F150F5BFD %0FFFAF3D15FD2D1B3DAFFD10FF85FD2D0F85FD10FFAF431B1B1BFB1B1B1B %FB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B %1B1BFB1B1B1BFB61FD13FFA90F0F150F150F150F150F150F150F150F150F %150F150F150F150F150F150F150F150F150F150F150F150F150FFD12FFAF %43FD291B3DA9FD15FF85FD2A0F85FD14FF67FD271B8BFD18FF850F0F150F %0F0F150F0F0F150F0F0F150F0F0F150F0F0F150F0F0F150F0F0F150F0F0F %150F0F0F150F5BFD16FF67FD251BAFFD1AFF7FFD260F5BFD18FF8BFD051B %FB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFBFD041B61FD %1DFF850F0F150F150F150F150F150F150F150F150F150F150F150F150F15 %0F150F150F150F0F0FAFFD1AFF8BFD1F1B3D85FD1FFF5BFD210F5BFD1DFF %AFFD1D1B67FD22FF7FFD040F150F0F0F150F0F0F150F0F0F150F0F0F150F %0F0F15FD050F37A9FD1FFFAFFD1B1BAFFD24FF5BFD1C0F85FD23FF3D1B1B %FB1B1B1BFB1B1B1BFB1B1B1BFB1B1B1BFBFD041B61FD27FF5B0F0F150F15 %0F150F150F150F150F150F150F150F150F150F155BFD26FF3DFD151B85FD %29FF5BFD160F5BA9FD28FF61FD121B67FD2CFF610F0F150F0F0F150F0F0F %150F0F0F15FD040F37AFFD2BFF85FD101B8BFD2EFF5BFD100F3785FD2EFF %AF431B1B1BFB1B1B1BFBFD041B3DFD31FF85370F0F0F150F150F150F150F %0F0F85FD31FFAF67FD091B3D85FD33FFA98531FD080F375BFD36FF61673D %433D6761AFFD38FFAFA9FD0585FD3CFFAFFD64FFFF %%EndData endstream endobj 25 0 obj <>stream %AI12_CompressedDataxO&Iv޷oA}?b,[#fHFhÒݢ2 m#Q>D[3= %ݗ7#3223~wt]>~ׯ~/O ng?3_yX]%_yf^O޽{-W_[S?n\.?y_7jꉃy?pi4%vU񛟼椻Ksu4.Z =-]_jj[*T:vUͭ^cw}_^w_{.G~n-./xvO_⵽/_}} I/C7_|O^+ xTW֑C?}@v;}qvTgWu/|_rf_7Лޕ'u=NXWXW5^B^]__O޽}=ų_ԿdM?훯mUdžvŵ_;_{ǯ6}ך}?||{݈^sݭ6>?G|bo/ϯ_K;{ am(呡Z ͑Z%ی}~Sϟk{2_lPu/;ҁOmztG?k?%o5Ѣ&V~_s?x,R?Kwj~sYlv,5;6?39hٿvݨXgv`7giK?KeMrS~cfz.:i_q¡<Џ^^|s~/͟}ū\V oK~_f_}śx7_߽<54}ؒ̑o1-tnf//_7_>ftmSv߯o-} uoD-W==ȝ}Z>~=jo1#뷟u\lǕn&潗o~埽W_l<1܊|_6iO~?.ogW1 ?y՗|SGM]?}?#Dqu[l`Rbhg><ExiVHѾp5j]{ b}uFϽCI2{z=}/_x^e{Y_ez_ۋ/^<qًh/"H/b{xb [W[)_~]/fw -]O=<]s[Ͽ5N3PmN'/m=7oޭo6m<lV!f2a=s~S~ٛ罅cuLޮq×[oQ>'^;F}f_y׾`_&CyQl~4'35m k^z}o4KC(|d]K([XrMӼkloiPL7}w^KPzL.>l_l~ڟ/NR ^.g7:ضz{h@7`@yg@R[mp&~۴{0lc،(6?͔`b͢S6Æ=BXl&Olyl_8r-E[ul9-m.g=R>|{-%PZ*eZlP(m훗6#)O>ʒ.Zga՟VV:ONu6M*yMHRLɌ)=LR6-lC!|oSDe'Vvj}2 2WUsgOiE 徨}i]%e^hrn/zUÃ]ؒHðYr 䀪GO:Lj)/Uf9,\ǥ^}[| ǭTQ6(Mm}/ǵb7 iO[8鸆smw}46.kΒfʙ Ir56 2&iӘ4Fl `Fcئx&`_#)U̬jfZ/MTr jg2l4lŚ[l 7[ִlAjP0LͰ4)k2` 3hĻ /[׌eĻ 0滛I2hZW?y o=jW]ʗYbs8Wܙ37jk,mWD):{>hΟ5{;/g3љ;s0{? *3xqGQ(!3fi._L7ɞZf&iYp-͜5cs8o|3[kV,a`*DO͋p[lN\5x>;κq~,Ԯh |qK˜!ȗ]9bsb40JY,sLJybs*uA!y0>7bʒӜzz _ܝeAg*H;i&V@N y0㑃욶gZQ{`8jom>YHmfhC~Ծb%Ͷ{f0PaVI5gS3|-A;po_7ϧIm:ni;O6U]9[؎U6)/ly=7̤M7SMdPE6$ӃI{T8qڦ=yy<^4q4NưVSy]8 +SMv).RF~j!f vy$DGޕP xn@1yݳmmJK٬O{9ڸ[ûJi!rgF)?(%|W۰ƥ {lVOax53f])B^ ˁ*?f%7g.eF]M&ZMzW7l $Şv[\613>$OrZݧ0] Kv/n]?. k(7|nʘCooo?G]3ֆRlHS=f4Flcei GI&mO_iQqT;p$ah%Ck)Bt٧jkpb|r }=33#( N]Z'CgX}b/!3\pcD3Bpg_F] 6BS.m(laTCmG mۙ(6.'^6ݪgJVkH5waln;{/jU6l<ߘ3L#hc#3l lG;f7iԢY&2ww*6xyvI f]U;!}tni|26̺:ҧB؜Dgؽ9ĆΰA yޒNG[(M XvF0)ǔ0 Q<<0SE^1gQ3=Uy~Zs0)>]`οi YOiUǤyF!lf>=Cl{cd)E'Φ' 1By&z&/ d.c!jgIطLز.& |nVkį, HWf @NKXD ]sSQ\P۲ j']mҳmVtyǀ6ׁ60WgP3J`}v6Hm ̹X_,VОG $ q\ZC4 LGMsؤs[&9zvF-FtY4Ff3}$aqd^56ۆcHQwɶga$AOְ-} VN*7>ưI?آM۽أ͌.߄=*'؇OfBB[ xdIOP Ce("\j;ch*,iHr)ƶUl;5X>8W /CV8?nS{ [ k+&"HwMӰ-?۴Cn2'=;|cóly u3II'DN2NЀifa9ն>l6uY&ٲ>Ŕ-{({!|-섔!tk/RۘPLegkV&˘l0 brVo6Ziy95; stm4Sdֹm&|X0P7)p1/]lO0K=7FK䗡[ZSF>AUfFj;*z g]D\<{4}'EdmWL*{ȁb{-M^ꆚ9_]o3jmf&"wMy2ljj0L2=goUto}~~k@M`q֐ЀP3jKI6k]iM w0<@wwg;?~i7w6C=b4eVeE62?ӞܦV 1>1%]f0)TI]^f{Ծ64MWF@|-PWL,DNZmaiΠoӼlNׅIf`FLJ2*7ZsVv*5Z~w,LҀT밬i^Tfc% I{ymǷI br/wfUӨ&j y++oڤ6Z*a"*{X3iMY&MHZQ>M]/4۟v[{]㚶>Mik5qĄ4{>h4XWtt^W#MVT4 pd܎K e _V ѓlFIGAw$dll֝7|\4RN ;2Q!7@,6kQ1Sd `% K64yٕZLJ P3c#ìfDɌ/,ZHjݲ?ԆCk:1SvuF1Ԭhg-WMIU`j˩,i&?m)R$f0x~OLrf,}K=le8.^dl}Msi"`M\& j20ۋ'F[` _6شvgb[+ZمՐH0l-s+l o={M"60y7{^?"j t1 BoYR.~Yf 8n@o %ZmA5Et8n4634\1@aןXsŌoo%lezn^l!71 _Ko5a2/J#VB&]\k>GSlvʫ .6FOeTf(c&BdG[p'_7Xkհ*`ש%# Ą7!&wt'hmXRyvT yV&" &Ӷ_x3 y,rЊ;vǣ6뮏6%1x4!#LRn 6'_EXAB|q_z|!`Lk׺m%Ѐnj9* xMtͲM^vm[KKfƞ(fn̛F#ێarX͆a`Jq[M.d~FܪΈPhJ~U̴ϋU QcIsEH&;,CUd vFv|.3g @8!qhX W/wcL!I毟rڇQtF$h»R3psFSᬇG44zKe 9)[5Sxxk)9`nOZM(}aЫӸ7V=lS$-ǀMw(bGrN`(%xH4#^0] WUr'.Dl3f&mu^j"%;vHq2q#%B-EQ\?CK8c3d"`NqE쉍EbM]” # Kx330g/ lO< P*M˲"= uWQ:V]VZC>4MЫT%F}Kz(yqJzArURZ%r!* RgHx/h TUv­S_~f5\$UjQ;{!@Axe* ok+֞Y0|MT+<<̠/)N4Q3F7錚;HtC8x[cUiqtud$qޠ4:ͷ3t'p)T7b;u'r^+يcּ5d-Q!}Dah#\k,`ʊEOvPXËfɸw$|#lM oZ$̐(!HiowLx߹1iE6B51;dP/4*k}pZl(,x8e.w’;v:=)lfK6]1zIO#jaq#w;$[%RãKtm~Fà33ھVrAHm$6"dg8C8`J3(}7]EZ(>/ u3D#/O]@W! $cQtC X1[d'@ۥ\Zo 3-G>rDlM1dfӕwd,sVJa8irH7=iJ72k;䂸{0'TLB)N57JhՀM &2os;尩6Z)}x&OIwpDL+Zj-fXtvr<"ߪq׳E~ĠX/%^N@_iA)7` $IM!u/h.4_0:h*^0fXq[giJWT/DԨmA:hu;h%St܌`?tASiSl:{t@Y@pz?B~4UEǧlC94¤ȨF&΅DizP$?B> ۻ}Qy(a(nP@(Y h*Od:0"Ay$b)U#kwh-(0qph0f|gxT ϖ/_J5ɤLŤ 5^f\reQv?C^hNNu-7v@&#XTk s@\u'2k4hACw'$o4_? xVPҒBɣ#lL!~ ׋B6xo$ZzgzFЫΑgઝmfCZmT+uEngRԔbnjwŭ#lQWUiڃ.M\~x!J4nϊt$DU-hzNv@D}E"IO5Y a6CEn{;X8K_EaUAc!ZN?AIݠjWYaEQkA X ;5)ۉyӔyHāy7RHSjhuy4Ss7U"AYâEZ[_bcT͇fq]w͟Vg]lTjIƥtF6g%*{ǢzJl*$)WBu0$x}4P܆mJ@# PkkbqE2jf / iAСLiBݶ |yO||YOG%Fh7Uj T.\F͆Mł@i%R4 A{r"<%qBZW ZvMTS\v\~Z#%m6h\DU6D OktBn )YQY6lEI@g%DO;BuFPT^̺=P6-5c BXFz%Ja[PcUwqEGU0h!8AFnQ(ē_uA띻d0Ifqٶ9`UB1rQ!@X7 ,8nA2 ">;o~,Mf|Gm$\Tz67(UȎ+PA/_X&jȺoiͻߝ-*nE6MO ;5 XUK"j.ʡ3(Kߑ[I*G$,2i)j 42]4Ѵ}rK߿O~/߻g|w_DžveĄ :qS hQӌ12Cl!Bɂm݆*%Y3Qy{"QP$ d(o:{ 3CameS+L} gLͬݵIԃmo z(0Up`D==%YP1/g@Kb*vz[YFզ Ny"2Q n:)](Q G~MF›4Yޠ"=oAVd`TM яwPY>FNsFzGl⑙,wk+ɫeW썎ExnڌO#ٸǩ!>YXiKޖ0ӌLiEWj]iUj>Rx扬4(3ljI5x |.b yT|j a&LJVi0?LX<ʐmЄUPNWS!v[R%ѳu]eOjH(fk4C$q)ԢH|Uas'j|\]fX>J;mܒg4>]R&zQ,Ch8k4  "  0R*4G%*N^ Ifak s7eͱc\'hF:V ݖU&♓'hjZw/mvO'OBܩ:leO/=TRfl$R]+1!Ƶa{}vw T;GDY%b`0 5nD$ AxFzRUK⋶)o{Q+j*cmz4=VF!qђd rodS6C:;Ti05oEIme>fL*րF˘#^Lf 07RD^&0Jw`ooA09P:Q9!K5ȡcbc*:@gO79TQv z!JW PhU4sJO~/DE/'A!$+WiLb&7m# pasx,XުB5u 7^-agTQ+qd) rtʮʳzcln3\)Il7_ !F2d:兂^¤ܨdXUXI Xu)w Yh3II.BXAJ)C8٨O3Y'<1ƭ+\!#$yIPDZ\wCϿA$3 Eْ$! LgQ VBG@PMYl;Zs%J!n 띵.n:Pp^Lb3ֆo!B/4gӄ.wiPv1EY) a% cZAP4DItF͞乜#Hf%iڥS3<{MHđy|I$X!zY@Hқd'PO:C+耊T?:J"mJbKUp )&\rl+hz͚eițOw*ǧU/fW΄_j{yT)]#7C]y<9*+7~E}sfW^K G ^$2^Sj}TI{-~RJ.@Aot Iyz}CU:5t\5=A"F2G%} ըհT}Rf  y"~%zPuKAyKY&3STbRP:MepJ,~25]*j#/TVU5L>q7#O+2EG-[% KW)aXIgj4* dq}Zq9wWk*#ˉ$>YU Y@J$8TL Ȯ1kkN$WPѳ\ˀ,6M4>@C ;UY5 +(NZߐ_RYu@tb5ܒr\,fGQeQ@9쪽X%K*չ +Ĝ@?U/5ɫ.pTȎzVpd*iП2 >fwo<ȮZTu9p ) mTI_µO"2<1M wU*PGɣ];S\, а217OZhT|"pA|![֋JЪt%2SԠEj6 (`Q4 .f63 #2J2f6.*/Py}yfZdVd8eN7U1'{ rTvI}t`Ymg使FP2iۤyjfcTszm dq.3/)lp^ lR>k@5̔<,,ΏJGyDӪ] 4y|dݑs\C7?\ 69L0@E-R0#Cj}'LgN 5[=@f`4*ȡ_9٢s>&OBBV7OKi!Z2 T4ey\=mŽwW#`{ˉ1V/VUw8N?U{Rvڗ[BTeS٦Q#˪#_ɣ=72ƄSHHEBUl *,v$%|MH摴 %Ҡ*4bB_JCgYrpJ|5,3+eoulYI-\ir=7Υ4ݐХQ_14{oX]ZLނ*Nc"b}6`n]Qh*ZYnwt V!jUyuԤj^߽)WRGU;UnC4 U <\*Bpm϶S6kVt uh{SM% U!lԊtho 8j@RS?Z(()8Dُ+GIaG{ O ݉Hi=9^">z-,T!vun,>W/ЦcRz8j?VteS ТZDkMPQ>v gl]nettm YC.3h-7yaH੽jfieWzJDmPQќVKd.uwB7bG6E}E%U;pʕj@ ) Ƀ0) o)Ѷ!XhмXl>$ D{)^JD `i]!K$}DBR 9}kŋ/@)̃WeU^~*[]!Ą*I]ۂkbZeSe$B^˓S ZiClNVGT(ud7@vH[;ᡨZRfpf/rSdϬB漆z` RBDM?3M]' <@&-/?Ff*ɇ] 4/NSp>LUgRDddw{17'R?DUzc8g֨VQUZJР@Imە ܓ2sf@}D Y!O3`{Zy.s6SؠV7/eJs*6$bbP%l>">sy tbNC06/ l'3t7lpe**q4#E_W(Tc4IBjiYD6&|hRl>>ӂGEnS&lw9RM֎4o++bր셔gɽ,rz lCdp/n>.O2Mdg1}ٴ[ S1%1.lA=d(n󿉱Ak PNYvZr P,TE8I`{*1FpmbƜ b9:fqO 5B0IUToOn< =H2%ÝJ݃SC JKUF"O<^r(,z&'''"4URx1e#,>0D5߇KXkճ8R xZENZƖ+N7ig(jsܴ:o8 Lf BjuSkD3XtY絓<- Qw<- ڥ٫i#DH+CұN&$W-"\Ԗ }مX`=7PgLDgRjuMܿ"fbzՏ;L<4'TlBDF褱VHQwJʓBzb3;=I{kzOݯGV%^Y}iB{\!N$NFf[iSI/>:Qw]ЩH=qgx¥XQVBgU6]\4!PwJͫk<axR\j3f|gn1ҝ;e: " itO+J&ذ:\Bߩϫ9q\x'sݬqֲn[y.9gU ;9Lr/2s(~0Õе䝱߈Qb\a`9; &_7c)g>vC5zɺMo;Rs,vTvk{yߦx6:Fdb(h ߕdXdLuֆnyfuFZ j-l'ⵙK6H E]˙s_w" U/kX'nkS xRZ9b*nyU ifKZ[rRCG}Nw.j+58QOGTw35٥S=IAzNʉB *y;s4/shfq&~ +|Bo NHVj#; ]ϛ矟yakJyEIٻIMK^CeYC'fX7vzf߹^YS|ɘlm'a&Jޙ6 @I|'Nr\K蕛˨U*QTy^lEy\}2U<%Gdʯ 0Oh Wjy\DxߝxNP}Ѽ'$pEs"7!HY/2MI,ƬWAt'6NdErck<SN=ߓXRRirۼlܩH7 ĶZYy:ٝ8 h+0TbޠTτ}_˫$U/C"δ{:H{vh路}I 6q1.f#3oEțf5 ZMpC 3$݅Wޑk) !#-܂+R`Sı#_uoܫLpa[)j]bq*<˹gΞyC pjXnH:T)ۤ .+eA+亁(`i.Rݖ"/B\7TN)}$Ϩճ~#[N].P~R7,=%EQuR:&LRqjV%FqLWF]죥PWDdצ i`8cB]J>RL>@뼹YG >&Gz2sVotu vƶ>ˎ{>U4tHt5-]?@Kd\|k"eg;!-zg&]_j87xzO1 @@W<_×&PO2>U2P5.,2jPqI9nB ;c*]#=rvӜSWgEj{ĩCOsv.QiJZ$R]k [vUucjzL5H/OC&-gy'-1SK*+2(2jN3GmOJVA>$o[jתLDj(P`j53ȴQc'31dNTr'ZЈIT#;eቤ#gu'UB{gZ^gF1smԪ& ՝l_SkĆu"Ev H΋eESLp^l,{rfU#LeV5%fÓZKJJPzbU$ V;kTCe쬵j(3kZUSbe P70e6,X1fT ;}.ja)\5kڡf3-䝵);Jr ~&')xeU[fI3ת bvEp-s8|-'#:e|UE ՝Ö^ Ԃ9lՠ2[8z+6kUf%e¢ϖHt 9b9 2v>[WT@'-*D간lUV˯pap߿r{RIЖ\V%\)~"UӋjȓΖr긊qj`lq~<V)VF>)3qzlYPrMm7ʋQ2Vc:͖މ͖q/tGdj1-g(Πc2[Ag(I6[G$Iؒ-݃Ges55|a+ZvD%'2[1VVHlkQw8EI$-iAfBĖhH1mP S>@b BnJ|Lbn5aHJX<تUBҏIl c_:x tm&D:z%Ȝ;-w)TGZlП@g6[ f(<}6Q.cl4x-Tl Zv:[5iS\|@ &>?0d;$cH;-j#{1/ZAbةh{!eer0#N~f7>rpsZ'~ dcRA[lISGغڤ ] '6> P1M,H"$];.Sel+N͋ v<®C TI7HgiE۷ y07w"/Wɲ^'W{kIΕj('Wa+y~s:Td1,V~1+a`'>V M>V êp g՚b]e}h*"ucuVQ}GFUTZ?,{d+|Xl.r&GU &'*)Q\ v@20uc;Ҙ(98WhgO6!)12xE0|3ىOۉOi)>BM)I/.b]sR!%KԴ>oqqc4v8ӬhpfgS 5'jPS`xps}~P'{ms}* ِP3קZl^\JՃT윞 )eόSlߘ闩& ȟȹ s:'O޻1u"|[Z$uJgOŵʢ;ǧӺ|AC{UgXrZ$+=UG'h3).S.E@!\îL=Ù%0=fk!=L'jϧZSv 1V# }bTr;S3zF9*8d'¿GFO~l\.Ź\-JOgR) $%Zy:2E8oF; qϔYWTu/"EeɘhcZ 3"dlNbKI;MŢZvM')ޢpvwEE$elY̵H^vEw1djP*n3o/funNdؤ @P8.G2I-;뢰dYx&{[YA(RgEḯ+Jy;UA`?_e1`O.?b[$"fHԳGc&=bR?@O(|N7q̊Slu⥏Ϙ޳{x,V3>'#<$4ga9&OXe|{svD=xrɉ-Q&TFG%+:E/@Nl/niuFkW]'iձQ-hQdQNI6Q/MaMja2y1 (obMBE36eietfK ̶wD{'j&f":̖gHWD%k8^N\!Δ |HTd- 2I4@$j_bgD ʍoò)s#Ґ(/!+O$r.%GAIJ㕷TwD$5黐N^ǦW;ICCPN$*9(vD d ν#6]3MOɖqv ugKح@+,gDlUwD59#Ŗʙ#ئ6vDQaZ-D.'i@q7rS$ /g|rk+^(zl`86XNH]T P'nDZf~QR-LCjNa57c?3I;XzHs$AdIQ3Gj jL;G? B}E c!H d W))mu.D1>k'Dl8N y5ĝ"_)iANTt‹"Q 3G""iR$*sQ$j¿3C"` l*TraR%2MŧParaL|p"O|:Y;Ye]i7؎Ts>(ݫ]~,6jV)wGǏ$C185c*8b=Q'%=UÒlp\7<Y4 Zr <NxMSt#ſVP7EE3[pT$% Ky'D]QH("#BG OOta2#(:8Q[\|;_" nlc+^h%6iMTCUm4QjpCgDMGb q^JHl\>'8$,7{ץz8ITϥ}'BlcWDe&V#oР|AA.ELCc!Pd}fqH1o 9I\9U#Eg7N:s8O="Px0T|p2ܟFRAN 'Jn'0*{IGǘ9Ñs~&*-GAm-yM|7QuyěoofǼ˘=]q" NIs‰:Qp_zb ۪myNtQnD.HpNg<"QTʔHJ̇#Eڇ(zJQU1'}uwr<"ST%%3P6QNܞ[aZNdL%7?8aT!qERaCĩ"_bA$~"?9XT `$"+3Coi 5MHgo9 )$J;U!6pP'B28 ,>E u#`!ڮd#Ndi 1I5o.N u7Cz'(xEiɱڜ` A8oLD3? v1iE\lPw?‰78@Q0J~H޹n(щlf 8'U0v>`FY*և۩ٲH֘BG\ ;'*RٍD6T.\Բ5]fNDxK+^xI sGhLh&B''Zl.;{ȀF=F@`O;~!;YIig͐3M2;rfnxHW2Wv$pǙ%e7VⓒLtD\Y dq݋xLJ>DXO7e[ӳne5MChBn !:KYDD:-npy9D)f?+ނL_\ mn. S{=ŀqlcMTDOb|h~<6~~LhzC$G`Sg҇9;^~X'0BX*jW/?|1A!-L߼  ǹKlK鋡v͌8m!5Z-׵G#rB`-Ȣo{s 7&?Ym#xP`{ rO3£1,,ʟܳl<LJ .ӬzXdQz\f 6 3kOX`j}񱼚U$}f5 >*k=qg5'+~ŤJ_zTg~ d\39~`vqi<{-&TW>SVR+UrYM]WcGG񓺮hQ {2iM+ o+?YDtu\uPd\O?5_'9G"ɻ*[>NF-o\(޷.&!;\[&*L4,$x2};+끦ӕ^c([=Gx-]O;9l[s%$N-hJFޒ@ m?}TKoK҄x?͑>GIEimk﬐픹B"ɎN7/wW34J<̏oGpUzJa88~p6"a;ˣFeШ]7#6\Ui_ 8E z=YXRǣȬsf4rGK"p #Q;`HDo7Wlr7!6;745/>ʨ$D*ǥu5> >qG1mݜmiE>f'0c8-e;mU aGĭ|% G]C iO{o s[2wa ;)*CɭHY_(& F`6iSLj8֗#LVMiZ[1ps9yFɗװ]%TP:}諴cyن}]Z9މѮ`j$rz?FǮՂ'??|EY`]Q*>3b_gvBRm{z@HTb: K꾖0^bI'mZw7-V)M )Svo1PFf9A nة1L6lK:q> $𱏏[ZYiA#u!Ur,=ؼwS5߁ʷv Ix @EoҔX۵>x=HAG¿/^^nu NJb^= 1e^6fk.!.3UyG[/k mlTl} ـxWm*Zo9aYV\]n8l[ p[rƚ^[fOb)N~OlEtcZ|n7]bf߬Ԙ.rұѲxgkj h%+dPf+q憸õ> _ۆ~95KϾezp=$Z_#Έ5B͈=ԕfM|q9籭|xlኮdPwZfJOښ6M'o#ں_MCI '^Dp& BvMȠvl5o#P02w$lB; Øݿw_ اR(5QQ41p҆ ܡ_5»i\HLf?J6H8lwԃa]S鮩3b,+DK sU^자Cr(i`svۉt{hC?C-9lc2ZW @ 8V^*ak`wga,FaGq]xeR?C˩j8Z&bMqzMU< E:{AkѽaCt;@q'r⓰ғ|e\oJkec$h>O⭞ z>1s;F {YN `vv.߽KY_IW@NdtFD0W*u72%#2#qǽa+1=hLu|TuTZ2@+u\@ޗt8Naj]]*sBd#圵*>/1u!+?u*F'k}?'wQפ` Q(FQ"Z ˏ㱸O[D M Wc |1y_ N#F:8shX%7۽F. % 9Fd &gv"f'Cm4?́4j.,YJ4UZiÛY n[y u[V9NZ#@?8@O U-1PrWtM[!yhtMu8Vq%>P~;ۋ0mt,]嘾C:^`L V}uh(G)@P5dQBvd9r ޖ]`5CY#;*5 J7]^ܑ5KH:0º$ꌐ'˲L\?o>SѬ(CBHI[<Hwv"̺,TIXLs5<䚾muMR WZiG.\ Ia&uv"mICdJrݚ7kFŜ3Ed`͝lqv1MVD\Ó8 5r޾ wesߦg7X<˯c.:e5`/y9H kϔ՜G!;KSŽ-نyIG7VԴWɷ`p5*?Ԥ`> * G,mMm.χQeMV!q&d㫿 xÊN=$V# b. :ovXI$X2s҈`-MU#c/lSi"Yb |$H,DOWW|6G o Ivd>ꪮh܉'So3ê2jye5oVyu{| $_5AifD$u[vpWXynCV@af2C|iWk =c +4oTÊ΋s?w}+m5<5Zt<)Ϥ*Y(*bUxw WQw~pG8i7:Pz_$ cU-=jJ^8LJ LB8#ҳ;&{F@U%;ۦvvP)Go5l^-rYsdS E)>_T:6#no6GGA˲%c \*!FN)\Sjw=Zy֦8NDf&vf\#}{[KYA̡ĤoH0`ŚHm&D6R`rf@侫8{fu%Ɂ׀ ږ]PHiDPhS`)skntD^d&Ԕψaߩt,(ck?#UávQ#Q';[q} Nl"Ϫ, Wr#)Ms!k)WwGPdcr~`0]^I=s0|d#$:"L0ݎj4oѝj%L ^Z= l!҄7ۊH*}}.BC#;l͚PI>"KfFC福{No k3# |ր_.DZw5_QЕz7Gvg{>-,ك`{u_[J{z<g\6Vkt *gkQq h-çbn|Ќ̹Xw tMu7a˻[u=Ta@x]A_ã]|m7$Ql+Fݴ-;kgؕa bo4pl`NtD^~vlz O鐬O< 5u=ݖj0y?tM9f|lbjK$"Gy&)5|HE(JG^ Zq ujɆyJ,klġ>wTeˡkFxgֲSB/9c!WDӟCck #F@gg3wM׋ {\Ι[ԝiY]+nn|y^ Y< itM'd5rk;9X2WAIN̙+[_>rNi(ӣr3蟁dpAυ)Fu5K8_3P( #4׀gHT7WBdܘsRXM#hit5~CGT}q끭23Q.d"hWnwflqxYov?gFC.7.l> ՛펰b`<(fp[ʮ4+9SpOXY` 45bzJ$EF^saULiA{˜mK8c l=TnIcrQv$J;[ λgX]j@2B۞fz-N}<׾2a\9?LNR̝bMv|8`-;^ 5/#ӆKѠ[VlvMl¬IPivES]Z-y$qckvѝ/uZ fzA|dѫV1ZvWFeAc}la^ְu]=i S_ur=̢s߼anU[.6$။a! \NVy-uX WtUz4]$XM `wdbX3$7uOT@9{GfeHY.oUwBD112B9@ NJl^aaW[ZN6{T|ia*T"OSEE+rP+`JzLLLJ@~G܆àPWdF]g P^sDOBw j:KxmoOOWjyd<~C;~AM ]/TbN;_լ:mE:"ӣqEYܨn zo"4 U:Alxޗ e@(g`4`8i zA}6T:LVw\s='gx/D!4gk3.Iy@W\BPrJ2&L1:-w"LkN{r [Ӗb!`! DpHaUrF྿H7{͎f+: lDD$KꔻdnEHqޅ?wEH = u/+Of|,eՑ X߭4DDۧygcophEɷUn8 qL收 vOHan Ȋ9Dbg E#%;KMW>28moFWT^u6ER[0`%Ayk< X.lmiߍ2#hLv҃0nלsu_ηQ@8dFg !Ak\K1G\ZH* eV,DUksd@TNAA,635P3bˈk*J{!5qXo[)nU /\A+་D]i*v { [ dx\FvY0 k^kFa}Pf[aP2&wt(fg1Z P kP[; >$yqxv> ۪Rb.+w33 ɬAzesP5x-ѪC>Lޗ#QOI0~.h͵ѦFzT׉<)_3[t(2 SF.;:Cs&eߏZ $<`+HrMMhatxZm@Qr{DF }Ӕ=r.J^0Lϟ#jEyy}Gwu"tj`J&m#byZ 򃅿ϼi25HF1 5'sc˻lVFK\"f&=Rֈ!!EΫmK){ =x*RF)q};[tU`ޚc?ݑq'+z_a4,(|ٔ[xޤ ^)r$wd1}+;7*$G44[#[]MFJOH :0_}qHdv(SM!\{ 1@ت}"]8) q(Z1`to@}-ay%ZGgIy4߈rQ>*Ziz+!hogWٝ,*k;j .#ŷNJET_)mMOUg0cԅ 8dWLid׶LgdN6$T"xQ+tLCʫZtvz}w96HYF1(`\ /Կ'եSզ[G:LxۦJq-j~k=I2C(D^/`H!pW?F4A]5l|j2){ދª[]E+F5w8 Gu+ȞN!.Azm`UIу;]GU%OG5aI q9R&feddlu )C(I[F^JlTgхifIq <(F Gۜ DJM ̺C tLIscE9"OtmMvinղTCPF߶hqB<2R2z=eAgr5 pz(9ޮ:_弈 vHY_jBAkd[L#OCmaWSs6֕}j{3蒑c!šY?>%EFifTN'BV {4@G#d1{^ܯHL, yݻN9 a,a_3d@]#$Q^ͷ-Gܒ;r0^RS6BggEk+GY5.GD<F^]{ C\Vj <]hǶQY2W:z#]z}jw|ח#lR{9vSPcazó' w @#a 񎘋+*U)bpM\`J?kDaGq֎.I{'"߻2y>ϹWS`uNUb)P6n.A"J 0u~_ށQّ8)x M51C[HZCt/2`:]p*WgUϽ8B2ŷxI X]-5t |e;(jnevQ %y]'*[ Rց,'>$n k o)wFlKH)Ϥ7>6@υ3qoƻHg;֭?bG'OshR[P l +Nr]<#c"֚ /)?940̣ja|+ĜTu]]x2.f3j¥P<}}jwMr# _=iɊ _i -AF~=z(>[rTm|iiG6Kܵ1Lеi"(ޖ>"F鄞 漫p";ennHC\#""IIJE{ѹ#/S*'"I**ԙ>y[I({ mYB [R0޾Sg1Z AgkkC `[hQ{qTr Wp3I4E!1`d?OplySWiӅn}@ C6c+̵ܴU oM#2Smk{#'j  L8ф?ld9TkQqo)JC]U\ Tmpis1PYyKBq ]q2y*Jج*;]i (PѥN֟C4gԖ8 v#ws.r>|J%}5-&=7,Bz\>Wپ$*ۻ&Pfԃm8C'FMʊHѿopVI]fl9ߌ(( }s{޿i!ق!7D'dnȘ57 PQ'3tTih ArÚ_ȊW;>Wr6azL&,'hL#*`HjQ].@UrX3ufG$#RNYr(('+k2\sjw0#eywiTLf As8H`WzuTWOe}C:鄣o@~wg_f{rtu`"W5k `-;RZ{3/VPVLY%-eo~ɸ*,(V *azmӧdxbrF+E vÒkc3 jᕁb!C@9GDfYGCB$;ʲtc QnGRI+PGZx3lWԂrT rJe:(mm(U$ ÷_I@2QZ1,$P֩e"9Sh):|<u~CcqnqSؽAY|ct?=FP"E0|A!KĩefXnRLq"4ؖS)FB*`VQTYic5GDi~V׈wO%)6##xr1GXA+\aSGngbK $aUoJ;@&ㅲct:}+vUD-VVjLVܫ+O@3[} %^(Z(|/4_UE)Ͽ1M=qir?ƽm+,o=C06-A[1mk |pK T!yjKc(< R`,pzG~O8jammx Ty$U;S_/p-}w$t 6 P̫}~z)uhʒ#_.0#St[) *`HGbWTcҍϣ$ "8xCwԚEX#i($*(B4J>˺:@g:FQ@tWuBl1A9ZX.7n3)#FkcE寒/'AvZiJ~FLc/AT;*260)?f `tVq+GS'ڂqFrR&3P NW`sjZώeeuNTX3XˈSos!C# ew #*PHH/M`F k0eT zt\sǫBwSUEyyIW(Fm+d7b)"yHwI2M n62yj.uZaͲzvR-f7p3 z1ٛkO-8q }~ZiX.C %-5_`11IT Jd;QS+ރ7~D~-5 mn6$B/V uaxQjdwyy/xzY`˺}ڴ[ ]׈cqIv3)*oW % V4gzV7W.*j/:p%B5Z߯;땍c;)挾gYeĕ"cR m. VT_^Ri{(:`6`IŽ@ 5o]+[`ge#1'5-A015W&=SY*̬ɻӄ(7F Dnjb!(O6 G^ݳ#Sx OκQ ~@MmpV m؟+;`ey^ij#n׳񣓩ʒ5[uuc(5&BCcϩԁ{+!>6Y''w":hӄlزNzhsQ.C)G\ӇTc`.gKx=%}S4Gh GE{I>3G~:@w ~j0`TAU+r4.U;X> "ݚ\g6סgcU߷L~ FJgTw;1VvkIo)(u^`~A%] z>7[VJ<̊?;r/ GIyNF{&0ց%+13RXIJ1z/!VـIed8)9Vڅ]GC^2APh@ݤlQ*J KA5~̀vt-<dDY(BCJur)?.l3`0QA(ܩ #V@h`D[ xl;mQHkAb1#/O!Eڽ!WyvByrcZ- fN+3&=&.j&8̥OBuM!qX=%zh=`ީ nntQ91f1H?ZOd5d]$gJPk聎]&k3 /ɏ<cHEx:22`/]Yւ/C!N N-5 S\3z~K bBVjͧ& MRTJޱJO{>4 s"˦?l{RoCeAVsև}+v%κj$ 7\`CO"?;ÚD`|IVi&f&~gWP!\ VYF|ކQLOX#(b(FWǰV˄g] ǃay3īQE^L&aΤ:)E ߑ'3d7*':n٩18[.*%m Fԟv%̛v{lNU :?;r,i׳EI61y3Yx_CbC]sJB?}DWGhRQ=$d 8fDnubUd2{z8Q^jU/8^~_tJoЎq,Fd ۝!1Ənq0 B3\e"%97pGĿq6e@ʀsChe; Yr$=@|()U\ǙA$t+uhZzM P%R6ˢNS V %'a*Sy#M`Y= ]NχW&z^V,NyMwE q0OP30,eBm;^!lrq`bYhqꆬ%2WXȐ92TǸM.u=pc<6,[^=\> #@H+9{r{%c `qX/W@/FhŤꁱbԋ-âr !Eȏ fsz%Zȧ;hGMˑUPG.?iئbR.@\_OXx$~k;;V틐^RHh3Gc"Иَj`ey=OkE%~|]n%QIWbkyM-d-S[Ҏ Y>L1.hnly!(jM86Y ZQulEHHPl|UJ#`L͔+(=C49A[{i"z՝_o?wO/jW?O??/_o_l s K~UW溾kZ9$waűfN`+F xU@%v,lg@5#VN)˴=ҦH7}4"3S?VVv"O{"~{=N$__Q5%&A-H{ƿsUxn(rCԊXݪӍ\k.HwZ!p$zU&;crP gZV) қU(Me\~o/$UzKY%rؠof7Rޫ%av@D}bu޺9 ǮH\󮭟 =IH5)4a5e8:߀+߻܇VN痍GhnmP8L׳mXx-Lߝ o(NC-$YFqn/n$jǃ[L,ROSrR9?,ٍ#rXA { Z|F!_$nb#Ê5c#u3E<JXc7 4 JHՒ}W 7!hHͩ=ņq2ƃ\"!/r7wi!k؞^={ FZI~ [ِN OTˢصѼZ3YHgTbM|~FԼI=\s.m=bia8֔ [v@.ԿĔ݋>ß\%8I7~fP&ߊspN;?xi\Zq" R6&XNZn9 _?~]0r|?{C_Ir֚L@H(q]Win.bkCG"$ x̳tזvk3~yl32j;ɇ&nJz9{աnJЮs=}mG#Ɖj|jCӷSp>)TS\MYyĎ3t)tDz{Jj+i+#D,NA49Rֈ G"qJhcI_K XՋ^hcժPBK _ \=Sw#F"`Y>i t޴[R@ F}#q.[ ^l$r8̉#BmS=څkČ,m{bN@}w*u%暻^KI; "7ؚV i?O$ ئ+>٣%MgKluΞjy 95ȾܜS=K*>Aϳ VmT5-Y.NCS+u 0,ݮ][e롷ljl ?1&Hu5EBsYuFs0+4_@Ekg}! YŬ+`XX\Q5ZoDMSl WKV< ˆ3ڈݶvNJFZ/J^zۓ;JD 2@t>E (/V* v{Y6íQH|j*dLp+]yЬ)׃7"IuxK~ OԘUƅ_fbYh8G鿗#x.3鑥$x "$[̶2lj>CGQN%[adP:ªwh8pFZ^CkCN kon7}Jw SbkC' 8Ny(Ӓ-FtF4k87"K>ӣՏtYWqzQeG);-{Tz F'Gac٭$yυ٠D"52 !-k/ ?*-e7{OXn|,$Oݤ6%l m=nzG?L9d>uVjݷCT{@ZHg0;k/tM c?J?ـVK7b\z(*":%^W*-ky(liH/yBlW0УXĕ=*\Bqte3u qx`j}Ak tMnӼ(! E%)+W* N]lHuB@\UWEmͺ箈ܞ|+X,ZMN9oOŖP}TҰ> j(sk8El" ^f+Fe"Ueqϟ_U3/Ik]؆)sӁO G6ǣ<65&bL}BV.~ܐXsF c7v/CVg45bCu Et||]9.5XMJϤ)M[4t oA ϸIz3Vhmqo8S ~Ĕ/%VSyzI5wiUP% kZ8.lBW.0Z1hL(gdLF8$PusE; ^ [{z ]0Y3Dt!& M%xi93m0Y @jG R 41M*z7i'u/%zUzE] Xixt߫HshW~M| |;rG~G?}͎#PrP8/wZZŹ|˳-ĕܴUI<[X4wdlj`R$TØ?6o7F^)BfA(W,{h?Uec"33xĽnࠦTC)GKޟv(w/%^+'TJgϟ<¶K7$=mewLC%fϔL6qEL'l@X'sL?oI <5/Uo-h{qIGL^JlcXBxM65c$-?gy&}а`.)E\giʢUqg2}Y yqks#IS\#?T9?rȚ6X{1%nd=[7@B_D%ePpYXcݻ쒺z(UD@~rvƾWЗ }Rn=z6:0긮\M.[[w<)մ/M_| ,1sMȇq'5tPQٸbBu\#GXB Ds͕a{0ۡ$^ .g-qsugв %-䥐B6Z؄QR:Osӭk՚"9zL,` [S1~8ˬ~Jy$|1fv.Kj|#/ƤṃWWΥ]Bj!huF48^$2$"V<2gnbLUjuF[ H+g}a|QR\VGvֽLɰM5놞*kw t<6 IkxFʼn/J40:;\'rz=  Rֈy,]lJ9HG2Hz>Qܲ ݊u_PH])vd#qՃ<棃3j5QF 4ATJ= DVW:6݊6iz<± "U0ny/,m;KCCw`*tB,f7)e-aHfE*8|I50DCeAj{V7 u˵NRWxm?TL4 bC)#PZ(1X$Q;\TOE;Z;ԻQlܷQUSJ2ϋv7rhctF/ /݃!> NO# Z\2-G]n߿;7aޚlDCng@G ApVjtTZbӺ*.7>Kd1Ԧ]va/2 :@!; |@z!.XSjR/[A47߮&mjHh- vT%!e /xcd ho9)s ť:,g+FC<:(Ux/!Hd/tPiQOFs=$va}JJYUEyk,@ղ0%@S1v7lG~c UP/;nNG?l#"ō<]UA5qψF|8䖔"a'%cY\1r|_xp?-8ihy0{$ȷHBVf~ +\uZ8C4ii/=u ;qMQƺx~ /=t.B<4_CEM;vd~E|>4Q8ZCڬS1/7dP.Vz+>Bl@s;.g_o=K@Spڦw *iNkϩ:aDzTlc Ap(^-aѸfDYhd@D{=tKXe14֝vԎxVB[s)=G|=Sl,{ 49T,7~/S%9vdN]M-lh]G&b-/FOxONYf>bPݶ sԝ^Ax $@lj,58Kc/3 <u]# EM.z;`ChN+OF-||hm3 ٍLΒQ"zyڗ!&IMus ĉ^xq_VQ6?aIimqdn͈R "TtyBN__W:*wUDlՄh rt& dVt4tӎL9lRim5wKxlE"~>j ]dQ-Fx--py߫vVwm雔fy);wͼ(n4JL3t>Y@-lxNXllλ4 Eu1AiiihKTor=ӊn*gM=~ԯn }+]+, 2?SEPP0D󎏟AP۠Eq\!q0r8 ; R}WtN`@M$9NfEKǁLECLoD J. z"a! "Ei}3e eմo#0/3kB FD< E_a 0YwEjŹ9U5zzN(TgYŀHؠ`Clrzr э_7VH\*,$J [$$Rq q?mlJ~ۊPX #rw)AQ3xXغUS96H>bڜ!l=\PvRdBӟEgC =J>%a\o71/ B!UV5)Q熤t߷Ky M5ЋL=*[?OKw~-if3P& yLS iه^+ԲyYIMR"3* ##oH3H;eٰI) !~|ԍ}$IwvPKNgÑ /j^݄*䕬,qXM:6yZlR1WnU? Y ~EauM _R,}s}͗oml֩u[5Smd:<}Q~sM[A/1v^!Yq@* 0Eޘ!rhW/:sz:)#Ϋ`ԂVHQ.O,zK%iKކ@""PoޥP~%Bdy!S\43hQ=q ;z_<=+YW"MZvsr \O<tʓy-7X(govr_k3 Arƕ/N|) cAqco:cA65sDi*qdԎhB&P7?ޤ."EFmHP*px/|[] $Cb(n ?ZΞWBBuWFbOBb0(g#d=Ϙ;L8, Ž~e!8SP$)r`6G|ħ3 -mRT'  wtZVZͬ"OrJ:% !MxΏ?́{{Mz!(wW(W( 5+5XeJօ,b>O5A$k5?î .LWʾmHo Ìt+J/wG?ilf/w(G*˓kD7fGR0-k*Eֈ:g),->la(gv/fZGuu0PoTò b] ,@ۏL6ESYx8ͯJtuOL Y\(p nkp=Owzɤ}Fݺۻ^3z-ږ+Lx+[M<-j jnEs+bYCRB[}ƀ#C9"WEuIBTIaq o'hh5wltŎ!5Th0{I뾋=)Dq!ńD btm 6:p$nOZu^jZ1Ւr4!,q5q$y miŇ֫ yfB9c@%T҂*PȄqS'r uGqHV'#2J%g#VѰ9eLuo=R6޶fZ2zrg9ij %;2z|.t-~IQ׿7q]([Uc©XF|OHac]=~{L2.uLJc yݱydТwC=kNbr `gmxAYN[K>BΌfQ44PI@ZQI螁{`٬qL.7PpP|2@ *3t0{ G<+:J[4kFbTz[{|^e!Z֧I zzw];[kg6[ ?O,Wrn,8=mCOCv=.|:UNR8@ =؝x2ZxrrFu%\u<FҞTlt5 c"Ef~Vk".iW=TFWA9"Y"}粺# pN\ؠAfYU[f[,z5TVWL/5u y%XS(ADsDFuFnʯJ""{[IQ K{Y}lxΊr(A;"ţy =5;wLPkRrL"RI`?㯖0h5RtׇQ# jVbvr wK>b56Gab3D")v +K՜Īqvbp~c /, JoIQץ !|LAkN~H/x1Op JAꚪ'нDYk8 O>GL|W]Qc tlGo†, q6d Q)T?x<чA וa(Ekk-.ȖZS7t% B 4lTfx[-2f< =#]yaDe ϑZSIsK1xӶfl#j ;/Goˊ?0De" c(jɻk{)$gry3Vpz'LQ HK= 0͐--oZZޏStfjHo(|![/fD- {܊Rad|/!S@] `/}~==wWRxRh\6C=F^֏أDt͑q\ޣ+~4#?EN1-#K󀄢'A=#RI$WyΦZa#ƭ>0PVw奌^KWdš)[{ |ģk y+ݽXBB{B1QRܨBDGq0vo_u̝^^C$ڪΈM:+g;ۗ#4QK ׀ T6K%iwDD5`6LpC2z0hz\z"/S$_#jB=l*O{?i3!er yE7nk%@:*rݿ1A5pI21) @ BW^9JO]{MК4:ݰe)uݢOBЛsy6 _5jo;o"C 7.+.-?ѧR\(Xf!_{ڨY^=ReN"ü3[9i)mEgUӇEjݪ+D lmim+j *]gY&y ҝd }/9xf37EIi0g.¨ MxoII+\Ԛ8%; i:>:9v y8!I;(RM@ur@=À˖]tANq߼TYo#>0IC.7zHCVl  +VDL^d(N>J(.+TS\,g )G!JRKqܠ$E'LQZ&#^;E3[D9MW%> CCH&qeK{א 4,6v's, @F/!l#P̓_<dhێT /6rd<q]B6zt/Qk%r= ȃF&1\ _ D|A7(F1K "P]\ /ZtU8viT(pbpA#ΧoDФ>Au@ ]\h(|mIHA/9وq/)q4$œǡ.^Z.r3X8>zǑ8˒ Ԙ ^EE),dg_-sQ%kBuH盇+QY\҄ n9ɓc=02ZzH,n+%1J0RfPR\3Olҁdu2oP,+8IHZYV-݀漄8H A/8F<*\d-Pky)991- )BL$ 8z5&p+InlE/~1oΓ#WhJb/4#j ; f!A| h^4'&1 $c/WpEq.̚ U*}^pz*v#F*EzP,ΐ̰ena&?֝5;hHv+$H::p΍]|Р^DiLy4/fb/ Gѕ3E4WCTs K/zQ3'>\ލuLβu !M\U J zgਜVHX =8qȕjs^N-I:`zD| GކjbྻyK_ફS`1*#3!f*w B2؜i%~R n, L!N 6V^j/}!Pd 0~$+([CHxk*^AMC 8 zO5Hb7H?D"\R{Ϥ2<ؒ fMׄ2$ۉ* 3C":2>ev ,b$ [ xަQn(@vNQ'>Lio7p4à ]s0 G4ICj8uDT`xjc^^iL<}F7"lhѤ֘Hqc mUZ7Ca$2|q\k8#ʨ[^eӊ֢E$jt06C9RVsbˣ#[vp(P 0^=vC&r/3I {Dˠ1\rAJ. ܻQqQj2*418T0gqF7&{aEn ?|\up쵲mҀ_JA*2"CEؑvlpv3X LBr#!EE槹 ( pxb|r4ӷ *Ũ Q{8& vtBU %R l4BPUM±0"%5Q*eF4*6ދ_ⷈi21Rl$!5v5ȇ<.z?]~aST,IJCnlFX@P_Eѳf5LÁME+$.GcQXE~ bA}z l{.^,Emj%!ݴ8PZDHEߋ9H)P)ꎨx=)r:Pp͢`Jl9}O Ȳ>M7D!(Ӑrc`;VrEBO/Y W١T qϊvp z_yc5{h=@Pb&RyX{MRaɢ "ŠZb h(NcN9q۳EQ癘, 6l!<\H~.r?q]H˸Ģ 4T01WgMFKf45B!ͦM5_QDUgHMg5ڥ[wΎgo/.O}ѽN='sm7ޜ}+뎏~rq^ qv$;yZ[?8_엗g_3_o>}`Lwzrtm#}6^,1 ;wvp? 杣{^L~p DesIaW g8{o>dNiAC{ @A؛|%~~:7Hjɐ+ `,,@$$ؗ<5>Qv;Iyʖ?-ÀLPGIJ+*,`4 [CQ1X68VQIG@7شן\)65TV@kYgmq+`ѾxQ۵+Dř@_%'DO+278F8$@\9qNJ8xxQؖ%(V]OJ D+Ю0$YfBX{dX(,;ԮVp,Jf.,bO+n\r@6 YVqҾ|v G2;ET9 "z@ZFGq=]{aLvij{ǖS۝:"lLTO½7x:<+lոӃiy<|W ؖ}!c_e zם}"O 0K~hjϐ 8\%~'bxR\G3 W`wB 4~?q$ %V{>M5y%eHT;"r` \܂+bf92I7˞*0;1T6""iHUF'WNm:wIX.J ѱ[aцpTd-Kvt@mR5@(!a:AB](Y $$uӹ/ڞtI9M#|ahc?.d'.:Gl&( E%aX-tUh5!# O'eg4pa#^WG'ZͥL8@DƉ.6d Z #r#F:sY ;7{#—lz銍#9d"6t{SDN'DM'FKƙREK*чsSŦP  GK m$&"(ADLfT,76nSrV.`zu[( ~_Џ!wK>,^;%SډpMrvEM^1ai @b4"v'>Aq^ׁi.?Ylpwu`r&0^Wr2*~"нB*>ڂvFMDɹv=] |Aåӵ:paSںR[g -EUgKa Y}ePY*7KS؝>eQKdIC "ҁ9N٥.8zLu UeBIvWZz2ro3bI5uxbߡhD`]M< wVUaf^q^(IA!ܸ>l?3U|w\^T`v!dx!.[vYQW~:``)qB2؝E0Wc jV*Er'Shp* z5BLBUk)̟^Ef'˖! +N M/ϷYWF@6h0Llh;(w }'v2Nةe';1˦)7? Nara<2{mwlj F] ppse^NJ|_Bhb䅑|Q%+V7X6A ¡`e'eݵj$ -g+'0[ E tnA줦>_Gy}?IBΦ) 0.3npIWb'#uԡn5)ٌ}kFua$U3LTDX[>]&#gꨶBiI]yq͸>K]\˵uH]DP?[ M2Aj=i$3/vEq1 :+NN`6+]G;mߙ}34yk o7;Bxۗ~zБ%#HTjn QJ"{;I*kg{֞TvKu-MoE-kDɵHr7ICGw =\D]FQkaE~ZUt[A&0/B6&ɠVP<ڃ&Fx8hg:$jPK=aq$T!6bQ+|éa쪔S=!w"lAB @'VE W!(VZp K0J =bUȣC2lWm0lQpij9{V`km2̺`?p'2si&VqtbVI):BT$D lUp K/H%ZBD@j|U]B(^‘ę7'0{D䤑!q,'A R G/z+ub9.Q\ƙP'MYJNX&N&Ha*lK5/{;rl`@Hs@bC2n^4Jt ]HI 3n?msjm##T{26` מh beI--q ^polp LBבiU(`x-3#M\4Н@iy>$#;Θfف"9 )\1`So;.qAǚIkSض& `eiTtkd \7N N,L9\k'|dcC zpITgU-\gWʏb E:JѦGP[ }DY܂p;Rmm8jR:iohܔ endstream endobj 26 0 obj <>stream \o7'_U[UQœ XlwMaʍSj|F7j v̽2:°ct!I ;̓RG$6_bTU\~]F'Sdy?Ƈl[F(3b`MPS^,jiv4J k-m2@,ll^k5gsWY*oį:_Q8)d&SuPT]8@S7UD{٥^(77x/ui qafU%B0YEV#wQ/$T9'k藔;#EAn~r q$ /Ylv { T,Wc3e1"5$38>}R1ps]o°T+޶23b>klüc.L&m\bvaldsCgز4 >8e!dDE@`Y{r~$%!N~_K  =XvZb0at ԰ jVT`u&%qo u9q*<Ľa0 ?,Lwz(WT]Ӕr̺gK2e2; :XZ@Ͱz(=z Xiw.b潿B#UϞ 9eգpd^#FjTk=֧@v:rZ{̴A5DW~jHnNcWXwAd- ׭=\c 6*s} Ebde!wf ùub#gb'[F۝TdA6֝=5 VbN]W1Pf@`D~yD5SaҀIY!ț&B5"D*dEr_]0}WXK{g&=I4rlB%Ɯl΂{F sdOltìq t .;A>DŽt2y=^C#z\*xs #C,7@YMk=eQ$Y4 /#IuxSkZ* EP (8ABI<\c DjW!oB" 4:5IT`GW><7'LxkM=: b+t*Y 뎍TC}5?GKҳOj5ȿD-UIYbA$tW!1`*&ڮpp1;z"'.IٵR(~ĢT(6ejIM0g$@n\%6sQ.K>e?/FЁ>3F>B҈Vj[ycH1YIM,K0ElaGb:#usd#@G}u J6@miX>$;Z,T!~<5ZSL#>I{O;-ɰ uLG}sٓZg,;ktD#X"ĵ>{K_4{E9[D%v }˝zSQe=&OʮG%f2m}GrLi*IP૭U۝:{~|ߏQVPa,ɨT}:&΃ ҵ$]qO&Xwp4ZS(@k nu`/-m`@,w&w]pc8Ǩo4}p 'fF"lgIP",&+M`ˢ`\ Wt[ă!oҬ$>-u~1>vË#(oۊ`X' ҢDsdViě ѲѮSh1q\'wmMeS^0]&u>GKODChe4EM T?99e |4 8"y;nzTXL\Ơ:fa67yIc1D~rP8mËĊhQ)AO=r ac(އM^UL:">MsziZ2$V=Dz:[S"r;F5-Eݶ+6@4&IHXŏ^{tH))@8$T˂``ٲ$a" TD~hQ\|bڥɵhV6LG[:^!<g-:}8LJ)sUetsnWPxϷcrji&t͌hEeg CSww@1WeKR_'[m/Dnd8w⓷ Bq1xyG^R Tw;60t)5z<cØS$L*>씃a~Cbh魐GVE7g\`2UbMM*[AByX B(o6,ad̅#;L2:z#\%JGN=L2Q$fW2P'oS&TJ 5% jsd B@gby5°fc1͝f,vG4:jSj(LЀ>&jgW>>[~U$=_jH|ϭƎ#BMGRd'R)L̪GB]#2 l{5>GxsWfY^e"΢(3S$?zTkQi\GKB  "(B<0jxȪi;賃D.XZcQ]Jg-j8 7͒ݭ㹳TW9EJq,ĦEex R;ꯛ4h 7sJb9zGQIan$Osҥ4-lΚF2;.G MA\ݱQ|1xѢgeI;˲NC :gQ,Η.H{GL;7~JZ%NWh쁠kOPszέF!g?QB<\|8yzQhy>^T%Hpq=p ־析aZ8-&N8Н9,69V`v\:@grW*1 B>|㍍ew_Qnf9JRn9J ] X̞S^+ZB[ckn2-K>y֯:Ů>bΪ0 wSٺuWلwcA|I$|Ϭ(ޛlݦ{`ZTgQqz<$2 PWvꥮRNJja+zr ѿp3rk;E4s\G|d'zHrʲ2]:o{: wl3e&ZoMEh#TŸcD*-KC?(iaZa唈{&4I'I̡YTP{`,S19YiR3 =QCN2%Ƀe% 3U` &:"D&ٰ4 f7^ s'ta.D m$W4j+[VrgPSf_-s,NмsI:v<P&{=iWJz :wՐMX!%Sb<,u"IJAW"z’8?T+Ȳ6iLנYx`|B~Gj+Zg𔌹eM Z ; D_`zH~tDKR@ʃ}HI KWBȊ"$X:hbSHl%Cdi5.: Yܱ)x;m ,K"_mSPd"s~i> A@NCը+D:d\I&ZpF# yصbOk#˅-*bÝ׫ 4;=S6is!έ&6.~Ylo=)9sٙkvehtMcu N4VlyyOU|>X"oCjO>WuٜJևM&\=VNwpL@BRƉ Mp[{FGqV\21 騋DK)a0R$1'EbSok4HVOR3XgHjY)Tהyy#q߫ˀ2FfaZDJ+~#*^t/bMݫ:<mݑPz$3 >aj49YmX%Hj'Dg!l ^&:>Iֱ,,h9F,to1ƎcaitjV]\yhnh9mrUJr57{\oaJ٬ 7r9 @cԺp:pwu5X,Ma)=4 c?1xHf_<$)ruY3!^n0je2/Ma cky2F$K w51ѲB0￞V zu,JR{4v2ZAzX+g]L_}q+jq]`+`%Ìoʪlss^#&3x }g<1/@6{G7^w?zB~zt:G'g ׇ ?>C|tW g37ޛ~@, CȨNC+s7{AyEș&{+~&^xCt |ĺa%[q$[I nx-Z?сP|(dF%Q/E-C6~kq벲n: ,~W9l:OJDE=uI;L:VC^xKrWFIu&Pϗ-yqɗoƕ{9!X֍"|ys5Ձ# geO-7.=aBLZޖ)ٛfB92NH,l$64 F^&LWŸ W}7K4;NJ%LS}oV.ZPB`AD-].Z~cvw(ś7PV{WG}!~9{GGtOOOBӛo/>?|y>>#}k|Sy❣>>yb'&q}/^̿7'$`o.oO>ɭҹ,.G=? }>ߴ"uu.eq2f):w~&.p"7'qU/YܸOwN=:x1d95.bq;N emڪ><{|~pGk-߯\ ht>ÃgOltݞ["R}vt VWK7Xaqi'L7W_߻:@ ?./ѧ6NZF"'~Of*/ V9e:ꦟV;j[t3pnӳvN7^;]Gj7F"tdU}m f*rO?z>3]"?8-Z>q%˚woFp+fqчM[磇Gka츐%߼St:D#b|g~M[Z+X\?q oasEӿE_Xnɤst|ik>?<9-j]S_ѣӻϏ-s}|i'VֲOױRwܨ}|_#TUƭU7g[V(i8nǍZg}ow-"5G}'GgLJ:?ӫ<[t[N/gr+iFNu,U,I3ytxs:xx-OH,I\_j}#~%k\GkzY l..gIn{iwc]ZʒfLj:[iU[m7ǰ><m]=;èmw~ <յn$gh L㚝ѶdK2mKF|)םy&eoKH^i3kY֞y9K;fԝYnLݙ㣋Ҷn(V6Z^x͙-O~%x וo_/Zpא:nOց{ƌ}sqw[n[րpWgܶFӄF6Sxx? qm[׹]Wmq=NZъI%If7Vl|ó/qt?k ڳqNZoM+onܚ=߬0W&  BNhA)`&盇Ѳ%ꚶ.onOWፊ?ͱ۸ӛ@@1.Ћm|Kqqm6\/^zՏat`K݀)gG7hCojZZٰ??/N AwZ+\P[].[$xDn6hax{۰xީC36-`ldZ2ntl 0W>jÌ[1l[^zy3Eŭzyz˵VU/7k[UW:zU/zxɜvE1G6<6`s9a5ެ{fܘ"&B6T=q^I,6ԶpMm=>;{n7y ƺݽopnTqOZk&Gag=؊UkMS맭qуg>i_ӱpcJW""\(HgUp$G&_ג]:6K+QOXF.r-q[E[f@6T\Zko1k9žu뭠[9sm Y 2دzng&m&|^,հo3n-!V~e`U_ΒaλU:mUMXV^{˓_ Tqxu*n_~ gFϘonpܨ6x:<D9}|O7Z2oO>ɭV3YR?tÿg2cwu KY\ Y |pgGk7@~ZtCR3ۧ=ꍿm'O{ޥ<:詮?q謹:d:7\x*-\m&Ź7s"܌wng_,c_ܺyyc8}Ac2(QUwʯ֭S\kҕȑG|}|zc&7g븓xDh _x;e6̶1+nK_8"^6WbN_Ӷfm~̍2o--&vF xdMmS YKZz_şC[oFKN[Rݪz?|pv|s 7BEtV-ԗb-_),"z=85lySb4ĵ7&>-MT.~k:K7&І͎ۖcZ'r[ ѕDW2nC|^O$y\GOO/BXOw쟞xx|x+µKkY7|o㘺rH.(x%|0uhu Zݜ pp۞oyfuz6cAR:˺Y5ƺB?ܟkl);rR?=:ұHnߕxuOT=w kZ<'v] +:ByO6n燬-ʾ5T~ӾNi7.dq_k[^ǫ8^o,cl4d uLWt\GW oC&eK8۴ 쟳wik{R XdZ˾\zgs޺ȥֲnqhڰ\2ibdtsC]LVxmngZ˺9ln=dG]l71vV.ݜإX͉]Z m-]:Kk-.W*vi=9f.m]h7Džvp;]hk-XBV|7+|<lφUGګVo]8Wzz4oLx˪ſ_$y[:ts|x6m6)S7fsq/ԋOt=~ԛy6G?*R9e__ {86YJmuۨ7A7]DojLS,V9*[tnӭrJ(_7qn╺UUeO)^mfӰ2nL0=XþW7c`R-UT1o*^*9[x3dq+,nd?[[aqKo1YJ[x=JJ_#e$f> WK u5R9: &}5 ݶٶy puЫlbߘÓ3ub 7s!o+\MB B7R۶K)F/ፈ_.F ~bfٜ˿7_E5-nUٰ/?}w]@ݪf{ӮuӾp;cXN?a.h;w~߼8Qώi_7_fo03_{lww}is>ǧJ>{_av^0 ivǹ >_{vggvOwi;~ʇ2~VQ?E!1i8; Hz .MCz],~鍍(-G'˿a B={^>{ޥ_kaPe??%NuIݱC%lD۝ܪ?:H"88mq>S.rD #=eqi%"q_HOUTݛC$£o#w1۾qx1|1gg||ʑq/-.Y^ gNaѼc/h~xLt2Lf>8矐,H&8=ܦ7ޜ}+S֧ k%՟<~=5"n'"#B}+;΃! [oL~yg2[vu:EO+ 4lϕ7{k Ki|Km;.4.Ɲ+9[MoI!ŚC"va'Vbt^sb]>Zfo]]?9;?ee>>=ԇg2ج/oj oD6 ZE+~՝V92d#`%awj >T~"{"NDNhYLqN@&:=̥@$ {z@~=!B!7%#PJ۩~NYIif~f!9*s?H䓸Xq:/'VJlӇBE;ŁbvVЏC}H`f~UX'UwBh!rt>9 u+`ңKI 84L]^vJ hIW_hNw*tw&M=09қ~ #B$ɁΞ.v*^SB(}p@#l|bahcvt#Ѿƹh:tc]GjD&Ty+>ۡ;_K|Dsh H$SFk|V2@'V͟" ]UHw~r:IOs5ke%ҿtj]+}%teވbC)k$$@=N.cYJ>Th !Js`.;}5BF ЈHo;WaVv*QE09- 9*ښ#`>U#0ny8=P~$ U0_K~bcY:=-AWdPLdCWپP[饳X<0%]J҄}A ]@ƃ2xQaB-VpM;᯳"I" :iձ0jB $ΡH8zi4B9CL`z8cCg}Ф2I:tCl@ $A!RE+J`SGuB6|E7URBhMs5dLbGfi!?(+|<aAt2 XHD90!.CDaG" \PAA27v X31 P "@2R`Au$:I3/x"~ %b ZwqeO_Ѕ"U&&EUI4azzH{A# $9V%, $ 5E}AY.ˉKH*]j,(ծ hQuy HP}"}3< Gt9@T&;@l ٙ $i8y!& k(Io*qV42cvB 2e(U$=~$`%ՀfLvJɛ9K9  xcք *iY2QnLRU|ݬ^b!r%6WA !)V+0h "k! ,lzqKL2e$=9"hS6*у`Z}V^.VKb:{*N2y6C$3K!tAY@Lef7gCy>BE(si4(CaxUg#? rG 2cDܘKDJc"F3\D'I rISɐ`r4*9A8J'@B/@{%Y zEd!1$zKÐ@v+jBU~QH m𩱦z':=HT/#Nw& &%!iF;6=x,5d:'H%+\1.[s2P<; тLOD gkT`b>ĸ Pa!%v8{k ;5;#$X r÷ڭѤ3Ѹ²Œ(*L$DQ֝d%b#thL@T/=zAelἮžB[,NXNJf{-Pb!ŽE~H%Q$,'Cԁ$#b.Dw(zc!qnz %-{!HXMzY7a#^1BoZg&]b6K efٝC IeLOЍÌEn~+p}b,J$y@yΤlRAĎYhz6bQE  (fx7FrJZNF0)UY vH=TGi_FG*h, 1 Pza+,WFJ ىhn& ]B lȸ+ݛ7p_óvY? ^lNtm|/ϟ6]Za|v8$" UXb\#=v9mFSt5 ۗ="ܢl=pg#FʟFl+>هV'FnRCáI#W?__yCyJ;=BT; a-äO$"X&deH&eQ+޼{IGX|c61~O|_4_ߜ'n<[7=[tyӃ;A=X=~zPTٝ" |eҿ]ǰ=ʗz=OMGXmzا!tR^WO'D_ŘMHV2$dU:Rk%\<ő"!n =%{Bk$@%w@0D`_K@fDnbuRv|c^%į?~`y՗3vwSȩV,~-k~拣ӯs ?ysvsYh&%o 4XJg}-/4{h1|ww9vx].)3HLS|x>X9˻}}OtӖN : {l+_m#4~U2:6zs8Lx?670?|!_ J39[cޚ1q{˻ +_ϋ+gY\%ٍ0 . Nj܇%3/~g_G%{wωg{G!=iك{w^ؕ]Bfb3,~'+N'{Sy&</h/~o͗_?7_?5p,q믽Kg'NҷP XPM֮F}t:GXxgԿ|舤.t ^L?:: ُgɣC"$IC,Ȟć \?ׂĽH"pĞs3^0 ?<7z:o./bu!]~ #+-+p=K !~zSd^V+ѣǞOۆ<}:qZ8ijx58b!._Ǔ{vz-h~rp1ܸO} %IAvG~'r/?k0nԌ˿sKSw>|YjدhwH-ѹ=7!?9Κt= 7і={{~[ l0Povv |Ufns`wC(S mh>[.QznEd[\VrC-9̐FO犨cMF-!0g4!U~}zx-$>?>8Ϛ_?/&,S}pW/%MGvdφ@5%B׊+)wξ'n-gT_j_ogZbbB^;goAѕxp4G4b∶'[C!$U}#<>fISMR{r)%wmima(z_X[˱JKl/uQ9iDZb%ݘ zěcS~uJF!wMI.C!^PI`uLiÊ&vJ9yAnDH6~۾DB'](e7Z )#*k-Xt"qd#ryG.w݆(kJDPE%J=O1PEdTZ8a͟8숣LLz'`cd#ܡ}:ryr ~-GA(4ƔN *`3IsƙTyBv 5 TCd#jh14i@3;$gƅ0KI3F FZ.J; *ڴ-2I0芼D"J"-!2܈'QR>BQ{ B6҅X>:c;&3ɮF/wkJ"9EAk2xǒRC-^Lxp]rDA׳7_w_8}ܤBޏ$0b` 舐qs5i8G9Osn\:$t=otBhF43VDpLA6`8#ֵ9[qGl2M$IqG2GWItKCyL3VT2-@dF3Lx'̌J2+u V "zގPq@=Zfit!nH$VُBQh Dl $b[Ic5$~<J=[X3>ۏ4ׯ_1 ˭on_$B4$Pڏеg$C ~9R( IG gTLCq~ۘ`xu=yNfU^xϖ ւpF,Om`u?E>ϋ~X>F g(9;@*2%~~'2@[FNr&a"T$-|@+ >/pkOh/ؽ>MPձ$~5%ZzznvSLRn$4c0[hx!rh~~dG>cTQ>`4E |+YYzm`<0ذk ނ('O9Ĕ?FcwƉ&, a_`+sD}АpC{X?m#8IТ?*~7 =L| eU'ߘKE3S&LJun2?f:0`vsb)r3:J%~<;੻8l)ǬӌjA9#ԙP$M_h wK撟5cU훕:`5om-M@R1SX^ G_&p:a? cU3^[m{C0jZ ] 'z4/mra]o;'w*TpӃx /)bn~aIdof !'*7)2F,Tl_z>si^.3-|2!QxOFft4|1Gh$?\ݒK{$]7_bfFn=aߛ2/@G}_yHgv8Ew'y]~T>_fHMS{hªMT/S &RƣXͧns'8m6FMo[4/[V>Q[ N?qZe*v^r0!]JP2L)Pl@7B *Er~U'^v*ŗ)p4Yo>bMxlAn͇'͉<Qi0,NǞ?:ZM+ʚ@@ӻ7 }`"#'[* ύfUfDUލO6cWӋvS]b އoB3eft%?>9I#0wQ^<:1Lxl{؜~-|:".ZZrz Q66{HRg|7b$꡶ fIm%_@'u_;F{!8- "ipr˂ A}KUj$Tjr~.`Ύo1]{xcou f`*/ʿN}@)8k,p>NCo'Z7Cw^ę_s7^XEhEAs&͙O$| F^گ^'V%$?:Ƽ"f HM|:lC!W}7*f Э1)ʻE' GL8Ĥ/elSa25z!rۅ{7 QJve h`X"./&2Cxo-Njuw4= ]߭( hfv2X,ڨBۇ'O>ery7?7>w'?ſW7?_??ѯͿկӟO?vo~ݿ/;~ÿ= 'o?_ѯ~?m???m?o1x7b'}-`=Y"(,U:NS +`>kA{F G~@Qj,Rg&C}{:ɬ{9yh ) h8S V8/Ax܄XGMq1(t^h/-@O<6%xa`q8p}Np`\;X|A8棏 \jc37r`v|${:I 7s,? ^?c~t,ɿϷ73J/0"`kɤpqMw ;yjͨc/@syހYNW1$\ eY,6:\*C"Gc)%nnEe3Xd_jm79}q,;F\kuӯ?ݿ?__(OO|ZrqB>\:2 %f38aAmƽh=qJq;Nq<ᥐ/wl[a-͈.ͅhV̶cUb;eRXTH:#!\J(gC }e^6nvKx-MRq089Te[epxhE$]Jd[^8/ԥxGvɎ`Dd>kX}Ls ;=3_ZA;W#T1a*X=vVX"o/Ș1'`qYԃ"`N:h8}yYPICFZ`ǾƮM6j8sqȽ|:)Ɲ330) 2ٷ3\d0lP8cշɜVB5 ,>FBaF2dwtˉu~2JƋe'XG`]G3UX3x;`5Llc@F6( HߓAq<%" T.l ݬ bHw GI '[ ,F-AZЬSLtCCz_n?2 c'l36!ϸ?ٗ/ s?6~W>o;gt1:b6fneV_O%& ՓtTb ـSo ?8=?ؼ {{w9N6}b;X}IN1{,\j =]yf119WN_[~a_G[?)wVnM?B%l2}a?=կutZHkk~|S5:{YKtOr} jUvPK5VF SfFdr|:dxz2,,xyqԱ{oe *إoӹ{0h&&w٠5U*RUd೦ץ 9kx4c5[t| av$G/Gϩnu^hs9: F>AE#x~ĨM1ݡM[dT v3=3SvB|B;~D w H~ G/ӊw ҥM ?>F7?|dLN$td>qpw$3)2{%̩ڂBfI[Oѷ *n'\nצ>&ђY" :Dh0D}D8'"ͻ":D-0\$Ƌޖ,|^{GX WFgDSCkMDH}s%KE@7Zg0&m(8oiޭ6~^ijM\;7[{Vgsmc۬kIP+6j5C9Z;it˶vY`7[cëz̓^fuٯ\Vݾu.Y52+>Ntփ[WufXjuJo}ԾtttWck#z-v2c=*|=DKhuWpaIIʨϺbv}Wm;#ѷ͊ԽK~ی@77rƺ3nro~Ƭ7eC&Nn2Mpgћg3ngr||am0Nkip!CB tcxCi:7 ;Cocy5̓n~46v}|2m1jㅅۘ V8b|n\2{ƯbkN( ;x<otߚRГd>LVo`E,NzMxAk6G3a}bl*1Wӡ)x4-yn̫cIUg+K$Z.`X,ϋQʖe:iZlh[ik e}k|məgnUf6:+nW[j]qo?}k~}A{+\c>uT _K?sDK؍4=:[Whd|]N{w:3vw=U'M-jdKmEG6?d!c&g*n(lvRw5XhO%<[i7IV:HBL?Y>zU]dmoyW;>~ݸۄ}w3VɢߺG{o<֩e 捡m|%M:m49۞e]#ωeh+ƃnS_[=-SXv\ݗdr4D4.ۑemz Dg4s5 ~M1Ӟ\I,5|=~<>qx;v_’\;.\lq%bt1m{?LväᄐIdqK.J~9h6>~n!8.t~A]cw29svi JռΒB"٧q*>rz!͟ dy.#5_qs._7N<m_?4X3,qdf)<'JƄ.}CDckѣ+n[{G)OvHUݯRSct\t~= }tyxzUBV#O_wF_Fگu:mYz^ ~2hBR>4дQ8\jRx y}7_7{8Ͷ?Ǵ4x}v~/Do#/u[p2_;p|7 ZK_DaݴC`xۋq=ޙ,Hus&>r=jG<U^Y"T}weWǧ=pѮ}n0+ίx6]'94yh_'r YkY>i0Nɘo\fyGO_mCs)`Tk>pw ϱ]䳮Ÿ]nYuߖ +ݬoa1Ӯ c:ul76| -<ϖ=d.eĜ+o eo~81 Id*1A ~cª#ifI:%52޺o!:IҴڷ/[oɼ͗rR>kϓzY1̩A8M̵[2$Ɠ >nd˥֭?.j'u]*& 9Nʖ*< o: ~lhhwn(mr+}ͭo9r75SfVa4$З"I6WM:M`0E84\FS6Aem~:K>\82$ E/$2nm@;k8C(7%]ҽ3S}NiڼnPtk& 2fi\IgzO'qG4>JZu(FQf76?YCT[d%ޤz%d+=y{uz=EɹjTtCft"b^1_tPKXtj>]WƳ5 ^-XZwݗ맄f*+|94Ncq{|{%Mкaze8M4 $l|~zH `6%9]=nݕz%Ӆ8WD^g$Kt87${M 5oQCdIgeYWRk1Wn32nMq8^{u׃Oלv/>^a7L'N{-8VKW+Y+vҽ\b:!n=7!{7TIIv^a7lE>ZB6;wdMӨDZ"o[LYuB[S[/E2ݰdfܘL7edSb1}t[%-ULJnPڧCNl{L<ʟ,)kO%Tps%Hث;Ӫz^֢^34nOʻyղꝎ?S9kj?ղe~ U@-+TkG"R׈)eEкP.}0Qjّ_~:O{BU{͂h{ >8Ds\ܥlF(0ǟeMdr/Ow5ZJ?uC0I=+5` OOO샗;uSa!Ո{=^az Kģ4ErS/]n_@=uh$%ګl+o r#|R+K6TܯyavB|beћJV}|*&'~z wi4B.,ZQ_))O{&*FO:*nDרƒ6x:XP)=A<ςI4Og^n_No*ќ/3Oicؔ>l4>JAhvFܺXwZKӰn/6eVw۪P<::LcX:3C! 4O/b*uEt{p ~s*';K!Dd[wX'Li`5e[LEE#r#~1@廃$OF? vO/wMͬթMrD`ƻ4O~u.WK-^1{}2Y(kzun0t%ݱW?)\Ӆ w9&p HuF5{izeM}z!ȹ2)NaI/->.hƎUp1=@"ϟ;G4# 6hgtvtm:_Fd m^zuRHX㚨W x{HzmYo^m2,46}^~A7;\ E, &xG8!E8I)qƨ_,;(%֊ /8*/Nְ"̎dp66ztwLsߤI 2{-b7pfVZ{`\1Q Lnɾ"PƝQz̿G# \ Qpaݸf`mbX hȧ>0??*i8auwF%mc$p?6n1ۻxA@σH`̐\Cf62ִ3 gHz݆h 9Ock`^LSdk%Y*deZ+)C{j$K &Rl\)j+|%V I:P1[mO6Jg;=Sg%Ke[R=1ćˆ"!ъ{qt`h&(Mf'iM->ڜ{ڧj([?:i,VtIǃ#XLR$?0:xGx%7i (BmLfY2̈Ȳ"%)4ojJdJ2`}`neR+WkH6ԦyGGzG]b<0m$}u?8) 9,wX>5 !p~\ý{ze*_9O4ak5\ =3&mKjo.#R&[xFε"{ʚ F۞^NitE@Ptx9&'1#z.$Pxsh }44F#ăHD  DD[lNyQ"ъPXY=x2S7}ݾI;x.d|0E"LD#FSEp)(hoo$EI\CԈ?qLFu4ՁoD+9|f!iR&\S삱jꊣٱ ݥL͞mvi74Ӟ`^Ap) 垌 {t0MʰU0܉"Ü,PPS|O `jJmDў$ʓYΣRt GOށb'!N{Ė6`]uf.cL 4n1U+BR/웂X559hrSBNiEv?*i/ b]x֔ʊHƃ+ }̕ -V~(Մa.#94&xNql*;v$]7m $4<#FeAϱ0Si?a{J4ͮ쀂t;F$m:#@ k(`kxL&eJ/K8c4 T)=:4AD;>5yhvH& #s:LRwrC!|yr 2'vq,o $3kl!}t"$[p d{TaOi.8b洰ч' ѦNuek}EݸYzK.+H~qL=ج̬2Kh']WRQ֘H#g^K>#ӉcSqgf z )Acu.=D:ٹ )AM}}uAg9dg<PzK<z@H-뵃Y z_F2[rs Ej82V2]fM7c{k"{5T#\##!{]o>:Z:xOH@a>Yn{V.UL/,H[fF! WzD]sICԫۺJ זyvjWt[GA32!:3jC:0w \EuCݬL nNBYseQ{\znWyC$3"<;ph𔐱b3ԅ6!hf[DJ\e*p L\-CIeqR)m|e).'iv!I(̊\%2L@B! O瞸99 9TBv|SJba+GaJWȂQ+9IU"T!p  Rܫ/4EQ )r!ؙ9f0]JKGxM8T5 3yX< %WpW_CE' x^+D08B9j^_NN/iMe.$B)lrkmx%:pO0݆wJ~AQ@"H9z < ÙћӸS(zP{#Go ޓӨ(<'nF#&)+fSґ`e+2!Z9Y84tJ"/\ - Wʳ3]-opyƟ[SaGl7ũ aP@!8msY^^T|Y^܀:[K0KP|+TP,Oq O {?Ĭ._8 А2|t+ a<:(ؚZ0*F9~L'ϑBƢvТ92dO9(O>5ks$5Eko.Ns d>[SŰ5b QFN,(F<PŒbK1QH(pvyQሼkufjQf<(q\&D`Wddr?6%LuH#T6\ĊbCn9m(j\Q GF [Sw>gunnA*|VT0nHdZ+,]\84lͅkH6iڑR(ivK_(ŷ1q/ǣvmA;AI@_ڧYp? <LIQDGOU"B{8; b=vAkcuh`QS|D"\3|ʧ{V,F0&c0g(٨9?g)9ŊJ (.VT>Qj-!Ѱ BEdEqsOpQ\ͣ7E%/ <|vCcnM{6Urּ+v-Rgj%UEX[3pQ\(iEqL5\Ԋejᢈ`E5 l(.Vts \ݫ+gsᢸXQ%pQ+&VT#)TF'ƊX@-\+ M ^XQ1 bE! \Ŋl(.VT#+UJ+#EqpуZQ2!EֈVŊ}sᢸXQRM/y(˶?,>.z:&iW (N.$l(.VT|;ClC|7 ]T}R-\+zپY(xg\tX IQٶ4Y|IJ'5QYlGYS6mKͣ'\QeMA[\Enć^JD7CS ZcɞhG!}%)?f> )c(@^)?xM$)(⤒q2(G2\HUz2=zUΔ@))cAW׹)ch@]F}}sʘJ[ `2$x)c&DEUӽ"d G BE;#({CAVo#zE*n#*+吅z*U0:x홠FQ X/sŐAcu>"d&+QQupL(}'טk1JP;!*QʵOGҨdmP $!gNM?=DTIŌIzJh:_)*şKN"ԑJ*87rX,>1fES29N_kݜǭD zar#9(LUmA|acV%P?ìx fB[vU/=hLmከs )6ihq-u",EؒG[wX',V!܇-a/t=ic'[LT"|wj~Uֻ7,SF7g-7Btcl=ʲ^hV 4i)zgu+%t /rO =t"Uïy.'Pvг7zKCP U# Z7^Y-qZl},ҋ`(LXtx YL=<,尝:4zݦb5PA"3N vw\ 3!-(OնbחGQݾ\I0&.ʵPs+lR%^wx5(ϣB2Vq'-n~DJz8rHVL{):J+ tw/xMbb!*ƴȵL(C5dF \+W=)>|@cgIa8{NBCIJ8 Qp,pCxSZhI5le 9J|cbć+ }秺1Qr)e'OCC(AC9!#R0'϶u8ep) nٮP?Vzqv"Xx/&ᒩz[{U@EŢ V&Ll:OTŌ¦=mT:j컴basvT(lT޼ky1D)uvjb6P'9Poj"rpSxʀ?&2ZN mT dTf0# ޟӨM*݅k#i ෦b~)2v-[S³"ٸ'!G*o1EIxLE v;iJq@zn#h~Ph'T'ZDѸĒ3h b\/MdB 1 Fړ"jkv$r!0,ɡ rZµF.D{/" W#\8'dh0?΂TX XxYI E;; F[i("Ֆx%u83w;#^t+ip+`z||[ (My8VbC hB!L亦Z-Ag6C#u-(eke)5qԚLC 3^4ľ" C^l ||+r`Jfig?Ҝxl BSˡ}N&aq \nǞ"`y.]ȹE.T"/-'W+?^K2j!xh e~wr1֭[5 ݂(!)W+wgC6'%a, 3G!`_6RR'ܡz}땦X`}z]YXObzB. Q%fMRs02u M%_ ޻׍D)B\A/&^;H^Ǹ ߆ۚn&օ^zHPDW 1l5&U2WRcxA-eL^Uʸ]:BrwI.cRI3tv\e>W-p/j/eB8,<t4R/S*Rf1v6p R* "qVR T+@ˆY2SVv#pwLqj:uj50쇫bqkc189-gc5<"J]c|d lyc0|Ʌ|.+Ee1 ^ <%1g``E;HM9TӽfU%SU%] 5 *&SLWbd H|drFmx%"nQl 7(hў@zΓ#! XCVk`$j6WH3E_$LK - o.?9IàK=.*)dzX6__Pipn` m^YiUH24W'NW)DcޠuF6*|I`q1B찬k*=fhi. ደG~Rᇟ/)_Z~+vS0f\KԢJEkN (&mUE v'J8^F\-]8X*f/|N` ¸L(!4t_8 )ė􊅃S{V8Xj;`ѳ bރ/UU+檋p >LPFx"zaU ]+U_vVFEqqZ ?e,йl|p(O֠K_g׸ߠ6pVo (m ,0]%q:@CvtTi ;®F)̆pvF0⅀)}Eè R8`#w5*p^ldS+F֮R[2z#3jE(TV3yВZRP4J5%:ݝR]bвM X#D!KWi=Q4BcUWk'ury`.=نJ0xdkc Ҩ|4$ރCe])(:[֬'x0J !1u! [@gr .eCD7KlhJR5lhNb 8`]e[QCR:[ʸ8el蟠7~2< SF;W-G|oI|vFwB.%*ʱ??0l=) vgFiC+j4ap(^f73~(xb콵7ͼž8uXٜqYFB[sjl\Տ6:ǾhOw\Q}C`f7cXA2]xHŤHfnIVmǼ^:]f5ow]icQ-S,/pľ*e_! 2uכtޏl 2}workX91<T E1Z?8U| {iݻ]tٴwYN_+X5*ǡfkhkI.m o3yTpvHgoePO7c;[L]]7663G9A[D޾މ~DCEb F^0YSͧl&&Sp?pZ7̃Gmg@zܗރ2Re!u )[5L} ~8شج>J2䣲 >QHoaul+pmz_p/5y)N w| _ ?L[$o54#,@#&Sl ދB%,AM%n{lV5P;4l+QvIeX!ɱu)IUwgO'#hvt!k/<:ـ 4oSGxRydv:fHϗ}/νy!x~;n8/L ޳TߞO7 Y'Y&e ;a~Jj; {H6o4҇~C t7өRӿ/9`9J ,:p8Jg}j)wDP ! Sʘ6YZ@CvQ1s s?2=Z6]6}/ԖofFv[b~(ufn+ րGu8'ڊ|m#F [m kf=ǘ?c/]D{/DWl` 朓 mOlnVKJ1Ar  Ѝh԰YO[7v;̯&ަ!uL IZ 2O$㞕bױ`Gaj2 AC$`1 ?0}߃ܛ{ %$NckJI2MQex,d%XZuz&8 +@,+n񷲮4,-z:e/еt@ 0벡GwM,7n_v( 0lw1[! (,mHy-c[|To1IoE'vhk]+g9 % o\qh05ħ&C*[PUK&trF;9uZᝁ8@Z=@!0ٛcFyH+zon4%sV{0 >oN!8;+YC{ ҹ7GM:yuhXOoSl @_-Z>67l>"  _̂D-Aѵ W9H 3xDROI܊"r\T\| 0Rg*Q,Ju2 8!Ԡz[]vA;H24nmK2<ɈՓ 2+ g}ԹUIr19Kymϛ8hqv"ѥ2OV3n r/, II'Ɂ6M*Ȯa[r0"Jf@Z&:-eFo?dpɃv[Ordkt/FKH A ݤNR&\r}<>*>P/Ι ȯ4:_98*v&ubI[R#ǝzRFuvUʌQx,p20\1rn{a]OR]ohm6guкbя:A0}y50_uqFZc?1[4aoji,y< [FQa;y2 C ~/G?@DsmkkFٻWef <LK24#t8n9ܦz:t -0p9Gz -19t 3$*蓭d&s7supao0,bzLDhu^*0|vTsј}s-,ˆGa^Z06]Ui1tq%eAHcW.Ǒ oSs)IƿHD_(: h]=}-8AZp'څ@t^VڙZum, Ԛ$k4a- [Cos!|Y¼^f &s&͒l)!}sR0D4_bd$&`P{u^&˅ؖ|T0@/R NʲSpS_UNLJ3ghY v D!Q܋?$^zTuCL b6Y@a7'W^S粻O#>d'W2xX@civ5!|YZξQ& :eܸ =e n^T*zz /m[z E)[XR.X &lu' aOXJF!﬙PΔ Ѯz"e}R2'=Vc6)t<21"Pcj=Qw?B;# A٩~1gVL0E)wbZn!n, &O0Dc/ FЏ٨#1wsmlocYMB []w o{ؒUheb̝&lai\|ǀgSΤ)1!^͸1z;>2ylPş^EVKrI|be Xo 35>v2D|DNPkt BINظbFutPÉt;embkڊiZ7Ԙ90弁n_M#I`,ݝ,جf~XͥgV'9BP&%!PrZSҾ5 Gpyv݈l#V/U[O1{GVfhs#F N8gUoOY_FH!pYOLH:0G4L@y"C\V6ŠIJ.bO,D'$MN3`)74\-FdԔHB[ Q`9B&EQ G(+q 'ޞGlO3xGI)#Ӡ4nHV2YtULS״Yء mtֲ:)OܑW9OS O^a >mflDN7a9 ϻ/Kfߜr |'wX|s iKby8RH?.p{r'g y`TqL?S#p<&a/c<&W|%Mch~#Wܹx-DMxNпa8ɽ#ukwe=z }?2;[w$k \C+?3Kek~Hs7j P\C:~{6.ҼR0%Hp|>*[D. :S#̌ { ߯oFggf)d9fRӎfK|:=e}?d'zE֍c^xt!32B𪮠4 '&ZIYH^}f! H D!5yI"s~N"Y*0$q\=v,!'Ti}/d@|j uLUa܊RC,tmҋ2֊u˨{gSzlyzozclԿ2U Jt/Q{_G;{? 2ΓN+rk~{8I'Ϊsn U3=t 3Fn=\% N ,*]HC?qe2u(+z,"H6ʥ& V/!ŎA&qc'-}=|S7E_űQ, GI]d'sZ $ma,’DL{ؿͽmoo6IϤ$qiS%ОZm8§btJ 泧J$ bsj.C0i2Ư ›Z¸VpuθO@?@`KN KvH-|, ^-GKH#_: !AG84h+2nvfګ1_ɯ6~87iu9-e*ٶn"rZ؀lHp=%dN$ jdö;m n<ּL$E~Ѝ݊h RDZG8mЍ=1 n#ҤqX L0N.&s*&фp4cMOLAJs&%5{ٸ(o볇m>nU?N&]A-R~_0ydG-vJD1AΧlRa'C4)'3B%|qD+! 㔾v_ȉCte*fZχ7rxf%֧eWwKVMI(σ.uhr]͒GAHhһ{MiFIe9.rr`fWraBaeT^^7_nKzg ތNO+Fj/^rV`2"/c'YyGGqR*B U̵f $mV)D34ysjrTtmˍײk+}6]H>;8*%~n_dوQ-!I87M^wL"#U'rXmˋ51:DJLXqcK$*)ϧ+_${34! =բ6/a"c fC|,_E`6RAjdIA ˵o{s􀍇>ՉVni'C$Ԓ RrruCE =IDC-$JW4I7 rN._\J! 񹃜nj=ϞvgrΖߣslW|ȲIc6]Ӣ6yYƋV|^=<̊u%O[$di!}q6#" _}Fwet9G޲( $5GnǪinzJ~>ؗഁ0h|ؿ-g^Z\jWE`&Ă(Q?K)OW1WS5Lz!wYzDB&t.D5-LO)#?FzbBdtJ.st,⧆ LeoL/-ZV[Pƥ FEjLyZ- O|ţ4ׁ8LmSGrn=wRL~n`bPL\T7t pu+E}cj^_M0s9ZT0BX䕛EIƠuYZRљu6]NI"W5ӌ?]YO(76OW^߯s:hQ>-tw/'==`9^+Sc%~x|$k <# m#ι9YحN:awIt&lf;8S>Hn1W}iR!s:#^nzrxW?VBWaqrJuj8_v.H1@sdn֫tTn|޵! _amF =XY~}DEo"Nڄ9瘇O}yx( >$FY4HOv/$<}?]՞@a~1*q먙m^JJ`]{Va}}Wfu߯A0 "#^>F,{T%Wp;.2oR)Wa , ^ +-tקwqI4LgA*ǖ{ͤC^f;^!mgكی%gljܫ!ھh_H燭c{5¹̚h7<~p=n֡7Ifi/h)SǷ,F2%$P<,}4[>fr;/ko?>Fg&OU9!9۪7Ym{kٻ  Lk-j~86^pD"dTEv[d=JL8V~nۿ}J}] b".fZƫGD2)[ # hA79g ^ `Grbz z -I=QU>#ni!u 1EjxLJȌ z|aJ{3}䓡Nm'Q+&l[i\TNs p^^ ;D"uqA.~|!:thti0l ɣ{WZ{$yi=3Q%p7yt'XϤ6,X3^h]ci}f`|>{Es뭩W# dqƦW8 ,la뛉LmG,0|IFE" C2e ׇ,{C0ttq犆U~$0".5/{ՙr&&4+`MX7hf(~4$q:QՑHZڏI}<&*^K?d/MVBڍa0Þyrr5,O0)eD7%Sj5iaKz)MZ5*oC=+!CߞME}"R @b֠Q %'Rۃ~|jA%4u +< BE|~8X?d) S/ĭdZLv%~h\*]oA(8kW5?ewSOO6rЀUYZ6D ndD{ˇo7D4tsO4!n-~M-Wy0#Fs~o[pf[˴rr( K l9-Ғ!:]ZY ^`1(ui6Nq$pHoGb+}CCnH*0_stq0:4k~i.jnL1o,7)QcV!VGf'(89?`u7XB o5&`uޘõiPeߙ$]6 q(ʆeӭtuW9wcq'W7O۸ fEpNf*(m"+c)F_.arlhIO/^]9s q^l}!hmqJ:2DE4Jwx9FtT, ޱ Q.{ 9ӍxCtVM&g/EI:;њ-EiL;ƣ#ڡPӎٜvZHo< MiGڊG' apmL%m\Dgh*57$Eh[Alnqls +PBk8$ !/-4eJhyXn|cx:j+QˆbʭMC *> I%T{9AW)dКDc5)$RSH:NaIa4jF^\K7ĵ sfrޣ6%ݮ&t@!6 )kKMAi %[QcCdIBJ$~`\6q2eqdJK1,=GtU!<46-͕;abSMP@USE@}O=ZƵAg"P+&in0BH YXN_7fO=qM8:^jF!6KMG"ќ|ݦ8"kАiDyACN {nZ_X9|̇+c>Lh'>a0w (/-04j5PSۙ+<0$6ɒК%XZ>QsGތ yebM׳vaVv2b˚=rO=ڱ)ow k903eM5`vD;& FTۻ(}ʸa5yka]m -9Ⱦi-pc>_ђ`q6'K߭X8(r?hmʙCN8sþ$K]uY0͜1]TOXTes:Gj.CUΣ/\"eSNq\L4 zc35aQ:}̘i%% BƤģaB2Q00 $Qh%ϵ{nv;\ ϵz}z}snf|lNnR :rK?w}v l;Bk/&_ B! g}Lmm.&Ka~gk%lqnguR; jxP 4Q lk-*iF=-?Nd< P_S螿`h8dJA;5&gr)"ѡ 0 43Nn ë.w5),:OSFt?(S˜Vn kN: ؘ.= 6A|Ws t\>PsPtyar?mȸQXFmgrH=C[O |)b?&s,FTF=ԝBο`ZvG/X7X)6_Yh3ތiN[Λ4 xW1 ]ڨc'g ]CMGu]ФCtl/Zi3d|6PG=r V AM8y u36Gh75'f&ս(hN&wDs#b0έ/,ZhMȤѩ~۫{hfM =Ǔ>F2M^Ml X6QQ E@˜\%Ij(Xida@ !IiJ5L^5Eϡ;_:ƕ/B=BJ !#4qItI차7cR {jc͆T1 +jTq?Ryoښ? zoUI+uhXL t1 8=={ot =-7(*%%M @= fm34 gTQ,ƨHwLAqHX#fP*:M=Al+ BjzC^ 4=!F!:crFE<WmYsс\ܜ|vQ8u<У8!ַDǹ~@u& {4bpx_\aI!!7(r+L}^r  FrSk~%'6c-v٠֪ĨqWw g7nOJFQ j^5"|sRM֚W(g&f FVZ[:Rf0S=cF7pYLg_3JQ{L ތ{OoQ#Sn.Anbi؟$F{)VYJUĊsCъ62Kk QxT! Pk7JB%,W]^ifv#xc ;Qp~7K'Z{fV~~ckԾ qm"i6)6 `X7k1/j c噜mR$q?lf?3v2=/rd f +ks 7ui$Oi{"(1Cp*0*,]aL&c~l͙ɰsbĊYM:S+^ᢴXQumEiNHWpQZ)ϭ=\;\z5WV`EB* .JUApѸUx.Z]\27饎gR/TĬt(q㮿^.LXQ.(ࢲ+8pQZ(kEi*3\+ ݬŊʢ+\+%=Ei.Jb Ei>\3\+*;!EiEiJG(-V'Ŋ̰RwpQZ(րbExbEUF5KlzSybE)pQZ(eh=&k-\ N%<5\e0RNuࢴXQȵIaDEUMkMƃ&ZI׭Pל9k"*p&j)uM {ll(QSշmȹh]S:Q&=5)662 C†2KS٥t[*Rzhʘ.Acڔ1YgAz*cjy-W2PN.cB٣1)ʘJ Ͱ*c3WLi5W54 jteL}EQ,c:W*5MD,cJIu˘QZT9֬*ڡ2S8XgChP؀(QrpՕ_&vS:AFkEz 왫xR[D\ԡ̡3zF 8Sġ!Nwc#4`JCc)Ƥ4'7?'6Jfd3ʹQ@ַ]d"EJ6t*`B1YR:)›>h؏"j;*}BtX'rLEi^~M m/ e.`6iA[v6E0&'A|5eq:̪-Gs9aV׊)boEW઄>c@ i"L^$ ͅY?4V3V{_PQvygiYuBˁʎeW ŢaVE!*9K9=hunD^%I6 0}(aZjEjR7D8ʦګk,JikUKƂބeUIِjenTNt]-6jcRu8pRIk ޴+#]}[LWͫ >bAk:^;[J@Aeָ|l턴G ]lcyMZҟҴymJ×(ۆe+A(F s_vSN75:}Kb_V>;ZAΉnPSTuD{k lOJۏV|XfU7Dޏ`WN6Z3_@f71*xB(R8ʴ.9zsk+[wItf;wRAe9GtI QZP C+oLEst.~gޏ8#tTcTⱶB+kF BѨx)jCMJuc{MTC J]JR7(JusMϺV]` 8A Qh;粫_#1xϠM-v(*)Eu!aV)ȉfɔ͍d 2TO6@aݹEX,p9+-v˙[dh_gډ7=\qNhatw<m_Ծj%վFZ1v~?yfZ+:خ) 6_SأH՚-fTO_/VԀ}f4H\гvu@!f ? c%#݄~4W+tҟ<&E8@u೫ݘĹ2q|J}O?鵙ȑ{mn s(<X 'Lڀ{-n ?MɾߤQC\Y U伲;6qrH6o6KgS'C"gS dbaX0,0|IKi۵al!eo4 VJfكۆ5aw' + fO#W|Vʞw}ږ'"_9v^ Y ;h,M)Ic󓢾v%6^z T2>hx8(_c2{`XNJV]hI5`B֎bǪY2Dv;! `O'*KH%h:Zi}јla9ZcһTaQ͡HtYU/I#rNLNVDW?>u]u2B }FeĺEK>ic3윐&4RdK_SJs;\n$Kh]fD%D'bVpv4i>sv6ϜeBS^O}X{Lέ),@eZנbm{RFW^fs\Ch=|PQ" c)#sD7LJȁ"_+ڮצc4_Wk$69"㨣V֚JZ#ׅB4G+íjcFQ47&,):#yJ4q[` V E]m9 i#vZJO/(פ L!,s7H+M_ґr]BrăTu9yHkw]W[E+FBʺtyETH] [i)f:+RG{n)K65 /k)\ds)sSsqn*w`^xx71QXR;GBSN 8\;X\6&Rt;¸ɠZY;@r]6r?uHH]7j`q@;=Y׉v1E>R.6%!8 a\׮!:E#l+lmfAZ,&%GZ7;Ǒ:5ׁϩ@:j-oUR(h&6Z,q8vt8!측͔J9+6;ʟrg "?o2K#7vO.(iZy1grU(5Qƪ;Hګ$%ճ+[g=b"z j"M/&]A+ɨrevl{<7&ŴͨjSeB I:˘ ~EhH l 9ئTɾNZ* :NsӐ[BUQDMUw>mal\0_xMsMF$S~tm$Ep5V7TNj{N`P(T2VVּ6DcdCCWwY 6U(i'~̇+1 fq+n;#f+_f3uH'AF"ٞ6N#;=%Է-_8/_.Dni|Zznqk(I4ڃM$k':ǟr}jfZܭ#o.Dg0谭i'4/&STIBqJV7z_z@ dwI__sA6&ʿm%MBG$\&!`O0yֈ0aQwMbutJkYׇsa0i5]w[I=F/<*,Tu3njv|Nk:z6rOvUkirO54 g>t{37b&RJ?R[kV&*kD[ S:Q: (B%@OئXҚ9xXU05s~f ̙RVxG5t=4a 0]rHVS CZ F9tLbM*KUmqo',ep;ز^ G_75{e'ʽ,[oioI樲=-%o7c`>MdM)l6g:ڹp0m5 +|e6"$F [`d`#"V, [`Ue?Wv~lp0e躅iWT)V=:V'y UqAվSipմ"" #[صkP5AU{UǼ5dx!tt!9Ia86Z eC+)[<:$:㵷"EgDyd3i+QUukC/UzN݊ypCo }3ljFue ۢ N`S6QR`flcSK V`MH؀ŋ[ 36ѐӮ\մc}p(tw-0m:A> 'R6b_C{K!T> Oh5} _3~& 'Sjȁ ݸuRZA'!B>!fV k6W+307QPv3lfS]脁_MgGNcNYq5*8 Z[;"\^^s:ʸ3ۋ}̶֡7rf_kgmE#GZ&/ɒdŚe]VZp2zf m6e%6Zۆh,Med2ߺm:|8I!l}Gj} k})zM Jw"88h' chUfx6Hi62ةʨS?LxNY˗?{lZ-pO . I~hlV̄N_W~JE ϩJkೣvJ?r~ V@7*X]71pY6­C߫~S,:/_94z3o-d$w_Nk2]*0LJ"OX v~RBs0o|po Et{`8 My?< >`t]7<]t7/ꃄ4ϠR2 tCJ_ÎiLzy&П \ iRz%]E 2(DqƾN =X..ΫH, f|EJ*z Hz"6,2Lݤ=F6I6. p\ ^xss;3˝'ɸK_Zk`]'jj/'%'{GoܻoK$FSqߠ>.XZ rOeDnDO?A_~_Eb/g{{y:sH^U]!N~gy8Rz] xnN ?xhO<ŠQ~)]܇ω54bnԹ,j-J*5GA+"y%E?Y< q6>'c*h긔sJйXIوdQ؃ڥ|ZrN,Er`&0P5#61E~\K?6*G3Rm5 ca?g&d&ϥDG@(ث#'2g^doڰ DB7@Id;zƐ$$r9UkM&uHw2}W V:AL'Z.Ƥ#d j6f7ňϝ,Q }h a4wuCS:.,39t~TSI(0')߸Al-m{IЏ?5?#{y/:NwsЍ?~tGf? J3O$sdB(`zILf'؞`j|Q}zl鷜*C7ß9lv"\}0COIg@T^2ƕ^i4jT( 2]+6xFxJVcg<>8&ͅu y7QڞS;޴$^]t,e?FqH. (\k$ ^ѳ.hHrbS`^}~/ggXn$ըt?l<..Նڿ Xlҁ| $KIBkG#IT>տJl>歃˫`B彐-3 jcN!N_sdrV 3:I_E\HZ>n,@<V̄P7v!Ls *}8! ^wnRt'YÉL[9\hc,~i:ҷ?_pOOWIiZ;\̶R/;|Ij%p`)S*7jŘ.'P`dbZ!~??]\J1wB.,╤0Bh$Ndٝ$5]7S훍6}-)4g8V^i=Pbk6K0u\Ċdw^^c-y4폟ݙDc͞cZ0q%ݟh$:ݘG5~g9lܨWSuGi4ʳN4ԫDFs!S7o`f}iYYVQM a_8ք W= ;GzRc풁zX+٫l-׊:߸(fz%^= 1,}%1AHYkIyGWVؠd'ꔳ4ɁM$ĭ%0OLin\^wld${8?- v.F+psB7fwcv~/n6 FI ~{|6G仚OT,h1un`+ {!^}on+Z uCs UU!2Vf?|Z .ɿ/SǙX(gJc=/g{M8Q8u^񥗍5 UzG_cwݰKA guOmСinwj<4"Cxb}2qK%GhfLs97 ʒ%B:=7e#'E-BgόO參)'Or&)\O=r`KcRy:?4I$v>ymP*"bhˍǯh=Cq*ߠXc|f 8Qc)`+hQ F~=Gq3y)fZ֨]:ѕ-B%D[Ít$B$J reD(\Ehoe*URpenxH%DWOʰhpFi?7|d#d˄㑒,7RHgo<6)X;oŽY_u|Xt+X\5uܭtH0^r~S/6 0燶)wqkR!2tqJxX.h̪R)3Vz$\Y0^8B5,$ɷB$q2(p[{:qgٔFN,:/B.:Cyyh*}8* ,[mXs[B7vre-0:#{;0WF vm#}sEƣx{w3Pyhx;]y7#JXEZ\[;G :ugssHBc=Gh^uv㛑[cOך參dIsM}ILw6T(~du% L2Kb ?ڈTEMKްo#A)ܐG$# 64 2y)ۏGG-I4 1yJr|trV~D)PI_U"Om~8,v[HK_B7O}V}US:0Qc79DXZ9`q}4) 1@ "*hç~v\=ib3 R 9&q|Fŵ>GmK_PkhpDˀ|aӁ/p"11&%rB5xtyT`6'eփ_|~MKIN{tA|LD_؟?y`n(C_NjZ`??:+]cn׋y%9>gAD-%nq2b gOYwAҝs8W? 08%6&ل{zw"*:7Y\ªʇ _UEp"1jߔ0|s?jwu[v4|L^+g"v?*reW5>:Ѹų` ?GJO;6Ͻ_rmݔg*.$ҔX_' sƹԆ\+eʌњO%;;#D䏇Q1ڎ,9^Ф4SŻut\$Q.DFŻoEÏ~@ؿY"O@cc4m-iX[teSnױ3ҿӬs6ЄI%' і~ԫ_0U7A@M:xvO F4/{qJ{w;QpcC܊&"pX&°xb B~SbGy*J Rcit01g˙/ܒ3BK5ǽZ3m(-GJn6p] Os4 n@]m-oK"amE4֖voÆoJFPDFDF {{Y7Ӫ?+mD{ʩhiW=r^{48!aik^9MOUALliOV}&N#14İDDWkm>""X+bVDoC&T5M$̃,@Fjr@TۨBƛR`uVGAyӣ\ZQ rEiQ>v$SpgV\yAfdpO"q|]rϔդtaC]hl,y%X O7v,b_PZb2Ei1VeEޗEirO }<⥜zUIko76Vsw5v'0jYc7o>>'o^wAM~&,ɎV,cVNz\#*MS҇6D_#oU lňNOWj-4|s>5wgќ$CJiGclvlB/;}}{Y|$Gyf%IƓsEt&%׆4;1UPnA8)KW@$."Ee*nу:;г2z/~q] )_%AU}*rˢ]쁒wXԪacHr?)eyո$ɛ+^ X, h#)'851M\>dbg4FA;hWss4l[_N29?fKDu}-.b]*ϗd9.2lFsYu7C  3LgiN/e39N`fE>AD>Ê"dr\E.qLB*?_m|o[,uu7`^}:9ͦs9V[ bVb6c֏D:x1#Hu^α%K>,㓙qtah~gp=Y_tR f9'|5|Xa/w`0\XDLÒgY pItpKu2fg<Ç ?_#[ut}W~6Y_?#@bs}Άc'*Gƻui\ev+UL,||jHzb]uƮZ[kk"V\~ct1DOzgmhºw[hv<7݊|ODcrY|Yrt1N9) =|=ނcI9^4D&+FO<$ e,H-K璜 񖆗̙Ooe!o+'d-%&~>`ru4K_Rj75.6NNTip|Wo/_-2eK$QXR)Ns6Y ѻ7Cg9H-h{d $_&BڅH{^}‘kZce fYpEϠXg@I 4k @KҗK4,m^JItiYŋBRe2` 5'ZOg6Coq\M_d@WʠhH1Ex덴V Z-p ^$iPp+RgadxxS y^ Ln ,V@@,ȣWrIh 0Ua=@ʊBZM%E[0p F0YOj_ȠqZbwc^ @/m,bRί$w*j[) d ĤA~6O/ Q< 7툻!dp-lQU2 k;C %e'`ʠ$f,06t CPY +b h,<̈Ѡx+2 M CرvaY&˃ gn`ak 8$ep5VF fVO劬7i_eОQl̀$C2&* ZINcaB@g0rA*A]3`hc'ϱEIء0?@CBd qt&bBVYC ,7d5V,&a#aXtdJ8t2 ah1t0E:""xdM< ?JG&-#|GjV {*<,JGX2@c< !:A m($n,g9hzyX4 CC. ǒNK#XCrb- L+()`Wb@)V@s| A2VG8_} 'dc5GSx>hk17 I ~\ endstream endobj 32 0 obj [30 0 R 31 0 R 29 0 R 28 0 R] endobj 51 0 obj <> endobj xref 0 52 0000000004 65535 f 0000000016 00000 n 0000000194 00000 n 0000042840 00000 n 0000000000 00000 f 0000042891 00000 n 0000000000 00000 f 0000049256 00000 n 0000000000 00000 f 0000000000 00000 f 0000000000 00000 f 0000000000 00000 f 0000000000 00000 f 0000000000 00000 f 0000000000 00000 f 0000000000 00000 f 0000000000 00000 f 0000000000 00000 f 0000000000 00000 f 0000000000 00000 f 0000000000 00000 f 0000000000 00000 f 0000049329 00000 n 0000049525 00000 n 0000050687 00000 n 0000062292 00000 n 0000127881 00000 n 0000000000 00000 f 0000045582 00000 n 0000045657 00000 n 0000045807 00000 n 0000045732 00000 n 0000193363 00000 n 0000043337 00000 n 0000046572 00000 n 0000046346 00000 n 0000046459 00000 n 0000045360 00000 n 0000044214 00000 n 0000044798 00000 n 0000044846 00000 n 0000045519 00000 n 0000046230 00000 n 0000046261 00000 n 0000046114 00000 n 0000046145 00000 n 0000045998 00000 n 0000046029 00000 n 0000045882 00000 n 0000045913 00000 n 0000046607 00000 n 0000193409 00000 n trailer <]>> startxref 193591 %%EOF ================================================ FILE: Directory.Packages.props ================================================ true ================================================ FILE: LICENSE ================================================ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright © 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. “This License” refers to version 3 of the GNU General Public License. “Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. “The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations. To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work. A “covered work” means either the unmodified Program or a work based on the Program. To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work. A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”. c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. “Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. “Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor version”. A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about box”. You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ================================================ FILE: README.en.md ================================================

YMCL Logo

# ⛏️ Yu Minecraft Launcher 🐳 **Free, Cross-platform, Fully Open Source Minecraft Launcher** ![Latest Release](https://img.shields.io/github/v/release/yiikooo/YMCL.Avalonia?logo=github&style=for-the-badge&color=007ec6&label=Latest%20Release) ![Downloads](https://img.shields.io/github/downloads/yiikooo/YMCL.Avalonia/total?logo=github&label=Downloads&style=for-the-badge&color=44cc12) ![Stars](https://img.shields.io/github/stars/yiikooo/YMCL.Avalonia?logo=github&label=Star&style=for-the-badge) ![License](https://img.shields.io/badge/GPL%203.0%20License%20-%20?logo=github&label=License&style=for-the-badge&color=ff7a35) [中文](README.md)
### 📋 About **Yu Minecraft Launcher (YMCL)** is a modern, cross-platform Minecraft launcher built with Avalonia UI framework. It provides a smooth user experience and powerful features for both beginners and experienced players. ### ✨ Features - **Mod Management** - Install, manage, and switch mods easily - **Auto Installation** - One-click installation of Forge, NeoForge, Fabric, Quilt, OptiFine, and more - **Game Customization** - Flexible configuration of game parameters and launch options - **UI Customization** - Personalize launcher appearance and themes - **Multi-Account Support** - Manage multiple game accounts - **Cross-Platform Sync** - Seamless switching between different operating systems ### 🖥️ Platform Support | Architecture | Windows | Linux | macOS | | ------------ | :-----: | :---: | :---: | | x64 | ✅ | ✅ | ✅ | | x86 | ✅ | ❌ | ❌ | | ARM64 | ❔ | ❔ | ❌ | | ARM32 | ❌ | ❔ | ❌ | - ✅ Fully supported - ❔ Supported but not fully tested - ❌ Not supported ### 📥 Download Visit the [Releases page](https://github.com/yiikooo/YMCL.Avalonia/releases) to download the latest version. **System Requirements:** - Windows 10 or later - Ubuntu 20.04 LTS or later - macOS 10.15 or later ### 🚀 Quick Start 1. Download the version for your system from the Releases page 2. Install and launch YMCL 3. Configure Java path (if needed) 4. Add a game account 5. Select a version and launch the game ### 📖 Development **Tech Stack:** - Framework: .NET 8.0+ - UI: Avalonia UI - Architecture: MVVM + Reactive **Build:** ```bash dotnet build YMCL.sln ``` **Run:** ```bash dotnet run --project YMCL.Main/YMCL.Desktop ``` ### 📦 Dependencies Thanks to these amazing open-source projects: | Project | Purpose | | --------------------------------------------------------------------------------------- | -------------------------- | | [FluentAvaloniaUI](https://github.com/amwx/FluentAvalonia) | UI Components | | [MinecraftLaunch](https://github.com/Blessing-Studio/MinecraftLaunch) | Minecraft Launch Core | | [CurseForge.APIClient](https://github.com/CurseForgeCommunity/.NET-APIClient) | CurseForge API Integration | | [ReactiveUI](https://github.com/reactiveui/reactiveui) | Reactive Programming | | [Newtonsoft.Json](https://www.newtonsoft.com/json) | JSON Processing | | [NAudio](https://github.com/naudio/NAudio) | Audio Processing | | [HtmlAgilityPack](https://github.com/zzzprojects/html-agility-pack) | HTML Parsing | | [Semi.Avalonia](https://github.com/irihitech/Semi.Avalonia) | UI Themes | | [Irihi.Ursa](https://github.com/irihitech/Ursa.Avalonia) | UI Components | | [MinecraftLaunch.Skin](https://github.com/Blessing-Studio/MinecraftLaunch.Skin) | Skin Rendering | | [StarLight_Core](https://github.com/Ink-Marks-Studio/StarLight.Core) | Core Library | | [Afdian.Sdk](https://github.com/yiyungent/Afdian.Sdk) | Afdian SDK | | [AsyncImageLoader.Avalonia](https://github.com/AvaloniaUtils/AsyncImageLoader.Avalonia) | Async Image Loading | | [CommunityToolkit.Mvvm](https://github.com/CommunityToolkit/dotnet) | MVVM Toolkit | | [Tomlyn](https://github.com/xoofx/Tomlyn) | TOML Parsing | ### 📄 License This project is licensed under the **GPL 3.0** License. See [LICENSE](LICENSE) file for details. **GPL 3.0 Highlights:** - Freedom to use, modify, and distribute - Modified versions must remain GPL 3.0 licensed - Must retain original copyright notices - No warranty provided ### 💬 Community - **QQ Group:** 475032328 - **GitHub Issues:** Report bugs and suggest features ### 🤝 Contributing Pull requests and issues are welcome! ### 📝 Changelog See [Releases](https://github.com/yiikooo/YMCL.Avalonia/releases) page for details. ================================================ FILE: README.md ================================================

YMCL Logo

# ⛏️ Yu Minecraft Launcher 🐳 **免费、跨平台、完全开源的 Minecraft 启动器** ![Latest Release](https://img.shields.io/github/v/release/yiikooo/YMCL.Avalonia?logo=github&style=for-the-badge&color=007ec6&label=%E6%9C%80%E6%96%B0%E7%89%88%E6%9C%AC) ![Downloads](https://img.shields.io/github/downloads/yiikooo/YMCL.Avalonia/total?logo=github&label=%E4%B8%8B%E8%BD%BD%E9%87%8F&style=for-the-badge&color=44cc12) ![Stars](https://img.shields.io/github/stars/yiikooo/YMCL.Avalonia?logo=github&label=Star&style=for-the-badge) ![License](https://img.shields.io/badge/GPL%203.0%20License%20-%20?logo=github&label=%E5%BC%80%E6%BA%90%E5%8D%8F%E8%AE%AE&style=for-the-badge&color=ff7a35) [English](README.en.md)
### 📋 项目简介 **Yu Minecraft Launcher (YMCL)** 是一个现代化的跨平台 Minecraft 启动器,采用 Avalonia UI 框架开发,提供流畅的用户体验和强大的功能。无论你是 Minecraft 新手还是资深玩家,YMCL 都能满足你的需求。 ### ✨ 核心功能 - **Mod 管理** - 轻松安装、管理和切换 Mod - **自动安装** - 一键安装 Forge、NeoForge、Fabric、Quilt、OptiFine 等加载器 - **游戏自定义** - 灵活配置游戏参数和启动选项 - **界面自定义** - 个性化启动器外观和主题 - **多账户支持** - 管理多个游戏账户 - **跨平台同步** - 在不同操作系统间无缝切换 ### 🖥️ 平台支持 | 架构 | Windows | Linux | macOS | | ----- | :-----: | :---: | :---: | | x64 | ✅ | ✅ | ✅ | | x86 | ✅ | ❌ | ❌ | | ARM64 | ❔ | ❔ | ❌ | | ARM32 | ❌ | ❔ | ❌ | - ✅ 完全支持 - ❔ 支持但未充分测试 - ❌ 不支持 ### 📥 下载安装 访问 [Releases 页面](https://github.com/yiikooo/YMCL.Avalonia/releases) 下载最新版本。 **系统要求:** - Windows 10 或更高版本 - Ubuntu 20.04 LTS 或更高版本 - macOS 10.15 或更高版本 ### 🚀 快速开始 1. 从 Releases 页面下载适合你系统的版本 2. 安装并启动 YMCL 3. 配置 Java 路径(如需要) 4. 添加游戏账户 5. 选择版本并启动游戏 ### 📖 开发 **技术栈:** - 框架:.NET 8.0+ - UI:Avalonia UI - 架构:MVVM + Reactive **构建项目:** ```bash dotnet build YMCL.sln ``` **运行项目:** ```bash dotnet run --project YMCL.Main/YMCL.Desktop ``` ### 📦 依赖项目 感谢以下开源项目的支持: | 项目 | 用途 | | --------------------------------------------------------------------------------------- | ------------------- | | [FluentAvaloniaUI](https://github.com/amwx/FluentAvalonia) | UI 组件库 | | [MinecraftLaunch](https://github.com/Blessing-Studio/MinecraftLaunch) | Minecraft 启动核心 | | [CurseForge.APIClient](https://github.com/CurseForgeCommunity/.NET-APIClient) | CurseForge API 集成 | | [ReactiveUI](https://github.com/reactiveui/reactiveui) | 响应式编程框架 | | [Newtonsoft.Json](https://www.newtonsoft.com/json) | JSON 处理 | | [NAudio](https://github.com/naudio/NAudio) | 音频处理 | | [HtmlAgilityPack](https://github.com/zzzprojects/html-agility-pack) | HTML 解析 | | [Semi.Avalonia](https://github.com/irihitech/Semi.Avalonia) | UI 主题 | | [Irihi.Ursa](https://github.com/irihitech/Ursa.Avalonia) | UI 组件 | | [MinecraftLaunch.Skin](https://github.com/Blessing-Studio/MinecraftLaunch.Skin) | 皮肤渲染 | | [StarLight_Core](https://github.com/Ink-Marks-Studio/StarLight.Core) | 核心库 | | [Afdian.Sdk](https://github.com/yiyungent/Afdian.Sdk) | 爱发电 SDK | | [AsyncImageLoader.Avalonia](https://github.com/AvaloniaUtils/AsyncImageLoader.Avalonia) | 异步图片加载 | | [CommunityToolkit.Mvvm](https://github.com/CommunityToolkit/dotnet) | MVVM 工具包 | | [Tomlyn](https://github.com/xoofx/Tomlyn) | TOML 解析 | ### 📄 许可证 本项目采用 **GPL 3.0** 开源协议。详见 [LICENSE](LICENSE) 文件。 **GPL 3.0 要点:** - 自由使用、修改和分发 - 修改后的版本必须保持 GPL 3.0 许可 - 必须保留原始版权声明 - 不提供任何形式的保证 ### 💬 社区 - **QQ 群:** 475032328 - **GitHub Issues:** 报告 Bug 和功能建议 ### 🤝 贡献 欢迎提交 Pull Request 和 Issue! ### 📝 更新日志 详见 [Releases](https://github.com/yiikooo/YMCL.Avalonia/releases) 页面。 ================================================ FILE: YMCL.Main/YMCL/App.axaml ================================================ #00feff #00feff #00feff #00feff #00feff #00feff #00feff avares://YMCL/Public/Assets#MiSans Bold 1 5 ================================================ FILE: YMCL.Main/YMCL/App.axaml.cs ================================================ using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.Notifications; using Avalonia.Data.Core.Plugins; using Avalonia.Threading; using YMCL.Public.Module.App.Init; using YMCL.Public.Module.App.Init.SubModule; using YMCL.ViewModels; using YMCL.Views; using YMCL.Views.Initialize; using CrashWindow = YMCL.Views.CrashWindow; using MainView = YMCL.Views.Main.MainView; using MainWindow = YMCL.Views.Main.MainWindow; namespace YMCL; public class App : Application { public static MainView? UiRoot { get; private set; } public override void Initialize() { AvaloniaXamlLoader.Load(this); } public override async void OnFrameworkInitializationCompleted() { if (!Debugger.IsAttached) { AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; Dispatcher.UIThread.UnhandledException += UIThread_UnhandledException; } try { if (!await InitDispatcher.BeforeCreateUi()) return; } catch (Exception e) { Console.WriteLine(e); var win = new CrashWindow(e.ToString()); win.Show(); return; } var ifShowInit = Decision.WhetherToShowInitView(); if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { DisableAvaloniaDataAnnotationValidation(); if (ifShowInit.ifShow) { var view = new InitializeWindow(ifShowInit.page); Data.Notification = new Ursa.Controls.WindowNotificationManager(TopLevel.GetTopLevel(view)); Data.Toast = new Ursa.Controls.WindowToastManager(TopLevel.GetTopLevel(view)); desktop.MainWindow = view; } else { var view = new MainWindow(out var mainView); UiRoot = mainView; Data.Notification = new Ursa.Controls.WindowNotificationManager(TopLevel.GetTopLevel(view)); Data.Toast = new Ursa.Controls.WindowToastManager(TopLevel.GetTopLevel(view)); desktop.MainWindow = view; view.Show(); } } else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform) { if (ifShowInit.ifShow) { var view = new InitializeView(ifShowInit.page); Data.Notification = new Ursa.Controls.WindowNotificationManager(TopLevel.GetTopLevel(view)); Data.Toast = new Ursa.Controls.WindowToastManager(TopLevel.GetTopLevel(view)); singleViewPlatform.MainView = view; } else { var view = new MainView(); UiRoot = view; Data.Notification = new Ursa.Controls.WindowNotificationManager(TopLevel.GetTopLevel(view)); Data.Toast = new Ursa.Controls.WindowToastManager(TopLevel.GetTopLevel(view)); singleViewPlatform.MainView = view; } } Data.Notification.Position = NotificationPosition.BottomRight; Data.Toast.MaxItems = 2; base.OnFrameworkInitializationCompleted(); } private void UIThread_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) { Console.WriteLine(e.Exception); try { var win = new CrashWindow(e.Exception.ToString()); win.Show(); } finally { e.Handled = true; } } private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { Console.WriteLine(e); try { var win = new CrashWindow(e.ToString() ?? "Unhandled Exception"); win.Show(); } catch { // ignored } } private void DisableAvaloniaDataAnnotationValidation() { // Get an array of plugins to remove var dataValidationPluginsToRemove = BindingPlugins.DataValidators.OfType().ToArray(); // remove each entry found foreach (var plugin in dataValidationPluginsToRemove) { BindingPlugins.DataValidators.Remove(plugin); } } } ================================================ FILE: YMCL.Main/YMCL/FodyWeavers.xml ================================================  ================================================ FILE: YMCL.Main/YMCL/FodyWeavers.xsd ================================================  'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. A comma-separated list of error codes that can be safely ignored in assembly verification. 'false' to turn off automatic generation of the XML Schema file. ================================================ FILE: YMCL.Main/YMCL/GlobalUsings.cs ================================================ // global using 指令 global using System; global using Avalonia; global using Avalonia.Controls; global using Avalonia.Markup.Xaml; global using YMCL.Public.Const; global using static YMCL.Public.Module.Ui.Shower; global using Task = System.Threading.Tasks.Task; global using JavaEntry = YMCL.Public.Classes.Data.JavaEntry; ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Data/AggregateSearchEntry.cs ================================================ using MinecraftLaunch.Base.Models.Game; using MinecraftLaunch.Base.Models.Network; using YMCL.Public.Classes.Setting; namespace YMCL.Public.Classes.Data; public class AggregateSearchEntry() { public string Tag { get; set; } public int Order { get; set; } public string Type { get; set; } public string Summary { get; set; } public string Text { get; set; } public string? Target { get; set; } public MinecraftEntry? MinecraftEntry { get; set; } public VersionManifestEntry? VersionManifestEntry { get; set; } public string? Keyword { get; set; } public AccountInfo? Account { get; set; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Data/FavouriteResourceEntry.cs ================================================ using Newtonsoft.Json; using YMCL.Public.Classes.Data.ResourceFetcher; using YMCL.Public.Enum; using YMCL.Public.Langs; namespace YMCL.Public.Classes.Data; public record FavouriteResourceEntry { public ResourceSource Source { get; set; } = ResourceSource.Unknown; public ResourceType Type { get; set; } = ResourceType.Unknown; [JsonIgnore] public string DisplayType => Type switch { ResourceType.Mod => MainLang.Mod, ResourceType.DataPack => MainLang.DataPack, ResourceType.ResourcePack => MainLang.MaterialPack, ResourceType.ShaderPack => MainLang.ShaderPack, ResourceType.ModPack => MainLang.ModPack, ResourceType.Plugin => MainLang.Plugin, _ => MainLang.Unknown, }; public string Id { get; set; } public string Summary { get; set; } public string Icon { get; set; } public string Title { get; set; } public virtual bool Equals(FavouriteResourceEntry? other) { return Source == other?.Source && Id == other?.Id; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Data/JavaEntry.cs ================================================ namespace YMCL.Public.Classes.Data; public sealed record JavaEntry { public bool Is64bit { get; init; } public string JavaPath { get; set; } public string JavaType { get; init; } public string JavaVersion { get; init; } public string JavaFolder { get; init; } public int MajorVersion { get; init; } public bool Equals(JavaEntry? other) { if (other == null) return false; if (other.JavaVersion == "Auto" && JavaVersion == "Auto") return true; if (other.JavaVersion == "Global" && JavaVersion == "Global") return true; return Is64bit == other.Is64bit && JavaPath == other.JavaPath && JavaType == other.JavaType; } public static JavaEntry MlToYmcl(MinecraftLaunch.Base.Models.Game.JavaEntry entry) { return new JavaEntry { Is64bit = entry.Is64bit, JavaVersion = entry.JavaVersion, JavaPath = entry.JavaPath, JavaType = entry.JavaType, JavaFolder = entry.JavaFolder, MajorVersion = entry.MajorVersion }; } public static MinecraftLaunch.Base.Models.Game.JavaEntry YmclToMl(JavaEntry entry) { return new MinecraftLaunch.Base.Models.Game.JavaEntry { Is64bit = entry.Is64bit, JavaVersion = entry.JavaVersion, JavaPath = entry.JavaPath, JavaType = entry.JavaType, MajorVersion = entry.MajorVersion, }; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Data/Language.cs ================================================ namespace YMCL.Public.Classes.Data; public record Language { public string? Code { get; set; } public string? Label { get; set; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Data/LocalModEntry.cs ================================================ using System.IO; using Avalonia.Media; using FluentAvalonia.UI.Controls; using Microsoft.VisualBasic.FileIO; using ReactiveUI; using ReactiveUI.Fody.Helpers; using YMCL.Public.Enum; using YMCL.Public.Langs; namespace YMCL.Public.Classes.Data; public class LocalModEntry : ReactiveObject { [Reactive] public string FileName { get; set; } [Reactive] public string Path { get; set; } [Reactive] public bool IsEnable { get; set; } [Reactive] public Action Callback { get; set; } public TextDecorationCollection? Decoration => !IsEnable ? TextDecorations.Strikethrough : null; [Reactive] public string DisplayText { get; set; } [Reactive] public string Description { get; set; } [Reactive] public bool ShouldTranslateDescription { get; set; } = false; [Reactive] public bool ShouldTranslateInfoName { get; set; } = false; [Reactive] public string ModInfoName { get; set; } public void EnableOrDisable() { if (string.IsNullOrWhiteSpace(System.IO.Path.GetDirectoryName(Path))) return; if (System.IO.Path.GetExtension(Path) == ".disabled") File.Move(Path, System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Path)!, $"{FileName}.jar")); if (System.IO.Path.GetExtension(Path) == ".jar") File.Move(Path, Path + ".disabled"); Callback?.Invoke(); } public async Task Delete() { var text = $"• {System.IO.Path.GetFileName(FileName)}"; var title = YMCL.Public.Const.Data.DesktopType == DesktopRunnerType.Windows ? MainLang.MoveToRecycleBin : MainLang.DeleteSelect; var dialog = await ShowDialogAsync(title, text, b_cancel: MainLang.Cancel, b_primary: MainLang.Ok); if (dialog != ContentDialogResult.Primary) return; if (YMCL.Public.Const.Data.DesktopType == DesktopRunnerType.Windows) { FileSystem.DeleteFile(Path, UIOption.AllDialogs, RecycleOption.SendToRecycleBin); } else { File.Delete(Path); } Callback?.Invoke(); } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Data/LocalResourcePackEntry.cs ================================================ using Avalonia.Media.Imaging; using ReactiveUI; using ReactiveUI.Fody.Helpers; namespace YMCL.Public.Classes.Data; public class LocalResourcePackEntry : ReactiveObject { [Reactive] public string Name { get; set; } [Reactive] public string Path { get; set; } [Reactive] public Bitmap Icon { get; set; } [Reactive] public string Description { get; set; } = string.Empty; } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Data/LocalSaveEntry.cs ================================================ using System.IO; using Avalonia.Media.Imaging; using Avalonia.Platform.Storage; using FluentAvalonia.UI.Controls; using Microsoft.VisualBasic.FileIO; using ReactiveUI; using ReactiveUI.Fody.Helpers; using YMCL.Public.Enum; using YMCL.Public.Langs; using YMCL.Public.Module.IO.Disk; using YMCL.Views.Main.Pages.LaunchPages.SubPages; namespace YMCL.Public.Classes.Data; public class LocalSaveEntry : ReactiveObject { [Reactive] public string Name { get; set; } [Reactive] public string Path { get; set; } [Reactive] public Bitmap Icon { get; set; } [Reactive] public string Description { get; set; } = string.Empty; [Reactive] public Save.SaveInfo SaveInfo { get; set; } [Reactive] public Action Callback { get; set; } public async Task Delete() { var text = $"• {System.IO.Path.GetFileName(Name)}"; var title = YMCL.Public.Const.Data.DesktopType == DesktopRunnerType.Windows ? MainLang.MoveToRecycleBin : MainLang.DeleteSelect; var dialog = await ShowDialogAsync(title, text, b_cancel: MainLang.Cancel, b_primary: MainLang.Ok); if (dialog != ContentDialogResult.Primary) return; if (YMCL.Public.Const.Data.DesktopType == DesktopRunnerType.Windows) { FileSystem.DeleteDirectory(Path, UIOption.AllDialogs, RecycleOption.SendToRecycleBin); } else { Directory.Delete(Path); } Callback?.Invoke(); } public async Task ShowInfo() { var text = $"{MainLang.Name}: {SaveInfo.FolderName}\n" + $"{MainLang.Seed}: {SaveInfo.Seed}\n" + $"{MainLang.GameVersion}: {SaveInfo.Version}\n" + $"{MainLang.AllowCommands}: {SaveInfo.AllowCommands}\n" + $"{MainLang.GameType}: {SaveInfo.GameType}\n" + $"{MainLang.CreateTime}: {SaveInfo.CreationTime}\n" + $"{MainLang.LastPlayTime}: {SaveInfo.LastPlayTime}\n" + $"{MainLang.LastModifiedTime}: {SaveInfo.LastWriteTime}\n" + $"{MainLang.PlayerCount}: {SaveInfo.DatFileCount}\n" + $"{MainLang.DataPackCount}: {SaveInfo.ZipFileCount}"; await ShowDialogAsync(MainLang.SaveInfo, text, b_primary: MainLang.Ok); Callback?.Invoke(); } public void OpenFolder() { var path = SaveInfo.FolderPath; YMCL.Public.Module.IO.Disk.Setter.TryCreateFolder(path); _ = Opener.OpenFolder(path); } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Data/LogItemEntry.cs ================================================ using YMCL.Public.Enum; namespace YMCL.Public.Classes.Data; public class LogItemEntry { public string Message { get; set; } = string.Empty; public string Original { get; set; } public string Time { get; set; } public LogType Type { get; set; } public string Source { get; set; } public void SetOriginal() { Original = $"[{Time}] [{Source}/{Type}] {Message}"; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Data/MinecraftFolder.cs ================================================ namespace YMCL.Public.Classes.Data; public sealed record MinecraftFolder { public string Path { get; set; } public string Name { get; set; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Data/ModrinthFile.cs ================================================ using YMCL.Public.Module.Util.Extension; namespace YMCL.Public.Classes.Data; public class ModrinthFile { public int Size { get; set; } public string DisplaySize => Size.ToByteUnit(); public string FileName { get; set; } public string Title { get; set; } public string Url { get; set; } public int Downloads { get; set; } public string DisplayDownloads => Convert.ToDouble(Downloads).ToUnit(); public DateTime UpdateTime { get; set; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Data/NewsDataListEntry.cs ================================================ namespace YMCL.Public.Classes.Data; public class NewsDataListEntry() { public string Url { get; set; } public string Data { get; set; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Data/NotificationEntry.cs ================================================ using Avalonia.Controls.Notifications; namespace YMCL.Public.Classes.Data; public record NotificationEntry(object Content, NotificationType Type) { public object Content { get; set; } = Content; public NotificationType Type { get; set; } = Type; public virtual bool Equals(NotificationEntry? other) { return Content == other?.Content; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Data/ResourceFetcher/CurseForgeResourceEntry.cs ================================================ using System.Collections.Generic; using CurseForge.APIClient.Models; using CurseForge.APIClient.Models.Files; using CurseForge.APIClient.Models.Mods; using YMCL.Public.Enum; using YMCL.Public.Langs; namespace YMCL.Public.Classes.Data.ResourceFetcher; public class CurseForgeResourceEntry : IResourceEntry { string IResourceEntry.Summary => Summary; string IResourceEntry.Name => Name; ResourceSource IResourceEntry.Source => ResourceSource.CurseForge; DateTime IResourceEntry.LastUpdateTime => DateModified.DateTime; public string DisplayType => Type switch { ResourceType.Mod => MainLang.Mod, ResourceType.Map => MainLang.Map, ResourceType.DataPack => MainLang.DataPack, ResourceType.ResourcePack => MainLang.MaterialPack, ResourceType.ShaderPack => MainLang.ShaderPack, ResourceType.ModPack => MainLang.ModPack, _ => MainLang.Unknown, }; public ResourceType Type { get; set; } = ResourceType.Unknown; ulong IResourceEntry.DownloadCount => Convert.ToUInt64(DownloadCount); public int Id { get; set; } public int GameId { get; set; } public string Name { get; set; } public string Slug { get; set; } public ModLinks Links { get; set; } public string Summary { get; set; } string IResourceEntry.Pic => Logo?.Url; public ModStatus Status { get; set; } public double DownloadCount { get; set; } public bool IsFeatured { get; set; } public int PrimaryCategoryId { get; set; } public List Categories { get; set; } = []; public int? ClassId { get; set; } public List Authors { get; set; } = []; public ModAsset Logo { get; set; } public List Screenshots { get; set; } = []; public int MainFileId { get; set; } public List LatestFiles { get; set; } = []; public List LatestFilesIndexes { get; set; } = []; public DateTimeOffset DateCreated { get; set; } public DateTimeOffset DateModified { get; set; } public DateTimeOffset DateReleased { get; set; } public bool? AllowModDistribution { get; set; } public int GamePopularityRank { get; set; } public bool IsAvailable { get; set; } public int ThumbsUpCount { get; set; } public double? Rating { get; set; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Data/ResourceFetcher/CurseForgeResourceFileEntry.cs ================================================ using System.Collections.Generic; using CurseForge.APIClient.Models.Files; using CurseForge.APIClient.Models.Games; namespace YMCL.Public.Classes.Data.ResourceFetcher; public class CurseForgeResourceFileEntry : IResourceFileEntry { public int Id { get; set; } public int GameId { get; set; } public int ModId { get; set; } public bool IsAvailable { get; set; } public string DisplayName { get; set; } public string FileName { get; set; } public FileReleaseType ReleaseType { get; set; } public FileStatus FileStatus { get; set; } public List Hashes { get; set; } = []; public DateTimeOffset FileDate { get; set; } public long FileLength { get; set; } public long? FileSizeOnDisk { get; set; } public string Name { get; set; } public List McVersions { get; set; } public List Dependency { get; set; } public string Loader { get; set; } ulong IResourceFileEntry.DownloadCount => Convert.ToUInt64(DownloadCount); public long DownloadCount { get; set; } public string DownloadUrl { get; set; } public DateTime UpdateTime => FileDate.DateTime; public List GameVersions { get; set; } = []; public List SortableGameVersions { get; set; } = []; public List Dependencies { get; set; } = []; public bool? ExposeAsAlternative { get; set; } public int? ParentProjectFileId { get; set; } public int? AlternateFileId { get; set; } public bool? IsServerPack { get; set; } public int? ServerPackFileId { get; set; } public bool? IsEarlyAccessContent { get; set; } public DateTimeOffset? EarlyAccessEndDate { get; set; } public long FileFingerprint { get; set; } public List Modules { get; set; } = []; } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Data/ResourceFetcher/IResourceEntry.cs ================================================ using YMCL.Public.Enum; namespace YMCL.Public.Classes.Data.ResourceFetcher; public interface IResourceEntry { public string Name { get; } public string Summary { get; } public string Pic { get; } public string DisplayType { get; } public ulong DownloadCount { get; } public DateTime LastUpdateTime { get; } public ResourceSource Source { get; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Data/ResourceFetcher/IResourceFileEntry.cs ================================================ using System.Collections.Generic; namespace YMCL.Public.Classes.Data.ResourceFetcher; public interface IResourceFileEntry { public string Name { get; set; } public List McVersions { get; set; } public List Dependency { get; set; } public string Loader { get; set; } public ulong DownloadCount { get; } public string DownloadUrl { get; set; } public DateTime UpdateTime { get; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Data/ResourceFetcher/ModFileUiEntry.cs ================================================ using System.Collections.ObjectModel; using CurseForge.APIClient.Models.Files; using YMCL.Public.Enum; namespace YMCL.Public.Classes.Data.ResourceFetcher; public record ShortVersionEntry { public ObservableCollection VersionEntries { get; set; } = []; public string Version { get; set; } public string DisplayVersion { get; set; } } public record VersionEntry { public string Name => $"{Version} {Loader}"; public string Version { get; set; } public string Loader { get; set; } public Control Expander { get; set; } } public record ModFile { public string GameVersion { get; set; } public int FileId { get; set; } public string Filename { get; set; } public FileReleaseType ReleaseType { get; set; } public ModLoaderType Loader { get; set; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Data/ResourceFetcher/ModrinthResourceEntry.cs ================================================ using System.Runtime.CompilerServices; using System.Text.Json.Serialization; using Modrinth.Extensions; using Modrinth.Models; using Modrinth.Models.Enums; using Modrinth.Models.Enums.Project; using YMCL.Public.Enum; using YMCL.Public.Langs; using YMCL.Public.Module.Util.Extension; namespace YMCL.Public.Classes.Data.ResourceFetcher; public class ModrinthResourceEntry: IResourceEntry { public string Url => this.GetDirectUrl(); public string? Slug { get; set; } public string? Title { get; set; } public string? Description { get; set; } public string[] Categories { get; set; } public Side? ClientSide { get; set; } public Side? ServerSide { get; set; } public ProjectType ProjectType { get; set; } public int Downloads { get; set; } public string? IconUrl { get; set; } public string ProjectId { get; set; } public string Author { get; set; } public string[] DisplayCategories { get; set; } public DateTime DateCreated { get; set; } public DateTime DateModified { get; set; } public int Followers { get; set; } public string? LatestVersion { get; set; } public string License { get; set; } public string[] Versions { get; set; } public string[] Gallery { get; set; } public System.Drawing.Color? Color { get; set; } public string? FeaturedGallery { get; set; } public string[] Dependencies { get; set; } public string Name => Title; public string Summary => Description; public string Pic => IconUrl; public string DisplayType => ProjectType switch { ProjectType.Mod => MainLang.Mod, ProjectType.Datapack => MainLang.DataPack, ProjectType.Resourcepack => MainLang.MaterialPack, ProjectType.Shader => MainLang.ShaderPack, ProjectType.Modpack => MainLang.ModPack, ProjectType.Plugin => MainLang.Plugin, _ => MainLang.Unknown, }; public ulong DownloadCount => Convert.ToUInt64(Downloads); public DateTime LastUpdateTime => DateModified; public ResourceSource Source => ResourceSource.Modrinth; } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Data/SearchTabViewItemEntry.cs ================================================ using System.Linq; namespace YMCL.Public.Classes.Data; public record SearchTabViewItemEntry { public UserControl Content { get; set; } public string Title { get; set; } public string Tag { get; set; } public string Host { get; set; } public bool CanClose { get; set; } public void Close() { if (Host == nameof(Views.Main.Pages.DownloadPages.CurseForge)) { if (YMCL.App.UiRoot.ViewModel.Download._curseForge.SelectedItem == this) { YMCL.App.UiRoot.ViewModel.Download._curseForge.Items.Remove(this); YMCL.App.UiRoot.ViewModel.Download._curseForge.SelectedItem = YMCL.App.UiRoot.ViewModel.Download._curseForge.Items.LastOrDefault(); } else { YMCL.App.UiRoot.ViewModel.Download._curseForge.Items.Remove(this); } } else if (Host == nameof(Views.Main.Pages.DownloadPages.Modrinth)) { if (YMCL.App.UiRoot.ViewModel.Download._modrinth.SelectedItem == this) { YMCL.App.UiRoot.ViewModel.Download._modrinth.Items.Remove(this); YMCL.App.UiRoot.ViewModel.Download._modrinth.SelectedItem = YMCL.App.UiRoot.ViewModel.Download._modrinth.Items.LastOrDefault(); } else { YMCL.App.UiRoot.ViewModel.Download._modrinth.Items.Remove(this); } } else { throw new NotImplementedException(); } GC.Collect(2, GCCollectionMode.Aggressive, true); } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Data/Update.cs ================================================ namespace YMCL.Public.Classes.Data; public record CheckUpdateInfo { public bool Success { get; init; } public bool IsNeedUpdate { get; init; } public string NewVersion { get; init; } public string GithubUrl { get; init; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Json/AfdianSponsor.cs ================================================ using System.Collections.Generic; namespace YMCL.Public.Classes.Json; public class AfdianSponsor { public class Config { } public class Sponsor_plansItem { public double can_ali_agreement { get; set; } public string plan_id { get; set; } public double rank { get; set; } public string user_id { get; set; } public double status { get; set; } public string name { get; set; } public string pic { get; set; } public string desc { get; set; } public string price { get; set; } public double update_time { get; set; } public Timing timing { get; set; } public double pay_month { get; set; } public string show_price { get; set; } public string show_price_after_adjust { get; set; } public double has_coupon { get; set; } public List coupon { get; set; } public double favorable_price { get; set; } public double independent { get; set; } public double permanent { get; set; } public double can_buy_hide { get; set; } public double need_address { get; set; } public double product_type { get; set; } public double sale_limit_count { get; set; } public string need_invite_code { get; set; } public double bundle_stock { get; set; } public double bundle_sku_select_count { get; set; } public Config config { get; set; } public double has_plan_config { get; set; } public List shipping_fee_info { get; set; } public double expire_time { get; set; } public List sku_processed { get; set; } public double rankType { get; set; } } public class Timing { public double timing_on { get; set; } public double timing_off { get; set; } } public class Current_plan { public double can_ali_agreement { get; set; } public string plan_id { get; set; } public double rank { get; set; } public string user_id { get; set; } public double status { get; set; } public string name { get; set; } public string pic { get; set; } public string desc { get; set; } public string price { get; set; } public double update_time { get; set; } public Timing timing { get; set; } public double pay_month { get; set; } public string show_price { get; set; } public string show_price_after_adjust { get; set; } public double has_coupon { get; set; } public List coupon { get; set; } public double favorable_price { get; set; } public double independent { get; set; } public double permanent { get; set; } public double can_buy_hide { get; set; } public double need_address { get; set; } public double product_type { get; set; } public double sale_limit_count { get; set; } public string need_invite_code { get; set; } public double bundle_stock { get; set; } public double bundle_sku_select_count { get; set; } public Config config { get; set; } public double has_plan_config { get; set; } public List shipping_fee_info { get; set; } public double expire_time { get; set; } public List sku_processed { get; set; } public double rankType { get; set; } } public class User { public string user_id { get; set; } public string name { get; set; } public string avatar { get; set; } public string user_private_id { get; set; } } public class ListItem { public List sponsor_plans { get; set; } public Current_plan current_plan { get; set; } public string all_sum_amount { get; set; } public double first_pay_time { get; set; } public double last_pay_time { get; set; } public User user { get; set; } } public class Request { public string user_id { get; set; } public string @params { get; set; } public double ts { get; set; } public string sign { get; set; } } public class Data { public double total_count { get; set; } public double total_page { get; set; } public List list { get; set; } public Request request { get; set; } } public class Root { public double ec { get; set; } public string em { get; set; } public Data data { get; set; } } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Json/ModrinchVersionEntry.cs ================================================ using System.Collections.Generic; using System.Text.Json.Serialization; namespace YMCL.Public.Classes.Json; public class ModrinthVersionEntry { public class Root { public List game_versions { get; set; } [JsonPropertyName("loaders")] public List Loaders { get; set; } [JsonPropertyName("id")] public string Id { get; set; } [JsonPropertyName("project_id")] public string ProjectId { get; set; } [JsonPropertyName("author_id")] public string AuthorId { get; set; } [JsonPropertyName("featured")] public bool Featured { get; set; } [JsonPropertyName("name")] public string Name { get; set; } [JsonPropertyName("version_number")] public string VersionNumber { get; set; } [JsonPropertyName("changelog")] public string Changelog { get; set; } [JsonPropertyName("changelog_url")] public string ChangelogUrl { get; set; } public DateTime date_published { get; set; } [JsonPropertyName("downloads")] public int Downloads { get; set; } [JsonPropertyName("version_type")] public string VersionType { get; set; } [JsonPropertyName("status")] public string Status { get; set; } [JsonPropertyName("requested_status")] public object RequestedStatus { get; set; } [JsonPropertyName("files")] public List Files { get; set; } [JsonPropertyName("dependencies")] public List Dependencies { get; set; } } public class File { [JsonPropertyName("hashes")] public Dictionary Hashes { get; set; } [JsonPropertyName("url")] public string Url { get; set; } [JsonPropertyName("filename")] public string Filename { get; set; } [JsonPropertyName("primary")] public bool Primary { get; set; } [JsonPropertyName("size")] public int Size { get; set; } [JsonPropertyName("file_type")] public object FileType { get; set; } } public class Dependency { [JsonPropertyName("version_id")] public object VersionId { get; set; } [JsonPropertyName("project_id")] public string ProjectId { get; set; } [JsonPropertyName("file_name")] public object FileName { get; set; } [JsonPropertyName("dependency_type")] public string DependencyType { get; set; } } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Json/MojangJavaNews.cs ================================================ using System.Collections.Generic; namespace YMCL.Public.Classes.Json; public class MojangJavaNews() { public class Image { /// /// /// public string title { get; set; } /// /// /// public string url { get; set; } } public class EntriesItem { /// /// /// public string title { get; set; } /// /// /// public string version { get; set; } /// /// /// public string type { get; set; } /// /// /// public Image image { get; set; } /// /// /// public string contentPath { get; set; } /// /// /// public string id { get; set; } /// /// /// public string date { get; set; } /// /// /// public string shortText { get; set; } } public class Root { /// /// /// public int version { get; set; } /// /// /// public List entries { get; set; } } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Netease/Availability.cs ================================================ namespace YMCL.Public.Classes.Netease; public class Availability { public class Root { public bool success { get; set; } public string message { get; set; } public int code { get; set; } } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Netease/DefaultKeyword.cs ================================================ namespace YMCL.Public.Classes.Netease; public class DefaultKeyword { public class StyleKeyword { public string keyWord { get; set; } public object descWord { get; set; } } public class Data { public string showKeyword { get; set; } public StyleKeyword styleKeyword { get; set; } public string realkeyword { get; set; } public int searchType { get; set; } public int action { get; set; } public string alg { get; set; } public int gap { get; set; } public object source { get; set; } public string bizQueryInfo { get; set; } public object logInfo { get; set; } public object imageUrl { get; set; } public object trp_type { get; set; } public object trp_id { get; set; } } public class Root { public int code { get; set; } public object message { get; set; } public Data data { get; set; } } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Netease/Lyric.cs ================================================ using System.Collections.Generic; namespace YMCL.Public.Classes.Netease; public class Lyric { public class LyricInfo { public int t { get; set; } public List c { get; set; } } public class LyricPart { public string tx { get; set; } public string li { get; set; } public string or { get; set; } } public class LyricItem { public int version { get; set; } public string lyric { get; set; } } public class Root { public bool sgc { get; set; } public bool sfy { get; set; } public bool qfy { get; set; } public User transUser { get; set; } public User lyricUser { get; set; } public LyricItem lrc { get; set; } public LyricItem klyric { get; set; } public LyricItem tlyric { get; set; } public LyricItem romalrc { get; set; } public LyricItem yrc { get; set; } public LyricItem ytlrc { get; set; } public LyricItem yromalrc { get; set; } public int code { get; set; } } public class User { public int id { get; set; } public int status { get; set; } public int demand { get; set; } public int userid { get; set; } public string nickname { get; set; } public long uptime { get; set; } } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Netease/PlayList.cs ================================================ using System.Collections.Generic; namespace YMCL.Public.Classes.Netease; public class PlayList { public class Creator { public string nickname { get; set; } public long userId { get; set; } public int userType { get; set; } public object avatarUrl { get; set; } public int authStatus { get; set; } public object expertTags { get; set; } public object experts { get; set; } } public class Playlist { public long id { get; set; } public string name { get; set; } public string coverImgUrl { get; set; } public Creator creator { get; set; } public bool subscribed { get; set; } public int trackCount { get; set; } public long userId { get; set; } public long playCount { get; set; } public long bookCount { get; set; } public int specialType { get; set; } public object officialTags { get; set; } public object action { get; set; } public object actionType { get; set; } public object recommendText { get; set; } public object score { get; set; } public string description { get; set; } public bool highQuality { get; set; } } public class Result { public object searchQcReminder { get; set; } public List playlists { get; set; } public int playlistCount { get; set; } } public class Root { public Result result { get; set; } public int code { get; set; } } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Netease/RecordSongEntry.cs ================================================ namespace YMCL.Public.Classes.Netease; public class RecordSongEntry { public Enum.SongType Type { get; set; } = Enum.SongType.Unknown; public string SongPicUri { get; set; } = string.Empty; public string DisplayNumber { get; set; }=string.Empty; public uint Number { get; set; } = 0; public string SongName { get; set; } = string.Empty; public double SongId { get; set; } = -1; public string SongAuthors { get; set; } = string.Empty; public TimeSpan Duration { get; set; } public string DisplayDuration { get; set; } = string.Empty; public double AlbumId { get; set; } = -1; public string AlbumName { get; set; } = string.Empty; public string Path { get; set; } = string.Empty; } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Netease/SingleSong.cs ================================================ using System.Collections.Generic; namespace YMCL.Public.Classes.Netease; public class SearchSingleSong { public class ArItem { /// /// public double id { get; set; } /// /// 葛雨晴 /// public string name { get; set; } /// /// public List tns { get; set; } /// /// public List alias { get; set; } } public class Al { /// /// public double id { get; set; } /// /// 逃向宇宙 /// public string name { get; set; } /// /// public string picUrl { get; set; } /// /// public List tns { get; set; } /// /// public string pic_str { get; set; } /// /// public double pic { get; set; } } public class H { /// /// public double br { get; set; } /// /// public double fid { get; set; } /// /// public double size { get; set; } /// /// public double vd { get; set; } /// /// public double sr { get; set; } } public class M { /// /// public double br { get; set; } /// /// public double fid { get; set; } /// /// public double size { get; set; } /// /// public double vd { get; set; } /// /// public double sr { get; set; } } public class L { /// /// public double br { get; set; } /// /// public double fid { get; set; } /// /// public double size { get; set; } /// /// public double vd { get; set; } /// /// public double sr { get; set; } } public class Sq { /// /// public double br { get; set; } /// /// public double fid { get; set; } /// /// public double size { get; set; } /// /// public double vd { get; set; } /// /// public double sr { get; set; } } public class FreeTrialPrivilege { /// /// public string resConsumable { get; set; } /// /// public string userConsumable { get; set; } /// /// public string listenType { get; set; } /// /// public string cannotListenReason { get; set; } } public class ChargeInfoListItem { /// /// public double rate { get; set; } /// /// public string chargeUrl { get; set; } /// /// public string chargeMessage { get; set; } /// /// public double chargeType { get; set; } } public class Privilege { /// /// public double id { get; set; } /// /// public double fee { get; set; } /// /// public double payed { get; set; } /// /// public double st { get; set; } /// /// public double pl { get; set; } /// /// public double dl { get; set; } /// /// public double sp { get; set; } /// /// public double cp { get; set; } /// /// public double subp { get; set; } /// /// public string cs { get; set; } /// /// public double maxbr { get; set; } /// /// public double fl { get; set; } /// /// public string toast { get; set; } /// /// public double flag { get; set; } /// /// public string preSell { get; set; } /// /// public double playMaxbr { get; set; } /// /// public double downloadMaxbr { get; set; } /// /// public string maxBrLevel { get; set; } /// /// public string playMaxBrLevel { get; set; } /// /// public string downloadMaxBrLevel { get; set; } /// /// public string plLevel { get; set; } /// /// public string dlLevel { get; set; } /// /// public string flLevel { get; set; } /// /// public string rscl { get; set; } /// /// public FreeTrialPrivilege freeTrialPrivilege { get; set; } /// /// public double rightSource { get; set; } /// /// public List chargeInfoList { get; set; } } public class SongsItem { public string name { get; set; } public double id { get; set; } public List ar { get; set; } public Al al { get; set; } public double dt { get; set; } } public class Result { /// /// /// //public string searchQcReminder { get; set; } /// /// public List songs { get; set; } /// /// public double songCount { get; set; } } public class Root { /// /// public Result result { get; set; } /// /// public double code { get; set; } } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Netease/SongUrl.cs ================================================ using System.Collections.Generic; namespace YMCL.Public.Classes.Netease; public class SongUrl { public class DataItem { public string url { get; set; } public double time { get; set; } } public class Root { /// /// /// public List data { get; set; } /// /// /// public int code { get; set; } } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Operate/FavouriteMinecraftEntry.cs ================================================ using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using Avalonia.Controls.Notifications; using Avalonia.Layout; using Avalonia.Media; using Avalonia.Media.Imaging; using Avalonia.Platform.Storage; using FluentAvalonia.UI.Controls; using MinecraftLaunch.Components.Parser; using Newtonsoft.Json; using YMCL.Public.Langs; using YMCL.Public.Module.Mc; using YMCL.Public.Module.Mc.Launcher; using YMCL.Public.Module.Value; namespace YMCL.Public.Classes.Operate; public sealed class FavouriteMinecraftEntry : INotifyPropertyChanged { private string _iconBase64; private string _minecraftPath; private string _minecraftId; private string _displayName; private string _serverUrl; private string _worldName; private bool _isSupportJoinWorld = true; [JsonIgnore] public Bitmap Bitmap => Converter.Base64ToBitmap(IconBase64); [JsonProperty] public string IconBase64 { get => _iconBase64; set { if (SetField(ref _iconBase64, value)) OnPropertyChanged(nameof(Bitmap)); } } [JsonProperty] public string MinecraftPath { get => _minecraftPath; set => SetField(ref _minecraftPath, value); } [JsonProperty] public string MinecraftId { get => _minecraftId; set => SetField(ref _minecraftId, value); } [JsonProperty] public bool IsSupportJoinWorld { get => _isSupportJoinWorld; set => SetField(ref _isSupportJoinWorld, value); } [JsonProperty] public string DisplayName { get => _displayName; set => SetField(ref _displayName, value); } [JsonProperty] public string ServerUrl { get => _serverUrl; set => SetField(ref _serverUrl, value); } [JsonProperty] public string WorldName { get => _worldName; set => SetField(ref _worldName, value); } public bool Equals(FavouriteMinecraftEntry? other) { return other != null && MinecraftPath == other?.MinecraftPath && MinecraftId == other.MinecraftId && DisplayName == other.DisplayName && ServerUrl == other.ServerUrl; } public async void Rename() { var textBox = new TextBox { FontFamily = (FontFamily)Application.Current.Resources["Font"], TextWrapping = TextWrapping.Wrap, Text = DisplayName, HorizontalAlignment = HorizontalAlignment.Stretch, Width = 500 }; var cr = await ShowDialogAsync(MainLang.Rename, p_content: textBox, b_cancel: MainLang.Cancel, b_primary: MainLang.Ok); if (cr != ContentDialogResult.Primary) return; DisplayName = textBox.Text ?? MinecraftId; await File.WriteAllTextAsync(ConfigPath.FavouriteMinecraftDataPath, JsonConvert.SerializeObject(Const.Data.FavouriteMinecraft, Formatting.Indented)); } public void Del() { Const.Data.FavouriteMinecraft.Remove(this); File.WriteAllText(ConfigPath.FavouriteMinecraftDataPath, JsonConvert.SerializeObject(Const.Data.FavouriteMinecraft, Formatting.Indented)); } public async void SetIcon() { var list = await TopLevel.GetTopLevel(App.UiRoot).StorageProvider.OpenFilePickerAsync( new FilePickerOpenOptions { AllowMultiple = false, FileTypeFilter = [FilePickerFileTypes.ImageAll] }); if (list.Count == 0) return; try { var bitmap = new Bitmap(list[0].Path.LocalPath); IconBase64 = Converter.BitmapToBase64(bitmap); Notice(MainLang.OperateSuccess); } catch { Notice(MainLang.OperateFailed); } await File.WriteAllTextAsync(ConfigPath.FavouriteMinecraftDataPath, JsonConvert.SerializeObject(Const.Data.FavouriteMinecraft, Formatting.Indented)); } public async void SetServer() { var textBox = new TextBox { FontFamily = (FontFamily)Application.Current.Resources["Font"], TextWrapping = TextWrapping.Wrap, Text = ServerUrl, HorizontalAlignment = HorizontalAlignment.Stretch, Width = 500, Watermark = "example.com:25565" }; var cr = await ShowDialogAsync(MainLang.Rename, MainLang.SetAutoJoinServerTip, p_content: textBox, b_cancel: MainLang.Cancel, b_primary: MainLang.Ok); if (cr != ContentDialogResult.Primary) return; ServerUrl = textBox.Text ?? string.Empty; WorldName = string.Empty; await File.WriteAllTextAsync(ConfigPath.FavouriteMinecraftDataPath, JsonConvert.SerializeObject(Const.Data.FavouriteMinecraft, Formatting.Indented)); } public async void SetWorld() { var textBox = new TextBox { FontFamily = (FontFamily)Application.Current.Resources["Font"], TextWrapping = TextWrapping.Wrap, Text = WorldName, HorizontalAlignment = HorizontalAlignment.Stretch, Width = 500, Watermark = MainLang.SavesName }; var cr = await ShowDialogAsync(MainLang.Rename, IsSupportJoinWorld ? MainLang.SetAutoJoinWorldTip : $"{MainLang.CurrentVersionUnsupportOperation}\n{MainLang.SetAutoJoinWorldTip}", p_content: textBox, b_cancel: MainLang.Cancel, b_primary: MainLang.Ok); if (cr != ContentDialogResult.Primary) return; ServerUrl = string.Empty; WorldName = textBox.Text ?? string.Empty; await File.WriteAllTextAsync(ConfigPath.FavouriteMinecraftDataPath, JsonConvert.SerializeObject(Const.Data.FavouriteMinecraft, Formatting.Indented)); } public void Launch() { if (!Directory.Exists(MinecraftPath)) { Notice(MainLang.FolderNotExist, NotificationType.Error); return; } var parser = new MinecraftParser(MinecraftPath); var entry = parser.GetMinecraft(MinecraftId); if (entry == null) { Notice(MainLang.CreateGameEntryFail, NotificationType.Error); return; } var setting = MinecraftSetting.GetGameSetting(entry); MinecraftSetting.HandleGameSetting(setting); if (setting.Java.JavaVersion == "Auto") { setting.Java = YMCL.Public.Module.Value.Calculator.GetCurrentJava(Const.Data.JavaRuntimes.ToList(), entry); } if (setting.Java.JavaPath == "Error") { Notice($"{MainLang.CannotFandRightJava}\n{setting.Java.JavaVersion}", NotificationType.Error); return; } if (setting.Java.JavaPath == null) { Notice(MainLang.JavaRuntimeError, NotificationType.Error); return; } _ = JavaClient.Launch(MinecraftId, entry.MinecraftFolderPath, setting.MaxMem, JavaEntry.YmclToMl(setting.Java), p_fullUrl: !string.IsNullOrWhiteSpace(ServerUrl) ? ServerUrl : setting.AutoJoinServerIp, p_world: WorldName); } public event PropertyChangedEventHandler? PropertyChanged; private void OnPropertyChanged([CallerMemberName] string? propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private bool SetField(ref T field, T value, [CallerMemberName] string? propertyName = null) { if (EqualityComparer.Default.Equals(field, value)) return false; field = value; OnPropertyChanged(propertyName); return true; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Operate/MinecraftDataEntry.cs ================================================ using System.IO; using System.Linq; using Avalonia.Controls.Notifications; using Avalonia.Media.Imaging; using MinecraftLaunch.Base.Models.Game; using Newtonsoft.Json; using YMCL.Public.Langs; using YMCL.Public.Module.Mc; using YMCL.Public.Module.Mc.Launcher; using YMCL.Public.Module.Ui.Special; namespace YMCL.Public.Classes.Operate; public sealed record MinecraftDataEntry { [JsonIgnore] public bool IsFavourite { get; } [JsonIgnore] public Action? LaunchAction { get; set; } [JsonIgnore] public bool IsSettingVisible { get; set; } = true; [JsonIgnore] public string FavouriteIcon { get; set; } public string ListTip { get; set; } public string Loaders { get; set; } public string Id { get; set; } public string Type { get; set; } [JsonIgnore] public Bitmap Icon => Public.Module.Mc.Icon.GetMinecraftIcon(this); public MinecraftEntry MinecraftEntry { get; set; } public async Task SettingCommand() { await YMCL.App.UiRoot.ViewModel.Launch.CloseGameList(false); _ = YMCL.App.UiRoot.ViewModel.Launch.OpenGameSetting(MinecraftEntry); } public void LaunchCommand() { LaunchAction?.Invoke(); } public void FavouriteCommand() { if (string.IsNullOrWhiteSpace(MinecraftEntry.ClientJarPath)) return; var path = Path.Combine(MinecraftEntry.MinecraftFolderPath, "versions", MinecraftEntry.Id, "YMCL.Favourite"); YMCL.App.UiRoot.ViewModel.Launch._gameList.CanCloseGameList = false; var favourite = File.Exists(path); try { if (!favourite) { File.WriteAllText(path, string.Empty); } else { File.Delete(path); } } catch { } LaunchUi.LoadGames(); YMCL.App.UiRoot.ViewModel.Launch._gameList.CanCloseGameList = true; } public MinecraftDataEntry(MinecraftEntry minecraftEntry, bool favourite = false, bool isBedrock = false) { if (minecraftEntry == null && !isBedrock) return; if (isBedrock) Type = "bedrock"; IsFavourite = favourite; if (Type != "bedrock") { Id = minecraftEntry.Id; ListTip = minecraftEntry.Version.VersionId; MinecraftEntry = minecraftEntry; Loaders = MinecraftEntry.IsVanilla ? "Vanilla" : string.Join(" , ", (MinecraftEntry as ModifiedMinecraftEntry)?.ModLoaders.Select(a => $"{a.Type} {a.Version}")!); FavouriteIcon = favourite ? "F1 M 4.21875 19.53125 C 4.049479 19.53125 3.902995 19.467773 3.779297 19.34082 C 3.655599 19.213867 3.59375 19.065756 3.59375 18.896484 C 3.59375 18.850912 3.597005 18.815104 3.603516 18.789062 L 4.648438 12.675781 L 0.205078 8.349609 C 0.08138 8.225912 0.019531 8.079428 0.019531 7.910156 C 0.019531 7.760417 0.071615 7.623698 0.175781 7.5 C 0.279948 7.376303 0.406901 7.301434 0.556641 7.275391 L 6.689453 6.386719 L 9.443359 0.820312 C 9.495442 0.716146 9.571939 0.633139 9.672852 0.571289 C 9.773763 0.509441 9.879557 0.478516 9.990234 0.478516 C 10.107422 0.478516 10.218099 0.507812 10.322266 0.566406 C 10.426432 0.625 10.504557 0.709637 10.556641 0.820312 L 13.310547 6.386719 L 19.443359 7.275391 C 19.599609 7.301434 19.728189 7.373048 19.829102 7.490234 C 19.930012 7.607423 19.980469 7.744142 19.980469 7.900391 C 19.980469 8.082683 19.918619 8.232422 19.794922 8.349609 L 15.351562 12.675781 L 16.396484 18.789062 C 16.402994 18.815104 16.40625 18.850912 16.40625 18.896484 C 16.40625 19.065756 16.3444 19.21224 16.220703 19.335938 C 16.097004 19.459635 15.950521 19.521484 15.78125 19.521484 C 15.670572 19.521484 15.572916 19.498697 15.488281 19.453125 L 10 16.5625 L 4.511719 19.453125 C 4.420573 19.505209 4.322917 19.53125 4.21875 19.53125 Z " : "F1 M 4.648438 12.675781 L 0.205078 8.349609 C 0.08138 8.225912 0.019531 8.079428 0.019531 7.910156 C 0.019531 7.760417 0.071615 7.623698 0.175781 7.5 C 0.279948 7.376303 0.406901 7.301434 0.556641 7.275391 L 6.689453 6.386719 L 9.443359 0.820312 C 9.495442 0.716146 9.573567 0.633139 9.677734 0.571289 C 9.7819 0.509441 9.889322 0.478516 10 0.478516 C 10.110677 0.478516 10.218099 0.509441 10.322266 0.571289 C 10.426432 0.633139 10.504557 0.716146 10.556641 0.820312 L 13.310547 6.386719 L 19.443359 7.275391 C 19.599609 7.301434 19.728189 7.373048 19.829102 7.490234 C 19.930012 7.607423 19.980469 7.744142 19.980469 7.900391 C 19.980469 8.076172 19.918619 8.225912 19.794922 8.349609 L 15.351562 12.675781 L 16.396484 18.789062 C 16.402994 18.815104 16.40625 18.850912 16.40625 18.896484 C 16.40625 19.065756 16.3444 19.21224 16.220703 19.335938 C 16.097004 19.459635 15.950521 19.521484 15.78125 19.521484 C 15.670572 19.521484 15.572916 19.498697 15.488281 19.453125 L 10 16.5625 L 4.511719 19.453125 C 4.427083 19.498697 4.329427 19.521484 4.21875 19.521484 C 4.049479 19.521484 3.902995 19.459635 3.779297 19.335938 C 3.655599 19.21224 3.59375 19.065756 3.59375 18.896484 C 3.59375 18.850912 3.597005 18.815104 3.603516 18.789062 Z M 5.048828 17.753906 L 10 15.146484 L 14.951172 17.753906 C 14.794922 16.829428 14.640299 15.909831 14.487305 14.995117 C 14.33431 14.080404 14.173177 13.160808 14.003906 12.236328 L 18.017578 8.330078 L 12.480469 7.529297 C 12.057291 6.689453 11.642252 5.852865 11.235352 5.019531 C 10.82845 4.186199 10.416666 3.349609 10 2.509766 C 9.583333 3.349609 9.171549 4.186199 8.764648 5.019531 C 8.357747 5.852865 7.942708 6.689453 7.519531 7.529297 L 1.982422 8.330078 L 5.996094 12.236328 C 5.826823 13.160808 5.66569 14.080404 5.512695 14.995117 C 5.3597 15.909831 5.205078 16.829428 5.048828 17.753906 Z "; } else { Id = MainLang.BedRockVersion; ListTip = "如未安装基岩版则无法启动"; IsFavourite = true; } InitLaunchAction(minecraftEntry); } private void InitLaunchAction(MinecraftEntry? entry) { if (Type == "bedrock") { LaunchAction = () => { if (YMCL.App.UiRoot != null) YMCL.Public.Module.Mc.Launcher.BedRock.Launch(YMCL.App.UiRoot); }; } else { if (entry == null) return; LaunchAction = () => { var setting = MinecraftSetting.GetGameSetting(entry); MinecraftSetting.HandleGameSetting(setting); if (setting.Java.JavaVersion == "Auto") { setting.Java = YMCL.Public.Module.Value.Calculator.GetCurrentJava(Const.Data.JavaRuntimes.ToList(), entry); } if (setting.Java.JavaPath == "Error") { Notice($"{MainLang.CannotFandRightJava}\n{setting.Java.JavaVersion}", NotificationType.Error); return; } if (setting.Java.JavaPath == null) { Notice(MainLang.JavaRuntimeError, NotificationType.Error); return; } _ = JavaClient.Launch(Id, entry.MinecraftFolderPath, setting.MaxMem, JavaEntry.YmclToMl(setting.Java), p_fullUrl: setting.AutoJoinServerIp); }; } } public bool Equals(MinecraftDataEntry? other) { return other != null && Id == other.Id; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Operate/PluginInfoEntry.cs ================================================ using System.IO; using Newtonsoft.Json; using ReactiveUI; using ReactiveUI.Fody.Helpers; using YMCL.Plugin.Base; namespace YMCL.Public.Classes.Operate; public class PluginInfoEntry : ReactiveObject { public IPlugin Plugin { get; } [Reactive] public bool IsEnable { get; set; } public string Path { get; } public PluginInfoEntry(IPlugin plugin, string path, bool isEnable = false) { Plugin = plugin; Path = path; IsEnable = isEnable; PropertyChanged += (_, e) => { if (e.PropertyName != nameof(IsEnable)) return; if (IsEnable) { Const.Data.EnablePlugins.Add(Path); } else { Const.Data.EnablePlugins.Remove(Path); } File.WriteAllText(ConfigPath.PluginDataPath, JsonConvert.SerializeObject(Const.Data.EnablePlugins, Formatting.Indented)); try { Plugin.Execute(IsEnable); } catch { } }; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Operate/RegisteredPage.cs ================================================ using FluentAvalonia.UI.Controls; using YMCL.Public.Module.Ui; namespace YMCL.Public.Classes.Operate; public class RegisteredPage { public NavigationView Host { get; init; } public Control NavContent { get; init; } public string Tag { get; init; } public Control Page { get; init; } private NavigationViewItem _item; private EventHandler _handler; public void Show() { Host.MenuItems.Add(_item); Host.SelectionChanged += _handler; } public void Hide() { Host.MenuItems.Remove(_item); Host.SelectionChanged -= _handler; } public RegisteredPage Build() { _item = new NavigationViewItem() { Tag = Tag, Content = NavContent != null ? NavContent : Tag }; _handler = (o, e) => { var tag = ((e.SelectedItem as NavigationViewItem).Tag as string)!; if (tag != Tag) return; App.UiRoot.Frame.Content = Page; _ = Animator.PageLoading.LevelTwoPage(Page); }; return this; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Operate/SubTask.cs ================================================ using Avalonia.Media; using FluentAvalonia.UI.Controls; using ReactiveUI; using ReactiveUI.Fody.Helpers; using YMCL.Public.Enum; namespace YMCL.Public.Classes.Operate; public sealed class SubTask : ReactiveObject { public SubTask(string name, int totalTask = 1, int finishedTask = 0) { Name = name; TotalTask = totalTask; FinishedTask = finishedTask; PropertyChanged += (_, e) => { if (e.PropertyName == nameof(State)) { GetIcon(); } }; State = TaskState.Waiting; GetIcon(); } [Reactive] public string Name { get; set; } [Reactive] public int TotalTask { get; set; } [Reactive] public int FinishedTask { get; set; } [Reactive] public int FailedTask { get; set; } [Reactive] public Control Icon { get; set; } [Reactive] public TaskState State { get; set; } private void GetIcon() { Icon = State switch { TaskState.Finished => new PathIcon { Width = 14, Height = 16, Data = Geometry.Parse ("F1 M 0 9.375 C 0 9.205729 0.061849 9.059245 0.185547 8.935547 C 0.309245 8.81185 0.455729 8.75 0.625 8.75 C 0.794271 8.75 0.940755 8.81185 1.064453 8.935547 L 6.875 14.736328 L 18.935547 2.685547 C 19.059244 2.56185 19.205729 2.5 19.375 2.5 C 19.54427 2.5 19.690754 2.56185 19.814453 2.685547 C 19.93815 2.809246 20 2.95573 20 3.125 C 20 3.294271 19.93815 3.440756 19.814453 3.564453 L 7.314453 16.064453 C 7.190755 16.188152 7.044271 16.25 6.875 16.25 C 6.705729 16.25 6.559244 16.188152 6.435547 16.064453 L 0.185547 9.814453 C 0.061849 9.690756 0 9.544271 0 9.375 Z ") }, TaskState.Waiting => new PathIcon { Width = 12, Height = 16, Data = Geometry.Parse ("F1 M 3.125 10.625 C 2.955729 10.625 2.809245 10.563151 2.685547 10.439453 C 2.561849 10.315756 2.5 10.169271 2.5 10 C 2.5 9.830729 2.561849 9.684245 2.685547 9.560547 C 2.809245 9.43685 2.955729 9.375 3.125 9.375 L 16.875 9.375 C 17.04427 9.375 17.190754 9.43685 17.314453 9.560547 C 17.43815 9.684245 17.5 9.830729 17.5 10 C 17.5 10.169271 17.43815 10.315756 17.314453 10.439453 C 17.190754 10.563151 17.04427 10.625 16.875 10.625 Z ") }, TaskState.Running => new ProgressRing { Width = 16, Height = 16 }, _ => null }; } public void Finish() { State = TaskState.Finished; FinishedTask = TotalTask; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Operate/TaskEntryOperateButtonEntry.cs ================================================ using ReactiveUI; using ReactiveUI.Fody.Helpers; namespace YMCL.Public.Classes.Operate; public class TaskEntryOperateButtonEntry : ReactiveObject { [Reactive] public Action Action { get; set; } public void ActionInvoke() { Action.Invoke(); } [Reactive] public object Content { get; set; } public TaskEntryOperateButtonEntry(object content, Action action) { Content = content; Action = action; } public void UpdateAction(Action action) { Action = action; } public void UpdateContent(object context) { Content = context; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Setting/Account.cs ================================================ using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; using Avalonia.Media.Imaging; using MinecraftLaunch.Skin; using Newtonsoft.Json; using YMCL.Public.Module.Value; namespace YMCL.Public.Classes.Setting; public sealed record AccountInfo : INotifyPropertyChanged { public Enum.Setting.AccountType AccountType { get; set; } public string Name { get; set; } = "Unnamed"; public string AddTime { get; set; } = "1970-01-01T00:00:00+08:00"; public string? Data { get; set; } public string Skin { get; set; } = "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAFDUlEQVR42u2a20sUURzH97G0LKMotPuWbVpslj1olJXdjCgyisowsSjzgrB0gSKyC5UF1ZNQWEEQSBQ9dHsIe+zJ/+nXfM/sb/rN4ZwZ96LOrnPgyxzP/M7Z+X7OZc96JpEISfWrFhK0YcU8knlozeJKunE4HahEqSc2nF6zSEkCgGCyb+82enyqybtCZQWAzdfVVFgBJJNJn1BWFgC49/VpwGVlD0CaxQiA5HSYEwBM5sMAdKTqygcAG9+8coHKY/XXAZhUNgDYuBSPjJL/GkzVVhAEU5tqK5XZ7cnFtHWtq/TahdSw2l0HUisr1UKIWJQBAMehDuqiDdzndsP2EZECAG1ZXaWMwOCODdXqysLf++uXUGv9MhUHIByDOijjdiSAoH3ErANQD73C7TXXuGOsFj1d4YH4OTJAEy8y9Hd0mCaeZ5z8dfp88zw1bVyiYhCLOg1ZeAqC0ybaDttHRGME1DhDeVWV26u17lRAPr2+mj7dvULfHw2q65fhQRrLXKDfIxkau3ZMCTGIRR3URR5toU38HbaPiMwUcKfBAkoun09PzrbQ2KWD1JJaqswjdeweoR93rirzyCMBCmIQizqoizZkm2H7iOgAcHrMHbbV9KijkUYv7qOn55sdc4fo250e+vUg4329/Xk6QB/6DtOws+dHDGJRB3XRBve+XARt+4hIrAF4UAzbnrY0ve07QW8uHfB+0LzqanMM7qVb+3f69LJrD90/1axiEIs6qIs21BTIToewfcSsA+Bfb2x67OoR1aPPzu2i60fSNHRwCw221Suz0O3jO+jh6V1KyCMGse9721XdN5ePutdsewxS30cwuMjtC860T5JUKpXyKbSByUn7psi5l+juDlZYGh9324GcPKbkycaN3jUSAGxb46IAYPNZzW0AzgiQ5tVnzLUpUDCAbakMQXXrOtX1UMtHn+Q9/X5L4wgl7t37r85OSrx+TYl379SCia9KXjxRpiTjIZTBFOvrV1f8ty2eY/T7XJ81FQAwmA8ASH1ob68r5PnBsxA88/xAMh6SpqW4HRnLBrkOA9Xv5wPAZjAUgOkB+SHxgBgR0qSMh0zmZRsmwDJm1gFg2PMDIC8/nAHIMls8x8GgzOsG5WiaqREgYzDvpTwjLDy8NM15LpexDEA3LepjU8Z64my+8PtDCmUyRr+fFwA2J0eAFYA0AxgSgMmYBMZTwFQnO9RNAEaHOj2DXF5UADmvAToA2ftyxZYA5BqgmZZApDkdAK4mAKo8GzPlr8G8AehzMAyA/i1girUA0HtYB2CaIkUBEHQ/cBHSvwF0AKZFS5M0ZwMQtEaEAmhtbSUoDADH9ff3++QZ4o0I957e+zYAMt6wHkhzpjkuAcgpwNcpA7AZDLsvpwiuOkBvxygA6Bsvb0HlaeKIF2EbADZpGiGzBsA0gnwQHGOhW2snRpbpPexbAB2Z1oicAMQpTnGKU5ziFKc4xSlOcYpTnOIUpzgVmgo+XC324WfJAdDO/+ceADkCpuMFiFKbApEHkOv7BfzfXt+5gpT8V7rpfYJcDz+jAsB233r6yyBsJ0mlBCDofuBJkel4vOwBFPv8fyYAFPJ+wbSf/88UANNRVy4Awo6+Ig2gkCmgA5DHWjoA+X7AlM//owLANkX0w0359od++pvX8fdMAcj3/QJ9iJsAFPQCxHSnQt8vMJ3v2wCYpkhkAOR7vG7q4aCXoMoSgG8hFAuc/grMdAD4B/kHl9da7Ne9AAAAAElFTkSuQmCC"; [JsonIgnore] public Bitmap Bitmap => HandleHeadSkin(); public void UpdateSkin(byte[] data) { if (data == null) return; Skin = Convert.ToBase64String(data); } private Bitmap HandleHeadSkin() { SkinResolver SkinResolver = new(Convert.FromBase64String(Skin)); var bytes = ImageHelper.ConvertToByteArray(SkinResolver.CropSkinHeadBitmap()); return Converter.Base64ToBitmap(Converter.BytesToBase64(bytes)); } public bool Equals(AccountInfo? other) { return other != null && Skin == other.Skin && Name == other.Name && Data == other.Data; } public event PropertyChangedEventHandler? PropertyChanged; private void OnPropertyChanged([CallerMemberName] string? propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private bool SetField(ref T field, T value, [CallerMemberName] string? propertyName = null) { if (EqualityComparer.Default.Equals(field, value)) return false; field = value; OnPropertyChanged(propertyName); return true; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Setting/ExchangeSettingEntry.cs ================================================ using System.Collections.Generic; using Avalonia.Media; using YMCL.Public.Classes.Data; namespace YMCL.Public.Classes.Setting; public record ExchangeSettingEntry { public record Data { public NetworkSettings? NetworkSettings { get; set; } public LaunchSettings? LaunchSettings { get; set; } public UiSettings? UiSettings { get; set; } public OtherSettings? OtherSettings { get; set; } public IEnumerable? AccountSettings { get; set; } } public record NetworkSettings { public bool EnableAutoCheckUpdate { get; set; } public int MaxDownloadThread { get; set; } public string? CustomUpdateUrl { get; set; } public bool EnableCustomUpdateUrl { get; set; } public string? MusicApiWithIPAddress { get; set; } public Enum.Setting.DownloadSource DownloadSource { get; set; } public string? MusicApi { get; set; } public int MaxFileFragmentation { get; set; } } public record LaunchSettings { public double MaxMem { get; set; } public bool EnableAutoAllocateMem { get; set; } public bool EnableIndependencyCore { get; set; } } public record UiSettings { public double TranslucentBackgroundOpacity { get; set; } public Enum.Setting.Theme Theme { get; set; } public Enum.Setting.LauncherVisibility LauncherVisibility { get; set; } public string? SpecialControlEnableTranslucent { get; set; } public int CornerRadius { get; set; } public string? CustomHomePageUrl { get; set; } public bool? EnableIndependencyWindowNotification { get; set; } public Color DeskLyricColor { get; set; } public Enum.Setting.NoticeWay NoticeWay { get; set; } public Color AccentColor { get; set; } public Language Language { get; set; } public Enum.Setting.CustomBackGroundWay CustomBackGround { get; set; } public double DeskLyricSize { get; set; } public TextAlignment DeskLyricAlignment { get; set; } public string? WindowBackGroundImgData { get; set; } } public record OtherSettings { public double Volume { get; set; } public Enum.Setting.Repeat Repeat { get; set; } } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Setting/GameSettingEntry.cs ================================================ using MinecraftLaunch.Base.Models.Game; using Newtonsoft.Json; using ReactiveUI; using ReactiveUI.Fody.Helpers; using YMCL.Public.Classes.Data; namespace YMCL.Public.Classes.Setting; public sealed class GameSettingEntry : ReactiveObject { [Reactive] [JsonProperty] public Enum.Setting.VersionSettingEnableIndependencyCore EnableIndependencyCore { get; set; } = Enum.Setting.VersionSettingEnableIndependencyCore.Global; [Reactive] [JsonProperty] public JavaEntry Java { get; set; } = new() { JavaVersion = "Global" }; [Reactive] [JsonProperty] public double MaxMem { get; set; } = -2; [Reactive] [JsonProperty] public string AutoJoinServerIp { get; set; } = string.Empty; [Reactive] [JsonProperty] public Enum.Setting.MaxMemWay MaxMemWay { get; set; } = Enum.Setting.MaxMemWay.Global; [Reactive] [JsonIgnore] public bool IsEnableIndependencyCore { get; set; } [Reactive] [JsonIgnore] public MinecraftEntry MinecraftEntry { get; set; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Setting/SettingEntry.cs ================================================ using Avalonia.Media; using Avalonia.Threading; using MinecraftLaunch; using MinecraftLaunch.Components.Authenticator; using Newtonsoft.Json; using ReactiveUI; using ReactiveUI.Fody.Helpers; using YMCL.Public.Langs; using YMCL.Public.Module; using YMCL.Public.Module.App; using YMCL.Public.Module.App.Init.SubModule; using YMCL.Public.Module.Ui.Special; using YMCL.Views.Main; using Language = YMCL.Public.Classes.Data.Language; using MinecraftFolder = YMCL.Public.Classes.Data.MinecraftFolder; using Setter = YMCL.Public.Module.Ui.Setter; namespace YMCL.Public.Classes.Setting; public class SettingEntry : ReactiveObject { [Reactive] [JsonProperty] public string SkipUpdateVersion { get; set; } = string.Empty; [Reactive] [JsonProperty] public bool EnableAutoCheckUpdate { get; set; } = true; [Reactive] [JsonProperty] public int MaxDownloadThread { get; set; } = 64; [Reactive] [JsonProperty] public double TranslucentBackgroundOpacity { get; set; } = 0.68; [Reactive] [JsonProperty] public bool IsCompleteJavaInitialize { get; set; } [Reactive] [JsonProperty] public bool IsCompleteMinecraftFolderInitialize { get; set; } [Reactive] [JsonProperty] public bool IsCompleteAccountInitialize { get; set; } [Reactive] [JsonProperty] public string? CustomHomePageUrl { get; set; } [Reactive] [JsonProperty] public Enum.Setting.NoticeWay NoticeWay { get; set; } = Enum.Setting.NoticeWay.Bubble; [Reactive] [JsonProperty] public Enum.Setting.DownloadSource DownloadSource { get; set; } = Enum.Setting.DownloadSource.Mojang; [Reactive] [JsonProperty] public Enum.Setting.LauncherVisibility LauncherVisibility { get; set; } = Enum.Setting.LauncherVisibility.AfterLaunchKeepLauncherVisible; [Reactive] [JsonProperty] public Enum.Setting.Theme Theme { get; set; } = Enum.Setting.Theme.Dark; [Reactive] [JsonProperty] public double MaxMem { get; set; } = 1024; [Reactive] [JsonProperty] public int MaxFileFragmentation { get; set; } = 8; [Reactive] [JsonProperty] public int CornerRadius { get; set; } = 5; [Reactive] [JsonProperty] public double Volume { get; set; } = 50; [Reactive] [JsonProperty] public double DeskLyricSize { get; set; } = 16; [Reactive] [JsonProperty] public Enum.Setting.Repeat Repeat { get; set; } = Enum.Setting.Repeat.RepeatAll; [Reactive] [JsonProperty] public TextAlignment DeskLyricAlignment { get; set; } = TextAlignment.Center; [Reactive] [JsonProperty] public string? SelectedMinecraftId { get; set; } [Reactive] [JsonProperty] public bool EnableIndependencyCore { get; set; } = true; [Reactive] [JsonProperty] public bool EnableCustomUpdateUrl { get; set; } [Reactive] [JsonProperty] public bool EnableAutoAllocateMem { get; set; } [Reactive] [JsonProperty] public bool EnableIndependencyWindowNotification { get; set; } = true; [Reactive] [JsonProperty] public string? CustomUpdateUrl { get; set; } = "https://github.moeyy.xyz/{%url%}"; [Reactive] [JsonProperty] public string? MusicApi { get; set; } = "http://music.api.yik.at/"; [Reactive] [JsonProperty] public string SpecialControlEnableTranslucent { get; set; } = "ContentDialog,NotificationCard,NotificationBubble,Popup"; [Reactive] [JsonProperty] public Enum.Setting.CustomBackGroundWay CustomBackGround { get; set; } = Enum.Setting.CustomBackGroundWay.Default; [Reactive] [JsonProperty] public Enum.Setting.CustomHomePageWay CustomHomePage { get; set; } = Enum.Setting.CustomHomePageWay.None; [Reactive] [JsonProperty] public string? MusicApiWithIPAddress { get; set; } = "120.230.112.69"; [Reactive] [JsonProperty] public Language Language { get; set; } = new(); [Reactive] [JsonProperty] public MinecraftFolder MinecraftFolder { get; set; } [Reactive] [JsonProperty] public Color AccentColor { get; set; } = Color.Parse("#00b2ff"); [Reactive] [JsonProperty] public Color DeskLyricColor { get; set; } = Color.Parse("#00b2ff"); [Reactive] [JsonProperty] public JavaEntry Java { get; set; } = new() { JavaPath = MainLang.LetYMCLChooseJava, JavaVersion = "Auto" }; [Reactive] [JsonProperty] public AccountInfo Account { get; set; } = new() { Name = "Steve", AccountType = Enum.Setting.AccountType.Offline, AddTime = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:sszzz"), Data = JsonConvert.SerializeObject(new OfflineAuthenticator().Authenticate("Steve")) }; [Reactive] [JsonProperty] public string? WindowBackGroundImgData { get; set; } = string.Empty; public SettingEntry() { var accentColorSetter = new Debouncer(() => { Public.Module.Ui.Setter.SetAccentColor(AccentColor); }, 5); var _setBackGroundDebouncer = new Debouncer( () => { Dispatcher.UIThread.Invoke(Public.Module.Ui.Setter.SetBackGround); }, 500); PropertyChanged += (o, e) => { if (e.PropertyName == nameof(Language)) { LangHelper.Current.ChangedCulture(Const.Data.SettingEntry.Language.Code); } if (e.PropertyName == nameof(AccentColor)) { accentColorSetter.Trigger(); } if (e.PropertyName == nameof(MinecraftFolder)) { LaunchUi.LoadGames(); } if (e.PropertyName == nameof(CustomHomePage)) { _ = InitUi.SetCustomHomePage(); } if (e.PropertyName == nameof(CustomBackGround)) { try { Setter.SetBackGround(); } catch { } } if (e.PropertyName == nameof(EnableIndependencyWindowNotification)) { if (EnableIndependencyWindowNotification) { NoticeWindow(MainLang.ExampleNotification, MainLang.ExampleNotification); } } if (e.PropertyName == nameof(TranslucentBackgroundOpacity)) { Application.Current.Resources["MainOpacity"] = TranslucentBackgroundOpacity; if (TopLevel.GetTopLevel(YMCL.App.UiRoot) is MainWindow window) { try { (Public.Module.Ui.Getter.FindControlByName(window, "PART_PaneRoot") as Panel).Opacity = (double)Application.Current.Resources["MainOpacity"]!; } catch { } } _setBackGroundDebouncer.Trigger(); } if (e.PropertyName == nameof(CornerRadius)) { Application.Current.Resources["MainCornerRadius"] = new CornerRadius(CornerRadius); } if (e.PropertyName == nameof(SpecialControlEnableTranslucent)) { Public.Module.Ui.Setter.DynamicStyle.SetDynamicStyle(); } if (e.PropertyName == nameof(Theme)) { Public.Module.Ui.Setter.ToggleTheme(Theme); } if (e.PropertyName == nameof(MaxDownloadThread)) { DownloadMirrorManager.MaxThread = MaxDownloadThread; } AppMethod.SaveSetting(); }; } } ================================================ FILE: YMCL.Main/YMCL/Public/Classes/Setting/UiProperty.cs ================================================ using System.Collections.ObjectModel; using MinecraftLaunch.Base.Models.Network; using ReactiveUI; using ReactiveUI.Fody.Helpers; using YMCL.Public.Classes.Data; using YMCL.Public.Classes.Netease; using YMCL.Public.Classes.Operate; using YMCL.Public.Langs; namespace YMCL.Public.Classes.Setting; public sealed class UiProperty : ReactiveObject { private static UiProperty? _instance; public static ObservableCollection NotificationCards { get; } = []; public static ObservableCollection AllInstallableGames { get; } = []; public static ObservableCollection FilteredAllInstallableGames { get; set; } = []; public static ObservableCollection ReleaseInstallableGames { get; set; } = []; public static ObservableCollection SnapshotInstallableGames { get; set; } = []; public static ObservableCollection OldInstallableGames { get; set; } = []; public ObservableCollection FilteredAggregateSearchEntries { get; } = []; [Reactive] public VersionManifestEntry LatestReleaseGame { get; set; } = new() { ReleaseTime = new DateTime(1970, 1, 1, 0, 0, 0), Id = MainLang.Loading, Type = null }; [Reactive] public VersionManifestEntry LatestSnapshotGame { get; set; } = new() { ReleaseTime = new DateTime(1970, 1, 1, 0, 0, 0), Id = MainLang.Loading, Type = null }; [Reactive] public bool InstallableRingIsVisible { get; set; } = true; [Reactive] public bool IsAllImport { get; set; } = false; [Reactive] public double TaskEntryHeaderWidth { get; set; } [Reactive] public double SystemMaxMem { get; set; } [Reactive] public double AutoMaxMem { get; set; } [Reactive] public MinecraftDataEntry SelectedMinecraft { get; set; } [Reactive] public string AggregateSearchFilter { get; set; } = string.Empty; [Reactive] public double MusicTotalTime { get; set; } [Reactive] public double MusicCurrentTime { get; set; } [Reactive] public string InstallableGameSearchFilter { get; set; } = string.Empty; [Reactive] public RecordSongEntry? SelectedRecordSong { get; set; } [Reactive] public RecordSongEntry? SelectedSearchSong { get; set; } public UiProperty() { PropertyChanged += (_, e) => { if (e.PropertyName == nameof(AggregateSearchFilter)) { YMCL.Public.Module.Ui.Special.AggregateSearchUi.Filter(AggregateSearchFilter); } }; } public static UiProperty Instance { get { return _instance ??= new UiProperty(); } } } ================================================ FILE: YMCL.Main/YMCL/Public/Const/Data.cs ================================================ using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using Avalonia.Controls.Notifications; using MinecraftLaunch.Components.Parser; using Newtonsoft.Json; using ReactiveUI; using Ursa.Controls; using YMCL.Public.Classes; using YMCL.Public.Classes.Data; using YMCL.Public.Classes.Netease; using YMCL.Public.Classes.Operate; using YMCL.Public.Classes.Setting; using YMCL.Public.Controls; using YMCL.Public.Enum; using YMCL.Public.Langs; using Language = YMCL.Public.Classes.Data.Language; using WindowNotificationManager = Ursa.Controls.WindowNotificationManager; namespace YMCL.Public.Const; public sealed class Data : ReactiveObject { private static Data? _instance; public static ObservableCollection Langs => LangHelper.Langs; public static DesktopRunnerType DesktopType { get; set; } = DesktopRunnerType.Unknown; public static WindowNotificationManager Notification { get; set; } public static WindowToastManager Toast { get; set; } public static ObservableCollection MinecraftFolders { get; set; } public static ObservableCollection JavaRuntimes { get; set; } = []; public static ObservableCollection EnablePlugins { get; set; } = []; public static ObservableCollection IdentifiedPlugins { get; set; } = []; public static ObservableCollection Accounts { get; set; } public static ObservableCollection FavouriteResources { get; set; } = []; public static ObservableCollection FavouriteMinecraft { get; set; } public static ObservableCollection CurrentFolderGames { get; set; } = []; public static ObservableCollection TaskEntries { get; set; } = []; public static List AllAggregateSearchEntries { get; set; } = []; public static ObservableCollection RecordSongEntries { get; set; } = []; public static ObservableCollection SearchSongEntries { get; set; } = []; public static List NewsDataList { get; set; } = []; public static SettingEntry SettingEntry { get; set; } public static UiProperty UiProperty { get; } = new(); public static string TranslateToken { get; set; } public static string[] AppArgs { get; set; } public static Data Instance { get { return _instance ??= new Data(); } } public Data() { UiProperty.PropertyChanged += (_, e) => { if (e.PropertyName == nameof(UiProperty.SelectedMinecraft) && !string.IsNullOrEmpty(UiProperty.SelectedMinecraft?.Id)) { if (UiProperty.SelectedMinecraft.Type == "bedrock") { if (DesktopType == DesktopRunnerType.Windows && Environment.OSVersion.Version.Major >= 10) { SettingEntry.SelectedMinecraftId = "bedrock"; } } else { SettingEntry.SelectedMinecraftId = UiProperty.SelectedMinecraft.Id; } } }; FavouriteResources.CollectionChanged += (_, _) => { File.WriteAllText(ConfigPath.FavouriteResourceDataPath, JsonConvert.SerializeObject(FavouriteResources, Formatting.Indented)); }; SettingEntry.PropertyChanged += (_, e) => { try { if (e.PropertyName != nameof(SettingEntry.SelectedMinecraftId) || string.IsNullOrEmpty(SettingEntry.SelectedMinecraftId)) return; if (SettingEntry.SelectedMinecraftId == "bedrock") { UiProperty.SelectedMinecraft = new MinecraftDataEntry(null, true, true) { IsSettingVisible = false, Type = "bedrock" }; } else { var parser = new MinecraftParser(SettingEntry.MinecraftFolder.Path); UiProperty.SelectedMinecraft = new MinecraftDataEntry(parser.GetMinecraft(SettingEntry.SelectedMinecraftId)); } } catch (Exception exception) { Console.WriteLine(exception); } }; } } ================================================ FILE: YMCL.Main/YMCL/Public/Const/Path.cs ================================================ using System.IO; namespace YMCL.Public.Const; public class ConfigPath { public static string UserDataRootPath { get; protected set; } public static string SettingDataPath { get; protected set; } public static string MinecraftFolderDataPath { get; protected set; } public static string JavaDataPath { get; protected set; } public static string AppPathDataPath { get; protected set; } public static string PlayerDataPath { get; protected set; } public static string CustomHomePageXamlDataPath { get; protected set; } public static string AccountDataPath { get; protected set; } public static string PluginDataPath { get; protected set; } public static string FavouriteResourceDataPath { get; protected set; } public static string PluginFolderPath { get; protected set; } public static string TempFolderPath { get; protected set; } public static string UpdateFolderPath { get; protected set; } public static string LauncherClPath { get; protected set; } public static string FavouriteMinecraftDataPath { get; protected set; } public static void InitPath() { UserDataRootPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "DaiYu.Platform.YMCL"); SettingDataPath = Path.Combine(UserDataRootPath, "YMCL.Setting.DaiYu"); MinecraftFolderDataPath = Path.Combine(UserDataRootPath, "YMCL.MinecraftFolder.DaiYu"); JavaDataPath = Path.Combine(UserDataRootPath, "YMCL.Java.DaiYu"); AppPathDataPath = Path.Combine(UserDataRootPath, "YMCL.AppPath.DaiYu"); PlayerDataPath = Path.Combine(UserDataRootPath, "YMCL.Player.DaiYu"); CustomHomePageXamlDataPath = Path.Combine(UserDataRootPath, "YMCL.CustomHomePageXaml.DaiYu"); AccountDataPath = Path.Combine(UserDataRootPath, "YMCL.Account.DaiYu"); PluginDataPath = Path.Combine(UserDataRootPath, "YMCL.Plugin.DaiYu"); PluginFolderPath = Path.Combine(UserDataRootPath, "Plugin"); TempFolderPath = Path.Combine(UserDataRootPath, "Temp"); LauncherClPath = Path.Combine(UserDataRootPath, "LauncherCl.bat"); UpdateFolderPath = Path.Combine(UserDataRootPath, "Update"); FavouriteResourceDataPath = Path.Combine(UserDataRootPath, "YMCL.FavouriteResource.DaiYu"); FavouriteMinecraftDataPath = Path.Combine(UserDataRootPath, "YMCL.FavouriteMinecraft.DaiYu"); } } ================================================ FILE: YMCL.Main/YMCL/Public/Const/String.cs ================================================ namespace YMCL.Public.Const; public class String { public static string AppTitle => "Yu Minecraft Launcher"; public static string AzureClientId => "c06d4d68-7751-4a8a-a2ff-d1b46688f428"; public static string CurseForgeApiKey => "$2a$10$ndSPnOpYqH3DRmLTWJTf5Ofm7lz9uYoTGvhSj0OjJWJ8WdO4ZTsr."; public static string GithubUpdateApiUrl => "https://api.github.com/repos/DaiYu-233/YMCL.Avalonia/releases?per_page=1"; } ================================================ FILE: YMCL.Main/YMCL/Public/Controls/CourseForgeFileExpander.axaml ================================================  ================================================ FILE: YMCL.Main/YMCL/Public/Controls/CourseForgeFileExpander.axaml.cs ================================================ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using Avalonia; using Avalonia.Controls; using Avalonia.Markup.Xaml; using Avalonia.Threading; using CurseForge.APIClient; using CurseForge.APIClient.Models.Files; using DynamicData; using YMCL.Public.Classes.Data; using YMCL.Public.Classes.Data.ResourceFetcher; using YMCL.Public.Enum; using YMCL.Views.Main.Pages.DownloadPages.CurseForgePages; using ModLoaderType = CurseForge.APIClient.Models.Mods.ModLoaderType; namespace YMCL.Public.Controls; public partial class CurseForgeFileExpander : UserControl { private readonly string _version; private bool _firstLoad = true; public ObservableCollection Files { get; } = []; public ObservableCollection DependencyItems { get; } = []; public ObservableCollection DependencyIds { get; } = []; public CurseForgeFileExpander(string version, int id, string name, ModLoaderType? loader, ResourceType type) { _version = version; InitializeComponent(); Expander.Header = name; DataContext = this; Loaded += (_, _) => { if (!_firstLoad) return; _firstLoad = false; _ = Init(version, id, loader); }; ListView.SelectionChanged += async (_, _) => { if (ListView.SelectedItem == null) return; Public.Module.Op.DownloadResource.SaveCurseForge(type, ListView.SelectedItem as File); await Task.Delay(300); ListView.SelectedItem = null; }; ListBox.SelectionChanged += (_, _) => { if (ListBox.SelectedItem == null) return; var item = ListBox.SelectedItem as CurseForgeResourceEntry; YMCL.App.UiRoot.ViewModel.Download._curseForge.CreateNewPage(new SearchTabViewItemEntry() { CanClose = true, Host = nameof(Views.Main.Pages.DownloadPages.CurseForge), Content = new ModFileResult(item!), Title = $"{item.DisplayType}: {item.Name}" }); ListBox.SelectedItem = null; }; } public CurseForgeFileExpander() { } private async Task Init(string version, int id, ModLoaderType? type) { ApiClient apiClient = new(Const.String.CurseForgeApiKey); var data = await apiClient.GetModFilesAsync(id, version, type ?? null); data.Data.ForEach(x => { Files.Add(x); x.Dependencies.ForEach(y => { if (y.RelationType == FileRelationType.RequiredDependency && !DependencyIds.Contains(y.ModId)) { DependencyIds.Add(y.ModId); } }); }); Ring.IsVisible = false; if (DependencyIds.Count != 0) { var tasks = new List(); Dependencies.IsVisible = true; DependencyIds.ToList().ForEach(x => { tasks.Add(GetProject(x)); }); await Task.WhenAll(tasks.ToArray()); ListBox.IsVisible = true; DependenciesRing.IsVisible = false; } if (DependencyItems.Count == 0) DependenciesRing.IsVisible = false; } private async Task GetProject(int id) { ApiClient apiClient = new(Public.Const.String.CurseForgeApiKey); var res = await apiClient.GetModAsync(id); var item = res.Data; var conVersion = false; item.LatestFiles.ForEach(x => { if (x.GameVersions.All(y => y != _version)) return; conVersion = true; }); if (!conVersion) return; var entry = new CurseForgeResourceEntry() { Id = item.Id, GameId = item.GameId, Name = item.Name, Slug = item.Slug, Summary = item.Summary, Status = item.Status, DownloadCount = item.DownloadCount, IsFeatured = item.IsFeatured, PrimaryCategoryId = item.PrimaryCategoryId, ClassId = item.ClassId, Authors = item.Authors, Logo = item.Logo, LatestFiles = item.LatestFiles, LatestFilesIndexes = item.LatestFilesIndexes, DateCreated = item.DateCreated, DateModified = item.DateModified, DateReleased = item.DateReleased, AllowModDistribution = item.AllowModDistribution, GamePopularityRank = item.GamePopularityRank, IsAvailable = item.IsAvailable, ThumbsUpCount = item.ThumbsUpCount, Rating = item.Rating }; entry.Type = item.ClassId switch { 6 => ResourceType.Mod, 12 => ResourceType.ResourcePack, 17 => ResourceType.Map, 6552 => ResourceType.ShaderPack, 6945 => ResourceType.DataPack, 4471 => ResourceType.ModPack, _ => ResourceType.Unknown }; DependencyItems.Add(entry); } } ================================================ FILE: YMCL.Main/YMCL/Public/Controls/Drawers/MsgHistory.axaml ================================================  ================================================ FILE: YMCL.Main/YMCL/Public/Controls/Drawers/MsgHistory.axaml.cs ================================================ using System.Linq; using Avalonia.Interactivity; using Ursa.Controls; using YMCL.Public.Classes; using YMCL.Public.Classes.Setting; namespace YMCL.Public.Controls.Drawers; public partial class MsgHistory : UserControl { public MsgHistory() { InitializeComponent(); DataContext = Data.Instance; } private void MessageCard_OnMessageClosed(object? sender, RoutedEventArgs e) { var card = sender as NotificationCard; var notification = UiProperty.NotificationCards .FirstOrDefault(x => x.Content == card.Content); if (notification is not null) { UiProperty.NotificationCards.Remove(notification); } } } ================================================ FILE: YMCL.Main/YMCL/Public/Controls/LogViewer.axaml ================================================