Compare commits
71 Commits
Author | SHA1 | Date |
---|---|---|
yangzhi | bfb0adb849 | |
yangzhi | 24a0af3d58 | |
yangzhi | a5a10e60cb | |
yangzhi | fc6dc349da | |
yangzhi | 0de3a3ad41 | |
yangzhi | 4317b930aa | |
yangzhi | 77c15400b8 | |
yangzhi | ac1465bedf | |
yangzhi | 917eaf48c4 | |
yangzhi | bf0903b173 | |
yangzhi | 68a88ef3ba | |
yangzhi | f628466adb | |
Jesse Plamondon-Willard | 0ce39e2330 | |
Jesse Plamondon-Willard | 4e27841fb2 | |
Jesse Plamondon-Willard | eeb4e12f75 | |
Jesse Plamondon-Willard | 7d96f29aff | |
Jesse Plamondon-Willard | db33481dff | |
Jesse Plamondon-Willard | f52b2a5ad4 | |
Jesse Plamondon-Willard | 421dfbe912 | |
Jesse Plamondon-Willard | dd352d409f | |
Jesse Plamondon-Willard | 36606e4a4a | |
nea | ebdb17bf81 | |
Jesse Plamondon-Willard | ae36b9b166 | |
atravita-mods | 7c6da8e5ec | |
Jesse Plamondon-Willard | 5196c3bad9 | |
Jesse Plamondon-Willard | 05695be390 | |
Marie Ramlow | 654ad4b4b2 | |
Christopher Hiller | 15ab3ccd09 | |
Jesse Plamondon-Willard | 251d83472c | |
Jesse Plamondon-Willard | 2f1f274b2d | |
Jesse Plamondon-Willard | 3c46bdaeb3 | |
Jesse Plamondon-Willard | 5d2afc0aa4 | |
Jesse Plamondon-Willard | 76a0497684 | |
Jesse Plamondon-Willard | 342b91ff80 | |
Jesse Plamondon-Willard | 445370b75b | |
Jesse Plamondon-Willard | 9dd702a162 | |
yangzhi | bdd506b0db | |
yangzhi | f59c4f194b | |
yangzhi | 18f34debcc | |
yangzhi | 8dbd00eade | |
zhiyang7 | 4ebf03ee48 | |
Jesse Plamondon-Willard | 53e0e8cd24 | |
Jesse Plamondon-Willard | 46947683cd | |
ZaneYork | d9440155ca | |
zhiyang7 | 2801638122 | |
Jesse Plamondon-Willard | 2e618672aa | |
Jesse Plamondon-Willard | c2e9aad698 | |
Jesse Plamondon-Willard | c0ac58f277 | |
Jesse Plamondon-Willard | d2134f0f70 | |
Jesse Plamondon-Willard | d13046edb6 | |
Jesse Plamondon-Willard | 45903dbf3e | |
Jesse Plamondon-Willard | dc027f4eff | |
atravita-mods | c12e9d788e | |
atravita-mods | 58ccaf9a1e | |
Freya Arbjerg | fe43ec51d0 | |
ORMEEHYUNGKEUN CHA | 5e578725bf | |
Jesse Plamondon-Willard | 7b5566d075 | |
Jesse Plamondon-Willard | 7f7561469f | |
Jesse Plamondon-Willard | 072efba6dc | |
Jesse Plamondon-Willard | eb2a9b69bc | |
zhiyang7 | e618785e93 | |
zhiyang7 | 3c59a5fc6a | |
zhiyang7 | 48fd5a490b | |
zhiyang7 | a406411a04 | |
zhiyang7 | 0f94f4609d | |
zhiyang7 | a797608622 | |
zhiyang7 | 7c6fc4cd19 | |
zhiyang7 | ab67f2b233 | |
zhiyang7 | 8fcb6e9041 | |
Jesse Plamondon-Willard | b9fe45b091 | |
Jesse Plamondon-Willard | 8ee555c07a |
|
@ -1,30 +0,0 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Report a problem with SMAPI.
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
|
||||
Only report a bug here if you're sure it's a SMAPI bug!
|
||||
To request support instead, see https://smapi.io/community.
|
||||
|
||||
Replace the instructions below with the bug details.
|
||||
|
||||
-->
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is. Provide any other details you think might be relevant here.
|
||||
|
||||
**To Reproduce**
|
||||
Exact steps which reproduce the bug, if possible. For example:
|
||||
1. Load save '...'.
|
||||
2. Walk to '....'.
|
||||
3. Click '....'.
|
||||
4. Error occurs.
|
||||
|
||||
**Log file**
|
||||
Upload your SMAPI log to https://smapi.io/log and post a link here.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
|
@ -0,0 +1,8 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Troubleshooting guide for players
|
||||
url: https://smapi.io/troubleshoot
|
||||
about: See if your question is already answered first!
|
||||
- name: Get help or discuss
|
||||
url: https://smapi.io/help
|
||||
about: Ask for help from the community, or join the Stardew Valley Discord to ask questions, report issues, or discuss with the SMAPI developer, players, and mod authors. The SMAPI developer is @Pathoschild#0001 on Discord.
|
|
@ -0,0 +1,37 @@
|
|||
---
|
||||
name: Create a development task
|
||||
about: DON'T DO THIS BEFORE READING. This is for specific changes to the code or technical bug reports. See below if something isn't working, you have questions or ideas, or you want to discuss something.
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
|
||||
|
||||
|
||||
|
||||
STOP!
|
||||
|
||||
Is this a specific development task? Don't create an issue if not!
|
||||
See https://smapi.io/community if something isn't working, you have questions or ideas, or you want
|
||||
to discuss something.
|
||||
|
||||
If you're absolutely sure it's a specific development task (e.g. a specific bug, not just
|
||||
'something went wrong on my computer'), edit the template below.
|
||||
|
||||
-->
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is. Provide any other details you think might be relevant here.
|
||||
|
||||
**To Reproduce**
|
||||
Exact steps which reproduce the bug, if possible. For example:
|
||||
1. Load save '...'.
|
||||
2. Walk to '....'.
|
||||
3. Click '....'.
|
||||
4. Error occurs.
|
||||
|
||||
**Log file**
|
||||
Upload your SMAPI log to https://smapi.io/log and post a link here.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
|
@ -1,12 +0,0 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for SMAPI.
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
|
||||
GitHub issues are only used for development tasks. Please don't submit feature requests here!
|
||||
Instead, see https://smapi.io/community to discuss SMAPI.
|
||||
|
||||
-->
|
|
@ -1,12 +0,0 @@
|
|||
---
|
||||
name: General
|
||||
about: Create a ticket about something else.
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
|
||||
GitHub issues are only used for development tasks.
|
||||
For support and questions, see https://smapi.io/community instead.
|
||||
|
||||
-->
|
|
@ -44,3 +44,4 @@ src/Loader/libs/
|
|||
|
||||
# VSHistory
|
||||
**/.vshistory/
|
||||
/build/StardewValleyAndroidStuff/
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -7,13 +7,16 @@ repo. It imports the other MSBuild files as needed.
|
|||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<!--set general build properties -->
|
||||
<Version>3.18.2</Version>
|
||||
<Version>3.18.4</Version>
|
||||
<Product>SMAPI</Product>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<AssemblySearchPaths>$(AssemblySearchPaths);{GAC}</AssemblySearchPaths>
|
||||
<DefineConstants Condition="$(OS) == 'Windows_NT' AND '$(BUILD_FOR_MOBILE)' == ''">$(DefineConstants);SMAPI_DEPRECATED;SMAPI_FOR_WINDOWS</DefineConstants>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
||||
<!--embed symbols for error stack trace line numbers on Linux/macOS: https://github.com/dotnet/runtime/issues/39987-->
|
||||
<DebugType>embedded</DebugType>
|
||||
|
||||
<!--enable nullable annotations, except in .NET Standard 2.0 where they aren't supported-->
|
||||
<Nullable Condition="'$(TargetFramework)' != 'netstandard2.0'">enable</Nullable>
|
||||
<NoWarn Condition="'$(TargetFramework)' == 'netstandard2.0'">$(NoWarn);CS8632</NoWarn>
|
||||
|
|
|
@ -8,6 +8,6 @@
|
|||
<!-- <BUILD_FOR_MOBILE>SAMSUNG</BUILD_FOR_MOBILE>-->
|
||||
<!-- <BUILD_FOR_MOBILE>GOOGLE_LEGACY</BUILD_FOR_MOBILE>-->
|
||||
<COMPILE_WITH_PLUGIN>False</COMPILE_WITH_PLUGIN>
|
||||
<DefineConstants Condition="'$(BUILD_FOR_MOBILE)' == 'GOOGLE'">$(DefineConstants);SMAPI_FOR_MOBILE;ANDROID_TARGET_GOOGLE;MonoAndroid10</DefineConstants>
|
||||
<DefineConstants Condition="'$(BUILD_FOR_MOBILE)' == 'GOOGLE'">SMAPI_DEPRECATED;SMAPI_FOR_MOBILE;ANDROID_TARGET_GOOGLE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
@ -18,7 +18,6 @@ This assumes `find-game-folder.targets` has already been imported and validated.
|
|||
<Copy SourceFiles="$(TargetDir)\$(TargetName).dll" DestinationFolder="$(GamePath)" />
|
||||
<Copy SourceFiles="$(TargetDir)\$(TargetName).exe" DestinationFolder="$(GamePath)" Condition="$(OS) == 'Windows_NT'" />
|
||||
<Copy SourceFiles="$(TargetDir)\$(TargetName)" DestinationFolder="$(GamePath)" Condition="$(OS) != 'Windows_NT'" />
|
||||
<Copy SourceFiles="$(TargetDir)\$(TargetName).pdb" DestinationFolder="$(GamePath)" />
|
||||
<Copy SourceFiles="$(TargetDir)\$(TargetName).xml" DestinationFolder="$(GamePath)" />
|
||||
<Copy SourceFiles="$(TargetDir)\SMAPI.config.json" DestinationFiles="$(GamePath)\smapi-internal\config.json" />
|
||||
<Copy SourceFiles="$(TargetDir)\SMAPI.metadata.json" DestinationFiles="$(GamePath)\smapi-internal\metadata.json" />
|
||||
|
@ -62,7 +61,6 @@ This assumes `find-game-folder.targets` has already been imported and validated.
|
|||
</ItemGroup>
|
||||
|
||||
<Copy SourceFiles="$(TargetDir)\$(TargetName).dll" DestinationFolder="$(GamePath)\Mods\$(AssemblyName)" />
|
||||
<Copy SourceFiles="$(TargetDir)\$(TargetName).pdb" DestinationFolder="$(GamePath)\Mods\$(AssemblyName)" Condition="Exists('$(TargetDir)\$(TargetName).pdb')" />
|
||||
<Copy SourceFiles="$(TargetDir)\manifest.json" DestinationFolder="$(GamePath)\Mods\$(AssemblyName)" />
|
||||
<Copy SourceFiles="@(TranslationFiles)" DestinationFolder="$(GamePath)\Mods\$(AssemblyName)\i18n" />
|
||||
</Target>
|
||||
|
@ -70,12 +68,10 @@ This assumes `find-game-folder.targets` has already been imported and validated.
|
|||
<!-- toolkit -->
|
||||
<Target Name="CopyToolkit" Condition="'$(MSBuildProjectName)' == 'SMAPI.Toolkit'" AfterTargets="PostBuildEvent">
|
||||
<Copy SourceFiles="$(TargetDir)\$(TargetName).dll" DestinationFolder="$(GamePath)\smapi-internal" />
|
||||
<Copy SourceFiles="$(TargetDir)\$(TargetName).pdb" DestinationFolder="$(GamePath)\smapi-internal" />
|
||||
<Copy SourceFiles="$(TargetDir)\$(TargetName).xml" DestinationFolder="$(GamePath)\smapi-internal" />
|
||||
</Target>
|
||||
<Target Name="CopyToolkitCoreInterfaces" Condition="'$(MSBuildProjectName)' == 'SMAPI.Toolkit.CoreInterfaces'" AfterTargets="PostBuildEvent">
|
||||
<Copy SourceFiles="$(TargetDir)\$(TargetName).dll" DestinationFolder="$(GamePath)\smapi-internal" />
|
||||
<Copy SourceFiles="$(TargetDir)\$(TargetName).pdb" DestinationFolder="$(GamePath)\smapi-internal" />
|
||||
<Copy SourceFiles="$(TargetDir)\$(TargetName).xml" DestinationFolder="$(GamePath)\smapi-internal" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#
|
||||
#
|
||||
|
@ -122,7 +122,7 @@ for folder in ${folders[@]}; do
|
|||
fi
|
||||
|
||||
# bundle root files
|
||||
for name in "StardewModdingAPI" "StardewModdingAPI.dll" "StardewModdingAPI.pdb" "StardewModdingAPI.xml" "steam_appid.txt"; do
|
||||
for name in "StardewModdingAPI" "StardewModdingAPI.dll" "StardewModdingAPI.xml" "steam_appid.txt"; do
|
||||
if [ $name == "StardewModdingAPI" ] && [ $folder == "windows" ]; then
|
||||
name="$name.exe"
|
||||
fi
|
||||
|
@ -134,7 +134,7 @@ for folder in ${folders[@]}; do
|
|||
cp -r "$smapiBin/i18n" "$bundlePath/smapi-internal"
|
||||
|
||||
# bundle smapi-internal
|
||||
for name in "0Harmony.dll" "0Harmony.xml" "Mono.Cecil.dll" "Mono.Cecil.Mdb.dll" "Mono.Cecil.Pdb.dll" "MonoMod.Common.dll" "Newtonsoft.Json.dll" "Pathoschild.Http.Client.dll" "Pintail.dll" "TMXTile.dll" "SMAPI.Toolkit.dll" "SMAPI.Toolkit.pdb" "SMAPI.Toolkit.xml" "SMAPI.Toolkit.CoreInterfaces.dll" "SMAPI.Toolkit.CoreInterfaces.pdb" "SMAPI.Toolkit.CoreInterfaces.xml" "System.Net.Http.Formatting.dll"; do
|
||||
for name in "0Harmony.dll" "0Harmony.xml" "Mono.Cecil.dll" "Mono.Cecil.Mdb.dll" "Mono.Cecil.Pdb.dll" "MonoMod.Common.dll" "Newtonsoft.Json.dll" "Pathoschild.Http.Client.dll" "Pintail.dll" "TMXTile.dll" "SMAPI.Toolkit.dll" "SMAPI.Toolkit.xml" "SMAPI.Toolkit.CoreInterfaces.dll" "SMAPI.Toolkit.CoreInterfaces.xml" "System.Net.Http.Formatting.dll"; do
|
||||
cp "$smapiBin/$name" "$bundlePath/smapi-internal"
|
||||
done
|
||||
|
||||
|
@ -164,7 +164,6 @@ for folder in ${folders[@]}; do
|
|||
mkdir "$targetPath" --parents
|
||||
|
||||
cp "$fromPath/$modName.dll" "$targetPath"
|
||||
cp "$fromPath/$modName.pdb" "$targetPath"
|
||||
cp "$fromPath/manifest.json" "$targetPath"
|
||||
if [ -d "$fromPath/i18n" ]; then
|
||||
cp -r "$fromPath/i18n" "$targetPath"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#
|
||||
#
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
##########
|
||||
## Read config
|
||||
|
|
|
@ -142,7 +142,7 @@ foreach ($folder in $folders) {
|
|||
}
|
||||
|
||||
# bundle root files
|
||||
foreach ($name in @("StardewModdingAPI", "StardewModdingAPI.dll", "StardewModdingAPI.pdb", "StardewModdingAPI.xml", "steam_appid.txt")) {
|
||||
foreach ($name in @("StardewModdingAPI", "StardewModdingAPI.dll", "StardewModdingAPI.xml", "steam_appid.txt")) {
|
||||
if ($name -eq "StardewModdingAPI" -and $folder -eq "windows") {
|
||||
$name = "$name.exe"
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ foreach ($folder in $folders) {
|
|||
cp -Recurse "$smapiBin/i18n" "$bundlePath/smapi-internal"
|
||||
|
||||
# bundle smapi-internal
|
||||
foreach ($name in @("0Harmony.dll", "0Harmony.xml", "Mono.Cecil.dll", "Mono.Cecil.Mdb.dll", "Mono.Cecil.Pdb.dll", "MonoMod.Common.dll", "Newtonsoft.Json.dll", "Pathoschild.Http.Client.dll", "Pintail.dll", "TMXTile.dll", "SMAPI.Toolkit.dll", "SMAPI.Toolkit.pdb", "SMAPI.Toolkit.xml", "SMAPI.Toolkit.CoreInterfaces.dll", "SMAPI.Toolkit.CoreInterfaces.pdb", "SMAPI.Toolkit.CoreInterfaces.xml", "System.Net.Http.Formatting.dll")) {
|
||||
foreach ($name in @("0Harmony.dll", "0Harmony.xml", "Mono.Cecil.dll", "Mono.Cecil.Mdb.dll", "Mono.Cecil.Pdb.dll", "MonoMod.Common.dll", "Newtonsoft.Json.dll", "Pathoschild.Http.Client.dll", "Pintail.dll", "TMXTile.dll", "SMAPI.Toolkit.dll", "SMAPI.Toolkit.xml", "SMAPI.Toolkit.CoreInterfaces.dll", "SMAPI.Toolkit.CoreInterfaces.xml", "System.Net.Http.Formatting.dll")) {
|
||||
cp "$smapiBin/$name" "$bundlePath/smapi-internal"
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,6 @@ foreach ($folder in $folders) {
|
|||
mkdir "$targetPath" > $null
|
||||
|
||||
cp "$fromPath/$modName.dll" "$targetPath"
|
||||
cp "$fromPath/$modName.pdb" "$targetPath"
|
||||
cp "$fromPath/manifest.json" "$targetPath"
|
||||
if (Test-Path "$fromPath/i18n" -PathType Container) {
|
||||
cp -Recurse "$fromPath/i18n" "$targetPath"
|
||||
|
|
|
@ -7,6 +7,48 @@
|
|||
_If needed, you can update to SMAPI 3.16.0 first and then install the latest version._
|
||||
-->
|
||||
|
||||
## 3.18.4
|
||||
Released 24 June 2023 for Stardew Valley 1.5.6 or later.
|
||||
|
||||
* For players:
|
||||
* In multiplayer, the game/SMAPI window titles now show whether you're the main player or a farmhand.
|
||||
* The `test_input` console command now logs input until the command is run again (instead of for 30 seconds).
|
||||
* Fixed logged SMAPI errors not having line numbers on Linux/macOS.
|
||||
* Fixed wezterm terminal support on Linux/macoS (thanks to romangraef!).
|
||||
* Fixed install error if a game folder has an invalid symlink.
|
||||
|
||||
* For mod authors:
|
||||
* Added `--no-prompt` installer command-line argument for automated tools (thanks to NyCodeGHG!).
|
||||
* Added clearer error message when a map tilesheet has no image source (thanks to atravita!).
|
||||
* Fixed `Context.HasRemotePlayers` being true when there's no farmhands connected.
|
||||
* Fixed error loading a mod if it explicitly sets `"MinimumApiVersion": null`.
|
||||
* Updated Newtonsoft.Json 13.0.2 → 13.0.3 (see [changes](https://github.com/JamesNK/Newtonsoft.Json/releases/tag/13.0.3)) and Pintail 2.2.2 → 2.3.0 (see [changes](https://github.com/Nanoray-pl/Pintail/blob/master/docs/release-notes.md#230)).
|
||||
|
||||
* For SMAPI toolkit users:
|
||||
* Fixed `ModFolder` not being JSON-serializable.
|
||||
|
||||
* For the web API:
|
||||
* Fixed manifest schema format for the `examples` field (thanks to boneskull!).
|
||||
|
||||
## 3.18.3
|
||||
Released 09 April 2023 for Stardew Valley 1.5.6 or later.
|
||||
|
||||
* For players:
|
||||
* Fixed `findstr` installer error for some players.
|
||||
* Fixed installer error for some Linux players due to a non-portable shebang (thanks to freyacoded!).
|
||||
* Fixed error using load order overrides when there are broken mods installed (thanks to atravita!).
|
||||
* Removed `LargeAddressAware` flag on SMAPI (no longer needed since it's 64-bit now).
|
||||
* Improved translations. Thanks to stylemate (updated Korean)!
|
||||
|
||||
* For mod authors:
|
||||
* Added `IsActiveForScreen()` method to `PerScreen<T>`.
|
||||
* Updated to [FluentHttpClient](https://github.com/Pathoschild/FluentHttpClient#readme) 4.3.0 (see [changes](https://github.com/Pathoschild/FluentHttpClient/blob/develop/RELEASE-NOTES.md#430)).
|
||||
* Adjusted `ModContentManager.HandleUnknownFileType` to let mods patch it.
|
||||
* Fixed `Context.IsWorldReady` being editable by mods.
|
||||
|
||||
* For the web UI:
|
||||
* Updated the JSON validator/schema for Content Patcher 1.29.0.
|
||||
|
||||
## 3.18.2
|
||||
Released 09 January 2023 for Stardew Valley 1.5.6 or later.
|
||||
|
||||
|
|
|
@ -99,6 +99,10 @@ There are two places you can put them:
|
|||
2. Open the `.csproj` file in a text editor (Notepad is fine).
|
||||
3. Add the properties between the first `<PropertyGroup>` and `</PropertyGroup>` tags you find.
|
||||
|
||||
**Note:** you can't use a property before it's defined. That mainly means that when setting
|
||||
`GameModsPath`, you'll need to either specify `GamePath` manually or put the full path in
|
||||
`GameModsPath`.
|
||||
|
||||
### Available properties
|
||||
These are the options you can set:
|
||||
|
||||
|
@ -412,28 +416,33 @@ The NuGet package is generated automatically in `StardewModdingAPI.ModBuildConfi
|
|||
when you compile it.
|
||||
|
||||
## Release notes
|
||||
## 4.1.1
|
||||
Released 24 June 2023 for SMAPI 3.13.0 or later.
|
||||
|
||||
* Replaced `.pdb` files with embedded symbols by default. This fixes logged errors not having line numbers on Linux/macOS.
|
||||
|
||||
### 4.1.0
|
||||
Released 08 January 2023.
|
||||
Released 08 January 2023 for SMAPI 3.13.0 or later.
|
||||
|
||||
* Added `manifest.json` format validation on build (thanks to tylergibbs2!).
|
||||
* Fixed game DLLs not excluded from the release zip when they're referenced explicitly but `BundleExtraAssemblies` isn't set.
|
||||
|
||||
### 4.0.2
|
||||
Released 09 October 2022.
|
||||
Released 09 October 2022 for SMAPI 3.13.0 or later.
|
||||
|
||||
* Switched to the newer crossplatform `portable` debug symbols (thanks to lanturnalis!).
|
||||
* Fixed `BundleExtraAssemblies` option being partly case-sensitive.
|
||||
* Fixed `BundleExtraAssemblies` not applying `All` value to game assemblies.
|
||||
|
||||
### 4.0.1
|
||||
Released 14 April 2022.
|
||||
Released 14 April 2022 for SMAPI 3.13.0 or later.
|
||||
|
||||
* Added detection for Xbox app game folders.
|
||||
* Fixed "_conflicts between different versions of Microsoft.Win32.Registry_" warnings in recent SMAPI versions.
|
||||
* Internal refactoring.
|
||||
|
||||
### 4.0.0
|
||||
Released 30 November 2021.
|
||||
Released 30 November 2021 for SMAPI 3.13.0 or later.
|
||||
|
||||
* Updated for Stardew Valley 1.5.5 and SMAPI 3.13.0. (Older versions are no longer supported.)
|
||||
* Added `IgnoreModFilePaths` option to ignore literal paths.
|
||||
|
@ -455,7 +464,7 @@ Released 30 November 2021.
|
|||
documentation](#configure).
|
||||
|
||||
### 3.3.0
|
||||
Released 30 March 2021.
|
||||
Released 30 March 2021 for SMAPI 3.0.0 or later.
|
||||
|
||||
* Added a build warning when the mod isn't compiled for `Any CPU`.
|
||||
* Added a `GameFramework` build property set to `MonoGame` or `Xna` based on the platform. This can
|
||||
|
@ -464,32 +473,32 @@ Released 30 March 2021.
|
|||
* The package now suppresses the misleading 'processor architecture mismatch' warnings.
|
||||
|
||||
### 3.2.2
|
||||
Released 23 September 2020.
|
||||
Released 23 September 2020 for SMAPI 3.0.0 or later.
|
||||
|
||||
* Reworked and streamlined how the package is compiled.
|
||||
* Added [SMAPI-ModTranslationClassBuilder](https://github.com/Pathoschild/SMAPI-ModTranslationClassBuilder)
|
||||
files to the ignore list.
|
||||
|
||||
### 3.2.1
|
||||
Released 11 September 2020.
|
||||
Released 11 September 2020 for SMAPI 3.0.0 or later.
|
||||
|
||||
* Added more detailed logging.
|
||||
* Fixed _path's format is not supported_ error when using default `Mods` path in 3.2.
|
||||
|
||||
### 3.2.0
|
||||
Released 07 September 2020.
|
||||
Released 07 September 2020 for SMAPI 3.0.0 or later.
|
||||
|
||||
* Added option to change `Mods` folder path.
|
||||
* Rewrote documentation to make it easier to read.
|
||||
|
||||
### 3.1.0
|
||||
Released 01 February 2020.
|
||||
Released 01 February 2020 for SMAPI 3.0.0 or later.
|
||||
|
||||
* Added support for semantic versioning 2.0.
|
||||
* `0Harmony.dll` is now ignored if the mod references Harmony directly (it's bundled with SMAPI).
|
||||
|
||||
### 3.0.0
|
||||
Released 26 November 2019.
|
||||
Released 26 November 2019 for SMAPI 3.0.0 or later.
|
||||
|
||||
* Updated for SMAPI 3.0 and Stardew Valley 1.4.
|
||||
* Added automatic support for `assets` folders.
|
||||
|
|
|
@ -32,6 +32,7 @@ argument | purpose
|
|||
`--install` | Preselects the install action, skipping the prompt asking what the user wants to do.
|
||||
`--uninstall` | Preselects the uninstall action, skipping the prompt asking what the user wants to do.
|
||||
`--game-path "path"` | Specifies the full path to the folder containing the Stardew Valley executable, skipping automatic detection and any prompt to choose a path. If the path is not valid, the installer displays an error.
|
||||
`--no-prompt` | Don't let the installer wait for user input (e.g. for cases where it's being run by a script). If the installer is unable to continue without user input, it'll fail instead.
|
||||
|
||||
SMAPI itself recognises five arguments, but these are meant for internal use or testing, and might
|
||||
change without warning. **On Linux/macOS**, command-line arguments won't work; see _environment
|
||||
|
|
|
@ -18,10 +18,12 @@
|
|||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
|
||||
<TargetFrameworkVersion>v12.0</TargetFrameworkVersion>
|
||||
<TargetFramework>net5.0-android</TargetFramework>
|
||||
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
|
||||
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
|
||||
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
|
||||
<AndroidEnableSGenConcurrent>true</AndroidEnableSGenConcurrent>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
|
@ -31,29 +33,31 @@
|
|||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
|
||||
<AndroidUseSharedRuntime>true</AndroidUseSharedRuntime>
|
||||
<AndroidLinkMode>None</AndroidLinkMode>
|
||||
<EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
|
||||
<AndroidManagedSymbols>false</AndroidManagedSymbols>
|
||||
<AndroidUseAapt2>false</AndroidUseAapt2>
|
||||
<AndroidUseAapt2>true</AndroidUseAapt2>
|
||||
<AndroidSupportedAbis>armeabi-v7a;x86;arm64-v8a;x86_64</AndroidSupportedAbis>
|
||||
<AndroidDexTool>dx</AndroidDexTool>
|
||||
<AndroidDexTool>d8</AndroidDexTool>
|
||||
<!-- <AndroidLinkSkip>Mono.Android;MonoGame.Framework;mscorlib;System.Core;System;System.Drawing.Common;System.Numerics;System.Runtime.Serialization;System.Xml;System.Xml.Linq</AndroidLinkSkip>-->
|
||||
<AndroidEnableMultiDex>true</AndroidEnableMultiDex>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
<DebugSymbols>False</DebugSymbols>
|
||||
<DebugType>portable</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AndroidManagedSymbols>true</AndroidManagedSymbols>
|
||||
<AndroidManagedSymbols>false</AndroidManagedSymbols>
|
||||
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
|
||||
<AndroidLinkMode>None</AndroidLinkMode>
|
||||
<EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
|
||||
<AndroidUseAapt2>false</AndroidUseAapt2>
|
||||
<AndroidUseAapt2>true</AndroidUseAapt2>
|
||||
<AndroidSupportedAbis>armeabi-v7a;x86;arm64-v8a;x86_64</AndroidSupportedAbis>
|
||||
<AndroidDexTool>dx</AndroidDexTool>
|
||||
<AndroidDexTool>d8</AndroidDexTool>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Resources\Resource.designer.cs" />
|
||||
|
@ -76,44 +80,12 @@
|
|||
<AndroidResource Include="Resources\values\styles.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Mono.Android" />
|
||||
<Reference Include="Mono.Security" />
|
||||
<ProjectReference Include="..\SMAPI\SMAPI.csproj" />
|
||||
<Reference Include="Microsoft.AppCenter, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
|
||||
<HintPath>..\packages\Microsoft.AppCenter.2.6.4\lib\MonoAndroid403\Microsoft.AppCenter.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AppCenter.Analytics, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
|
||||
<HintPath>..\packages\Microsoft.AppCenter.Analytics.2.6.4\lib\MonoAndroid403\Microsoft.AppCenter.Analytics.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AppCenter.Analytics.Android.Bindings, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
|
||||
<HintPath>..\packages\Microsoft.AppCenter.Analytics.2.6.4\lib\MonoAndroid403\Microsoft.AppCenter.Analytics.Android.Bindings.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AppCenter.Android.Bindings, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
|
||||
<HintPath>..\packages\Microsoft.AppCenter.2.6.4\lib\MonoAndroid403\Microsoft.AppCenter.Android.Bindings.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AppCenter.Crashes, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
|
||||
<HintPath>..\packages\Microsoft.AppCenter.Crashes.2.6.4\lib\MonoAndroid403\Microsoft.AppCenter.Crashes.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AppCenter.Crashes.Android.Bindings, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
|
||||
<HintPath>..\packages\Microsoft.AppCenter.Crashes.2.6.4\lib\MonoAndroid403\Microsoft.AppCenter.Crashes.Android.Bindings.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<PackageReference Include="MonoGame.Framework.Android">
|
||||
<Version>3.6.0.862</Version>
|
||||
</PackageReference>
|
||||
<Reference Include="MonoGame.Framework, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
|
||||
<HintPath>..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.5.145\assemblies\MonoGame.Framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MonoGame.Framework.Content.Pipeline">
|
||||
<HintPath>..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.5.145\assemblies\MonoGame.Framework.Content.Pipeline.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="Mono.Android" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\mipmap\ic_launcher.png" />
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="151" android:versionName="1.4.5.151" android:installLocation="auto" package="com.zane.stardewvalley2" platformBuildVersionCode="29" platformBuildVersionName="9">
|
||||
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="29" />
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="156" android:versionName="1.5.6.31" android:installLocation="auto" package="com.zane.stardewvalley2" platformBuildVersionCode="31" platformBuildVersionName="9">
|
||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
|
@ -15,6 +15,7 @@
|
|||
android:allowBackup="true"
|
||||
android:resizeableActivity="false"
|
||||
android:debuggable="true"
|
||||
android:requestLegacyExternalStorage="true"></application>
|
||||
android:requestLegacyExternalStorage="true">
|
||||
</application>
|
||||
<uses-permission android:name="com.android.vending.CHECK_LICENSE" />
|
||||
</manifest>
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Android.App;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Loader")]
|
||||
|
@ -19,11 +17,11 @@ using Android.App;
|
|||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Loader
|
|||
{
|
||||
|
||||
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "13.2.0.99")]
|
||||
public partial class Resource
|
||||
{
|
||||
|
||||
|
@ -25,217 +25,13 @@ namespace Loader
|
|||
|
||||
public static void UpdateIdValues()
|
||||
{
|
||||
global::StardewModdingAPI.Resource.Attribute.alpha = global::Loader.Resource.Attribute.alpha;
|
||||
global::StardewModdingAPI.Resource.Attribute.font = global::Loader.Resource.Attribute.font;
|
||||
global::StardewModdingAPI.Resource.Attribute.fontProviderAuthority = global::Loader.Resource.Attribute.fontProviderAuthority;
|
||||
global::StardewModdingAPI.Resource.Attribute.fontProviderCerts = global::Loader.Resource.Attribute.fontProviderCerts;
|
||||
global::StardewModdingAPI.Resource.Attribute.fontProviderFetchStrategy = global::Loader.Resource.Attribute.fontProviderFetchStrategy;
|
||||
global::StardewModdingAPI.Resource.Attribute.fontProviderFetchTimeout = global::Loader.Resource.Attribute.fontProviderFetchTimeout;
|
||||
global::StardewModdingAPI.Resource.Attribute.fontProviderPackage = global::Loader.Resource.Attribute.fontProviderPackage;
|
||||
global::StardewModdingAPI.Resource.Attribute.fontProviderQuery = global::Loader.Resource.Attribute.fontProviderQuery;
|
||||
global::StardewModdingAPI.Resource.Attribute.fontStyle = global::Loader.Resource.Attribute.fontStyle;
|
||||
global::StardewModdingAPI.Resource.Attribute.fontVariationSettings = global::Loader.Resource.Attribute.fontVariationSettings;
|
||||
global::StardewModdingAPI.Resource.Attribute.fontWeight = global::Loader.Resource.Attribute.fontWeight;
|
||||
global::StardewModdingAPI.Resource.Attribute.ttcIndex = global::Loader.Resource.Attribute.ttcIndex;
|
||||
global::StardewModdingAPI.Resource.Color.notification_action_color_filter = global::Loader.Resource.Color.notification_action_color_filter;
|
||||
global::StardewModdingAPI.Resource.Color.notification_icon_bg_color = global::Loader.Resource.Color.notification_icon_bg_color;
|
||||
global::StardewModdingAPI.Resource.Color.ripple_material_light = global::Loader.Resource.Color.ripple_material_light;
|
||||
global::StardewModdingAPI.Resource.Color.secondary_text_default_material_light = global::Loader.Resource.Color.secondary_text_default_material_light;
|
||||
global::StardewModdingAPI.Resource.Dimension.compat_button_inset_horizontal_material = global::Loader.Resource.Dimension.compat_button_inset_horizontal_material;
|
||||
global::StardewModdingAPI.Resource.Dimension.compat_button_inset_vertical_material = global::Loader.Resource.Dimension.compat_button_inset_vertical_material;
|
||||
global::StardewModdingAPI.Resource.Dimension.compat_button_padding_horizontal_material = global::Loader.Resource.Dimension.compat_button_padding_horizontal_material;
|
||||
global::StardewModdingAPI.Resource.Dimension.compat_button_padding_vertical_material = global::Loader.Resource.Dimension.compat_button_padding_vertical_material;
|
||||
global::StardewModdingAPI.Resource.Dimension.compat_control_corner_material = global::Loader.Resource.Dimension.compat_control_corner_material;
|
||||
global::StardewModdingAPI.Resource.Dimension.compat_notification_large_icon_max_height = global::Loader.Resource.Dimension.compat_notification_large_icon_max_height;
|
||||
global::StardewModdingAPI.Resource.Dimension.compat_notification_large_icon_max_width = global::Loader.Resource.Dimension.compat_notification_large_icon_max_width;
|
||||
global::StardewModdingAPI.Resource.Dimension.notification_action_icon_size = global::Loader.Resource.Dimension.notification_action_icon_size;
|
||||
global::StardewModdingAPI.Resource.Dimension.notification_action_text_size = global::Loader.Resource.Dimension.notification_action_text_size;
|
||||
global::StardewModdingAPI.Resource.Dimension.notification_big_circle_margin = global::Loader.Resource.Dimension.notification_big_circle_margin;
|
||||
global::StardewModdingAPI.Resource.Dimension.notification_content_margin_start = global::Loader.Resource.Dimension.notification_content_margin_start;
|
||||
global::StardewModdingAPI.Resource.Dimension.notification_large_icon_height = global::Loader.Resource.Dimension.notification_large_icon_height;
|
||||
global::StardewModdingAPI.Resource.Dimension.notification_large_icon_width = global::Loader.Resource.Dimension.notification_large_icon_width;
|
||||
global::StardewModdingAPI.Resource.Dimension.notification_main_column_padding_top = global::Loader.Resource.Dimension.notification_main_column_padding_top;
|
||||
global::StardewModdingAPI.Resource.Dimension.notification_media_narrow_margin = global::Loader.Resource.Dimension.notification_media_narrow_margin;
|
||||
global::StardewModdingAPI.Resource.Dimension.notification_right_icon_size = global::Loader.Resource.Dimension.notification_right_icon_size;
|
||||
global::StardewModdingAPI.Resource.Dimension.notification_right_side_padding_top = global::Loader.Resource.Dimension.notification_right_side_padding_top;
|
||||
global::StardewModdingAPI.Resource.Dimension.notification_small_icon_background_padding = global::Loader.Resource.Dimension.notification_small_icon_background_padding;
|
||||
global::StardewModdingAPI.Resource.Dimension.notification_small_icon_size_as_large = global::Loader.Resource.Dimension.notification_small_icon_size_as_large;
|
||||
global::StardewModdingAPI.Resource.Dimension.notification_subtext_size = global::Loader.Resource.Dimension.notification_subtext_size;
|
||||
global::StardewModdingAPI.Resource.Dimension.notification_top_pad = global::Loader.Resource.Dimension.notification_top_pad;
|
||||
global::StardewModdingAPI.Resource.Dimension.notification_top_pad_large_text = global::Loader.Resource.Dimension.notification_top_pad_large_text;
|
||||
global::StardewModdingAPI.Resource.Drawable.notification_action_background = global::Loader.Resource.Drawable.notification_action_background;
|
||||
global::StardewModdingAPI.Resource.Drawable.notification_bg = global::Loader.Resource.Drawable.notification_bg;
|
||||
global::StardewModdingAPI.Resource.Drawable.notification_bg_low = global::Loader.Resource.Drawable.notification_bg_low;
|
||||
global::StardewModdingAPI.Resource.Drawable.notification_bg_low_normal = global::Loader.Resource.Drawable.notification_bg_low_normal;
|
||||
global::StardewModdingAPI.Resource.Drawable.notification_bg_low_pressed = global::Loader.Resource.Drawable.notification_bg_low_pressed;
|
||||
global::StardewModdingAPI.Resource.Drawable.notification_bg_normal = global::Loader.Resource.Drawable.notification_bg_normal;
|
||||
global::StardewModdingAPI.Resource.Drawable.notification_bg_normal_pressed = global::Loader.Resource.Drawable.notification_bg_normal_pressed;
|
||||
global::StardewModdingAPI.Resource.Drawable.notification_icon_background = global::Loader.Resource.Drawable.notification_icon_background;
|
||||
global::StardewModdingAPI.Resource.Drawable.notification_template_icon_bg = global::Loader.Resource.Drawable.notification_template_icon_bg;
|
||||
global::StardewModdingAPI.Resource.Drawable.notification_template_icon_low_bg = global::Loader.Resource.Drawable.notification_template_icon_low_bg;
|
||||
global::StardewModdingAPI.Resource.Drawable.notification_tile_bg = global::Loader.Resource.Drawable.notification_tile_bg;
|
||||
global::StardewModdingAPI.Resource.Drawable.notify_panel_notification_icon_bg = global::Loader.Resource.Drawable.notify_panel_notification_icon_bg;
|
||||
global::StardewModdingAPI.Resource.Id.actions = global::Loader.Resource.Id.actions;
|
||||
global::StardewModdingAPI.Resource.Id.action_container = global::Loader.Resource.Id.action_container;
|
||||
global::StardewModdingAPI.Resource.Id.action_divider = global::Loader.Resource.Id.action_divider;
|
||||
global::StardewModdingAPI.Resource.Id.action_image = global::Loader.Resource.Id.action_image;
|
||||
global::StardewModdingAPI.Resource.Id.action_text = global::Loader.Resource.Id.action_text;
|
||||
global::StardewModdingAPI.Resource.Id.appIcon = global::Loader.Resource.Id.appIcon;
|
||||
global::StardewModdingAPI.Resource.Id.async = global::Loader.Resource.Id.async;
|
||||
global::StardewModdingAPI.Resource.Id.blocking = global::Loader.Resource.Id.blocking;
|
||||
global::StardewModdingAPI.Resource.Id.chronometer = global::Loader.Resource.Id.chronometer;
|
||||
global::StardewModdingAPI.Resource.Id.description = global::Loader.Resource.Id.description;
|
||||
global::StardewModdingAPI.Resource.Id.forever = global::Loader.Resource.Id.forever;
|
||||
global::StardewModdingAPI.Resource.Id.icon = global::Loader.Resource.Id.icon;
|
||||
global::StardewModdingAPI.Resource.Id.icon_group = global::Loader.Resource.Id.icon_group;
|
||||
global::StardewModdingAPI.Resource.Id.info = global::Loader.Resource.Id.info;
|
||||
global::StardewModdingAPI.Resource.Id.italic = global::Loader.Resource.Id.italic;
|
||||
global::StardewModdingAPI.Resource.Id.line1 = global::Loader.Resource.Id.line1;
|
||||
global::StardewModdingAPI.Resource.Id.line3 = global::Loader.Resource.Id.line3;
|
||||
global::StardewModdingAPI.Resource.Id.normal = global::Loader.Resource.Id.normal;
|
||||
global::StardewModdingAPI.Resource.Id.notificationLayout = global::Loader.Resource.Id.notificationLayout;
|
||||
global::StardewModdingAPI.Resource.Id.notification_background = global::Loader.Resource.Id.notification_background;
|
||||
global::StardewModdingAPI.Resource.Id.notification_main_column = global::Loader.Resource.Id.notification_main_column;
|
||||
global::StardewModdingAPI.Resource.Id.notification_main_column_container = global::Loader.Resource.Id.notification_main_column_container;
|
||||
global::StardewModdingAPI.Resource.Id.progress_bar = global::Loader.Resource.Id.progress_bar;
|
||||
global::StardewModdingAPI.Resource.Id.progress_bar_frame = global::Loader.Resource.Id.progress_bar_frame;
|
||||
global::StardewModdingAPI.Resource.Id.progress_text = global::Loader.Resource.Id.progress_text;
|
||||
global::StardewModdingAPI.Resource.Id.right_icon = global::Loader.Resource.Id.right_icon;
|
||||
global::StardewModdingAPI.Resource.Id.right_side = global::Loader.Resource.Id.right_side;
|
||||
global::StardewModdingAPI.Resource.Id.spacer = global::Loader.Resource.Id.spacer;
|
||||
global::StardewModdingAPI.Resource.Id.tag_transition_group = global::Loader.Resource.Id.tag_transition_group;
|
||||
global::StardewModdingAPI.Resource.Id.tag_unhandled_key_event_manager = global::Loader.Resource.Id.tag_unhandled_key_event_manager;
|
||||
global::StardewModdingAPI.Resource.Id.tag_unhandled_key_listeners = global::Loader.Resource.Id.tag_unhandled_key_listeners;
|
||||
global::StardewModdingAPI.Resource.Id.text = global::Loader.Resource.Id.text;
|
||||
global::StardewModdingAPI.Resource.Id.text2 = global::Loader.Resource.Id.text2;
|
||||
global::StardewModdingAPI.Resource.Id.time = global::Loader.Resource.Id.time;
|
||||
global::StardewModdingAPI.Resource.Id.time_remaining = global::Loader.Resource.Id.time_remaining;
|
||||
global::StardewModdingAPI.Resource.Id.title = global::Loader.Resource.Id.title;
|
||||
global::StardewModdingAPI.Resource.Integer.status_bar_notification_info_maxnum = global::Loader.Resource.Integer.status_bar_notification_info_maxnum;
|
||||
global::StardewModdingAPI.Resource.Layout.notification_action = global::Loader.Resource.Layout.notification_action;
|
||||
global::StardewModdingAPI.Resource.Layout.notification_action_tombstone = global::Loader.Resource.Layout.notification_action_tombstone;
|
||||
global::StardewModdingAPI.Resource.Layout.notification_template_custom_big = global::Loader.Resource.Layout.notification_template_custom_big;
|
||||
global::StardewModdingAPI.Resource.Layout.notification_template_icon_group = global::Loader.Resource.Layout.notification_template_icon_group;
|
||||
global::StardewModdingAPI.Resource.Layout.notification_template_part_chronometer = global::Loader.Resource.Layout.notification_template_part_chronometer;
|
||||
global::StardewModdingAPI.Resource.Layout.notification_template_part_time = global::Loader.Resource.Layout.notification_template_part_time;
|
||||
global::StardewModdingAPI.Resource.Layout.status_bar_ongoing_event_progress_bar = global::Loader.Resource.Layout.status_bar_ongoing_event_progress_bar;
|
||||
global::StardewModdingAPI.Resource.String.app_name = global::Loader.Resource.String.app_name;
|
||||
global::StardewModdingAPI.Resource.String.hello = global::Loader.Resource.String.hello;
|
||||
global::StardewModdingAPI.Resource.String.kilobytes_per_second = global::Loader.Resource.String.kilobytes_per_second;
|
||||
global::StardewModdingAPI.Resource.String.notification_download_complete = global::Loader.Resource.String.notification_download_complete;
|
||||
global::StardewModdingAPI.Resource.String.notification_download_failed = global::Loader.Resource.String.notification_download_failed;
|
||||
global::StardewModdingAPI.Resource.String.state_completed = global::Loader.Resource.String.state_completed;
|
||||
global::StardewModdingAPI.Resource.String.state_connecting = global::Loader.Resource.String.state_connecting;
|
||||
global::StardewModdingAPI.Resource.String.state_downloading = global::Loader.Resource.String.state_downloading;
|
||||
global::StardewModdingAPI.Resource.String.state_failed = global::Loader.Resource.String.state_failed;
|
||||
global::StardewModdingAPI.Resource.String.state_failed_cancelled = global::Loader.Resource.String.state_failed_cancelled;
|
||||
global::StardewModdingAPI.Resource.String.state_failed_fetching_url = global::Loader.Resource.String.state_failed_fetching_url;
|
||||
global::StardewModdingAPI.Resource.String.state_failed_sdcard_full = global::Loader.Resource.String.state_failed_sdcard_full;
|
||||
global::StardewModdingAPI.Resource.String.state_failed_unlicensed = global::Loader.Resource.String.state_failed_unlicensed;
|
||||
global::StardewModdingAPI.Resource.String.state_fetching_url = global::Loader.Resource.String.state_fetching_url;
|
||||
global::StardewModdingAPI.Resource.String.state_idle = global::Loader.Resource.String.state_idle;
|
||||
global::StardewModdingAPI.Resource.String.state_paused_by_request = global::Loader.Resource.String.state_paused_by_request;
|
||||
global::StardewModdingAPI.Resource.String.state_paused_network_setup_failure = global::Loader.Resource.String.state_paused_network_setup_failure;
|
||||
global::StardewModdingAPI.Resource.String.state_paused_network_unavailable = global::Loader.Resource.String.state_paused_network_unavailable;
|
||||
global::StardewModdingAPI.Resource.String.state_paused_roaming = global::Loader.Resource.String.state_paused_roaming;
|
||||
global::StardewModdingAPI.Resource.String.state_paused_sdcard_unavailable = global::Loader.Resource.String.state_paused_sdcard_unavailable;
|
||||
global::StardewModdingAPI.Resource.String.state_paused_wifi_disabled = global::Loader.Resource.String.state_paused_wifi_disabled;
|
||||
global::StardewModdingAPI.Resource.String.state_paused_wifi_unavailable = global::Loader.Resource.String.state_paused_wifi_unavailable;
|
||||
global::StardewModdingAPI.Resource.String.state_unknown = global::Loader.Resource.String.state_unknown;
|
||||
global::StardewModdingAPI.Resource.String.status_bar_notification_info_overflow = global::Loader.Resource.String.status_bar_notification_info_overflow;
|
||||
global::StardewModdingAPI.Resource.String.time_remaining = global::Loader.Resource.String.time_remaining;
|
||||
global::StardewModdingAPI.Resource.String.time_remaining_notification = global::Loader.Resource.String.time_remaining_notification;
|
||||
global::StardewModdingAPI.Resource.Style.ButtonBackground = global::Loader.Resource.Style.ButtonBackground;
|
||||
global::StardewModdingAPI.Resource.Style.NotificationText = global::Loader.Resource.Style.NotificationText;
|
||||
global::StardewModdingAPI.Resource.Style.NotificationTextSecondary = global::Loader.Resource.Style.NotificationTextSecondary;
|
||||
global::StardewModdingAPI.Resource.Style.NotificationTextShadow = global::Loader.Resource.Style.NotificationTextShadow;
|
||||
global::StardewModdingAPI.Resource.Style.NotificationTitle = global::Loader.Resource.Style.NotificationTitle;
|
||||
global::StardewModdingAPI.Resource.Style.TextAppearance_Compat_Notification = global::Loader.Resource.Style.TextAppearance_Compat_Notification;
|
||||
global::StardewModdingAPI.Resource.Style.TextAppearance_Compat_Notification_Info = global::Loader.Resource.Style.TextAppearance_Compat_Notification_Info;
|
||||
global::StardewModdingAPI.Resource.Style.TextAppearance_Compat_Notification_Line2 = global::Loader.Resource.Style.TextAppearance_Compat_Notification_Line2;
|
||||
global::StardewModdingAPI.Resource.Style.TextAppearance_Compat_Notification_Time = global::Loader.Resource.Style.TextAppearance_Compat_Notification_Time;
|
||||
global::StardewModdingAPI.Resource.Style.TextAppearance_Compat_Notification_Title = global::Loader.Resource.Style.TextAppearance_Compat_Notification_Title;
|
||||
global::StardewModdingAPI.Resource.Style.Widget_Compat_NotificationActionContainer = global::Loader.Resource.Style.Widget_Compat_NotificationActionContainer;
|
||||
global::StardewModdingAPI.Resource.Style.Widget_Compat_NotificationActionText = global::Loader.Resource.Style.Widget_Compat_NotificationActionText;
|
||||
global::StardewModdingAPI.Resource.Styleable.ColorStateListItem = global::Loader.Resource.Styleable.ColorStateListItem;
|
||||
global::StardewModdingAPI.Resource.Styleable.ColorStateListItem_alpha = global::Loader.Resource.Styleable.ColorStateListItem_alpha;
|
||||
global::StardewModdingAPI.Resource.Styleable.ColorStateListItem_android_alpha = global::Loader.Resource.Styleable.ColorStateListItem_android_alpha;
|
||||
global::StardewModdingAPI.Resource.Styleable.ColorStateListItem_android_color = global::Loader.Resource.Styleable.ColorStateListItem_android_color;
|
||||
global::StardewModdingAPI.Resource.Styleable.FontFamily = global::Loader.Resource.Styleable.FontFamily;
|
||||
global::StardewModdingAPI.Resource.Styleable.FontFamilyFont = global::Loader.Resource.Styleable.FontFamilyFont;
|
||||
global::StardewModdingAPI.Resource.Styleable.FontFamilyFont_android_font = global::Loader.Resource.Styleable.FontFamilyFont_android_font;
|
||||
global::StardewModdingAPI.Resource.Styleable.FontFamilyFont_android_fontStyle = global::Loader.Resource.Styleable.FontFamilyFont_android_fontStyle;
|
||||
global::StardewModdingAPI.Resource.Styleable.FontFamilyFont_android_fontVariationSettings = global::Loader.Resource.Styleable.FontFamilyFont_android_fontVariationSettings;
|
||||
global::StardewModdingAPI.Resource.Styleable.FontFamilyFont_android_fontWeight = global::Loader.Resource.Styleable.FontFamilyFont_android_fontWeight;
|
||||
global::StardewModdingAPI.Resource.Styleable.FontFamilyFont_android_ttcIndex = global::Loader.Resource.Styleable.FontFamilyFont_android_ttcIndex;
|
||||
global::StardewModdingAPI.Resource.Styleable.FontFamilyFont_font = global::Loader.Resource.Styleable.FontFamilyFont_font;
|
||||
global::StardewModdingAPI.Resource.Styleable.FontFamilyFont_fontStyle = global::Loader.Resource.Styleable.FontFamilyFont_fontStyle;
|
||||
global::StardewModdingAPI.Resource.Styleable.FontFamilyFont_fontVariationSettings = global::Loader.Resource.Styleable.FontFamilyFont_fontVariationSettings;
|
||||
global::StardewModdingAPI.Resource.Styleable.FontFamilyFont_fontWeight = global::Loader.Resource.Styleable.FontFamilyFont_fontWeight;
|
||||
global::StardewModdingAPI.Resource.Styleable.FontFamilyFont_ttcIndex = global::Loader.Resource.Styleable.FontFamilyFont_ttcIndex;
|
||||
global::StardewModdingAPI.Resource.Styleable.FontFamily_fontProviderAuthority = global::Loader.Resource.Styleable.FontFamily_fontProviderAuthority;
|
||||
global::StardewModdingAPI.Resource.Styleable.FontFamily_fontProviderCerts = global::Loader.Resource.Styleable.FontFamily_fontProviderCerts;
|
||||
global::StardewModdingAPI.Resource.Styleable.FontFamily_fontProviderFetchStrategy = global::Loader.Resource.Styleable.FontFamily_fontProviderFetchStrategy;
|
||||
global::StardewModdingAPI.Resource.Styleable.FontFamily_fontProviderFetchTimeout = global::Loader.Resource.Styleable.FontFamily_fontProviderFetchTimeout;
|
||||
global::StardewModdingAPI.Resource.Styleable.FontFamily_fontProviderPackage = global::Loader.Resource.Styleable.FontFamily_fontProviderPackage;
|
||||
global::StardewModdingAPI.Resource.Styleable.FontFamily_fontProviderQuery = global::Loader.Resource.Styleable.FontFamily_fontProviderQuery;
|
||||
global::StardewModdingAPI.Resource.Styleable.GradientColor = global::Loader.Resource.Styleable.GradientColor;
|
||||
global::StardewModdingAPI.Resource.Styleable.GradientColorItem = global::Loader.Resource.Styleable.GradientColorItem;
|
||||
global::StardewModdingAPI.Resource.Styleable.GradientColorItem_android_color = global::Loader.Resource.Styleable.GradientColorItem_android_color;
|
||||
global::StardewModdingAPI.Resource.Styleable.GradientColorItem_android_offset = global::Loader.Resource.Styleable.GradientColorItem_android_offset;
|
||||
global::StardewModdingAPI.Resource.Styleable.GradientColor_android_centerColor = global::Loader.Resource.Styleable.GradientColor_android_centerColor;
|
||||
global::StardewModdingAPI.Resource.Styleable.GradientColor_android_centerX = global::Loader.Resource.Styleable.GradientColor_android_centerX;
|
||||
global::StardewModdingAPI.Resource.Styleable.GradientColor_android_centerY = global::Loader.Resource.Styleable.GradientColor_android_centerY;
|
||||
global::StardewModdingAPI.Resource.Styleable.GradientColor_android_endColor = global::Loader.Resource.Styleable.GradientColor_android_endColor;
|
||||
global::StardewModdingAPI.Resource.Styleable.GradientColor_android_endX = global::Loader.Resource.Styleable.GradientColor_android_endX;
|
||||
global::StardewModdingAPI.Resource.Styleable.GradientColor_android_endY = global::Loader.Resource.Styleable.GradientColor_android_endY;
|
||||
global::StardewModdingAPI.Resource.Styleable.GradientColor_android_gradientRadius = global::Loader.Resource.Styleable.GradientColor_android_gradientRadius;
|
||||
global::StardewModdingAPI.Resource.Styleable.GradientColor_android_startColor = global::Loader.Resource.Styleable.GradientColor_android_startColor;
|
||||
global::StardewModdingAPI.Resource.Styleable.GradientColor_android_startX = global::Loader.Resource.Styleable.GradientColor_android_startX;
|
||||
global::StardewModdingAPI.Resource.Styleable.GradientColor_android_startY = global::Loader.Resource.Styleable.GradientColor_android_startY;
|
||||
global::StardewModdingAPI.Resource.Styleable.GradientColor_android_tileMode = global::Loader.Resource.Styleable.GradientColor_android_tileMode;
|
||||
global::StardewModdingAPI.Resource.Styleable.GradientColor_android_type = global::Loader.Resource.Styleable.GradientColor_android_type;
|
||||
}
|
||||
|
||||
public partial class Attribute
|
||||
{
|
||||
|
||||
// aapt resource value: 0x7f010000
|
||||
public const int alpha = 2130771968;
|
||||
|
||||
// aapt resource value: 0x7f010008
|
||||
public const int font = 2130771976;
|
||||
|
||||
// aapt resource value: 0x7f010001
|
||||
public const int fontProviderAuthority = 2130771969;
|
||||
|
||||
// aapt resource value: 0x7f010004
|
||||
public const int fontProviderCerts = 2130771972;
|
||||
|
||||
// aapt resource value: 0x7f010005
|
||||
public const int fontProviderFetchStrategy = 2130771973;
|
||||
|
||||
// aapt resource value: 0x7f010006
|
||||
public const int fontProviderFetchTimeout = 2130771974;
|
||||
|
||||
// aapt resource value: 0x7f010002
|
||||
public const int fontProviderPackage = 2130771970;
|
||||
|
||||
// aapt resource value: 0x7f010003
|
||||
public const int fontProviderQuery = 2130771971;
|
||||
|
||||
// aapt resource value: 0x7f010007
|
||||
public const int fontStyle = 2130771975;
|
||||
|
||||
// aapt resource value: 0x7f01000a
|
||||
public const int fontVariationSettings = 2130771978;
|
||||
|
||||
// aapt resource value: 0x7f010009
|
||||
public const int fontWeight = 2130771977;
|
||||
|
||||
// aapt resource value: 0x7f01000b
|
||||
public const int ttcIndex = 2130771979;
|
||||
|
||||
static Attribute()
|
||||
{
|
||||
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
|
||||
|
@ -249,29 +45,17 @@ namespace Loader
|
|||
public partial class Color
|
||||
{
|
||||
|
||||
// aapt resource value: 0x7f080006
|
||||
public const int colorAccent = 2131230726;
|
||||
// aapt resource value: 0x7F010000
|
||||
public const int colorAccent = 2130771968;
|
||||
|
||||
// aapt resource value: 0x7f080004
|
||||
public const int colorPrimary = 2131230724;
|
||||
// aapt resource value: 0x7F010001
|
||||
public const int colorPrimary = 2130771969;
|
||||
|
||||
// aapt resource value: 0x7f080005
|
||||
public const int colorPrimaryDark = 2131230725;
|
||||
// aapt resource value: 0x7F010002
|
||||
public const int colorPrimaryDark = 2130771970;
|
||||
|
||||
// aapt resource value: 0x7f080007
|
||||
public const int ic_launcher_background = 2131230727;
|
||||
|
||||
// aapt resource value: 0x7f080000
|
||||
public const int notification_action_color_filter = 2131230720;
|
||||
|
||||
// aapt resource value: 0x7f080001
|
||||
public const int notification_icon_bg_color = 2131230721;
|
||||
|
||||
// aapt resource value: 0x7f080002
|
||||
public const int ripple_material_light = 2131230722;
|
||||
|
||||
// aapt resource value: 0x7f080003
|
||||
public const int secondary_text_default_material_light = 2131230723;
|
||||
// aapt resource value: 0x7F010003
|
||||
public const int ic_launcher_background = 2130771971;
|
||||
|
||||
static Color()
|
||||
{
|
||||
|
@ -283,135 +67,20 @@ namespace Loader
|
|||
}
|
||||
}
|
||||
|
||||
public partial class Dimension
|
||||
{
|
||||
|
||||
// aapt resource value: 0x7f070004
|
||||
public const int compat_button_inset_horizontal_material = 2131165188;
|
||||
|
||||
// aapt resource value: 0x7f070005
|
||||
public const int compat_button_inset_vertical_material = 2131165189;
|
||||
|
||||
// aapt resource value: 0x7f070006
|
||||
public const int compat_button_padding_horizontal_material = 2131165190;
|
||||
|
||||
// aapt resource value: 0x7f070007
|
||||
public const int compat_button_padding_vertical_material = 2131165191;
|
||||
|
||||
// aapt resource value: 0x7f070008
|
||||
public const int compat_control_corner_material = 2131165192;
|
||||
|
||||
// aapt resource value: 0x7f070009
|
||||
public const int compat_notification_large_icon_max_height = 2131165193;
|
||||
|
||||
// aapt resource value: 0x7f07000a
|
||||
public const int compat_notification_large_icon_max_width = 2131165194;
|
||||
|
||||
// aapt resource value: 0x7f07000b
|
||||
public const int notification_action_icon_size = 2131165195;
|
||||
|
||||
// aapt resource value: 0x7f07000c
|
||||
public const int notification_action_text_size = 2131165196;
|
||||
|
||||
// aapt resource value: 0x7f07000d
|
||||
public const int notification_big_circle_margin = 2131165197;
|
||||
|
||||
// aapt resource value: 0x7f070001
|
||||
public const int notification_content_margin_start = 2131165185;
|
||||
|
||||
// aapt resource value: 0x7f07000e
|
||||
public const int notification_large_icon_height = 2131165198;
|
||||
|
||||
// aapt resource value: 0x7f07000f
|
||||
public const int notification_large_icon_width = 2131165199;
|
||||
|
||||
// aapt resource value: 0x7f070002
|
||||
public const int notification_main_column_padding_top = 2131165186;
|
||||
|
||||
// aapt resource value: 0x7f070003
|
||||
public const int notification_media_narrow_margin = 2131165187;
|
||||
|
||||
// aapt resource value: 0x7f070010
|
||||
public const int notification_right_icon_size = 2131165200;
|
||||
|
||||
// aapt resource value: 0x7f070000
|
||||
public const int notification_right_side_padding_top = 2131165184;
|
||||
|
||||
// aapt resource value: 0x7f070011
|
||||
public const int notification_small_icon_background_padding = 2131165201;
|
||||
|
||||
// aapt resource value: 0x7f070012
|
||||
public const int notification_small_icon_size_as_large = 2131165202;
|
||||
|
||||
// aapt resource value: 0x7f070013
|
||||
public const int notification_subtext_size = 2131165203;
|
||||
|
||||
// aapt resource value: 0x7f070014
|
||||
public const int notification_top_pad = 2131165204;
|
||||
|
||||
// aapt resource value: 0x7f070015
|
||||
public const int notification_top_pad_large_text = 2131165205;
|
||||
|
||||
static Dimension()
|
||||
{
|
||||
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
|
||||
}
|
||||
|
||||
private Dimension()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Drawable
|
||||
{
|
||||
|
||||
// aapt resource value: 0x7f020000
|
||||
// aapt resource value: 0x7F020000
|
||||
public const int icon = 2130837504;
|
||||
|
||||
// aapt resource value: 0x7f020001
|
||||
public const int notification_action_background = 2130837505;
|
||||
// aapt resource value: 0x7F020001
|
||||
public const int splash = 2130837505;
|
||||
|
||||
// aapt resource value: 0x7f020002
|
||||
public const int notification_bg = 2130837506;
|
||||
// aapt resource value: 0x7F020002
|
||||
public const int splash_logos_crop = 2130837506;
|
||||
|
||||
// aapt resource value: 0x7f020003
|
||||
public const int notification_bg_low = 2130837507;
|
||||
|
||||
// aapt resource value: 0x7f020004
|
||||
public const int notification_bg_low_normal = 2130837508;
|
||||
|
||||
// aapt resource value: 0x7f020005
|
||||
public const int notification_bg_low_pressed = 2130837509;
|
||||
|
||||
// aapt resource value: 0x7f020006
|
||||
public const int notification_bg_normal = 2130837510;
|
||||
|
||||
// aapt resource value: 0x7f020007
|
||||
public const int notification_bg_normal_pressed = 2130837511;
|
||||
|
||||
// aapt resource value: 0x7f020008
|
||||
public const int notification_icon_background = 2130837512;
|
||||
|
||||
// aapt resource value: 0x7f02000e
|
||||
public const int notification_template_icon_bg = 2130837518;
|
||||
|
||||
// aapt resource value: 0x7f02000f
|
||||
public const int notification_template_icon_low_bg = 2130837519;
|
||||
|
||||
// aapt resource value: 0x7f020009
|
||||
public const int notification_tile_bg = 2130837513;
|
||||
|
||||
// aapt resource value: 0x7f02000a
|
||||
public const int notify_panel_notification_icon_bg = 2130837514;
|
||||
|
||||
// aapt resource value: 0x7f02000b
|
||||
public const int splash = 2130837515;
|
||||
|
||||
// aapt resource value: 0x7f02000c
|
||||
public const int splash_logos_crop = 2130837516;
|
||||
|
||||
// aapt resource value: 0x7f02000d
|
||||
public const int splash_screen = 2130837517;
|
||||
// aapt resource value: 0x7F020003
|
||||
public const int splash_screen = 2130837507;
|
||||
|
||||
static Drawable()
|
||||
{
|
||||
|
@ -423,190 +92,19 @@ namespace Loader
|
|||
}
|
||||
}
|
||||
|
||||
public partial class Id
|
||||
{
|
||||
|
||||
// aapt resource value: 0x7f0a000d
|
||||
public const int action_container = 2131361805;
|
||||
|
||||
// aapt resource value: 0x7f0a0019
|
||||
public const int action_divider = 2131361817;
|
||||
|
||||
// aapt resource value: 0x7f0a000e
|
||||
public const int action_image = 2131361806;
|
||||
|
||||
// aapt resource value: 0x7f0a000f
|
||||
public const int action_text = 2131361807;
|
||||
|
||||
// aapt resource value: 0x7f0a001a
|
||||
public const int actions = 2131361818;
|
||||
|
||||
// aapt resource value: 0x7f0a001d
|
||||
public const int appIcon = 2131361821;
|
||||
|
||||
// aapt resource value: 0x7f0a0008
|
||||
public const int async = 2131361800;
|
||||
|
||||
// aapt resource value: 0x7f0a0009
|
||||
public const int blocking = 2131361801;
|
||||
|
||||
// aapt resource value: 0x7f0a0018
|
||||
public const int chronometer = 2131361816;
|
||||
|
||||
// aapt resource value: 0x7f0a0022
|
||||
public const int description = 2131361826;
|
||||
|
||||
// aapt resource value: 0x7f0a000a
|
||||
public const int forever = 2131361802;
|
||||
|
||||
// aapt resource value: 0x7f0a0011
|
||||
public const int icon = 2131361809;
|
||||
|
||||
// aapt resource value: 0x7f0a001b
|
||||
public const int icon_group = 2131361819;
|
||||
|
||||
// aapt resource value: 0x7f0a0014
|
||||
public const int info = 2131361812;
|
||||
|
||||
// aapt resource value: 0x7f0a000b
|
||||
public const int italic = 2131361803;
|
||||
|
||||
// aapt resource value: 0x7f0a0000
|
||||
public const int line1 = 2131361792;
|
||||
|
||||
// aapt resource value: 0x7f0a0001
|
||||
public const int line3 = 2131361793;
|
||||
|
||||
// aapt resource value: 0x7f0a000c
|
||||
public const int normal = 2131361804;
|
||||
|
||||
// aapt resource value: 0x7f0a001c
|
||||
public const int notificationLayout = 2131361820;
|
||||
|
||||
// aapt resource value: 0x7f0a0016
|
||||
public const int notification_background = 2131361814;
|
||||
|
||||
// aapt resource value: 0x7f0a0012
|
||||
public const int notification_main_column = 2131361810;
|
||||
|
||||
// aapt resource value: 0x7f0a0010
|
||||
public const int notification_main_column_container = 2131361808;
|
||||
|
||||
// aapt resource value: 0x7f0a0021
|
||||
public const int progress_bar = 2131361825;
|
||||
|
||||
// aapt resource value: 0x7f0a0020
|
||||
public const int progress_bar_frame = 2131361824;
|
||||
|
||||
// aapt resource value: 0x7f0a001e
|
||||
public const int progress_text = 2131361822;
|
||||
|
||||
// aapt resource value: 0x7f0a0015
|
||||
public const int right_icon = 2131361813;
|
||||
|
||||
// aapt resource value: 0x7f0a0013
|
||||
public const int right_side = 2131361811;
|
||||
|
||||
// aapt resource value: 0x7f0a0023
|
||||
public const int spacer = 2131361827;
|
||||
|
||||
// aapt resource value: 0x7f0a0002
|
||||
public const int tag_transition_group = 2131361794;
|
||||
|
||||
// aapt resource value: 0x7f0a0003
|
||||
public const int tag_unhandled_key_event_manager = 2131361795;
|
||||
|
||||
// aapt resource value: 0x7f0a0004
|
||||
public const int tag_unhandled_key_listeners = 2131361796;
|
||||
|
||||
// aapt resource value: 0x7f0a0005
|
||||
public const int text = 2131361797;
|
||||
|
||||
// aapt resource value: 0x7f0a0006
|
||||
public const int text2 = 2131361798;
|
||||
|
||||
// aapt resource value: 0x7f0a0017
|
||||
public const int time = 2131361815;
|
||||
|
||||
// aapt resource value: 0x7f0a001f
|
||||
public const int time_remaining = 2131361823;
|
||||
|
||||
// aapt resource value: 0x7f0a0007
|
||||
public const int title = 2131361799;
|
||||
|
||||
static Id()
|
||||
{
|
||||
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
|
||||
}
|
||||
|
||||
private Id()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Integer
|
||||
{
|
||||
|
||||
// aapt resource value: 0x7f0b0000
|
||||
public const int status_bar_notification_info_maxnum = 2131427328;
|
||||
|
||||
static Integer()
|
||||
{
|
||||
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
|
||||
}
|
||||
|
||||
private Integer()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Layout
|
||||
{
|
||||
|
||||
// aapt resource value: 0x7f040000
|
||||
public const int notification_action = 2130968576;
|
||||
|
||||
// aapt resource value: 0x7f040001
|
||||
public const int notification_action_tombstone = 2130968577;
|
||||
|
||||
// aapt resource value: 0x7f040002
|
||||
public const int notification_template_custom_big = 2130968578;
|
||||
|
||||
// aapt resource value: 0x7f040003
|
||||
public const int notification_template_icon_group = 2130968579;
|
||||
|
||||
// aapt resource value: 0x7f040004
|
||||
public const int notification_template_part_chronometer = 2130968580;
|
||||
|
||||
// aapt resource value: 0x7f040005
|
||||
public const int notification_template_part_time = 2130968581;
|
||||
|
||||
// aapt resource value: 0x7f040006
|
||||
public const int status_bar_ongoing_event_progress_bar = 2130968582;
|
||||
|
||||
static Layout()
|
||||
{
|
||||
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
|
||||
}
|
||||
|
||||
private Layout()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Mipmap
|
||||
{
|
||||
|
||||
// aapt resource value: 0x7f030000
|
||||
// aapt resource value: 0x7F030000
|
||||
public const int ic_launcher = 2130903040;
|
||||
|
||||
// aapt resource value: 0x7f030001
|
||||
// aapt resource value: 0x7F030001
|
||||
public const int ic_launcher_background = 2130903041;
|
||||
|
||||
// aapt resource value: 0x7f030002
|
||||
// aapt resource value: 0x7F030002
|
||||
public const int ic_launcher_foreground = 2130903042;
|
||||
|
||||
// aapt resource value: 0x7f030003
|
||||
// aapt resource value: 0x7F030003
|
||||
public const int ic_launcher_round = 2130903043;
|
||||
|
||||
static Mipmap()
|
||||
|
@ -622,86 +120,14 @@ namespace Loader
|
|||
public partial class String
|
||||
{
|
||||
|
||||
// aapt resource value: 0x7f06001a
|
||||
public const int action_settings = 2131099674;
|
||||
// aapt resource value: 0x7F040000
|
||||
public const int action_settings = 2130968576;
|
||||
|
||||
// aapt resource value: 0x7f060002
|
||||
public const int app_name = 2131099650;
|
||||
// aapt resource value: 0x7F040001
|
||||
public const int app_name = 2130968577;
|
||||
|
||||
// aapt resource value: 0x7f060001
|
||||
public const int hello = 2131099649;
|
||||
|
||||
// aapt resource value: 0x7f060003
|
||||
public const int kilobytes_per_second = 2131099651;
|
||||
|
||||
// aapt resource value: 0x7f060004
|
||||
public const int notification_download_complete = 2131099652;
|
||||
|
||||
// aapt resource value: 0x7f060005
|
||||
public const int notification_download_failed = 2131099653;
|
||||
|
||||
// aapt resource value: 0x7f060006
|
||||
public const int state_completed = 2131099654;
|
||||
|
||||
// aapt resource value: 0x7f060007
|
||||
public const int state_connecting = 2131099655;
|
||||
|
||||
// aapt resource value: 0x7f060008
|
||||
public const int state_downloading = 2131099656;
|
||||
|
||||
// aapt resource value: 0x7f060009
|
||||
public const int state_failed = 2131099657;
|
||||
|
||||
// aapt resource value: 0x7f06000a
|
||||
public const int state_failed_cancelled = 2131099658;
|
||||
|
||||
// aapt resource value: 0x7f06000b
|
||||
public const int state_failed_fetching_url = 2131099659;
|
||||
|
||||
// aapt resource value: 0x7f06000c
|
||||
public const int state_failed_sdcard_full = 2131099660;
|
||||
|
||||
// aapt resource value: 0x7f06000d
|
||||
public const int state_failed_unlicensed = 2131099661;
|
||||
|
||||
// aapt resource value: 0x7f06000e
|
||||
public const int state_fetching_url = 2131099662;
|
||||
|
||||
// aapt resource value: 0x7f06000f
|
||||
public const int state_idle = 2131099663;
|
||||
|
||||
// aapt resource value: 0x7f060010
|
||||
public const int state_paused_by_request = 2131099664;
|
||||
|
||||
// aapt resource value: 0x7f060011
|
||||
public const int state_paused_network_setup_failure = 2131099665;
|
||||
|
||||
// aapt resource value: 0x7f060012
|
||||
public const int state_paused_network_unavailable = 2131099666;
|
||||
|
||||
// aapt resource value: 0x7f060013
|
||||
public const int state_paused_roaming = 2131099667;
|
||||
|
||||
// aapt resource value: 0x7f060014
|
||||
public const int state_paused_sdcard_unavailable = 2131099668;
|
||||
|
||||
// aapt resource value: 0x7f060015
|
||||
public const int state_paused_wifi_disabled = 2131099669;
|
||||
|
||||
// aapt resource value: 0x7f060016
|
||||
public const int state_paused_wifi_unavailable = 2131099670;
|
||||
|
||||
// aapt resource value: 0x7f060017
|
||||
public const int state_unknown = 2131099671;
|
||||
|
||||
// aapt resource value: 0x7f060000
|
||||
public const int status_bar_notification_info_overflow = 2131099648;
|
||||
|
||||
// aapt resource value: 0x7f060018
|
||||
public const int time_remaining = 2131099672;
|
||||
|
||||
// aapt resource value: 0x7f060019
|
||||
public const int time_remaining_notification = 2131099673;
|
||||
// aapt resource value: 0x7F040002
|
||||
public const int hello = 2130968578;
|
||||
|
||||
static String()
|
||||
{
|
||||
|
@ -716,44 +142,8 @@ namespace Loader
|
|||
public partial class Style
|
||||
{
|
||||
|
||||
// aapt resource value: 0x7f09000a
|
||||
public const int ButtonBackground = 2131296266;
|
||||
|
||||
// aapt resource value: 0x7f090008
|
||||
public const int NotificationText = 2131296264;
|
||||
|
||||
// aapt resource value: 0x7f090007
|
||||
public const int NotificationTextSecondary = 2131296263;
|
||||
|
||||
// aapt resource value: 0x7f09000b
|
||||
public const int NotificationTextShadow = 2131296267;
|
||||
|
||||
// aapt resource value: 0x7f090009
|
||||
public const int NotificationTitle = 2131296265;
|
||||
|
||||
// aapt resource value: 0x7f090000
|
||||
public const int TextAppearance_Compat_Notification = 2131296256;
|
||||
|
||||
// aapt resource value: 0x7f090001
|
||||
public const int TextAppearance_Compat_Notification_Info = 2131296257;
|
||||
|
||||
// aapt resource value: 0x7f090006
|
||||
public const int TextAppearance_Compat_Notification_Line2 = 2131296262;
|
||||
|
||||
// aapt resource value: 0x7f090002
|
||||
public const int TextAppearance_Compat_Notification_Time = 2131296258;
|
||||
|
||||
// aapt resource value: 0x7f090003
|
||||
public const int TextAppearance_Compat_Notification_Title = 2131296259;
|
||||
|
||||
// aapt resource value: 0x7f09000c
|
||||
public const int Theme_Splash = 2131296268;
|
||||
|
||||
// aapt resource value: 0x7f090004
|
||||
public const int Widget_Compat_NotificationActionContainer = 2131296260;
|
||||
|
||||
// aapt resource value: 0x7f090005
|
||||
public const int Widget_Compat_NotificationActionText = 2131296261;
|
||||
// aapt resource value: 0x7F050000
|
||||
public const int Theme_Splash = 2131034112;
|
||||
|
||||
static Style()
|
||||
{
|
||||
|
@ -768,8 +158,8 @@ namespace Loader
|
|||
public partial class Xml
|
||||
{
|
||||
|
||||
// aapt resource value: 0x7f050000
|
||||
public const int provider_paths = 2131034112;
|
||||
// aapt resource value: 0x7F060000
|
||||
public const int provider_paths = 2131099648;
|
||||
|
||||
static Xml()
|
||||
{
|
||||
|
@ -780,161 +170,6 @@ namespace Loader
|
|||
{
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Styleable
|
||||
{
|
||||
|
||||
public static int[] ColorStateListItem = new int[] {
|
||||
16843173,
|
||||
16843551,
|
||||
2130771968};
|
||||
|
||||
// aapt resource value: 2
|
||||
public const int ColorStateListItem_alpha = 2;
|
||||
|
||||
// aapt resource value: 1
|
||||
public const int ColorStateListItem_android_alpha = 1;
|
||||
|
||||
// aapt resource value: 0
|
||||
public const int ColorStateListItem_android_color = 0;
|
||||
|
||||
public static int[] FontFamily = new int[] {
|
||||
2130771969,
|
||||
2130771970,
|
||||
2130771971,
|
||||
2130771972,
|
||||
2130771973,
|
||||
2130771974};
|
||||
|
||||
// aapt resource value: 0
|
||||
public const int FontFamily_fontProviderAuthority = 0;
|
||||
|
||||
// aapt resource value: 3
|
||||
public const int FontFamily_fontProviderCerts = 3;
|
||||
|
||||
// aapt resource value: 4
|
||||
public const int FontFamily_fontProviderFetchStrategy = 4;
|
||||
|
||||
// aapt resource value: 5
|
||||
public const int FontFamily_fontProviderFetchTimeout = 5;
|
||||
|
||||
// aapt resource value: 1
|
||||
public const int FontFamily_fontProviderPackage = 1;
|
||||
|
||||
// aapt resource value: 2
|
||||
public const int FontFamily_fontProviderQuery = 2;
|
||||
|
||||
public static int[] FontFamilyFont = new int[] {
|
||||
16844082,
|
||||
16844083,
|
||||
16844095,
|
||||
16844143,
|
||||
16844144,
|
||||
2130771975,
|
||||
2130771976,
|
||||
2130771977,
|
||||
2130771978,
|
||||
2130771979};
|
||||
|
||||
// aapt resource value: 0
|
||||
public const int FontFamilyFont_android_font = 0;
|
||||
|
||||
// aapt resource value: 2
|
||||
public const int FontFamilyFont_android_fontStyle = 2;
|
||||
|
||||
// aapt resource value: 4
|
||||
public const int FontFamilyFont_android_fontVariationSettings = 4;
|
||||
|
||||
// aapt resource value: 1
|
||||
public const int FontFamilyFont_android_fontWeight = 1;
|
||||
|
||||
// aapt resource value: 3
|
||||
public const int FontFamilyFont_android_ttcIndex = 3;
|
||||
|
||||
// aapt resource value: 6
|
||||
public const int FontFamilyFont_font = 6;
|
||||
|
||||
// aapt resource value: 5
|
||||
public const int FontFamilyFont_fontStyle = 5;
|
||||
|
||||
// aapt resource value: 8
|
||||
public const int FontFamilyFont_fontVariationSettings = 8;
|
||||
|
||||
// aapt resource value: 7
|
||||
public const int FontFamilyFont_fontWeight = 7;
|
||||
|
||||
// aapt resource value: 9
|
||||
public const int FontFamilyFont_ttcIndex = 9;
|
||||
|
||||
public static int[] GradientColor = new int[] {
|
||||
16843165,
|
||||
16843166,
|
||||
16843169,
|
||||
16843170,
|
||||
16843171,
|
||||
16843172,
|
||||
16843265,
|
||||
16843275,
|
||||
16844048,
|
||||
16844049,
|
||||
16844050,
|
||||
16844051};
|
||||
|
||||
// aapt resource value: 7
|
||||
public const int GradientColor_android_centerColor = 7;
|
||||
|
||||
// aapt resource value: 3
|
||||
public const int GradientColor_android_centerX = 3;
|
||||
|
||||
// aapt resource value: 4
|
||||
public const int GradientColor_android_centerY = 4;
|
||||
|
||||
// aapt resource value: 1
|
||||
public const int GradientColor_android_endColor = 1;
|
||||
|
||||
// aapt resource value: 10
|
||||
public const int GradientColor_android_endX = 10;
|
||||
|
||||
// aapt resource value: 11
|
||||
public const int GradientColor_android_endY = 11;
|
||||
|
||||
// aapt resource value: 5
|
||||
public const int GradientColor_android_gradientRadius = 5;
|
||||
|
||||
// aapt resource value: 0
|
||||
public const int GradientColor_android_startColor = 0;
|
||||
|
||||
// aapt resource value: 8
|
||||
public const int GradientColor_android_startX = 8;
|
||||
|
||||
// aapt resource value: 9
|
||||
public const int GradientColor_android_startY = 9;
|
||||
|
||||
// aapt resource value: 6
|
||||
public const int GradientColor_android_tileMode = 6;
|
||||
|
||||
// aapt resource value: 2
|
||||
public const int GradientColor_android_type = 2;
|
||||
|
||||
public static int[] GradientColorItem = new int[] {
|
||||
16843173,
|
||||
16844052};
|
||||
|
||||
// aapt resource value: 0
|
||||
public const int GradientColorItem_android_color = 0;
|
||||
|
||||
// aapt resource value: 1
|
||||
public const int GradientColorItem_android_offset = 1;
|
||||
|
||||
static Styleable()
|
||||
{
|
||||
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
|
||||
}
|
||||
|
||||
private Styleable()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore 1591
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.AppCenter" version="2.6.4" targetFramework="monoandroid10.0" />
|
||||
<package id="Microsoft.AppCenter.Analytics" version="2.6.4" targetFramework="monoandroid10.0" />
|
||||
<package id="Microsoft.AppCenter.Crashes" version="2.6.4" targetFramework="monoandroid10.0" />
|
||||
</packages>
|
||||
</packages>
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
#nullable enable
|
||||
namespace System.Linq
|
||||
{
|
||||
public static class EnumerableExtension
|
||||
{
|
||||
/// <summary>Produces a sequence of tuples with elements from the two specified sequences.</summary>
|
||||
/// <param name="first">The first sequence to merge.</param>
|
||||
/// <param name="second">The second sequence to merge.</param>
|
||||
/// <typeparam name="TFirst">The type of the elements of the first input sequence.</typeparam>
|
||||
/// <typeparam name="TSecond">The type of the elements of the second input sequence.</typeparam>
|
||||
/// <returns>A sequence of tuples with elements taken from the first and second sequences, in that order.</returns>
|
||||
public static IEnumerable<(TFirst First, TSecond Second)> Zip<TFirst, TSecond>(
|
||||
this IEnumerable<TFirst> first,
|
||||
IEnumerable<TSecond> second)
|
||||
{
|
||||
if (first == null)
|
||||
throw new ArgumentNullException("first");
|
||||
if (second == null)
|
||||
throw new ArgumentNullException("second");
|
||||
return ZipIterator<TFirst, TSecond>(first, second);
|
||||
}
|
||||
#nullable disable
|
||||
private static IEnumerable<(TFirst First, TSecond Second)> ZipIterator<TFirst, TSecond>(
|
||||
IEnumerable<TFirst> first,
|
||||
IEnumerable<TSecond> second)
|
||||
{
|
||||
using (IEnumerator<TFirst> e1 = first.GetEnumerator())
|
||||
{
|
||||
using (IEnumerator<TSecond> e2 = second.GetEnumerator())
|
||||
{
|
||||
while (e1.MoveNext() && e2.MoveNext())
|
||||
yield return (e1.Current, e2.Current);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
|
||||
|
||||
#nullable enable
|
||||
namespace System.Collections.Generic
|
||||
{
|
||||
/// <summary>An <see cref="T:System.Collections.Generic.IEqualityComparer`1" /> that uses reference equality (<see cref="M:System.Object.ReferenceEquals(System.Object,System.Object)" />) instead of value equality (<see cref="M:System.Object.Equals(System.Object)" />) when comparing two object instances.</summary>
|
||||
public sealed class ReferenceEqualityComparer : IEqualityComparer<object?>, IEqualityComparer
|
||||
{
|
||||
private ReferenceEqualityComparer()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Gets the singleton <see cref="T:System.Collections.Generic.ReferenceEqualityComparer" /> instance.</summary>
|
||||
public static ReferenceEqualityComparer Instance { get; } = new ReferenceEqualityComparer();
|
||||
|
||||
/// <summary>Determines whether two object references refer to the same object instance.</summary>
|
||||
/// <param name="x">The first object to compare.</param>
|
||||
/// <param name="y">The second object to compare.</param>
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if both <paramref name="x" /> and <paramref name="y" /> refer to the same object instance or if both are <see langword="null" />; otherwise, <see langword="false" />.</returns>
|
||||
public bool Equals(object? x, object? y) => x == y;
|
||||
|
||||
/// <summary>Returns a hash code for the specified object. The returned hash code is based on the object identity, not on the contents of the object.</summary>
|
||||
/// <param name="obj">The object for which to retrieve the hash code.</param>
|
||||
/// <returns>A hash code for the identity of <paramref name="obj" />.</returns>
|
||||
public int GetHashCode(object? obj) => RuntimeHelpers.GetHashCode(obj);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{E5FE4C97-1A7C-4A97-9904-7351CA020C7F}</ProjectGuid>
|
||||
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>MobilePatch</RootNamespace>
|
||||
<AssemblyName>MobilePatch</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
|
||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
|
||||
<TargetFrameworkVersion>v12.0</TargetFrameworkVersion>
|
||||
<TargetFramework>net5.0-android</TargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Mono.Android" />
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Mobile\EnumerableExtension.cs" />
|
||||
<Compile Include="Mobile\MobileMemoryExtension.cs" />
|
||||
<Compile Include="Mobile\MobileTypeExtension.cs" />
|
||||
<Compile Include="Mobile\ReferenceEqualityComparer.cs" />
|
||||
<Compile Include="Resources\Resource.Designer.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\AboutResources.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\values\strings.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Resources\drawable\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -0,0 +1,30 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Android.App;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("MobilePatch")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("MobilePatch")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2023")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,59 @@
|
|||
#pragma warning disable 1591
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
[assembly: global::Android.Runtime.ResourceDesignerAttribute("MobilePatch.Resource", IsApplication=false)]
|
||||
|
||||
namespace MobilePatch
|
||||
{
|
||||
|
||||
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "13.2.0.99")]
|
||||
public partial class Resource
|
||||
{
|
||||
|
||||
static Resource()
|
||||
{
|
||||
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
|
||||
}
|
||||
|
||||
public partial class Attribute
|
||||
{
|
||||
|
||||
static Attribute()
|
||||
{
|
||||
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
|
||||
}
|
||||
|
||||
private Attribute()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public partial class String
|
||||
{
|
||||
|
||||
// aapt resource value: 0x7F010000
|
||||
public static int app_name = 2130771968;
|
||||
|
||||
// aapt resource value: 0x7F010001
|
||||
public static int hello = 2130771969;
|
||||
|
||||
static String()
|
||||
{
|
||||
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
|
||||
}
|
||||
|
||||
private String()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore 1591
|
|
@ -1,4 +1,4 @@
|
|||
<resources>
|
||||
<string name="hello">Hello World, Click Me!</string>
|
||||
<string name="app_name">SMAPI</string>
|
||||
<string name="app_name">MobilePatch</string>
|
||||
</resources>
|
|
@ -47,8 +47,8 @@ namespace StardewModdingApi.Installer
|
|||
yield return GetInstallPath("StardewModdingAPI.dll");
|
||||
yield return GetInstallPath("StardewModdingAPI.exe");
|
||||
yield return GetInstallPath("StardewModdingAPI.exe.config");
|
||||
yield return GetInstallPath("StardewModdingAPI.exe.mdb"); // Linux/macOS only
|
||||
yield return GetInstallPath("StardewModdingAPI.pdb"); // Windows only
|
||||
yield return GetInstallPath("StardewModdingAPI.exe.mdb"); // before 3.18.4 (Linux/macOS only)
|
||||
yield return GetInstallPath("StardewModdingAPI.pdb"); // before 3.18.4 (Windows only)
|
||||
yield return GetInstallPath("StardewModdingAPI.runtimeconfig.json");
|
||||
yield return GetInstallPath("StardewModdingAPI.xml");
|
||||
yield return GetInstallPath("smapi-internal");
|
||||
|
@ -135,35 +135,24 @@ namespace StardewModdingApi.Installer
|
|||
Console.Title = $"SMAPI {context.GetInstallerVersion()} installer on {context.Platform} {context.PlatformName}";
|
||||
Console.WriteLine();
|
||||
|
||||
/****
|
||||
** Check if correct installer
|
||||
****/
|
||||
#if SMAPI_FOR_WINDOWS
|
||||
if (context.IsUnix)
|
||||
{
|
||||
this.PrintError($"This is the installer for Windows. Run the 'install on {context.Platform}.{(context.Platform == Platform.Mac ? "command" : "sh")}' file instead.");
|
||||
Console.ReadLine();
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (context.IsWindows)
|
||||
{
|
||||
this.PrintError($"This is the installer for Linux/macOS. Run the 'install on Windows.exe' file instead.");
|
||||
Console.ReadLine();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****
|
||||
** read command-line arguments
|
||||
****/
|
||||
// get action from CLI
|
||||
// get input mode
|
||||
bool allowUserInput = !args.Contains("--no-prompt");
|
||||
|
||||
// get action
|
||||
bool installArg = args.Contains("--install");
|
||||
bool uninstallArg = args.Contains("--uninstall");
|
||||
if (installArg && uninstallArg)
|
||||
{
|
||||
this.PrintError("You can't specify both --install and --uninstall command-line flags.");
|
||||
Console.ReadLine();
|
||||
this.AwaitConfirmation(allowUserInput);
|
||||
return;
|
||||
}
|
||||
if (!allowUserInput && !installArg && !uninstallArg)
|
||||
{
|
||||
this.PrintError("You must specify --install or --uninstall when running with --no-prompt.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -175,12 +164,31 @@ namespace StardewModdingApi.Installer
|
|||
gamePathArg = args[pathIndex];
|
||||
}
|
||||
|
||||
/****
|
||||
** Check if correct installer
|
||||
****/
|
||||
#if SMAPI_FOR_WINDOWS
|
||||
if (context.IsUnix)
|
||||
{
|
||||
this.PrintError($"This is the installer for Windows. Run the 'install on {context.Platform}.{(context.Platform == Platform.Mac ? "command" : "sh")}' file instead.");
|
||||
this.AwaitConfirmation(allowUserInput);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (context.IsWindows)
|
||||
{
|
||||
this.PrintError($"This is the installer for Linux/macOS. Run the 'install on Windows.exe' file instead.");
|
||||
this.AwaitConfirmation(allowUserInput);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*********
|
||||
** Step 2: choose a theme (can't auto-detect on Linux/macOS)
|
||||
*********/
|
||||
MonitorColorScheme scheme = MonitorColorScheme.AutoDetect;
|
||||
if (context.IsUnix)
|
||||
if (context.IsUnix && allowUserInput)
|
||||
{
|
||||
/****
|
||||
** print header
|
||||
|
@ -245,7 +253,7 @@ namespace StardewModdingApi.Installer
|
|||
if (installDir == null)
|
||||
{
|
||||
this.PrintError("Failed finding your game path.");
|
||||
Console.ReadLine();
|
||||
this.AwaitConfirmation(allowUserInput);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -262,7 +270,7 @@ namespace StardewModdingApi.Installer
|
|||
if (!File.Exists(paths.GameDllPath))
|
||||
{
|
||||
this.PrintError("The detected game install path doesn't contain a Stardew Valley executable.");
|
||||
Console.ReadLine();
|
||||
this.AwaitConfirmation(allowUserInput);
|
||||
return;
|
||||
}
|
||||
Console.Clear();
|
||||
|
@ -340,7 +348,7 @@ namespace StardewModdingApi.Installer
|
|||
if (context.IsUnix && File.Exists(paths.BackupLaunchScriptPath))
|
||||
{
|
||||
this.PrintDebug("Removing SMAPI launcher...");
|
||||
this.InteractivelyDelete(paths.VanillaLaunchScriptPath);
|
||||
this.InteractivelyDelete(paths.VanillaLaunchScriptPath, allowUserInput);
|
||||
File.Move(paths.BackupLaunchScriptPath, paths.VanillaLaunchScriptPath);
|
||||
}
|
||||
|
||||
|
@ -352,7 +360,7 @@ namespace StardewModdingApi.Installer
|
|||
{
|
||||
this.PrintDebug(action == ScriptAction.Install ? "Removing previous SMAPI files..." : "Removing SMAPI files...");
|
||||
foreach (string path in removePaths)
|
||||
this.InteractivelyDelete(path);
|
||||
this.InteractivelyDelete(path, allowUserInput);
|
||||
}
|
||||
|
||||
// move global save data folder (changed in 3.2)
|
||||
|
@ -364,7 +372,7 @@ namespace StardewModdingApi.Installer
|
|||
if (oldDir.Exists)
|
||||
{
|
||||
if (newDir.Exists)
|
||||
this.InteractivelyDelete(oldDir.FullName);
|
||||
this.InteractivelyDelete(oldDir.FullName, allowUserInput);
|
||||
else
|
||||
oldDir.MoveTo(newDir.FullName);
|
||||
}
|
||||
|
@ -379,7 +387,7 @@ namespace StardewModdingApi.Installer
|
|||
this.PrintDebug("Adding SMAPI files...");
|
||||
foreach (FileSystemInfo sourceEntry in paths.BundleDir.EnumerateFileSystemInfos().Where(this.ShouldCopy))
|
||||
{
|
||||
this.InteractivelyDelete(Path.Combine(paths.GameDir.FullName, sourceEntry.Name));
|
||||
this.InteractivelyDelete(Path.Combine(paths.GameDir.FullName, sourceEntry.Name), allowUserInput);
|
||||
this.RecursiveCopy(sourceEntry, paths.GameDir);
|
||||
}
|
||||
|
||||
|
@ -394,7 +402,7 @@ namespace StardewModdingApi.Installer
|
|||
if (!File.Exists(paths.BackupLaunchScriptPath))
|
||||
File.Move(paths.VanillaLaunchScriptPath, paths.BackupLaunchScriptPath);
|
||||
else
|
||||
this.InteractivelyDelete(paths.VanillaLaunchScriptPath);
|
||||
this.InteractivelyDelete(paths.VanillaLaunchScriptPath, allowUserInput);
|
||||
}
|
||||
|
||||
// add new launcher
|
||||
|
@ -464,7 +472,7 @@ namespace StardewModdingApi.Installer
|
|||
|
||||
// remove existing folder
|
||||
if (targetFolder.Exists)
|
||||
this.InteractivelyDelete(targetFolder.FullName);
|
||||
this.InteractivelyDelete(targetFolder.FullName, allowUserInput);
|
||||
|
||||
// copy files
|
||||
this.RecursiveCopy(sourceMod.Directory, paths.ModsDir, filter: this.ShouldCopy);
|
||||
|
@ -482,7 +490,7 @@ namespace StardewModdingApi.Installer
|
|||
|
||||
#if SMAPI_DEPRECATED
|
||||
// remove obsolete appdata mods
|
||||
this.InteractivelyRemoveAppDataMods(paths.ModsDir, bundledModsDir);
|
||||
this.InteractivelyRemoveAppDataMods(paths.ModsDir, bundledModsDir, allowUserInput);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -513,7 +521,7 @@ namespace StardewModdingApi.Installer
|
|||
);
|
||||
}
|
||||
|
||||
Console.ReadKey();
|
||||
this.AwaitConfirmation(allowUserInput);
|
||||
}
|
||||
|
||||
|
||||
|
@ -581,7 +589,8 @@ namespace StardewModdingApi.Installer
|
|||
|
||||
/// <summary>Interactively delete a file or folder path, and block until deletion completes.</summary>
|
||||
/// <param name="path">The file or folder path.</param>
|
||||
private void InteractivelyDelete(string path)
|
||||
/// <param name="allowUserInput">Whether the installer can ask for user input from the terminal.</param>
|
||||
private void InteractivelyDelete(string path, bool allowUserInput)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
|
@ -594,7 +603,7 @@ namespace StardewModdingApi.Installer
|
|||
{
|
||||
this.PrintError($"Oops! The installer couldn't delete {path}: [{ex.GetType().Name}] {ex.Message}.");
|
||||
this.PrintError("Try rebooting your computer and then run the installer again. If that doesn't work, try deleting it yourself then press any key to retry.");
|
||||
Console.ReadKey();
|
||||
this.AwaitConfirmation(allowUserInput);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -814,7 +823,8 @@ namespace StardewModdingApi.Installer
|
|||
/// <summary>Interactively move mods out of the app data directory.</summary>
|
||||
/// <param name="properModsDir">The directory which should contain all mods.</param>
|
||||
/// <param name="packagedModsDir">The installer directory containing packaged mods.</param>
|
||||
private void InteractivelyRemoveAppDataMods(DirectoryInfo properModsDir, DirectoryInfo packagedModsDir)
|
||||
/// <param name="allowUserInput">Whether the installer can ask for user input from the terminal.</param>
|
||||
private void InteractivelyRemoveAppDataMods(DirectoryInfo properModsDir, DirectoryInfo packagedModsDir, bool allowUserInput)
|
||||
{
|
||||
// get packaged mods to delete
|
||||
string[] packagedModNames = packagedModsDir.GetDirectories().Select(p => p.Name).ToArray();
|
||||
|
@ -841,7 +851,7 @@ namespace StardewModdingApi.Installer
|
|||
if (isDir && packagedModNames.Contains(entry.Name, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
this.PrintDebug($" Deleting {entry.Name} because it's bundled into SMAPI...");
|
||||
this.InteractivelyDelete(entry.FullName);
|
||||
this.InteractivelyDelete(entry.FullName, allowUserInput);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -906,5 +916,13 @@ namespace StardewModdingApi.Installer
|
|||
_ => true
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>Wait until the user presses enter to confirm, if user input is allowed.</summary>
|
||||
/// <param name="allowUserInput">Whether the installer can ask for user input from the terminal.</param>
|
||||
private void AwaitConfirmation(bool allowUserInput)
|
||||
{
|
||||
if (allowUserInput)
|
||||
Console.ReadLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
cd "`dirname "$0"`"
|
||||
internal/linux/SMAPI.Installer
|
||||
|
|
|
@ -4,7 +4,9 @@ setlocal enabledelayedexpansion
|
|||
SET installerDir="%~dp0"
|
||||
|
||||
REM make sure we're not running within a zip folder
|
||||
echo %installerDir% | findstr /C:"%TEMP%" 1>nul
|
||||
REM The error level is usually 0 (install dir contains temp path), 1 (it doesn't), or 9009 (findstr doesn't exist due to a Windows issue).
|
||||
REM If the command doesn't exist, just skip this check.
|
||||
echo %installerDir% | findstr /C:"%TEMP%" 1>nul 2>null
|
||||
if %ERRORLEVEL% EQU 0 (
|
||||
echo Oops! It looks like you're running the installer from inside a zip file. Make sure you unzip the download first.
|
||||
echo.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
cd "`dirname "$0"`"
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ else
|
|||
# run in terminal
|
||||
if [ "$USE_CURRENT_SHELL" == "false" ]; then
|
||||
# select terminal (prefer xterm for best compatibility, then known supported terminals)
|
||||
for terminal in xterm gnome-terminal kitty terminator xfce4-terminal konsole terminal termite alacritty mate-terminal x-terminal-emulator; do
|
||||
for terminal in xterm gnome-terminal kitty terminator xfce4-terminal konsole terminal termite alacritty mate-terminal x-terminal-emulator wezterm; do
|
||||
if command -v "$terminal" 2>/dev/null; then
|
||||
export TERMINAL_NAME=$terminal
|
||||
break;
|
||||
|
@ -132,6 +132,11 @@ else
|
|||
exec "$TERMINAL_NAME" -- env TERM=xterm $LAUNCH_FILE "$@"
|
||||
;;
|
||||
|
||||
wezterm)
|
||||
# consumes all arguments after start --. does not copy working directory automatically, needs --cwd for that.
|
||||
exec "$TERMINAL_NAME" start --cwd "$(pwd)" -- env TERM=xterm $LAUNCH_FILE "$@"
|
||||
;;
|
||||
|
||||
kitty)
|
||||
# consumes all trailing arguments
|
||||
exec "$TERMINAL_NAME" env TERM=xterm $LAUNCH_FILE "$@"
|
||||
|
|
|
@ -15,7 +15,9 @@ namespace StardewModdingAPI.Internal.ConsoleWriting
|
|||
private readonly IDictionary<ConsoleLogLevel, ConsoleColor>? Colors;
|
||||
|
||||
/// <summary>Whether the current console supports color formatting.</summary>
|
||||
// [MemberNotNullWhen(true, nameof(ColorfulConsoleWriter.Colors))]
|
||||
#if !SMAPI_FOR_MOBILE
|
||||
[MemberNotNullWhen(true, nameof(ColorfulConsoleWriter.Colors))]
|
||||
#endif
|
||||
private bool SupportsColor { get; }
|
||||
|
||||
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.10.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<!--NuGet package-->
|
||||
<PackageId>Pathoschild.Stardew.ModBuildConfig</PackageId>
|
||||
<Title>Build package for SMAPI mods</Title>
|
||||
<Version>4.1.0</Version>
|
||||
<Version>4.1.1</Version>
|
||||
<Authors>Pathoschild</Authors>
|
||||
<Description>Automates the build configuration for crossplatform Stardew Valley SMAPI mods. For SMAPI 3.13.0 or later.</Description>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
|
@ -24,7 +24,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="16.10" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
|
||||
<!--
|
||||
This is imported through Microsoft.Build.Utilities.Core. When installed by a mod, NuGet
|
||||
|
|
|
@ -8,8 +8,9 @@
|
|||
** Set build options
|
||||
**********************************************-->
|
||||
<PropertyGroup>
|
||||
<!-- enable line numbers in stack traces -->
|
||||
<!-- enable line numbers in stack traces (needs to embedded for Linux/macOS: https://github.com/dotnet/runtime/issues/39987) -->
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>embedded</DebugType>
|
||||
|
||||
<!-- don't create the 'refs' folder (which isn't useful for mods) -->
|
||||
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Other
|
||||
|
@ -10,11 +9,8 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Other
|
|||
/*********
|
||||
** Fields
|
||||
*********/
|
||||
/// <summary>The number of seconds for which to log input.</summary>
|
||||
private readonly int LogSeconds = 30;
|
||||
|
||||
/// <summary>When the command should stop printing input, or <c>null</c> if currently disabled.</summary>
|
||||
private long? ExpiryTicks;
|
||||
/// <summary>Whether the command should print input.</summary>
|
||||
private bool Enabled;
|
||||
|
||||
|
||||
/*********
|
||||
|
@ -30,21 +26,12 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Other
|
|||
/// <param name="args">The command arguments.</param>
|
||||
public override void Handle(IMonitor monitor, string command, ArgumentParser args)
|
||||
{
|
||||
this.ExpiryTicks = DateTime.UtcNow.Add(TimeSpan.FromSeconds(this.LogSeconds)).Ticks;
|
||||
monitor.Log($"OK, logging all player input for {this.LogSeconds} seconds.", LogLevel.Info);
|
||||
}
|
||||
this.Enabled = !this.Enabled;
|
||||
|
||||
/// <summary>Perform any logic needed on update tick.</summary>
|
||||
/// <param name="monitor">Writes messages to the console and log file.</param>
|
||||
public override void OnUpdated(IMonitor monitor)
|
||||
{
|
||||
// handle expiry
|
||||
if (this.ExpiryTicks != null && this.ExpiryTicks <= DateTime.UtcNow.Ticks)
|
||||
{
|
||||
monitor.Log("No longer logging input.", LogLevel.Info);
|
||||
this.ExpiryTicks = null;
|
||||
return;
|
||||
}
|
||||
monitor.Log(
|
||||
this.Enabled ? "OK, logging all player input until you run this command again." : "OK, no longer logging player input.",
|
||||
LogLevel.Info
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Perform any logic when input is received.</summary>
|
||||
|
@ -52,7 +39,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Other
|
|||
/// <param name="button">The button that was pressed.</param>
|
||||
public override void OnButtonPressed(IMonitor monitor, SButton button)
|
||||
{
|
||||
if (this.ExpiryTicks != null)
|
||||
if (this.Enabled)
|
||||
monitor.Log($"Pressed {button}", LogLevel.Info);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
#if SMAPI_FOR_MOBILE
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using StardewValley;
|
||||
using StardewValley.Mobile;
|
||||
|
||||
namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Other
|
||||
{
|
||||
/// <summary>A command which sends a debug command to the game.</summary>
|
||||
internal class ZoomCommand : TrainerCommand
|
||||
{
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Construct an instance.</summary>
|
||||
public ZoomCommand()
|
||||
: base("zoom", "Modify game's zoom level.\n\nUsage: zoom <zoomLevel>\n- zoomLevel: the target zoomLevel (a number).\nFor example, 'zoom 1.5' set zoom level to 1.5 * NativeZoomLevel.") { }
|
||||
|
||||
/// <summary>Handle the command.</summary>
|
||||
/// <param name="monitor">Writes messages to the console and log file.</param>
|
||||
/// <param name="command">The command name.</param>
|
||||
/// <param name="args">The command arguments.</param>
|
||||
public override void Handle(IMonitor monitor, string command, ArgumentParser args)
|
||||
{
|
||||
// submit command
|
||||
decimal zoomLevel;
|
||||
if (!args.Any())
|
||||
{
|
||||
zoomLevel = 1.0m;
|
||||
}
|
||||
else if (!args.TryGetDecimal(0, "zoomLevel", out zoomLevel, min: 0.1m, max: 10m))
|
||||
return;
|
||||
object viewport = typeof(Game1).GetField("viewport", BindingFlags.Static | BindingFlags.Public).GetValue(null);
|
||||
PropertyInfo x = viewport.GetType().GetProperty("X");
|
||||
PropertyInfo y = viewport.GetType().GetProperty("Y");
|
||||
int oldX = (int)x.GetValue(viewport);
|
||||
int oldY = (int)y.GetValue(viewport);
|
||||
FieldInfo _lastPinchZoomLevel = typeof(PinchZoom).GetField("_lastPinchZoomLevel", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
FieldInfo _pinchZoomLevel = typeof(PinchZoom).GetField("_pinchZoomLevel", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
Game1.options.zoomLevel = Game1.NativeZoomLevel * (float)zoomLevel;
|
||||
float oldZoom = (float)_lastPinchZoomLevel.GetValue(PinchZoom.Instance);
|
||||
_lastPinchZoomLevel.SetValue(PinchZoom.Instance, _pinchZoomLevel.GetValue(PinchZoom.Instance));
|
||||
_pinchZoomLevel.SetValue(PinchZoom.Instance, Game1.options.zoomLevel);
|
||||
Game1.game1.refreshWindowSettings();
|
||||
PinchZoom.Instance.Center();
|
||||
WeatherDebrisManager.Instance.RepositionOnZoomChange(oldX, oldY, (int)x.GetValue(viewport), (int)y.GetValue(viewport), oldZoom, Game1.options.zoomLevel);
|
||||
RainManager.Instance.UpdateRainPositionForPinchZoom((float)(oldX - (int)x.GetValue(viewport)), (float)(oldY - (int)y.GetValue(viewport)));
|
||||
// show result
|
||||
monitor.Log("Zoom level changed.", LogLevel.Info);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -30,16 +30,16 @@
|
|||
|
||||
<ItemGroup Condition="'$(BUILD_FOR_MOBILE)' != ''">
|
||||
<Reference Include="MonoGame.Framework">
|
||||
<HintPath>..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.5.145\assemblies\MonoGame.Framework.dll</HintPath>
|
||||
<HintPath>..\..\build\StardewValleyAndroidStuff\base_1.5.6.39\assemblies\MonoGame.Framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="StardewModdingAPI">
|
||||
<HintPath>..\SMAPI\bin\Release\StardewModdingAPI.dll</HintPath>
|
||||
<HintPath>..\SMAPI\bin\Debug\StardewModdingAPI.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="StardewValley">
|
||||
<HintPath>..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.5.151\assemblies_decrypt\StardewValley.dll</HintPath>
|
||||
<HintPath>..\..\build\StardewValleyAndroidStuff\base_1.5.6.39\assemblies\StardewValley.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="StardewValley.GameData">
|
||||
<HintPath>..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.5.151\assemblies_decrypt\StardewValley.GameData.dll</HintPath>
|
||||
<HintPath>..\..\build\StardewValleyAndroidStuff\base_1.5.6.39\assemblies\StardewValley.GameData.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"Name": "Console Commands",
|
||||
"Author": "SMAPI",
|
||||
"Version": "3.18.2",
|
||||
"Version": "3.18.4",
|
||||
"Description": "Adds SMAPI console commands that let you manipulate the game.",
|
||||
"UniqueID": "SMAPI.ConsoleCommands",
|
||||
"EntryDll": "ConsoleCommands.dll",
|
||||
"MinimumApiVersion": "3.18.2"
|
||||
"MinimumApiVersion": "3.18.4"
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"Name": "Error Handler",
|
||||
"Author": "SMAPI",
|
||||
"Version": "3.18.2",
|
||||
"Version": "3.18.4",
|
||||
"Description": "Handles some common vanilla errors to log more useful info or avoid breaking the game.",
|
||||
"UniqueID": "SMAPI.ErrorHandler",
|
||||
"EntryDll": "ErrorHandler.dll",
|
||||
"MinimumApiVersion": "3.18.2"
|
||||
"MinimumApiVersion": "3.18.4"
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
<HintPath>..\SMAPI\bin\Release\StardewModdingAPI.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="StardewValley">
|
||||
<HintPath>..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.5.151\assemblies_decrypt\StardewValley.dll</HintPath>
|
||||
<HintPath>..\..\build\StardewValleyAndroidStuff\base_1.4.5.151\assemblies_decrypt\StardewValley.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"Name": "Save Backup",
|
||||
"Author": "SMAPI",
|
||||
"Version": "3.18.2",
|
||||
"Version": "3.18.4",
|
||||
"Description": "Automatically backs up all your saves once per day into its folder.",
|
||||
"UniqueID": "SMAPI.SaveBackup",
|
||||
"EntryDll": "SaveBackup.dll",
|
||||
"MinimumApiVersion": "3.18.2"
|
||||
"MinimumApiVersion": "3.18.4"
|
||||
}
|
||||
|
|
|
@ -1,74 +1,58 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using StardewModdingAPI.Events;
|
||||
using StardewModdingAPI.Framework;
|
||||
using StardewModdingAPI.Framework.Input;
|
||||
using StardewValley;
|
||||
using StardewValley.Menus;
|
||||
using System.Reflection;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using static StardewModdingAPI.Mods.VirtualKeyboard.ModConfig;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace StardewModdingAPI.Mods.VirtualKeyboard
|
||||
{
|
||||
class KeyButton
|
||||
{
|
||||
private readonly IModHelper helper;
|
||||
private readonly IMonitor Monitor;
|
||||
private readonly Rectangle buttonRectangle;
|
||||
private readonly Rectangle ButtonRectangle;
|
||||
|
||||
private object buttonPressed;
|
||||
private object buttonReleased;
|
||||
|
||||
private readonly MethodBase RaiseButtonPressed;
|
||||
private readonly MethodBase RaiseButtonReleased;
|
||||
|
||||
private readonly SButton buttonKey;
|
||||
private readonly float transparency;
|
||||
private readonly string alias;
|
||||
private readonly string command;
|
||||
public bool hidden;
|
||||
private bool raisingPressed = false;
|
||||
private bool raisingReleased = false;
|
||||
private readonly SButton ButtonKey;
|
||||
private readonly float Transparency;
|
||||
private readonly string Alias;
|
||||
private readonly string Command;
|
||||
public bool Hidden;
|
||||
private bool RaisingPressed;
|
||||
private bool RaisingReleased;
|
||||
|
||||
public KeyButton(IModHelper helper, VirtualButton buttonDefine, IMonitor monitor)
|
||||
{
|
||||
this.Monitor = monitor;
|
||||
this.helper = helper;
|
||||
this.hidden = true;
|
||||
this.buttonRectangle = new Rectangle(buttonDefine.rectangle.X, buttonDefine.rectangle.Y, buttonDefine.rectangle.Width, buttonDefine.rectangle.Height);
|
||||
this.buttonKey = buttonDefine.key;
|
||||
this.Hidden = true;
|
||||
this.ButtonRectangle = new Rectangle(buttonDefine.rectangle.X, buttonDefine.rectangle.Y, buttonDefine.rectangle.Width, buttonDefine.rectangle.Height);
|
||||
this.ButtonKey = buttonDefine.key;
|
||||
|
||||
if (buttonDefine.alias == null)
|
||||
this.alias = this.buttonKey.ToString();
|
||||
this.Alias = this.ButtonKey.ToString();
|
||||
else
|
||||
this.alias = buttonDefine.alias;
|
||||
this.command = buttonDefine.command;
|
||||
this.Alias = buttonDefine.alias;
|
||||
this.Command = buttonDefine.command;
|
||||
|
||||
if (buttonDefine.transparency <= 0.01f || buttonDefine.transparency > 1f)
|
||||
{
|
||||
buttonDefine.transparency = 0.5f;
|
||||
}
|
||||
this.transparency = buttonDefine.transparency;
|
||||
this.Transparency = buttonDefine.transparency;
|
||||
|
||||
helper.Events.Display.Rendered += this.OnRendered;
|
||||
helper.Events.Input.ButtonReleased += this.EventInputButtonReleased;
|
||||
helper.Events.Input.ButtonPressed += this.EventInputButtonPressed;
|
||||
}
|
||||
|
||||
private object GetSCore(IModHelper helper)
|
||||
private bool ShouldTrigger(Vector2 screenPixels, SButton button)
|
||||
{
|
||||
MainActivity activity = this.helper.Reflection.GetField<MainActivity>(typeof(MainActivity), "instance").GetValue();
|
||||
object score = activity.GetType().GetField("core", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(activity);
|
||||
return score;
|
||||
}
|
||||
|
||||
private bool shouldTrigger(Vector2 screenPixels, SButton button)
|
||||
{
|
||||
if (this.buttonRectangle.Contains(screenPixels.X * Game1.options.zoomLevel, screenPixels.Y * Game1.options.zoomLevel) && !this.hidden && button == SButton.MouseLeft)
|
||||
if (this.ButtonRectangle.Contains(screenPixels.X, screenPixels.Y) && !this.Hidden && button == SButton.MouseLeft)
|
||||
{
|
||||
if (!this.hidden)
|
||||
if (!this.Hidden)
|
||||
Toolbar.toolbarPressed = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -77,34 +61,34 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
|
|||
|
||||
private void EventInputButtonPressed(object sender, ButtonPressedEventArgs e)
|
||||
{
|
||||
if (this.raisingPressed)
|
||||
if (this.RaisingPressed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 screenPixels = e.Cursor.ScreenPixels;
|
||||
if (this.buttonKey != SButton.None && this.shouldTrigger(screenPixels, e.Button))
|
||||
Vector2 screenPixels = Utility.ModifyCoordinatesForUIScale(e.Cursor.ScreenPixels);
|
||||
if (this.ButtonKey != SButton.None && this.ShouldTrigger(screenPixels, e.Button))
|
||||
{
|
||||
object input = this.helper.Reflection.GetField<object>(typeof(Game1), "input").GetValue();
|
||||
this.raisingPressed = true;
|
||||
input.GetType().GetMethod("OverrideButton").Invoke(input, new object[] { this.buttonKey, true });
|
||||
this.raisingPressed = false;
|
||||
this.RaisingPressed = true;
|
||||
SInputState input = Game1.input as SInputState;
|
||||
input?.OverrideButton(this.ButtonKey, true);
|
||||
this.RaisingPressed = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void EventInputButtonReleased(object sender, ButtonReleasedEventArgs e)
|
||||
{
|
||||
if (this.raisingReleased)
|
||||
if (this.RaisingReleased)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 screenPixels = e.Cursor.ScreenPixels;
|
||||
if (this.shouldTrigger(screenPixels, e.Button))
|
||||
Vector2 screenPixels = Utility.ModifyCoordinatesForUIScale(e.Cursor.ScreenPixels);
|
||||
if (this.ShouldTrigger(screenPixels, e.Button))
|
||||
{
|
||||
if (this.buttonKey == SButton.RightWindows)
|
||||
if (this.ButtonKey == SButton.RightWindows)
|
||||
{
|
||||
KeyboardInput.Show("Command", "", "", false).ContinueWith<string>(delegate (Task<string> s) {
|
||||
KeyboardInput.Show("Command", "").ContinueWith(delegate (Task<string> s) {
|
||||
string command;
|
||||
command = s.Result;
|
||||
if (command.Length > 0)
|
||||
|
@ -115,36 +99,31 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
|
|||
});
|
||||
return;
|
||||
}
|
||||
if (this.buttonKey == SButton.RightControl)
|
||||
if (this.ButtonKey == SButton.RightControl)
|
||||
{
|
||||
SGameConsole.Instance.Show();
|
||||
return;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(this.command))
|
||||
if (!string.IsNullOrEmpty(this.Command))
|
||||
{
|
||||
this.SendCommand(this.command);
|
||||
this.SendCommand(this.Command);
|
||||
return;
|
||||
}
|
||||
object input = this.helper.Reflection.GetField<object>(typeof(Game1), "input").GetValue();
|
||||
this.raisingReleased = true;
|
||||
input.GetType().GetMethod("OverrideButton").Invoke(input, new object[] { this.buttonKey, false });
|
||||
this.raisingReleased = false;
|
||||
this.RaisingReleased = true;
|
||||
SInputState input = Game1.input as SInputState;
|
||||
input?.OverrideButton(this.ButtonKey, false);
|
||||
this.RaisingReleased = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void SendCommand(string command)
|
||||
{
|
||||
object score = this.GetSCore(this.helper);
|
||||
ConcurrentQueue<string> commandQueue = score.GetType().GetProperty("CommandQueue", BindingFlags.Public | BindingFlags.Instance)?.GetValue(score) as ConcurrentQueue<string>;
|
||||
SCore score = SMainActivity.Instance.core;
|
||||
CommandQueue commandQueue = score.RawCommandQueue;
|
||||
if (commandQueue != null)
|
||||
{
|
||||
commandQueue.Enqueue(command);
|
||||
return;
|
||||
commandQueue.Add(command);
|
||||
}
|
||||
|
||||
object sgame = score.GetType().GetField("Game", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(score);
|
||||
commandQueue = sgame.GetType().GetProperty("CommandQueue", BindingFlags.Public | BindingFlags.Instance)?.GetValue(sgame) as ConcurrentQueue<string>;
|
||||
commandQueue?.Enqueue(command);
|
||||
}
|
||||
|
||||
/// <summary>Raised before drawing the HUD (item toolbar, clock, etc) to the screen.</summary>
|
||||
|
@ -152,19 +131,20 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
|
|||
/// <param name="e">The event arguments.</param>
|
||||
private void OnRendered(object sender, EventArgs e)
|
||||
{
|
||||
if (!this.hidden)
|
||||
if (!this.Hidden)
|
||||
{
|
||||
float scale = this.transparency;
|
||||
float scale = this.Transparency;
|
||||
if (!Game1.eventUp && Game1.activeClickableMenu is GameMenu == false && Game1.activeClickableMenu is ShopMenu == false && Game1.activeClickableMenu is IClickableMenu == false)
|
||||
{
|
||||
scale *= 0.5f;
|
||||
}
|
||||
System.Reflection.FieldInfo matrixField = Game1.spriteBatch.GetType().GetField("_matrix", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
object originMatrix = matrixField.GetValue(Game1.spriteBatch);
|
||||
System.Reflection.FieldInfo spriteEffectField = Game1.spriteBatch.GetType().GetField("_spriteEffect", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
SpriteEffect originSpriteEffect = spriteEffectField?.GetValue(Game1.spriteBatch) as SpriteEffect;
|
||||
var originMatrix = originSpriteEffect?.TransformMatrix;
|
||||
Game1.spriteBatch.End();
|
||||
Game1.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, Microsoft.Xna.Framework.Matrix.CreateScale(1f));
|
||||
Game1.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, Matrix.CreateScale(1f));
|
||||
IClickableMenu.drawTextureBoxWithIconAndText(Game1.spriteBatch, Game1.smallFont, Game1.mouseCursors, new Rectangle(0x100, 0x100, 10, 10), null, new Rectangle(0, 0, 1, 1),
|
||||
this.alias, this.buttonRectangle.X, this.buttonRectangle.Y, this.buttonRectangle.Width, this.buttonRectangle.Height, Color.BurlyWood * scale, 4f,
|
||||
this.Alias, this.ButtonRectangle.X, this.ButtonRectangle.Y, this.ButtonRectangle.Width, this.ButtonRectangle.Height, Color.BurlyWood * scale, 4f,
|
||||
true, false, true, false, false, false, false); // Remove bold to fix the text position issue
|
||||
Game1.spriteBatch.End();
|
||||
if(originMatrix != null)
|
||||
|
|
|
@ -2,18 +2,18 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
|
|||
{
|
||||
class ModConfig
|
||||
{
|
||||
public Toggle vToggle { get; set; } = new Toggle(new Rect(36, 12, 64, 64), true, SButton.None);
|
||||
public Toggle vToggle { get; set; } = new(new Rect(36, 12, 64, 64), true, SButton.None);
|
||||
public VirtualButton[] buttons { get; set;} = new VirtualButton[] {
|
||||
new VirtualButton(SButton.Q, new Rect(190, 80, 90, 90), 0.5f),
|
||||
new VirtualButton(SButton.I, new Rect(290, 80, 90, 90), 0.5f),
|
||||
new VirtualButton(SButton.O, new Rect(390, 80, 90, 90), 0.5f),
|
||||
new VirtualButton(SButton.P, new Rect(490, 80, 90, 90), 0.5f)
|
||||
new(SButton.Q, new Rect(190, 80, 90, 90), 0.5f),
|
||||
new(SButton.I, new Rect(290, 80, 90, 90), 0.5f),
|
||||
new(SButton.O, new Rect(390, 80, 90, 90), 0.5f),
|
||||
new(SButton.P, new Rect(490, 80, 90, 90), 0.5f)
|
||||
};
|
||||
public VirtualButton[] buttonsExtend { get; set; } = new VirtualButton[] {
|
||||
new VirtualButton(SButton.MouseRight, new Rect(190, 170, 162, 90), 0.5f, "RightMouse"),
|
||||
new VirtualButton(SButton.None, new Rect(360, 170, 92, 90), 0.5f, "Zoom", "zoom 1.0"),
|
||||
new VirtualButton(SButton.RightWindows, new Rect(460, 170, 162, 90), 0.5f, "Command"),
|
||||
new VirtualButton(SButton.RightControl, new Rect(630, 170, 162, 90), 0.5f, "Console")
|
||||
new(SButton.MouseRight, new Rect(190, 170, 162, 90), 0.5f, "RightMouse"),
|
||||
new(SButton.None, new Rect(360, 170, 92, 90), 0.5f, "Zoom", "zoom 1.0"),
|
||||
new(SButton.RightWindows, new Rect(460, 170, 162, 90), 0.5f, "Command"),
|
||||
new(SButton.RightControl, new Rect(630, 170, 162, 90), 0.5f, "Console")
|
||||
};
|
||||
internal class VirtualButton {
|
||||
public SButton key { get;set; }
|
||||
|
|
|
@ -1,14 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using StardewModdingAPI;
|
||||
|
||||
namespace StardewModdingAPI.Mods.VirtualKeyboard
|
||||
{
|
||||
class ModEntry : Mod
|
||||
{
|
||||
public static float ZoomScale;
|
||||
public override void Entry(IModHelper helper)
|
||||
{
|
||||
new VirtualToggle(helper, this.Monitor);
|
||||
|
|
|
@ -1,36 +1 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("StardewModdingAPI.Mods.VirtualKeyboard")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("StardewModdingAPI.Mods.VirtualKeyboard")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2019")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("29cce9c9-6811-415d-a681-a6d47073924d")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
|
@ -1,18 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{29CCE9C9-6811-415D-A681-A6D47073924D}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>StardewModdingAPI.Mods.VirtualKeyboard</RootNamespace>
|
||||
<AssemblyName>VirtualKeyboard</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -32,54 +28,16 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Mono.Android">
|
||||
<HintPath>..\..\..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.5.145\assemblies\Mono.Android.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MonoGame.Framework, Version=3.7.1.189, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="MonoGame.Framework">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.5.145\assemblies\MonoGame.Framework.dll</HintPath>
|
||||
<HintPath>..\..\build\StardewValleyAndroidStuff\base_1.5.6.39\assemblies\MonoGame.Framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="StardewModdingAPI">
|
||||
<HintPath>..\SMAPI\bin\Release\StardewModdingAPI.dll</HintPath>
|
||||
<HintPath>..\SMAPI\bin\Debug\StardewModdingAPI.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="StardewValley">
|
||||
<HintPath>..\..\..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.5.145\assemblies\StardewValley.dll</HintPath>
|
||||
<HintPath>..\..\build\StardewValleyAndroidStuff\base_1.5.6.39\assemblies\StardewValley.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System">
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Core">
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Drawing">
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Windows.Forms">
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq">
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.DataSetExtensions">
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data">
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http">
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml">
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="KeyButton.cs" />
|
||||
<Compile Include="ModConfig.cs" />
|
||||
<Compile Include="ModEntry.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="VirtualToggle.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="manifest.json" />
|
||||
|
@ -93,5 +51,4 @@
|
|||
<Name>SMAPI.Toolkit</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -10,105 +10,105 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
|
|||
{
|
||||
class VirtualToggle
|
||||
{
|
||||
private readonly IModHelper helper;
|
||||
private readonly IModHelper Helper;
|
||||
private readonly IMonitor Monitor;
|
||||
|
||||
private int enabledStage = 0;
|
||||
private bool autoHidden = true;
|
||||
private bool isDefault = true;
|
||||
private ClickableTextureComponent virtualToggleButton;
|
||||
private int EnabledStage = 0;
|
||||
private bool AutoHidden = true;
|
||||
private bool IsDefault = true;
|
||||
private ClickableTextureComponent VirtualToggleButton;
|
||||
|
||||
private List<KeyButton> keyboard = new List<KeyButton>();
|
||||
private List<KeyButton> keyboardExtend = new List<KeyButton>();
|
||||
private ModConfig modConfig;
|
||||
private Texture2D texture;
|
||||
private int lastPressTick = 0;
|
||||
private List<KeyButton> Keyboard = new();
|
||||
private List<KeyButton> KeyboardExtend = new();
|
||||
private ModConfig ModConfig;
|
||||
private Texture2D Texture;
|
||||
private int LastPressTick = 0;
|
||||
|
||||
public VirtualToggle(IModHelper helper, IMonitor monitor)
|
||||
{
|
||||
this.Monitor = monitor;
|
||||
this.helper = helper;
|
||||
this.texture = this.helper.Content.Load<Texture2D>("assets/togglebutton.png", ContentSource.ModFolder);
|
||||
this.Helper = helper;
|
||||
this.Texture = this.Helper.ModContent.Load<Texture2D>("assets/togglebutton.png");
|
||||
|
||||
this.modConfig = helper.ReadConfig<ModConfig>();
|
||||
for (int i = 0; i < this.modConfig.buttons.Length; i++)
|
||||
this.keyboard.Add(new KeyButton(helper, this.modConfig.buttons[i], this.Monitor));
|
||||
for (int i = 0; i < this.modConfig.buttonsExtend.Length; i++)
|
||||
this.keyboardExtend.Add(new KeyButton(helper, this.modConfig.buttonsExtend[i], this.Monitor));
|
||||
this.ModConfig = helper.ReadConfig<ModConfig>();
|
||||
for (int i = 0; i < this.ModConfig.buttons.Length; i++)
|
||||
this.Keyboard.Add(new KeyButton(helper, this.ModConfig.buttons[i], this.Monitor));
|
||||
for (int i = 0; i < this.ModConfig.buttonsExtend.Length; i++)
|
||||
this.KeyboardExtend.Add(new KeyButton(helper, this.ModConfig.buttonsExtend[i], this.Monitor));
|
||||
|
||||
if (this.modConfig.vToggle.rectangle.X != 36 || this.modConfig.vToggle.rectangle.Y != 12)
|
||||
this.isDefault = false;
|
||||
this.autoHidden = this.modConfig.vToggle.autoHidden;
|
||||
if (this.ModConfig.vToggle.rectangle.X != 36 || this.ModConfig.vToggle.rectangle.Y != 12)
|
||||
this.IsDefault = false;
|
||||
this.AutoHidden = this.ModConfig.vToggle.autoHidden;
|
||||
|
||||
this.virtualToggleButton = new ClickableTextureComponent(new Rectangle(Game1.toolbarPaddingX + 64, 12, 128, 128), this.texture, new Rectangle(0, 0, 16, 16), 5.75f, false);
|
||||
helper.WriteConfig(this.modConfig);
|
||||
this.VirtualToggleButton = new ClickableTextureComponent(new Rectangle(Game1.toolbarPaddingX + 64, 12, 128, 128), this.Texture, new Rectangle(0, 0, 16, 16), 4f, false);
|
||||
helper.WriteConfig(this.ModConfig);
|
||||
|
||||
this.helper.Events.Display.Rendered += this.OnRendered;
|
||||
this.helper.Events.Display.MenuChanged += this.OnMenuChanged;
|
||||
this.helper.Events.Input.ButtonPressed += this.VirtualToggleButtonPressed;
|
||||
this.Helper.Events.Display.Rendered += this.OnRendered;
|
||||
this.Helper.Events.Display.MenuChanged += this.OnMenuChanged;
|
||||
this.Helper.Events.Input.ButtonPressed += this.VirtualToggleButtonPressed;
|
||||
}
|
||||
|
||||
private void OnMenuChanged(object sender, MenuChangedEventArgs e)
|
||||
{
|
||||
if(this.autoHidden && e.NewMenu != null) {
|
||||
foreach (var keys in this.keyboard)
|
||||
if(this.AutoHidden && e.NewMenu != null) {
|
||||
foreach (var keys in this.Keyboard)
|
||||
{
|
||||
keys.hidden = true;
|
||||
keys.Hidden = true;
|
||||
}
|
||||
foreach (var keys in this.keyboardExtend)
|
||||
foreach (var keys in this.KeyboardExtend)
|
||||
{
|
||||
keys.hidden = true;
|
||||
keys.Hidden = true;
|
||||
}
|
||||
this.enabledStage = 0;
|
||||
this.EnabledStage = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void VirtualToggleButtonPressed(object sender, ButtonPressedEventArgs e)
|
||||
{
|
||||
Vector2 screenPixels = e.Cursor.ScreenPixels;
|
||||
if (this.modConfig.vToggle.key != SButton.None && e.Button == this.modConfig.vToggle.key)
|
||||
this.toggleLogic();
|
||||
else if (e.Button == SButton.MouseLeft && this.shouldTrigger(screenPixels))
|
||||
this.toggleLogic();
|
||||
Vector2 screenPixels = Utility.ModifyCoordinatesForUIScale(e.Cursor.ScreenPixels);
|
||||
if (this.ModConfig.vToggle.key != SButton.None && e.Button == this.ModConfig.vToggle.key)
|
||||
this.ToggleLogic();
|
||||
else if (e.Button == SButton.MouseLeft && this.ShouldTrigger(screenPixels))
|
||||
this.ToggleLogic();
|
||||
}
|
||||
|
||||
private void toggleLogic()
|
||||
private void ToggleLogic()
|
||||
{
|
||||
switch (this.enabledStage)
|
||||
switch (this.EnabledStage)
|
||||
{
|
||||
case 0:
|
||||
foreach (var keys in this.keyboard)
|
||||
foreach (var keys in this.Keyboard)
|
||||
{
|
||||
keys.hidden = false;
|
||||
keys.Hidden = false;
|
||||
}
|
||||
|
||||
foreach (var keys in this.keyboardExtend)
|
||||
foreach (var keys in this.KeyboardExtend)
|
||||
{
|
||||
keys.hidden = true;
|
||||
keys.Hidden = true;
|
||||
}
|
||||
|
||||
this.enabledStage = 1;
|
||||
this.EnabledStage = 1;
|
||||
break;
|
||||
case 1 when this.keyboardExtend.Count > 0:
|
||||
foreach (var keys in this.keyboardExtend)
|
||||
case 1 when this.KeyboardExtend.Count > 0:
|
||||
foreach (var keys in this.KeyboardExtend)
|
||||
{
|
||||
keys.hidden = false;
|
||||
keys.Hidden = false;
|
||||
}
|
||||
|
||||
this.enabledStage = 2;
|
||||
this.EnabledStage = 2;
|
||||
break;
|
||||
default:
|
||||
foreach (var keys in this.keyboard)
|
||||
foreach (var keys in this.Keyboard)
|
||||
{
|
||||
keys.hidden = true;
|
||||
keys.Hidden = true;
|
||||
}
|
||||
|
||||
foreach (var keys in this.keyboardExtend)
|
||||
foreach (var keys in this.KeyboardExtend)
|
||||
{
|
||||
keys.hidden = true;
|
||||
keys.Hidden = true;
|
||||
}
|
||||
|
||||
this.enabledStage = 0;
|
||||
this.EnabledStage = 0;
|
||||
if (Game1.activeClickableMenu is IClickableMenu menu && !(Game1.activeClickableMenu is DialogueBox))
|
||||
{
|
||||
menu.exitThisMenu();
|
||||
|
@ -119,16 +119,16 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
|
|||
}
|
||||
}
|
||||
|
||||
private bool shouldTrigger(Vector2 screenPixels)
|
||||
private bool ShouldTrigger(Vector2 screenPixels)
|
||||
{
|
||||
int tick = Game1.ticks;
|
||||
if(tick - this.lastPressTick <= 6)
|
||||
if(tick - this.LastPressTick <= 6)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this.virtualToggleButton.containsPoint((int)(screenPixels.X * Game1.options.zoomLevel), (int)(screenPixels.Y * Game1.options.zoomLevel)))
|
||||
if (this.VirtualToggleButton.containsPoint((int)screenPixels.X, (int)screenPixels.Y))
|
||||
{
|
||||
this.lastPressTick = tick;
|
||||
this.LastPressTick = tick;
|
||||
Toolbar.toolbarPressed = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -137,42 +137,43 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
|
|||
|
||||
private void OnRendered(object sender, EventArgs e)
|
||||
{
|
||||
if (this.isDefault)
|
||||
if (this.IsDefault)
|
||||
{
|
||||
if (Game1.options.verticalToolbar)
|
||||
this.virtualToggleButton.bounds.X = Game1.toolbarPaddingX + Game1.toolbar.itemSlotSize + 200;
|
||||
this.VirtualToggleButton.bounds.X = Game1.toolbarPaddingX + Game1.toolbar.itemSlotSize + 200;
|
||||
else
|
||||
this.virtualToggleButton.bounds.X = Game1.toolbarPaddingX + Game1.toolbar.itemSlotSize + 50;
|
||||
this.VirtualToggleButton.bounds.X = Game1.toolbarPaddingX + Game1.toolbar.itemSlotSize + 50;
|
||||
|
||||
if (Game1.toolbar.alignTop == true && !Game1.options.verticalToolbar)
|
||||
{
|
||||
object toolbarHeight = this.helper.Reflection.GetField<int>(Game1.toolbar, "toolbarHeight").GetValue();
|
||||
this.virtualToggleButton.bounds.Y = (int)toolbarHeight + 50;
|
||||
object toolbarHeight = this.Helper.Reflection.GetField<int>(Game1.toolbar, "toolbarHeight").GetValue();
|
||||
this.VirtualToggleButton.bounds.Y = (int)toolbarHeight + 50;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.virtualToggleButton.bounds.Y = 12;
|
||||
this.VirtualToggleButton.bounds.Y = 12;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.virtualToggleButton.bounds.X = this.modConfig.vToggle.rectangle.X;
|
||||
this.virtualToggleButton.bounds.Y = this.modConfig.vToggle.rectangle.Y;
|
||||
this.VirtualToggleButton.bounds.X = this.ModConfig.vToggle.rectangle.X;
|
||||
this.VirtualToggleButton.bounds.Y = this.ModConfig.vToggle.rectangle.Y;
|
||||
}
|
||||
|
||||
float scale = 1f;
|
||||
if (this.enabledStage == 0)
|
||||
if (this.EnabledStage == 0)
|
||||
{
|
||||
scale = 0.5f;
|
||||
}
|
||||
if (!Game1.eventUp && Game1.activeClickableMenu is GameMenu == false && Game1.activeClickableMenu is ShopMenu == false)
|
||||
scale = 0.25f;
|
||||
|
||||
System.Reflection.FieldInfo matrixField = Game1.spriteBatch.GetType().GetField("_matrix", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
object originMatrix = matrixField.GetValue(Game1.spriteBatch);
|
||||
System.Reflection.FieldInfo spriteEffectField = Game1.spriteBatch.GetType().GetField("_spriteEffect", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
SpriteEffect originSpriteEffect = spriteEffectField?.GetValue(Game1.spriteBatch) as SpriteEffect;
|
||||
var originMatrix = originSpriteEffect?.TransformMatrix;
|
||||
Game1.spriteBatch.End();
|
||||
Game1.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, Microsoft.Xna.Framework.Matrix.CreateScale(1f));
|
||||
this.virtualToggleButton.draw(Game1.spriteBatch, Color.White * scale, 0.000001f);
|
||||
this.VirtualToggleButton.draw(Game1.spriteBatch, Color.White * scale, 0.000001f);
|
||||
Game1.spriteBatch.End();
|
||||
if (originMatrix != null)
|
||||
{
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"Name": "VirtualKeyboard",
|
||||
"Author": "SMAPI",
|
||||
"Version": "3.3.1",
|
||||
"MinimumApiVersion": "3.4.0",
|
||||
"Version": "4.0.1",
|
||||
"MinimumApiVersion": "3.18.2",
|
||||
"Description": "A much needed Virtual Keyboard for SMAPI Android.",
|
||||
"UniqueID": "VirtualKeyboard",
|
||||
"EntryDll": "VirtualKeyboard.dll",
|
||||
|
|
|
@ -14,12 +14,12 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="6.8.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
|
||||
<PackageReference Include="FluentAssertions" Version="6.11.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
|
||||
<PackageReference Include="Moq" Version="4.18.4" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -2,7 +2,9 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
#if !SMAPI_FOR_MOBILE
|
||||
using Pathoschild.Http.Client;
|
||||
#endif
|
||||
using StardewModdingAPI.Toolkit.Serialization;
|
||||
using StardewModdingAPI.Toolkit.Utilities;
|
||||
|
||||
|
@ -17,8 +19,10 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
|
|||
/// <summary>The API version number.</summary>
|
||||
private readonly ISemanticVersion Version;
|
||||
|
||||
#if !SMAPI_FOR_MOBILE
|
||||
/// <summary>The underlying HTTP client.</summary>
|
||||
private readonly IClient Client;
|
||||
#endif
|
||||
|
||||
|
||||
/*********
|
||||
|
@ -30,10 +34,12 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
|
|||
public WebApiClient(string baseUrl, ISemanticVersion version)
|
||||
{
|
||||
this.Version = version;
|
||||
#if !SMAPI_FOR_MOBILE
|
||||
this.Client = new FluentClient(baseUrl)
|
||||
.SetUserAgent($"SMAPI/{version}");
|
||||
|
||||
this.Client.Formatters.JsonFormatter.SerializerSettings = JsonHelper.CreateDefaultSettings();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>Get metadata about a set of mods from the web API.</summary>
|
||||
|
@ -44,6 +50,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
|
|||
/// <param name="includeExtendedMetadata">Whether to include extended metadata for each mod.</param>
|
||||
public async Task<IDictionary<string, ModEntryModel>> GetModInfoAsync(ModSearchEntryModel[] mods, ISemanticVersion apiVersion, ISemanticVersion gameVersion, Platform platform, bool includeExtendedMetadata = false)
|
||||
{
|
||||
#if !SMAPI_FOR_MOBILE
|
||||
ModEntryModel[] result = await this.Client
|
||||
.PostAsync(
|
||||
$"v{this.Version}/mods",
|
||||
|
@ -52,12 +59,16 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
|
|||
.As<ModEntryModel[]>();
|
||||
|
||||
return result.ToDictionary(p => p.ID);
|
||||
#endif
|
||||
return new Dictionary<string, ModEntryModel>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
#if !SMAPI_FOR_MOBILE
|
||||
this.Client.Dispose();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ namespace StardewModdingAPI.Toolkit.Framework.GameScanning
|
|||
return GameFolderType.NoGameFound;
|
||||
|
||||
// apparently valid
|
||||
if (dir.EnumerateFiles("Stardew Valley.dll").Any())
|
||||
if (File.Exists(Path.Combine(dir.FullName, "Stardew Valley.dll")))
|
||||
return GameFolderType.Valid;
|
||||
|
||||
// doesn't contain any version of Stardew Valley
|
||||
|
@ -201,6 +201,9 @@ namespace StardewModdingAPI.Toolkit.Framework.GameScanning
|
|||
/// <summary>Get the custom install path from the <c>stardewvalley.targets</c> file in the home directory, if any.</summary>
|
||||
private IEnumerable<string> GetCustomInstallPaths()
|
||||
{
|
||||
#if SMAPI_FOR_MOBILE
|
||||
yield break;
|
||||
#else
|
||||
// get home path
|
||||
string homePath = Environment.GetEnvironmentVariable(this.Platform == Platform.Windows ? "USERPROFILE" : "HOME")!;
|
||||
if (string.IsNullOrWhiteSpace(homePath))
|
||||
|
@ -227,6 +230,7 @@ namespace StardewModdingAPI.Toolkit.Framework.GameScanning
|
|||
XElement? element = root.XPathSelectElement("//*[local-name() = 'GamePath']"); // can't use '//GamePath' due to the default namespace
|
||||
if (!string.IsNullOrWhiteSpace(element?.Value))
|
||||
yield return element.Value.Trim();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SMAPI_FOR_WINDOWS
|
||||
|
|
|
@ -3,6 +3,9 @@ using System.Diagnostics;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
#if SMAPI_FOR_WINDOWS
|
||||
using System.Management;
|
||||
#endif
|
||||
using System.Runtime.InteropServices;
|
||||
using StardewModdingAPI.Toolkit.Utilities;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using StardewModdingAPI.Toolkit.Serialization.Models;
|
||||
using StardewModdingAPI.Toolkit.Utilities;
|
||||
|
||||
|
@ -9,14 +10,25 @@ namespace StardewModdingAPI.Toolkit.Framework.ModScanning
|
|||
/// <summary>The info about a mod read from its folder.</summary>
|
||||
public class ModFolder
|
||||
{
|
||||
/*********
|
||||
** Fields
|
||||
*********/
|
||||
/// <summary>The backing field for <see cref="Directory"/>.</summary>
|
||||
private DirectoryInfo? DirectoryImpl;
|
||||
|
||||
|
||||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>A suggested display name for the mod folder.</summary>
|
||||
public string DisplayName { get; }
|
||||
|
||||
/// <summary>The folder path containing the mod's manifest.json.</summary>
|
||||
public string DirectoryPath { get; }
|
||||
|
||||
/// <summary>The folder containing the mod's manifest.json.</summary>
|
||||
public DirectoryInfo Directory { get; }
|
||||
[JsonIgnore]
|
||||
public DirectoryInfo Directory => this.DirectoryImpl ??= new DirectoryInfo(this.DirectoryPath);
|
||||
|
||||
/// <summary>The mod type.</summary>
|
||||
public ModType Type { get; }
|
||||
|
@ -52,7 +64,8 @@ namespace StardewModdingAPI.Toolkit.Framework.ModScanning
|
|||
public ModFolder(DirectoryInfo root, DirectoryInfo directory, ModType type, Manifest? manifest, ModParseError manifestParseError, string? manifestParseErrorText)
|
||||
{
|
||||
// save info
|
||||
this.Directory = directory;
|
||||
this.DirectoryImpl = directory;
|
||||
this.DirectoryPath = directory.FullName;
|
||||
this.Type = type;
|
||||
this.Manifest = manifest;
|
||||
this.ManifestParseError = manifestParseError;
|
||||
|
@ -64,6 +77,24 @@ namespace StardewModdingAPI.Toolkit.Framework.ModScanning
|
|||
: PathUtilities.GetRelativePath(root.FullName, directory.FullName);
|
||||
}
|
||||
|
||||
/// <summary>Construct an instance.</summary>
|
||||
/// <param name="displayName">A suggested display name for the mod folder.</param>
|
||||
/// <param name="directoryPath">The folder path containing the mod's manifest.json.</param>
|
||||
/// <param name="type">The mod type.</param>
|
||||
/// <param name="manifest">The mod manifest.</param>
|
||||
/// <param name="manifestParseError">The error which occurred parsing the manifest, if any.</param>
|
||||
/// <param name="manifestParseErrorText">A human-readable message for the <paramref name="manifestParseError"/>, if any.</param>
|
||||
[JsonConstructor]
|
||||
public ModFolder(string displayName, string directoryPath, ModType type, Manifest? manifest, ModParseError manifestParseError, string? manifestParseErrorText)
|
||||
{
|
||||
this.DisplayName = displayName;
|
||||
this.DirectoryPath = directoryPath;
|
||||
this.Type = type;
|
||||
this.Manifest = manifest;
|
||||
this.ManifestParseError = manifestParseError;
|
||||
this.ManifestParseErrorText = manifestParseErrorText;
|
||||
}
|
||||
|
||||
/// <summary>Get the update keys for a mod.</summary>
|
||||
/// <param name="manifest">The mod manifest.</param>
|
||||
public IEnumerable<string> GetUpdateKeys(Manifest manifest)
|
||||
|
|
|
@ -8,16 +8,18 @@
|
|||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- <Import Project="..\..\build\common.targets" />-->
|
||||
<!-- <Import Project="..\..\build\common.targets" />-->
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="Pathoschild.Http.FluentClient" Version="4.2.0" />
|
||||
<ItemGroup Condition="'$(BUILD_FOR_MOBILE)' != ''">
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\..\build\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(BUILD_FOR_MOBILE)' == ''">
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.28" />
|
||||
<PackageReference Include="Pathoschild.Http.FluentClient" Version="4.2.0" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.48" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="Pathoschild.Http.FluentClient" Version="4.3.0" />
|
||||
<PackageReference Include="System.Management" Version="5.0.0" Condition="'$(OS)' == 'Windows_NT'" />
|
||||
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" Condition="'$(OS)' == 'Windows_NT'" />
|
||||
<PackageReference Include="VdfConverter" Version="1.0.3" Condition="'$(OS)' == 'Windows_NT'" Private="False" />
|
||||
|
|
|
@ -44,6 +44,9 @@ namespace StardewModdingAPI.Toolkit.Serialization.Converters
|
|||
string path = reader.Path;
|
||||
switch (reader.TokenType)
|
||||
{
|
||||
case JsonToken.Null:
|
||||
return null;
|
||||
|
||||
case JsonToken.StartObject:
|
||||
return this.ReadObject(JObject.Load(reader));
|
||||
|
||||
|
|
|
@ -15,17 +15,17 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.Storage.Blobs" Version="12.14.1" />
|
||||
<PackageReference Include="Hangfire.AspNetCore" Version="1.7.32" />
|
||||
<PackageReference Include="Hangfire.MemoryStorage" Version="1.7.0" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.46" />
|
||||
<PackageReference Include="Azure.Storage.Blobs" Version="12.16.0" />
|
||||
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.2" />
|
||||
<PackageReference Include="Hangfire.MemoryStorage" Version="1.8.0" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.48" />
|
||||
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2022.3.1" />
|
||||
<PackageReference Include="Markdig" Version="0.30.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="7.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json.Schema" Version="3.0.14" />
|
||||
<PackageReference Include="Markdig" Version="0.31.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="7.0.8" />
|
||||
<PackageReference Include="Newtonsoft.Json.Schema" Version="3.0.15" />
|
||||
<PackageReference Include="Pathoschild.FluentNexus" Version="1.0.5" />
|
||||
<PackageReference Include="Pathoschild.Http.FluentClient" Version="4.2.0" />
|
||||
<PackageReference Include="Pathoschild.Http.FluentClient" Version="4.3.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="1.0.1" />
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
"title": "Format version",
|
||||
"description": "The format version. You should always use the latest version to enable the latest features, avoid obsolete behavior, and reduce load times.",
|
||||
"type": "string",
|
||||
"pattern": "^1\\.28\\.[0-9]+$",
|
||||
"pattern": "^1\\.29\\.[0-9]+$",
|
||||
"@errorMessages": {
|
||||
"pattern": "Incorrect value '@value'. You should always use the latest format version (currently 1.28.0) to enable the latest features, avoid obsolete behavior, and reduce load times."
|
||||
"pattern": "Incorrect value '@value'. You should always use the latest format version (currently 1.29.0) to enable the latest features, avoid obsolete behavior, and reduce load times."
|
||||
}
|
||||
},
|
||||
"ConfigSchema": {
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
"description": "The DLL filename SMAPI should load for this mod. Mutually exclusive with ContentPackFor.",
|
||||
"type": "string",
|
||||
"pattern": "^[a-zA-Z0-9_.-]+\\.dll$",
|
||||
"examples": "LookupAnything.dll",
|
||||
"examples": ["LookupAnything.dll"],
|
||||
"@errorMessages": {
|
||||
"pattern": "Invalid value; must be a filename ending with .dll."
|
||||
}
|
||||
|
|
|
@ -19,9 +19,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{4B1C
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ISSUE_TEMPLATE", "ISSUE_TEMPLATE", "{F4453AB6-D7D6-447F-A973-956CC777968F}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
..\.github\ISSUE_TEMPLATE\bug_report.md = ..\.github\ISSUE_TEMPLATE\bug_report.md
|
||||
..\.github\ISSUE_TEMPLATE\feature_request.md = ..\.github\ISSUE_TEMPLATE\feature_request.md
|
||||
..\.github\ISSUE_TEMPLATE\general.md = ..\.github\ISSUE_TEMPLATE\general.md
|
||||
..\.github\ISSUE_TEMPLATE\config.yml = ..\.github\ISSUE_TEMPLATE\config.yml
|
||||
..\.github\ISSUE_TEMPLATE\custom.md = ..\.github\ISSUE_TEMPLATE\custom.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{09CF91E5-5BAB-4650-A200-E5EA9A633046}"
|
||||
|
@ -84,9 +83,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SMAPI.Web", "SMAPI.Web\SMAP
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Android", "Android", "{6BBCA4D1-213F-4843-B910-DF2D66E3D8CF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SMAPI.Mods.VirtualKeyboard", "SMAPI.Mods.VirtualKeyboard\SMAPI.Mods.VirtualKeyboard.csproj", "{29CCE9C9-6811-415D-A681-A6D47073924D}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SMAPI.Mods.VirtualKeyboard", "SMAPI.Mods.VirtualKeyboard\SMAPI.Mods.VirtualKeyboard.csproj", "{29CCE9C9-6811-415D-A681-A6D47073924D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Loader", "Loader\Loader.csproj", "{45D7D2FB-6B70-45D1-A595-6E289D6A3468}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Loader", "Loader\Loader.csproj", "{45D7D2FB-6B70-45D1-A595-6E289D6A3468}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "windows", "windows", "{4D661178-38FB-43E4-AA5F-9B0406919344}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
|
@ -110,7 +109,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SMAPI.Tests.ModApiProvider"
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SMAPI.Tests.ModApiConsumer", "SMAPI.Tests.ModApiConsumer\SMAPI.Tests.ModApiConsumer.csproj", "{2A4DF030-E8B1-4BBD-AA93-D4DE68CB9D85}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SMAPI", "SMAPI\SMAPI.csproj", "{EBD13EAB-E70B-4D9F-92C2-C34A21E1FA32}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SMAPI", "SMAPI\SMAPI.csproj", "{EBD13EAB-E70B-4D9F-92C2-C34A21E1FA32}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MobilePatch", "MobilePatch\MobilePatch.csproj", "{E5FE4C97-1A7C-4A97-9904-7351CA020C7F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
@ -179,6 +180,10 @@ Global
|
|||
{EBD13EAB-E70B-4D9F-92C2-C34A21E1FA32}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EBD13EAB-E70B-4D9F-92C2-C34A21E1FA32}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EBD13EAB-E70B-4D9F-92C2-C34A21E1FA32}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E5FE4C97-1A7C-4A97-9904-7351CA020C7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E5FE4C97-1A7C-4A97-9904-7351CA020C7F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E5FE4C97-1A7C-4A97-9904-7351CA020C7F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E5FE4C97-1A7C-4A97-9904-7351CA020C7F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -203,14 +208,15 @@ Global
|
|||
{3B5BF14D-F612-4C83-9EF6-E3EBFCD08766} = {4D661178-38FB-43E4-AA5F-9B0406919344}
|
||||
{239AEEAC-07D1-4A3F-AA99-8C74F5038F50} = {82D22ED7-A0A7-4D64-8E92-4B6A5E74ED11}
|
||||
{2A4DF030-E8B1-4BBD-AA93-D4DE68CB9D85} = {82D22ED7-A0A7-4D64-8E92-4B6A5E74ED11}
|
||||
{E5FE4C97-1A7C-4A97-9904-7351CA020C7F} = {6BBCA4D1-213F-4843-B910-DF2D66E3D8CF}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {70143042-A862-47A8-A677-7C819DDC90DC}
|
||||
EndGlobalSection
|
||||
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
||||
SMAPI.Internal\SMAPI.Internal.projitems*{0634ea4c-3b8f-42db-aea6-ca9e4ef6e92f}*SharedItemsImports = 5
|
||||
SMAPI.Internal.Patching\SMAPI.Internal.Patching.projitems*{6c16e948-3e5c-47a7-bf4b-07a7469a87a5}*SharedItemsImports = 13
|
||||
SMAPI.Internal\SMAPI.Internal.projitems*{85208f8d-6fd1-4531-be05-7142490f59fe}*SharedItemsImports = 13
|
||||
SMAPI.Internal\SMAPI.Internal.projitems*{cd53ad6f-97f4-4872-a212-50c2a0fd3601}*SharedItemsImports = 5
|
||||
SMAPI.Internal.Patching\SMAPI.Internal.Patching.projitems*{ebd13eab-e70b-4d9f-92c2-c34a21e1fa32}*SharedItemsImports = 5
|
||||
SMAPI.Internal\SMAPI.Internal.projitems*{ebd13eab-e70b-4d9f-92c2-c34a21e1fa32}*SharedItemsImports = 5
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -13,7 +13,7 @@ using StardewModdingAPI.Framework.ModLoading;
|
|||
using StardewModdingAPI.Toolkit.Framework;
|
||||
using StardewModdingAPI.Toolkit.Utilities;
|
||||
using StardewValley;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace StardewModdingAPI
|
||||
{
|
||||
/// <summary>Contains constants that are accessed before the game itself has been loaded.</summary>
|
||||
|
@ -35,9 +35,9 @@ namespace StardewModdingAPI
|
|||
*********/
|
||||
#if SMAPI_FOR_MOBILE
|
||||
/// <summary>The path to the storage base folder.</summary>
|
||||
public static string StorageBasePath { get; } = Android.OS.Environment.ExternalStorageDirectory.Path;
|
||||
public static string StorageBasePath { get; } = SMainActivity.Instance.GetExternalFilesDir("").AbsolutePath;
|
||||
/// <summary>The path to the game's save folder.</summary>
|
||||
public static string StardewValleyBasePath { get; } = Path.Combine(EarlyConstants.StorageBasePath, "StardewValley");
|
||||
public static string StardewValleyBasePath { get; } = EarlyConstants.StorageBasePath;
|
||||
/// <summary>The path to the internal folder.</summary>
|
||||
public static string ExecutionPath { get; } = Path.Combine(EarlyConstants.StardewValleyBasePath, "smapi-internal");
|
||||
|
||||
|
@ -65,13 +65,20 @@ namespace StardewModdingAPI
|
|||
internal static GameFramework GameFramework { get; } = GameFramework.MonoGame;
|
||||
|
||||
/// <summary>The game's assembly name.</summary>
|
||||
#if SMAPI_FOR_MOBILE
|
||||
internal static string GameAssemblyName { get; } = "StardewValley";
|
||||
#else
|
||||
internal static string GameAssemblyName { get; } = "Stardew Valley";
|
||||
|
||||
#endif
|
||||
/// <summary>The <see cref="Context.ScreenId"/> value which should appear in the SMAPI log, if any.</summary>
|
||||
internal static int? LogScreenId { get; set; }
|
||||
|
||||
/// <summary>SMAPI's current raw semantic version.</summary>
|
||||
internal static string RawApiVersion = "3.18.2";
|
||||
#if !SMAPI_FOR_MOBILE
|
||||
internal static string RawApiVersion = "3.18.4";
|
||||
#else
|
||||
internal static string RawApiVersion = "3.18.4.1";
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>Contains SMAPI's constants and assumptions.</summary>
|
||||
|
@ -88,9 +95,6 @@ namespace StardewModdingAPI
|
|||
public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion(EarlyConstants.RawApiVersion);
|
||||
#else
|
||||
public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion(EarlyConstants.RawApiVersion);
|
||||
|
||||
/// <summary>Android SMAPI's current semantic version.</summary>
|
||||
public static ISemanticVersion AndroidApiVersion { get; } = new Toolkit.SemanticVersion("0.8.8");
|
||||
#endif
|
||||
|
||||
/// <summary>The minimum supported version of Stardew Valley.</summary>
|
||||
|
@ -139,11 +143,7 @@ namespace StardewModdingAPI
|
|||
/// <summary>The directory path in which error logs should be stored.</summary>
|
||||
public static string LogDir { get; } = Path.Combine(Constants.DataPath, "ErrorLogs");
|
||||
/// <summary>The directory path where all saves are stored.</summary>
|
||||
#if SMAPI_FOR_MOBILE
|
||||
public static string SavesPath { get; } = Constants.DataPath;
|
||||
#else
|
||||
public static string SavesPath { get; } = Path.Combine(Constants.DataPath, "Saves");
|
||||
#endif
|
||||
|
||||
/// <summary>The name of the current save folder (if save info is available, regardless of whether the save file exists yet).</summary>
|
||||
public static string? SaveFolderName => Constants.GetSaveFolderName();
|
||||
|
@ -289,6 +289,7 @@ namespace StardewModdingAPI
|
|||
{
|
||||
// add search paths
|
||||
resolver.TryAddSearchDirectory(Constants.GamePath);
|
||||
#if !SMAPI_FOR_MOBILE
|
||||
resolver.TryAddSearchDirectory(Constants.InternalFilesPath);
|
||||
|
||||
// add SMAPI explicitly
|
||||
|
@ -303,6 +304,7 @@ namespace StardewModdingAPI
|
|||
// - 'Stardew Valley': assembly name on Windows;
|
||||
// - 'Netcode': an assembly that was separate on Windows only before Stardew Valley 1.5.5.
|
||||
resolver.AddWithExplicitNames(AssemblyDefinition.ReadAssembly(typeof(Game1).Assembly.Location), "StardewValley", "Stardew Valley", "Netcode");
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>Get metadata for mapping assemblies to the current platform.</summary>
|
||||
|
@ -334,14 +336,17 @@ namespace StardewModdingAPI
|
|||
);
|
||||
|
||||
// Stardew Valley reference
|
||||
#if SMAPI_FOR_MOBILE
|
||||
removeAssemblyReferences.Add("Stardew Valley");
|
||||
#else
|
||||
removeAssemblyReferences.Add("StardewValley");
|
||||
#endif
|
||||
targetAssemblies.Add(typeof(StardewValley.Game1).Assembly);
|
||||
|
||||
return new PlatformAssemblyMap(targetPlatform, removeAssemblyReferences.ToArray(), targetAssemblies.ToArray());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*********
|
||||
** Private methods
|
||||
*********/
|
||||
|
@ -427,7 +432,9 @@ namespace StardewModdingAPI
|
|||
// ignore invalid path
|
||||
}
|
||||
}
|
||||
|
||||
#if SMAPI_FOR_MOBILE
|
||||
if (folder != null && rawSaveName.Length > 0) folder.Create();
|
||||
#endif
|
||||
// if save doesn't exist yet, return the default one we expect to be created
|
||||
return folder;
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ namespace StardewModdingAPI
|
|||
public static bool IsWorldReady
|
||||
{
|
||||
get => Context.IsWorldReadyForScreen.Value;
|
||||
set => Context.IsWorldReadyForScreen.Value = value;
|
||||
internal set => Context.IsWorldReadyForScreen.Value = value;
|
||||
}
|
||||
|
||||
/// <summary>Whether <see cref="IsWorldReady"/> is true and the player is free to act in the world (no menu is displayed, no cutscene is in progress, etc).</summary>
|
||||
|
@ -88,7 +88,7 @@ namespace StardewModdingAPI
|
|||
public static bool IsSplitScreen => LocalMultiplayer.IsLocalMultiplayer();
|
||||
|
||||
/// <summary>Whether there are players connected over the network.</summary>
|
||||
public static bool HasRemotePlayers => Context.IsMultiplayer && !Game1.hasLocalClientsOnly;
|
||||
public static bool HasRemotePlayers => Context.IsMultiplayer && !Game1.hasLocalClientsOnly && Game1.getOnlineFarmers().Count > 1;
|
||||
|
||||
/// <summary>Whether the current player is the main player. This is always true in single-player, and true when hosting in multiplayer.</summary>
|
||||
#if SMAPI_FOR_MOBILE
|
||||
|
@ -100,8 +100,7 @@ namespace StardewModdingAPI
|
|||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Get whether a screen ID is still active.</summary>
|
||||
/// <param name="id">The screen ID.</param>
|
||||
/// <summary>Get whether a screen ID is still active.</summary> <param name="id">The screen ID.</param>
|
||||
public static bool HasScreenId(int id)
|
||||
{
|
||||
return Context.ActiveScreenIds.Contains(id);
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
#if SMAPI_FOR_MOBILE
|
||||
using ReadOnlyCollectionsExtensions;
|
||||
#endif
|
||||
|
||||
namespace StardewModdingAPI.Events
|
||||
{
|
||||
|
@ -11,18 +14,10 @@ namespace StardewModdingAPI.Events
|
|||
** Accessors
|
||||
*********/
|
||||
/// <summary>The asset names that were invalidated.</summary>
|
||||
#if SMAPI_FOR_MOBILE
|
||||
public IReadOnlyCollection<IAssetName> Names { get; }
|
||||
#else
|
||||
public IReadOnlySet<IAssetName> Names { get; }
|
||||
#endif
|
||||
/// <summary>The <see cref="Names"/> with any locale codes stripped.</summary>
|
||||
/// <remarks>For example, if <see cref="Names"/> contains a locale like <c>Data/Bundles.fr-FR</c>, this will have the name without locale like <c>Data/Bundles</c>. If the name has no locale, this field is equivalent.</remarks>
|
||||
#if SMAPI_FOR_MOBILE
|
||||
public IReadOnlyCollection<IAssetName> NamesWithoutLocale { get; }
|
||||
#else
|
||||
public IReadOnlySet<IAssetName> NamesWithoutLocale { get; }
|
||||
#endif
|
||||
|
||||
|
||||
/*********
|
||||
|
@ -33,8 +28,13 @@ namespace StardewModdingAPI.Events
|
|||
/// <param name="namesWithoutLocale">The <paramref name="names"/> with any locale codes stripped.</param>
|
||||
internal AssetsInvalidatedEventArgs(IEnumerable<IAssetName> names, IEnumerable<IAssetName> namesWithoutLocale)
|
||||
{
|
||||
#if SMAPI_FOR_MOBILE
|
||||
this.Names = names.ToReadOnlySet();
|
||||
this.NamesWithoutLocale = namesWithoutLocale.ToReadOnlySet();
|
||||
#else
|
||||
this.Names = names.ToImmutableHashSet();
|
||||
this.NamesWithoutLocale = namesWithoutLocale.ToImmutableHashSet();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -412,17 +412,28 @@ namespace StardewModdingAPI.Framework
|
|||
// cached assets
|
||||
foreach (IContentManager contentManager in this.ContentManagers)
|
||||
{
|
||||
#if SMAPI_FOR_MOBILE
|
||||
HashSet<IAssetName> removingAssets = new HashSet<IAssetName>();
|
||||
#endif
|
||||
foreach ((string key, object asset) in contentManager.GetCachedAssets())
|
||||
{
|
||||
if (!predicate(contentManager, key, asset.GetType()))
|
||||
continue;
|
||||
|
||||
AssetName assetName = this.ParseAssetName(key, allowLocales: true);
|
||||
#if !SMAPI_FOR_MOBILE
|
||||
contentManager.InvalidateCache(assetName, dispose);
|
||||
#else
|
||||
removingAssets.Add(assetName);
|
||||
#endif
|
||||
|
||||
if (!invalidatedAssets.ContainsKey(assetName))
|
||||
invalidatedAssets[assetName] = asset.GetType();
|
||||
}
|
||||
#if SMAPI_FOR_MOBILE
|
||||
foreach (IAssetName assetName in removingAssets)
|
||||
contentManager.InvalidateCache(assetName, dispose);
|
||||
#endif
|
||||
}
|
||||
|
||||
// forget localized flags
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Buffers;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using BmFont;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
@ -23,6 +21,10 @@ using StardewValley;
|
|||
using xTile;
|
||||
using xTile.Format;
|
||||
using xTile.Tiles;
|
||||
#if SMAPI_FOR_MOBILE
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
#endif
|
||||
|
||||
namespace StardewModdingAPI.Framework.ContentManagers
|
||||
{
|
||||
|
@ -139,7 +141,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
|
|||
".png" => this.LoadImageFile<T>(assetName, file),
|
||||
".tbin" or ".tmx" => this.LoadMapFile<T>(assetName, file),
|
||||
".xnb" => this.LoadXnbFile<T>(assetName),
|
||||
_ => this.HandleUnknownFileType<T>(assetName, file)
|
||||
_ => (T)this.HandleUnknownFileType(assetName, file, typeof(T))
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -347,13 +349,15 @@ namespace StardewModdingAPI.Framework.ContentManagers
|
|||
}
|
||||
|
||||
/// <summary>Handle a request to load a file type that isn't supported by SMAPI.</summary>
|
||||
/// <typeparam name="T">The expected file type.</typeparam>
|
||||
/// <param name="assetName">The asset name relative to the loader root directory.</param>
|
||||
/// <param name="file">The file to load.</param>
|
||||
private T HandleUnknownFileType<T>(IAssetName assetName, FileInfo file)
|
||||
/// <param name="assetType">The expected file type.</param>
|
||||
private object HandleUnknownFileType(IAssetName assetName, FileInfo file, Type assetType)
|
||||
{
|
||||
this.ThrowLoadError(assetName, ContentLoadErrorType.InvalidName, $"unknown file extension '{file.Extension}'; must be one of '.fnt', '.json', '.png', '.tbin', '.tmx', or '.xnb'.");
|
||||
return default;
|
||||
return assetType.IsValueType
|
||||
? Activator.CreateInstance(assetType)
|
||||
: null;
|
||||
}
|
||||
|
||||
/// <summary>Assert that the asset type is compatible with one of the allowed types.</summary>
|
||||
|
@ -458,6 +462,10 @@ namespace StardewModdingAPI.Framework.ContentManagers
|
|||
tilesheet.ImageSource = this.NormalizePathSeparators(tilesheet.ImageSource);
|
||||
string imageSource = tilesheet.ImageSource;
|
||||
|
||||
// validate image source
|
||||
if (string.IsNullOrWhiteSpace(imageSource))
|
||||
throw new SContentLoadException(ContentLoadErrorType.InvalidData, $"{this.ModName} loaded map '{relativeMapPath}' with invalid tilesheet '{tilesheet.Id}'. This tilesheet has no image source.");
|
||||
|
||||
// reverse incorrect eager tilesheet path prefixing
|
||||
if (fixEagerPathPrefixes && relativeMapFolder.Length > 0 && imageSource.StartsWith(relativeMapFolder))
|
||||
imageSource = imageSource[(relativeMapFolder.Length + 1)..];
|
||||
|
|
|
@ -41,7 +41,9 @@ namespace StardewModdingAPI.Framework.Input
|
|||
** Accessors
|
||||
*********/
|
||||
/// <summary>Whether the gamepad is currently connected.</summary>
|
||||
// [MemberNotNullWhen(true, nameof(GamePadStateBuilder.ButtonStates))]
|
||||
#if !SMAPI_FOR_MOBILE
|
||||
[MemberNotNullWhen(true, nameof(GamePadStateBuilder.ButtonStates))]
|
||||
#endif
|
||||
public bool IsConnected { get; }
|
||||
|
||||
|
||||
|
@ -201,11 +203,6 @@ namespace StardewModdingAPI.Framework.Input
|
|||
leftTrigger: this.LeftTrigger,
|
||||
rightTrigger: this.RightTrigger,
|
||||
buttons: this.GetPressedGamePadButtons().ToArray()
|
||||
// #if MonoAndroid10_
|
||||
// buttons: new[] {this.GetButtonBitmask()}
|
||||
// #else
|
||||
// buttons: this.GetButtonBitmask() // MonoGame requires one bitmask here; don't specify multiple values
|
||||
// #endif
|
||||
);
|
||||
|
||||
return this.State.Value;
|
||||
|
|
|
@ -305,6 +305,7 @@ namespace StardewModdingAPI.Framework.Logging
|
|||
// developer mode
|
||||
if (settings.DeveloperMode)
|
||||
this.Monitor.Log("You enabled developer mode, so the console will be much more verbose. You can disable it by installing the non-developer version of SMAPI.", LogLevel.Info);
|
||||
|
||||
// warnings
|
||||
if (!settings.CheckForUpdates)
|
||||
this.Monitor.Log("You disabled update checks, so you won't be notified of new SMAPI or mod updates. Running an old version of SMAPI is not recommended. You can undo this by reinstalling SMAPI.", LogLevel.Warn);
|
||||
|
|
|
@ -178,7 +178,14 @@ namespace StardewModdingAPI.Framework.ModLoading
|
|||
using MemoryStream outSymbolStream = new();
|
||||
assembly.Definition.Write(outAssemblyStream, new WriterParameters { WriteSymbols = true, SymbolStream = outSymbolStream, SymbolWriterProvider = this.SymbolWriterProvider });
|
||||
byte[] bytes = outAssemblyStream.ToArray();
|
||||
lastAssembly = Assembly.Load(bytes, outSymbolStream.ToArray());
|
||||
if (assembly.File.Name != "MoonSharp.Interpreter.dll" && assembly.File.Name != "PyTK.dll" )
|
||||
{
|
||||
lastAssembly = Assembly.Load(bytes, outSymbolStream.ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
lastAssembly = Assembly.Load(bytes);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -405,9 +412,12 @@ namespace StardewModdingAPI.Framework.ModLoading
|
|||
}
|
||||
|
||||
// find or rewrite code
|
||||
InstructionMetadata instructionMetadata = new InstructionMetadata(this.Monitor);
|
||||
IInstructionHandler[] handlers = instructionMetadata.GetHandlers(this.ParanoidMode, platformChanged, this.RewriteMods).ToArray();
|
||||
RecursiveRewriter rewriter = new RecursiveRewriter(
|
||||
#if SMAPI_FOR_MOBILE
|
||||
IInstructionHandler[] handlers = new InstructionMetadata(this.Monitor).GetHandlers(this.ParanoidMode, platformChanged, this.RewriteMods).ToArray();
|
||||
#else
|
||||
IInstructionHandler[] handlers = new InstructionMetadata().GetHandlers(this.ParanoidMode, platformChanged, this.RewriteMods).ToArray();
|
||||
#endif
|
||||
RecursiveRewriter rewriter = new(
|
||||
module: module,
|
||||
rewriteModule: curModule =>
|
||||
{
|
||||
|
|
|
@ -21,7 +21,9 @@ namespace StardewModdingAPI.Framework.ModLoading
|
|||
public AssemblyLoadStatus Status;
|
||||
|
||||
/// <summary>Whether the <see cref="Definition"/> is loaded and ready (i.e. the <see cref="Status"/> is not <see cref="AssemblyLoadStatus.AlreadyLoaded"/> or <see cref="AssemblyLoadStatus.Failed"/>).</summary>
|
||||
// [MemberNotNullWhen(true, nameof(AssemblyParseResult.Definition))]
|
||||
#if !SMAPI_FOR_MOBILE
|
||||
[MemberNotNullWhen(true, nameof(AssemblyParseResult.Definition))]
|
||||
#endif
|
||||
public bool HasDefinition => this.Status == AssemblyLoadStatus.Okay;
|
||||
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ namespace StardewModdingAPI.Framework.ModLoading.Finders
|
|||
return false;
|
||||
}
|
||||
|
||||
#if SMAPI_FOR_MOBILE
|
||||
/*********
|
||||
** Protected methods
|
||||
*********/
|
||||
|
@ -75,5 +76,6 @@ namespace StardewModdingAPI.Framework.ModLoading.Finders
|
|||
&& fieldRef.DeclaringType.FullName == this.FullTypeName
|
||||
&& this.FieldNames.Contains(fieldRef.Name);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,7 +82,9 @@ namespace StardewModdingAPI.Framework.ModLoading
|
|||
public ModEntryModel? UpdateCheckData { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
// [MemberNotNullWhen(true, nameof(ModMetadata.ContentPack))]
|
||||
#if !SMAPI_FOR_MOBILE
|
||||
[MemberNotNullWhen(true, nameof(ModMetadata.ContentPack))]
|
||||
#endif
|
||||
[SuppressMessage("ReSharper", "ConditionalAccessQualifierIsNonNullableAccordingToAPIContract", Justification = "The manifest may be null for broken mods while loading.")]
|
||||
public bool IsContentPack => this.Manifest?.ContentPackFor != null;
|
||||
|
||||
|
@ -184,7 +186,9 @@ namespace StardewModdingAPI.Framework.ModLoading
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
// [MemberNotNullWhen(true, nameof(IModInfo.Manifest))]
|
||||
#if !SMAPI_FOR_MOBILE
|
||||
[MemberNotNullWhen(true, nameof(IModInfo.Manifest))]
|
||||
#endif
|
||||
public bool HasManifest()
|
||||
{
|
||||
return this.Manifest != null;
|
||||
|
|
|
@ -180,13 +180,16 @@ namespace StardewModdingAPI.Framework.ModLoading
|
|||
return mods
|
||||
.OrderBy(mod =>
|
||||
{
|
||||
string id = mod.Manifest.UniqueID;
|
||||
string? id = mod.Manifest?.UniqueID;
|
||||
|
||||
if (modIdsToLoadEarly.TryGetValue(id, out string? actualId))
|
||||
return -int.MaxValue + Array.IndexOf(earlyArray, actualId);
|
||||
if (id is not null)
|
||||
{
|
||||
if (modIdsToLoadEarly.TryGetValue(id, out string? actualId))
|
||||
return -int.MaxValue + Array.IndexOf(earlyArray, actualId);
|
||||
|
||||
if (modIdsToLoadLate.TryGetValue(id, out actualId))
|
||||
return int.MaxValue - Array.IndexOf(lateArray, actualId);
|
||||
if (modIdsToLoadLate.TryGetValue(id, out actualId))
|
||||
return int.MaxValue - Array.IndexOf(lateArray, actualId);
|
||||
}
|
||||
|
||||
return 0;
|
||||
})
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
|
||||
namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades;
|
||||
|
||||
public static class EnumMethods
|
||||
{
|
||||
public static string[] GetNames<TEnum>() where TEnum : struct, Enum
|
||||
{
|
||||
Type enumType = typeof(TEnum);
|
||||
return Enum.GetNames(enumType);
|
||||
}
|
||||
|
||||
public static bool IsDefined<TEnum>(TEnum value) where TEnum : struct, Enum
|
||||
{
|
||||
Type enumType = typeof(TEnum);
|
||||
return Enum.IsDefined(enumType, value);
|
||||
}
|
||||
}
|
|
@ -11,6 +11,15 @@ namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades
|
|||
{
|
||||
public class Game1Methods : Game1
|
||||
{
|
||||
|
||||
public static new IList<IClickableMenu> onScreenMenus => Game1.onScreenMenus;
|
||||
public static new RainDrop[] RainDropsProp => Game1.rainDrops.ToArray();
|
||||
|
||||
public static new IList<GameLocation> LocationsGetter()
|
||||
{
|
||||
return Game1.locations;
|
||||
}
|
||||
|
||||
#if SMAPI_LEGACY_PATCH
|
||||
public static RainDrop[] RainDropsProp => (typeof(RainManager).GetField("_rainDropList", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(RainManager.Instance) as List<RainDrop>).ToArray();
|
||||
|
||||
|
@ -35,8 +44,6 @@ namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades
|
|||
}
|
||||
|
||||
|
||||
public static new IList<IClickableMenu> onScreenMenus => Game1.onScreenMenus;
|
||||
|
||||
public static void updateDebrisWeatherForMovement(List<WeatherDebris> debris)
|
||||
{
|
||||
WeatherDebrisManager.Instance.UpdateDebrisWeatherForMovement();
|
||||
|
|
|
@ -37,10 +37,6 @@ namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades
|
|||
if (original != null)
|
||||
original = original.GetDeclaredMember();
|
||||
|
||||
#if SMAPI_FOR_MOBILE
|
||||
if (!Constants.HarmonyEnabled)
|
||||
return null;
|
||||
#endif
|
||||
// call Harmony 2.0 and show a detailed exception if it fails
|
||||
try
|
||||
{
|
||||
|
|
|
@ -16,11 +16,7 @@ namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades
|
|||
HarmonyMethod finalizer = null)
|
||||
{
|
||||
if (Constants.HarmonyEnabled)
|
||||
#if HARMONY_2
|
||||
return instance.Patch(original, prefix, postfix, transpiler, finalizer);
|
||||
#else
|
||||
return instance.Patch(original, prefix, postfix, transpiler);
|
||||
#endif
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using HarmonyLib;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using StardewValley.Menus;
|
||||
|
||||
namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades;
|
||||
|
||||
public class OptionsElementMethods
|
||||
{
|
||||
private static readonly ThreadLocal<int> _recursiveCounter = new(() => 0);
|
||||
private static readonly Dictionary<Type, MethodInfo?> MethodInfos = new();
|
||||
|
||||
public static void draw(OptionsElement instance, SpriteBatch b, int slotX, int slotY, IClickableMenu context = null)
|
||||
{
|
||||
if (instance.GetType().IsAssignableFrom(typeof(OptionsElement)))
|
||||
instance.draw(b, slotX, slotY);
|
||||
else
|
||||
{
|
||||
if (!MethodInfos.ContainsKey(instance.GetType())) OptionsElementMethods.MethodInfos[instance.GetType()] = AccessTools.Method(instance.GetType(), "draw", new[] { typeof(SpriteBatch), typeof(int), typeof(int), typeof(IClickableMenu) });
|
||||
MethodInfo? pcDraw = MethodInfos[instance.GetType()];
|
||||
if (pcDraw != null)
|
||||
{
|
||||
if (_recursiveCounter.Value == 0)
|
||||
{
|
||||
_recursiveCounter.Value++;
|
||||
try
|
||||
{
|
||||
pcDraw.Invoke(instance, new object[] { b, slotX, slotY, context });
|
||||
}
|
||||
finally
|
||||
{
|
||||
_recursiveCounter.Value--;
|
||||
}
|
||||
}
|
||||
else
|
||||
instance.draw(b, slotX, slotY);
|
||||
}
|
||||
else
|
||||
instance.draw(b, slotX, slotY);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
using System.Reflection;
|
||||
using HarmonyLib;
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
using StardewValley;
|
||||
|
||||
namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades;
|
||||
|
||||
public static class SoundBankMethods
|
||||
{
|
||||
public static void AddCue(this ISoundBank iSoundBank, CueDefinition cueDefinition)
|
||||
{
|
||||
if (iSoundBank is SoundBankWrapper soundBankWrapper)
|
||||
{
|
||||
SoundBank soundBank = (SoundBank)typeof(SoundBankWrapper)
|
||||
.GetField("soundBank", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
|
||||
?.GetValue(soundBankWrapper);
|
||||
soundBank?.AddCue(cueDefinition);
|
||||
}
|
||||
else
|
||||
AccessTools.Method(iSoundBank.GetType(), "AddCue", new[] { typeof(CueDefinition) })
|
||||
?.Invoke(iSoundBank, new[] { cueDefinition });
|
||||
}
|
||||
|
||||
public static CueDefinition GetCueDefinition(this ISoundBank iSoundBank, string name)
|
||||
{
|
||||
if (iSoundBank is SoundBankWrapper soundBankWrapper)
|
||||
{
|
||||
SoundBank soundBank = (SoundBank)typeof(SoundBankWrapper)
|
||||
.GetField("soundBank", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
|
||||
?.GetValue(soundBankWrapper);
|
||||
return soundBank?.GetCueDefinition(name);
|
||||
}
|
||||
|
||||
return (CueDefinition)AccessTools.Method(iSoundBank.GetType(), "GetCueDefinition", new[] { typeof(string) })
|
||||
?.Invoke(iSoundBank, new[] { name });
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ namespace StardewModdingAPI.Framework.ModLoading.Rewriters
|
|||
** Fields
|
||||
*********/
|
||||
/// <summary>The assembly names to which to rewrite broken references.</summary>
|
||||
private readonly HashSet<string> RewriteReferencesToAssemblies;
|
||||
private readonly ISet<string> RewriteReferencesToAssemblies;
|
||||
|
||||
|
||||
/*********
|
||||
|
@ -23,7 +23,7 @@ namespace StardewModdingAPI.Framework.ModLoading.Rewriters
|
|||
*********/
|
||||
/// <summary>Construct an instance.</summary>
|
||||
/// <param name="rewriteReferencesToAssemblies">The assembly names to which to rewrite broken references.</param>
|
||||
public HeuristicFieldAccessibilityRewriter(HashSet<string> rewriteReferencesToAssemblies)
|
||||
public HeuristicFieldAccessibilityRewriter(ISet<string> rewriteReferencesToAssemblies)
|
||||
: base(defaultPhrase: "field visibility changed to private") // ignored since we specify phrases
|
||||
{
|
||||
this.RewriteReferencesToAssemblies = rewriteReferencesToAssemblies;
|
||||
|
@ -164,9 +164,9 @@ namespace StardewModdingAPI.Framework.ModLoading.Rewriters
|
|||
instruction.Operand = fieldRef.DeclaringType;
|
||||
|
||||
this.Phrases.Add($"{fieldRef.DeclaringType.Name}.{fieldRef.Name} (field ref => reflection ref)");
|
||||
// #if SMAPI_FOR_MOBILE
|
||||
// this.Phrases.Add($"{cil.Body.Method.FullName} => {cil.Body.Instructions.Select(ins => ins.ToString()).Join(null, ";")}");
|
||||
// #endif
|
||||
#if SMAPI_FOR_MOBILE
|
||||
// this.Phrases.Add($"{cil.Body.Method.FullName} => {cil.Body.Instructions.Select(ins => ins.ToString()).Join(null, ";")}");
|
||||
#endif
|
||||
cil.Body.MaxStackSize += 5;
|
||||
return this.MarkRewritten();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using HarmonyLib;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using MonoMod.Utils;
|
||||
using StardewModdingAPI.Framework.ModLoading.Framework;
|
||||
|
||||
namespace StardewModdingAPI.Framework.ModLoading.Rewriters
|
||||
|
@ -31,7 +33,7 @@ namespace StardewModdingAPI.Framework.ModLoading.Rewriters
|
|||
/// <param name="toType">The type with methods to map to.</param>
|
||||
/// <param name="onlyIfPlatformChanged">Whether to only rewrite references if loading the assembly on a different platform than it was compiled on.</param>
|
||||
public MethodToAnotherStaticMethodRewriter(Type fromType, Predicate<MethodReference> fromMethodSelector, Type toType, string toMethod)
|
||||
: base( $"{fromType.Name} methods")
|
||||
: base($"{fromType.Name} methods")
|
||||
{
|
||||
this.FromType = fromType;
|
||||
this.FromMethodSelector = fromMethodSelector;
|
||||
|
@ -49,7 +51,14 @@ namespace StardewModdingAPI.Framework.ModLoading.Rewriters
|
|||
if (!this.IsMatch(instruction))
|
||||
return false;
|
||||
|
||||
instruction.Operand = module.ImportReference(this.ToType.GetMethod(this.ToMethod));
|
||||
MethodReference newReference = module.ImportReference(this.ToType.GetMethod(this.ToMethod));
|
||||
if (instruction.Operand is GenericInstanceMethod instructionOperand)
|
||||
{
|
||||
GenericInstanceMethod genericInstance = new(newReference);
|
||||
genericInstance.GenericArguments.AddRange(instructionOperand.GenericArguments);
|
||||
newReference = genericInstance;
|
||||
}
|
||||
instruction.Operand = newReference;
|
||||
return this.MarkRewritten();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
|
||||
namespace StardewModdingAPI.Framework.ModLoading.Rewriters
|
||||
{
|
||||
/// <summary>Rewrites all references to a type.</summary>
|
||||
internal class ModuleReferenceRewriter : IInstructionHandler
|
||||
{
|
||||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <inheritdoc />
|
||||
public string DefaultPhrase { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public ISet<InstructionHandleResult> Flags { get; } = new HashSet<InstructionHandleResult>();
|
||||
|
||||
/// <inheritdoc />
|
||||
public ISet<string> Phrases { get; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private readonly Dictionary<string, Version> AssemblyRules;
|
||||
|
||||
private readonly Dictionary<string, AssemblyNameReference> TargetMap = new();
|
||||
|
||||
|
||||
public ModuleReferenceRewriter(string phrase, Dictionary<string, Version> assemblyRules, Assembly[] assemblies)
|
||||
{
|
||||
this.DefaultPhrase = $"{phrase} assembly ref";
|
||||
this.AssemblyRules = assemblyRules;
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
AssemblyNameReference target = AssemblyNameReference.Parse(assembly.FullName);
|
||||
var map = assembly.GetTypes().ToDictionary(p => p.FullName, p => target);
|
||||
foreach (KeyValuePair<string, AssemblyNameReference> pair in map)
|
||||
{
|
||||
this.TargetMap.TryAdd(pair.Key, pair.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsMatch(AssemblyNameReference reference)
|
||||
{
|
||||
foreach ((string assemblyName, Version version) in this.AssemblyRules)
|
||||
{
|
||||
if (assemblyName.EndsWith('.'))
|
||||
{
|
||||
if (reference.Name.Equals(assemblyName) || reference.Name.StartsWith(assemblyName))
|
||||
return reference.Version.CompareTo(version) >= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (reference.Name.Equals(assemblyName))
|
||||
return reference.Version.CompareTo(version) >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsMatch(TypeReference reference)
|
||||
{
|
||||
foreach ((string assemblyName, Version _) in this.AssemblyRules)
|
||||
{
|
||||
if (assemblyName.EndsWith('.'))
|
||||
{
|
||||
if (reference.Scope.Name.Equals(assemblyName) || reference.Scope.Name.StartsWith(assemblyName))
|
||||
{
|
||||
return this.TargetMap.ContainsKey(reference.FullName.Split('/')[0]);
|
||||
}
|
||||
}
|
||||
else if(reference.Scope.Name.Equals(assemblyName))
|
||||
{
|
||||
return this.TargetMap.ContainsKey(reference.FullName.Split('/')[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool Handle(ModuleDefinition module)
|
||||
{
|
||||
if (!module.AssemblyReferences.Any(this.IsMatch))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// rewrite type scopes to use target assemblies
|
||||
IEnumerable<TypeReference> typeReferences = module.GetTypeReferences()
|
||||
.Where(this.IsMatch)
|
||||
.OrderBy(p => p.FullName);
|
||||
HashSet<string> assembliesAdded = new();
|
||||
foreach (TypeReference type in typeReferences)
|
||||
{
|
||||
AssemblyNameReference target = this.TargetMap[type.FullName.Split('/')[0]];
|
||||
// add target assembly references
|
||||
if (!module.AssemblyReferences.Contains(target) && !assembliesAdded.Contains(target.FullName))
|
||||
{
|
||||
module.AssemblyReferences.Add(target);
|
||||
assembliesAdded.Add(target.FullName);
|
||||
}
|
||||
|
||||
type.Scope = target;
|
||||
}
|
||||
|
||||
// rewrite types using custom attributes
|
||||
foreach (TypeDefinition type in module.GetTypes())
|
||||
{
|
||||
foreach (CustomAttribute attr in type.CustomAttributes)
|
||||
{
|
||||
foreach (CustomAttributeArgument conField in attr.ConstructorArguments)
|
||||
{
|
||||
if (conField.Value is TypeReference typeRef)
|
||||
if (this.TargetMap.ContainsKey(typeRef.FullName))
|
||||
{
|
||||
AssemblyNameReference target = this.TargetMap[type.FullName.Split('/')[0]];
|
||||
// add target assembly references
|
||||
if (!module.AssemblyReferences.Contains(target) && !assembliesAdded.Contains(target.FullName))
|
||||
{
|
||||
module.AssemblyReferences.Add(target);
|
||||
assembliesAdded.Add(target.FullName);
|
||||
}
|
||||
|
||||
type.Scope = target;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = module.AssemblyReferences.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (this.IsMatch(module.AssemblyReferences[i]))
|
||||
{
|
||||
module.AssemblyReferences.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
this.Flags.Add(InstructionHandleResult.Rewritten);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Handle(ModuleDefinition module, TypeReference type, Action<TypeReference> replaceWith)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool Handle(ModuleDefinition module, ILProcessor cil, Instruction instruction)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -52,14 +52,12 @@ namespace StardewModdingAPI.Framework.ModLoading.Rewriters
|
|||
if (this.GetterName != null && methodRef.Name == "get_" + this.PropertyName)
|
||||
{
|
||||
methodRef = module.ImportReference(this.ToType.GetMethod(this.GetterName));
|
||||
instruction.OpCode = OpCodes.Callvirt;
|
||||
instruction.Operand = methodRef;
|
||||
return true;
|
||||
}
|
||||
if(this.SetterName != null && methodRef.Name == "set_" + this.PropertyName)
|
||||
{
|
||||
methodRef = module.ImportReference(this.ToType.GetMethod(this.SetterName));
|
||||
instruction.OpCode = OpCodes.Callvirt;
|
||||
instruction.Operand = methodRef;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
#if SMAPI_FOR_MOBILE
|
||||
using System.Collections.Generic;
|
||||
#else
|
||||
using System.Runtime.Caching;
|
||||
#endif
|
||||
using StardewModdingAPI.Framework.Utilities;
|
||||
|
||||
namespace StardewModdingAPI.Framework.Reflection
|
||||
|
@ -17,15 +12,7 @@ namespace StardewModdingAPI.Framework.Reflection
|
|||
** Fields
|
||||
*********/
|
||||
/// <summary>The cached fields and methods found via reflection.</summary>
|
||||
#if SMAPI_FOR_MOBILE
|
||||
// private readonly Dictionary<string, CacheEntry> Cache = new Dictionary<string, CacheEntry>();
|
||||
private readonly IntervalMemoryCache<string, MemberInfo?> Cache = new();
|
||||
#else
|
||||
private readonly IntervalMemoryCache<string, MemberInfo?> Cache = new();
|
||||
#endif
|
||||
|
||||
/// <summary>The sliding cache expiration time.</summary>
|
||||
private readonly TimeSpan SlidingCacheExpiry = TimeSpan.FromMinutes(5);
|
||||
|
||||
|
||||
/*********
|
||||
|
@ -264,29 +251,8 @@ namespace StardewModdingAPI.Framework.Reflection
|
|||
private TMemberInfo? GetCached<TMemberInfo>(char memberType, Type type, string memberName, bool isStatic, Func<TMemberInfo?> fetch)
|
||||
where TMemberInfo : MemberInfo
|
||||
{
|
||||
// get from cache
|
||||
// #if SMAPI_FOR_MOBILE
|
||||
// if (this.Cache.ContainsKey(key))
|
||||
// #else
|
||||
// if (this.Cache.Contains(key))
|
||||
// #endif
|
||||
// {
|
||||
// CacheEntry entry = (CacheEntry)this.Cache[key];
|
||||
// return entry.IsValid
|
||||
// ? (TMemberInfo)entry.MemberInfo
|
||||
// : default;
|
||||
// }
|
||||
//
|
||||
// // fetch & cache new value
|
||||
// TMemberInfo result = fetch();
|
||||
// CacheEntry cacheEntry = new CacheEntry(result != null, result);
|
||||
#if SMAPI_FOR_MOBILE
|
||||
string key = $"{memberType}{(isStatic ? 's' : 'i')}{type.FullName}:{memberName}";
|
||||
return (TMemberInfo?)this.Cache.GetOrSet(key, fetch);
|
||||
#else
|
||||
string key = $"{memberType}{(isStatic ? 's' : 'i')}{type.FullName}:{memberName}";
|
||||
return (TMemberInfo?)this.Cache.GetOrSet(key, fetch);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,10 +11,6 @@ using System.Text;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Xna.Framework;
|
||||
#if SMAPI_FOR_MOBILE
|
||||
using System.Threading.Tasks;
|
||||
using Android.Widget;
|
||||
#endif
|
||||
#if SMAPI_FOR_WINDOWS
|
||||
using Microsoft.Win32;
|
||||
#endif
|
||||
|
@ -107,7 +103,6 @@ namespace StardewModdingAPI.Framework
|
|||
/// <summary>The underlying game instance.</summary>
|
||||
#if SMAPI_FOR_MOBILE
|
||||
internal SGameRunner Game = null!; // initialized very early
|
||||
// internal SGame Game;
|
||||
#else
|
||||
private SGameRunner Game = null!; // initialized very early
|
||||
#endif
|
||||
|
@ -294,6 +289,12 @@ namespace StardewModdingAPI.Framework
|
|||
MiniMonoModHotfix.Apply();
|
||||
HarmonyPatcher.Apply("SMAPI", this.Monitor,
|
||||
new Game1Patcher(this.Reflection, this.OnLoadStageChanged),
|
||||
#if SMAPI_FOR_MOBILE
|
||||
new StringPatcher(this.Reflection),
|
||||
new ThreadSilenceExitPatch(this.Monitor),
|
||||
new UIThreadPatch(this.Monitor),
|
||||
new SaveGamePatch(this.Translator, this.Monitor),
|
||||
#endif
|
||||
new TitleMenuPatcher(this.OnLoadStageChanged)
|
||||
);
|
||||
// new GamePatcher(this.Monitor).Apply(
|
||||
|
@ -347,8 +348,10 @@ namespace StardewModdingAPI.Framework
|
|||
{
|
||||
this.IsGameRunning = true;
|
||||
StardewValley.Program.releaseBuild = true; // game's debug logic interferes with SMAPI opening the game window
|
||||
#if !SMAPI_FOR_MOBILE
|
||||
this.Game.Run();
|
||||
this.Dispose(isError: false);
|
||||
#endif
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -356,12 +359,12 @@ namespace StardewModdingAPI.Framework
|
|||
this.LogManager.PressAnyKeyToExit();
|
||||
this.Dispose(isError: true);
|
||||
}
|
||||
#if !SMAPI_FOR_MOBILE
|
||||
finally
|
||||
{
|
||||
#if !SMAPI_FOR_MOBILE
|
||||
this.Dispose();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>Get the core logger and monitor on behalf of the game.</summary>
|
||||
|
@ -490,7 +493,7 @@ namespace StardewModdingAPI.Framework
|
|||
// apply load order customizations
|
||||
if (this.Settings.ModsToLoadEarly.Any() || this.Settings.ModsToLoadLate.Any())
|
||||
{
|
||||
HashSet<string> installedIds = new HashSet<string>(mods.Select(p => p.Manifest.UniqueID), StringComparer.OrdinalIgnoreCase);
|
||||
HashSet<string> installedIds = new HashSet<string>(mods.Select(p => p.Manifest?.UniqueID).Where(p => p is not null), StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
string[] missingEarlyMods = this.Settings.ModsToLoadEarly.Where(id => !installedIds.Contains(id)).OrderBy(p => p, StringComparer.OrdinalIgnoreCase).ToArray();
|
||||
string[] missingLateMods = this.Settings.ModsToLoadLate.Where(id => !installedIds.Contains(id)).OrderBy(p => p, StringComparer.OrdinalIgnoreCase).ToArray();
|
||||
|
@ -965,6 +968,9 @@ namespace StardewModdingAPI.Framework
|
|||
|
||||
this.Monitor.Log(context);
|
||||
|
||||
// add context to window titles
|
||||
this.UpdateWindowTitles();
|
||||
|
||||
// raise events
|
||||
this.OnLoadStageChanged(LoadStage.Ready);
|
||||
events.SaveLoaded.RaiseEmpty();
|
||||
|
@ -1352,6 +1358,7 @@ namespace StardewModdingAPI.Framework
|
|||
|
||||
case LoadStage.None:
|
||||
this.JustReturnedToTitle = true;
|
||||
this.UpdateWindowTitles();
|
||||
break;
|
||||
|
||||
case LoadStage.Loaded:
|
||||
|
@ -1603,15 +1610,14 @@ namespace StardewModdingAPI.Framework
|
|||
string consoleTitle = $"SMAPI {Constants.ApiVersion} - running Stardew Valley {Constants.GameVersion}";
|
||||
string gameTitle = $"Stardew Valley {Constants.GameVersion} - running SMAPI {Constants.ApiVersion}";
|
||||
|
||||
string suffix = "";
|
||||
if (this.ModRegistry.AreAllModsLoaded)
|
||||
{
|
||||
int modsLoaded = this.ModRegistry.GetAll().Count();
|
||||
consoleTitle += $" with {modsLoaded} mods";
|
||||
gameTitle += $" with {modsLoaded} mods";
|
||||
}
|
||||
suffix += $" with {this.ModRegistry.GetAll().Count()} mods";
|
||||
if (Context.IsMultiplayer)
|
||||
suffix += $" [{(Context.IsMainPlayer ? "main player" : "farmhand")}]";
|
||||
|
||||
this.Game.Window.Title = gameTitle;
|
||||
this.LogManager.SetConsoleTitle(consoleTitle);
|
||||
this.Game.Window.Title = gameTitle + suffix;
|
||||
this.LogManager.SetConsoleTitle(consoleTitle + suffix);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1664,6 +1670,7 @@ namespace StardewModdingAPI.Framework
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>Asynchronously check for a new version of SMAPI and any installed mods, and print alerts to the console if an update is available.</summary>
|
||||
/// <param name="mods">The mods to include in the update check (if eligible).</param>
|
||||
private async Task CheckForUpdatesAsync(IModMetadata[] mods)
|
||||
|
@ -2367,8 +2374,8 @@ namespace StardewModdingAPI.Framework
|
|||
errors.Add($"{file.Name} file couldn't be read"); // mainly happens when the file is corrupted or empty
|
||||
continue;
|
||||
}
|
||||
if(data != null)
|
||||
translations[locale] = data;
|
||||
|
||||
translations[locale] = data;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -65,6 +65,8 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
|
|||
field.OnArrayReplaced += this.OnArrayReplaced;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SMAPI_FOR_MOBILE
|
||||
private void hookField(int index, NetRef<TValue> field)
|
||||
{
|
||||
if (field == default)
|
||||
|
@ -81,6 +83,7 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
|
|||
this.hookField(index, array.Fields[index]);
|
||||
//this.innerArray.OnFieldCreate += new NetArray<TValue, NetRef<TValue>>.FieldCreateEvent(this.hookField);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Reset()
|
||||
|
|
|
@ -70,15 +70,8 @@ namespace StardewModdingAPI.Framework.StateTracking
|
|||
this.Location = location;
|
||||
|
||||
// init watchers
|
||||
this.BuildingsWatcher = location is BuildableGameLocation buildableLocation ?
|
||||
WatcherFactory.ForNetCollection($"{this.Name}.{nameof(buildableLocation.buildings)}", buildableLocation.buildings) :
|
||||
WatcherFactory.ForImmutableCollection<Building>();
|
||||
#if SMAPI_FOR_MOBILE
|
||||
// this.DebrisWatcher = WatcherFactory.ForNetCollection(location.debris.debrisNetCollection);
|
||||
this.BuildingsWatcher = location is BuildableGameLocation buildableLocation ? WatcherFactory.ForNetCollection($"{this.Name}.{nameof(buildableLocation.buildings)}", buildableLocation.buildings) : WatcherFactory.ForImmutableCollection<Building>();
|
||||
this.DebrisWatcher = WatcherFactory.ForNetCollection($"{this.Name}.{nameof(location.debris)}", location.debris);
|
||||
#else
|
||||
this.DebrisWatcher = WatcherFactory.ForNetCollection(location.debris);
|
||||
#endif
|
||||
this.LargeTerrainFeaturesWatcher = WatcherFactory.ForNetCollection($"{this.Name}.{nameof(location.largeTerrainFeatures)}", location.largeTerrainFeatures);
|
||||
this.NpcsWatcher = WatcherFactory.ForNetCollection($"{this.Name}.{nameof(location.characters)}", location.characters);
|
||||
this.ObjectsWatcher = WatcherFactory.ForNetDictionary($"{this.Name}.{nameof(location.netObjects)}", location.netObjects);
|
||||
|
|
|
@ -60,9 +60,15 @@ namespace StardewModdingAPI.Framework.StateTracking
|
|||
/// <param name="locations">The game's list of locations.</param>
|
||||
/// <param name="activeMineLocations">The game's list of active mine locations.</param>
|
||||
/// <param name="activeVolcanoLocations">The game's list of active volcano locations.</param>
|
||||
#if SMAPI_FOR_MOBILE
|
||||
public WorldLocationsTracker(IList<GameLocation> locations, IList<MineShaft> activeMineLocations, IList<VolcanoDungeon> activeVolcanoLocations)
|
||||
{
|
||||
this.LocationListWatcher = WatcherFactory.ForReferenceList($"{this.Name}.{nameof(locations)}", locations);
|
||||
#else
|
||||
public WorldLocationsTracker(ObservableCollection<GameLocation> locations, IList<MineShaft> activeMineLocations, IList<VolcanoDungeon> activeVolcanoLocations)
|
||||
{
|
||||
this.LocationListWatcher = WatcherFactory.ForObservableCollection($"{this.Name}.{nameof(locations)}", locations);
|
||||
#endif
|
||||
this.MineLocationListWatcher = WatcherFactory.ForReferenceList($"{this.Name}.{nameof(activeMineLocations)}", activeMineLocations);
|
||||
this.VolcanoLocationListWatcher = WatcherFactory.ForReferenceList($"{this.Name}.{nameof(activeVolcanoLocations)}", activeVolcanoLocations);
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue