Merge remote-tracking branch 'Pathoschild/stable' into android
# Conflicts: # src/SMAPI/Constants.cs # src/SMAPI/Framework/ContentManagers/ModContentManager.cs # src/SMAPI/SMAPI.csproj
This commit is contained in:
commit
fbfcf26ef5
|
@ -4,7 +4,7 @@
|
|||
|
||||
<!--set properties -->
|
||||
<PropertyGroup>
|
||||
<Version>3.3.2</Version>
|
||||
<Version>3.4.0</Version>
|
||||
<Product>SMAPI</Product>
|
||||
|
||||
<AssemblySearchPaths>$(AssemblySearchPaths);{GAC}</AssemblySearchPaths>
|
||||
|
|
|
@ -67,7 +67,7 @@ Chinese | ✓ [fully translated](../src/SMAPI/i18n/zh.json)
|
|||
French | ✓ [fully translated](../src/SMAPI/i18n/fr.json)
|
||||
German | ✓ [fully translated](../src/SMAPI/i18n/de.json)
|
||||
Hungarian | ✓ [fully translated](../src/SMAPI/i18n/hu.json)
|
||||
Italian | ❑ not translated
|
||||
Italian | ✓ [fully translated](../src/SMAPI/i18n/it.json)
|
||||
Japanese | ✓ [fully translated](../src/SMAPI/i18n/ja.json)
|
||||
Korean | ❑ not translated
|
||||
Portuguese | ✓ [fully translated](../src/SMAPI/i18n/pt.json)
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
← [README](README.md)
|
||||
|
||||
# Release notes
|
||||
## Upcoming release
|
||||
## 3.4
|
||||
Released 22 March 2020 for Stardew Valley 1.4.1 or later.
|
||||
|
||||
* For players:
|
||||
* Fixed semi-transparency issues on Linux/Mac in recent versions of Mono (e.g. pink shadows).
|
||||
* Fixed `player_add` command error if you have broken XNB mods.
|
||||
* Removed invalid-location check now handled by the game.
|
||||
* Updated translations. Thanks to Annosz (added Hungarian)!
|
||||
|
||||
* For modders:
|
||||
* Added support for flipped and rotated map tiles (in collaboration with Platonymous).
|
||||
* Added support for `.tmx` maps using zlib compression (thanks to Platonymous!).
|
||||
* Mods are no longer prevented from suppressing key presses in the chatbox. Use this power wisely.
|
||||
* Added `this.Monitor.LogOnce` method.
|
||||
* Mods are no longer prevented from suppressing key presses in the chatbox.
|
||||
|
||||
* For the web UI:
|
||||
* Added option to upload files using a file picker.
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
using StardewModdingAPI.Mods.ConsoleCommands.Framework.ItemData;
|
||||
using StardewValley;
|
||||
using StardewValley.Menus;
|
||||
|
@ -59,13 +60,13 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework
|
|||
yield return this.TryCreate(ItemType.Flooring, id, () => new Wallpaper(id, isFloor: true) { Category = SObject.furnitureCategory });
|
||||
|
||||
// equipment
|
||||
foreach (int id in Game1.content.Load<Dictionary<int, string>>("Data\\Boots").Keys)
|
||||
foreach (int id in this.TryLoad<int, string>("Data\\Boots").Keys)
|
||||
yield return this.TryCreate(ItemType.Boots, id, () => new Boots(id));
|
||||
foreach (int id in Game1.content.Load<Dictionary<int, string>>("Data\\hats").Keys)
|
||||
foreach (int id in this.TryLoad<int, string>("Data\\hats").Keys)
|
||||
yield return this.TryCreate(ItemType.Hat, id, () => new Hat(id));
|
||||
|
||||
// weapons
|
||||
foreach (int id in Game1.content.Load<Dictionary<int, string>>("Data\\weapons").Keys)
|
||||
foreach (int id in this.TryLoad<int, string>("Data\\weapons").Keys)
|
||||
{
|
||||
yield return this.TryCreate(ItemType.Weapon, id, () => (id >= 32 && id <= 34)
|
||||
? (Item)new Slingshot(id)
|
||||
|
@ -74,7 +75,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework
|
|||
}
|
||||
|
||||
// furniture
|
||||
foreach (int id in Game1.content.Load<Dictionary<int, string>>("Data\\Furniture").Keys)
|
||||
foreach (int id in this.TryLoad<int, string>("Data\\Furniture").Keys)
|
||||
{
|
||||
if (id == 1466 || id == 1468)
|
||||
yield return this.TryCreate(ItemType.Furniture, id, () => new TV(id, Vector2.Zero));
|
||||
|
@ -94,7 +95,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework
|
|||
// secret notes
|
||||
if (id == 79)
|
||||
{
|
||||
foreach (int secretNoteId in Game1.content.Load<Dictionary<int, string>>("Data\\SecretNotes").Keys)
|
||||
foreach (int secretNoteId in this.TryLoad<int, string>("Data\\SecretNotes").Keys)
|
||||
{
|
||||
yield return this.TryCreate(ItemType.Object, this.CustomIDOffset + secretNoteId, () =>
|
||||
{
|
||||
|
@ -233,6 +234,23 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework
|
|||
/*********
|
||||
** Private methods
|
||||
*********/
|
||||
/// <summary>Try to load a data file, and return empty data if it's invalid.</summary>
|
||||
/// <typeparam name="TKey">The asset key type.</typeparam>
|
||||
/// <typeparam name="TValue">The asset value type.</typeparam>
|
||||
/// <param name="assetName">The data asset name.</param>
|
||||
private Dictionary<TKey, TValue> TryLoad<TKey, TValue>(string assetName)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Game1.content.Load<Dictionary<TKey, TValue>>(assetName);
|
||||
}
|
||||
catch (ContentLoadException)
|
||||
{
|
||||
// generally due to a player incorrectly replacing a data file with an XNB mod
|
||||
return new Dictionary<TKey, TValue>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Create a searchable item if valid.</summary>
|
||||
/// <param name="type">The item type.</param>
|
||||
/// <param name="id">The unique ID (if different from the item's parent sheet index).</param>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"Name": "Console Commands",
|
||||
"Author": "SMAPI",
|
||||
"Version": "3.3.2",
|
||||
"Version": "3.4.0",
|
||||
"Description": "Adds SMAPI console commands that let you manipulate the game.",
|
||||
"UniqueID": "SMAPI.ConsoleCommands",
|
||||
"EntryDll": "ConsoleCommands.dll",
|
||||
"MinimumApiVersion": "3.3.2"
|
||||
"MinimumApiVersion": "3.4.0"
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"Name": "Save Backup",
|
||||
"Author": "SMAPI",
|
||||
"Version": "3.3.2",
|
||||
"Version": "3.4.0",
|
||||
"Description": "Automatically backs up all your saves once per day into its folder.",
|
||||
"UniqueID": "SMAPI.SaveBackup",
|
||||
"EntryDll": "SaveBackup.dll",
|
||||
"MinimumApiVersion": "3.3.2"
|
||||
"MinimumApiVersion": "3.4.0"
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.21" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.23" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="Pathoschild.Http.FluentClient" Version="3.3.1" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -12,14 +12,14 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.Storage.Blobs" Version="12.3.0" />
|
||||
<PackageReference Include="Azure.Storage.Blobs" Version="12.4.0" />
|
||||
<PackageReference Include="Hangfire.AspNetCore" Version="1.7.9" />
|
||||
<PackageReference Include="Hangfire.MemoryStorage" Version="1.7.0" />
|
||||
<PackageReference Include="Hangfire.Mongo" Version="0.6.6" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.21" />
|
||||
<PackageReference Include="Hangfire.Mongo" Version="0.6.7" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.23" />
|
||||
<PackageReference Include="Humanizer.Core" Version="2.7.9" />
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2019.1.3" />
|
||||
<PackageReference Include="Markdig" Version="0.18.1" />
|
||||
<PackageReference Include="Markdig" Version="0.18.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Rewrite" Version="2.2.0" />
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace StardewModdingAPI
|
|||
** Public
|
||||
****/
|
||||
/// <summary>SMAPI's current semantic version.</summary>
|
||||
public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion("3.3.2.4", allowNonStandard: true);
|
||||
public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion("3.4.0");
|
||||
|
||||
/// <summary>The minimum supported version of Stardew Valley.</summary>
|
||||
public static ISemanticVersion MinimumGameVersion { get; } = new GameVersion("1.4.5");
|
||||
|
@ -53,7 +53,7 @@ namespace StardewModdingAPI
|
|||
** Internal
|
||||
****/
|
||||
/// <summary>The URL of the SMAPI home page.</summary>
|
||||
internal const string HomePageUrl = "https://github.com/MartyrPher/SMAPI-Android-Installer/releases/latest";
|
||||
internal const string HomePageUrl = "https://smapi.io";
|
||||
|
||||
/// <summary>The default performance counter name for unknown event handlers.</summary>
|
||||
internal const string GamePerformanceCounterName = "<StardewValley>";
|
||||
|
|
|
@ -247,13 +247,6 @@ namespace StardewModdingAPI.Framework.ContentManagers
|
|||
/// <remarks>Based on <a href="https://gamedev.stackexchange.com/a/26037">code by David Gouveia</a>.</remarks>
|
||||
private Texture2D PremultiplyTransparency(Texture2D texture)
|
||||
{
|
||||
// Textures loaded by Texture2D.FromStream are already premultiplied on Linux/Mac, even
|
||||
// though the XNA documentation explicitly says otherwise. That's a glitch in MonoGame
|
||||
// fixed in newer versions, but the game uses a bundled version that will always be
|
||||
// affected. See https://github.com/MonoGame/MonoGame/issues/4820 for more info.
|
||||
if (Constants.TargetPlatform != GamePlatform.Windows && Constants.TargetPlatform != GamePlatform.Android)
|
||||
return texture;
|
||||
|
||||
// premultiply pixels
|
||||
Color[] data = new Color[texture.Width * texture.Height];
|
||||
texture.GetData(data);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using StardewModdingAPI.Framework.Logging;
|
||||
using StardewModdingAPI.Internal.ConsoleWriting;
|
||||
|
@ -26,6 +27,9 @@ namespace StardewModdingAPI.Framework
|
|||
/// <summary>The maximum length of the <see cref="LogLevel"/> values.</summary>
|
||||
private static readonly int MaxLevelLength = (from level in Enum.GetValues(typeof(LogLevel)).Cast<LogLevel>() select level.ToString().Length).Max();
|
||||
|
||||
/// <summary>A cache of messages that should only be logged once.</summary>
|
||||
private readonly HashSet<string> LogOnceCache = new HashSet<string>();
|
||||
|
||||
|
||||
/*********
|
||||
** Accessors
|
||||
|
@ -74,6 +78,15 @@ namespace StardewModdingAPI.Framework
|
|||
this.LogImpl(this.Source, message, (ConsoleLogLevel)level);
|
||||
}
|
||||
|
||||
/// <summary>Log a message for the player or developer, but only if it hasn't already been logged since the last game launch.</summary>
|
||||
/// <param name="message">The message to log.</param>
|
||||
/// <param name="level">The log severity level.</param>
|
||||
public void LogOnce(string message, LogLevel level = LogLevel.Trace)
|
||||
{
|
||||
if (this.LogOnceCache.Add($"{message}|{level}"))
|
||||
this.LogImpl(this.Source, message, (ConsoleLogLevel)level);
|
||||
}
|
||||
|
||||
/// <summary>Log a message that only appears when <see cref="IMonitor.IsVerbose"/> is enabled.</summary>
|
||||
/// <param name="message">The message to log.</param>
|
||||
public void VerboseLog(string message)
|
||||
|
|
|
@ -209,7 +209,7 @@ namespace StardewModdingAPI.Framework
|
|||
protected override void LoadContent()
|
||||
{
|
||||
base.LoadContent();
|
||||
//Game1.mapDisplayDevice = new SDisplayDevice(Game1.content, this.GraphicsDevice);
|
||||
Game1.mapDisplayDevice = new SDisplayDevice(Game1.content, this.GraphicsDevice);
|
||||
}
|
||||
|
||||
/// <summary>Initialize just before the game's first update tick.</summary>
|
||||
|
@ -307,8 +307,8 @@ namespace StardewModdingAPI.Framework
|
|||
{
|
||||
this.Multiplayer.CleanupOnMultiplayerExit();
|
||||
|
||||
//if (!(Game1.mapDisplayDevice is SDisplayDevice))
|
||||
// Game1.mapDisplayDevice = new SDisplayDevice(Game1.content, this.GraphicsDevice);
|
||||
if (!(Game1.mapDisplayDevice is SDisplayDevice))
|
||||
Game1.mapDisplayDevice = new SDisplayDevice(Game1.content, this.GraphicsDevice);
|
||||
}
|
||||
|
||||
/// <summary>Constructor a content manager to read XNB files.</summary>
|
||||
|
|
|
@ -18,6 +18,11 @@ namespace StardewModdingAPI
|
|||
/// <param name="level">The log severity level.</param>
|
||||
void Log(string message, LogLevel level = LogLevel.Trace);
|
||||
|
||||
/// <summary>Log a message for the player or developer, but only if it hasn't already been logged since the last game launch.</summary>
|
||||
/// <param name="message">The message to log.</param>
|
||||
/// <param name="level">The log severity level.</param>
|
||||
void LogOnce(string message, LogLevel level = LogLevel.Trace);
|
||||
|
||||
/// <summary>Log a message that only appears when <see cref="IsVerbose"/> is enabled.</summary>
|
||||
/// <param name="message">The message to log.</param>
|
||||
void VerboseLog(string message);
|
||||
|
|
|
@ -67,8 +67,7 @@ namespace StardewModdingAPI.Patches
|
|||
private static bool Before_SaveGame_LoadDataToLocations(List<GameLocation> gamelocations)
|
||||
{
|
||||
bool removedAny =
|
||||
LoadErrorPatch.RemoveInvalidLocations(gamelocations)
|
||||
| LoadErrorPatch.RemoveBrokenBuildings(gamelocations)
|
||||
LoadErrorPatch.RemoveBrokenBuildings(gamelocations)
|
||||
| LoadErrorPatch.RemoveInvalidNpcs(gamelocations);
|
||||
|
||||
if (removedAny)
|
||||
|
@ -77,28 +76,6 @@ namespace StardewModdingAPI.Patches
|
|||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Remove locations which don't exist in-game.</summary>
|
||||
/// <param name="locations">The current game locations.</param>
|
||||
private static bool RemoveInvalidLocations(List<GameLocation> locations)
|
||||
{
|
||||
bool removedAny = false;
|
||||
|
||||
foreach (GameLocation location in locations.ToArray())
|
||||
{
|
||||
if (location is Cellar)
|
||||
continue; // missing cellars will be added by the game code
|
||||
|
||||
if (Game1.getLocationFromName(location.name) == null)
|
||||
{
|
||||
LoadErrorPatch.Monitor.Log($"Removed invalid location '{location.Name}' to avoid a crash when loading save '{Constants.SaveFolderName}'. (Did you remove a custom location mod?)", LogLevel.Warn);
|
||||
locations.Remove(location);
|
||||
removedAny = true;
|
||||
}
|
||||
}
|
||||
|
||||
return removedAny;
|
||||
}
|
||||
|
||||
/// <summary>Remove buildings which don't exist in the game data.</summary>
|
||||
/// <param name="locations">The current game locations.</param>
|
||||
private static bool RemoveBrokenBuildings(IEnumerable<GameLocation> locations)
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<DebugType>portable</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG;ANDROID_TARGET_SAMSUNG</DefineConstants>
|
||||
<DefineConstants>TRACE;DEBUG</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<LangVersion>latest</LangVersion>
|
||||
|
|
Loading…
Reference in New Issue