Merge branch 'master'
This commit is contained in:
commit
c73c1a0ec7
|
@ -6,6 +6,7 @@ TrainerMod/obj/
|
|||
StardewInjector/bin/
|
||||
StardewInjector/obj/
|
||||
packages/
|
||||
steamapps/
|
||||
|
||||
*.symlink
|
||||
*.lnk
|
||||
|
|
|
@ -4,10 +4,9 @@
|
|||
|
||||
SMAPI (Stardew Mapping Application Programming Interface) is a tool to help modders make changes to Stardew. It is a standalone executable which goes alongside your Stardew.exe.
|
||||
|
||||
## Latest Version: 0.37.3
|
||||
- Small performance patch
|
||||
|
||||
Download: https://github.com/ClxS/SMAPI/releases/tag/0.37.3
|
||||
## Latest Version: 0.38.4
|
||||
- Support for new mod layout to help keep some level of order (note: old way of loading mods will soon be removed! please update your mods!)
|
||||
- Inbuilt support for configuration files
|
||||
|
||||
## Installation
|
||||
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
Copyright 2016 Zoey (Zoryn)
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace StardewModdingAPI
|
||||
{
|
||||
public class Config
|
||||
{
|
||||
[JsonIgnore]
|
||||
public virtual JObject JObject { get; protected set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public virtual string ConfigLocation { get; protected set; }
|
||||
|
||||
public static Config Instance
|
||||
{
|
||||
get { return new Config(); }
|
||||
}
|
||||
|
||||
public static Config InitializeConfig(string configLocation, Config baseConfig)
|
||||
{
|
||||
if (baseConfig == null)
|
||||
{
|
||||
Console.WriteLine("A config must be instantiated before being passed to Initialize.\n\t" + configLocation);
|
||||
return null;
|
||||
}
|
||||
|
||||
baseConfig.ConfigLocation = configLocation;
|
||||
return baseConfig.LoadConfig(baseConfig);
|
||||
}
|
||||
|
||||
public virtual Config GenerateBaseConfig(Config baseConfig)
|
||||
{
|
||||
//Must be implemented in sub-class
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual Config LoadConfig(Config baseConfig)
|
||||
{
|
||||
if (!File.Exists(baseConfig.ConfigLocation))
|
||||
{
|
||||
var v = (Config)baseConfig.GetType().GetMethod("GenerateBaseConfig", BindingFlags.Public | BindingFlags.Instance).Invoke(baseConfig, new object[] { baseConfig });
|
||||
v.WriteConfig();
|
||||
}
|
||||
else
|
||||
{
|
||||
var p = baseConfig.ConfigLocation;
|
||||
|
||||
try
|
||||
{
|
||||
var j = JObject.Parse(Encoding.UTF8.GetString(File.ReadAllBytes(baseConfig.ConfigLocation)));
|
||||
baseConfig = (Config)j.ToObject(baseConfig.GetType());
|
||||
baseConfig.ConfigLocation = p;
|
||||
baseConfig.JObject = j;
|
||||
|
||||
baseConfig = UpdateConfig(baseConfig);
|
||||
baseConfig.ConfigLocation = p;
|
||||
baseConfig.JObject = j;
|
||||
|
||||
baseConfig.WriteConfig();
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("Invalid JSON Renamed: " + p);
|
||||
if (File.Exists(p))
|
||||
File.Move(p, Path.Combine(Path.GetDirectoryName(p), Path.GetFileNameWithoutExtension(p) + "." + Guid.NewGuid() + ".json")); //Get it out of the way for a new one
|
||||
var v = (Config)baseConfig.GetType().GetMethod("GenerateBaseConfig", BindingFlags.Public | BindingFlags.Instance).Invoke(baseConfig, new object[] { baseConfig });
|
||||
v.WriteConfig();
|
||||
}
|
||||
}
|
||||
|
||||
return baseConfig;
|
||||
}
|
||||
|
||||
public virtual Config UpdateConfig(Config baseConfig)
|
||||
{
|
||||
try
|
||||
{
|
||||
//default config with all standard values
|
||||
var b = JObject.FromObject(baseConfig.GetType().GetMethod("GenerateBaseConfig", BindingFlags.Public | BindingFlags.Instance).Invoke(baseConfig, new object[] { baseConfig }));
|
||||
//user config with their values
|
||||
var u = baseConfig.JObject;
|
||||
|
||||
b.Merge(u);
|
||||
|
||||
return (Config)b.ToObject(baseConfig.GetType());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.ToString());
|
||||
}
|
||||
return baseConfig;
|
||||
}
|
||||
|
||||
public static string GetBasePath(Mod theMod)
|
||||
{
|
||||
return theMod.PathOnDisk + "\\config.json";
|
||||
}
|
||||
}
|
||||
|
||||
public static class ConfigExtensions
|
||||
{
|
||||
public static void WriteConfig(this Config baseConfig)
|
||||
{
|
||||
var toWrite = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(baseConfig, baseConfig.GetType(), Formatting.Indented, new JsonSerializerSettings()));
|
||||
if (!File.Exists(baseConfig.ConfigLocation) || !File.ReadAllBytes(baseConfig.ConfigLocation).SequenceEqual(toWrite))
|
||||
File.WriteAllBytes(baseConfig.ConfigLocation, toWrite);
|
||||
toWrite = null;
|
||||
}
|
||||
|
||||
public static Config ReloadConfig(this Config baseConfig)
|
||||
{
|
||||
return baseConfig.UpdateConfig(baseConfig);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,9 +33,9 @@ namespace StardewModdingAPI
|
|||
|
||||
public const int MajorVersion = 0;
|
||||
|
||||
public const int MinorVersion = 37;
|
||||
public const int MinorVersion = 38;
|
||||
|
||||
public const int PatchVersion = 2;
|
||||
public const int PatchVersion = 4;
|
||||
|
||||
public const string Build = "Alpha";
|
||||
|
||||
|
|
|
@ -11,7 +11,35 @@ namespace StardewModdingAPI.Events
|
|||
public static event EventHandler GameLoaded = delegate { };
|
||||
public static event EventHandler Initialize = delegate { };
|
||||
public static event EventHandler LoadContent = delegate { };
|
||||
public static event EventHandler FirstUpdateTick = delegate { };
|
||||
/// <summary>
|
||||
/// Fires every update (1/60 of a second)
|
||||
/// </summary>
|
||||
public static event EventHandler UpdateTick = delegate { };
|
||||
/// <summary>
|
||||
/// Fires every other update (1/30 of a second)
|
||||
/// </summary>
|
||||
public static event EventHandler SecondUpdateTick = delegate { };
|
||||
/// <summary>
|
||||
/// Fires every fourth update (1/15 of a second)
|
||||
/// </summary>
|
||||
public static event EventHandler FourthUpdateTick = delegate { };
|
||||
/// <summary>
|
||||
/// Fires every eighth update (roughly 1/8 of a second)
|
||||
/// </summary>
|
||||
public static event EventHandler EighthUpdateTick = delegate { };
|
||||
/// <summary>
|
||||
/// Fires every fifthteenth update (1/4 of a second)
|
||||
/// </summary>
|
||||
public static event EventHandler QuarterSecondTick = delegate { };
|
||||
/// <summary>
|
||||
/// Fires every thirtieth update (1/2 of a second)
|
||||
/// </summary>
|
||||
public static event EventHandler HalfSecondTick = delegate { };
|
||||
/// <summary>
|
||||
/// Fires every sixtieth update (a second)
|
||||
/// </summary>
|
||||
public static event EventHandler OneSecondTick = delegate { };
|
||||
|
||||
public static void InvokeGameLoaded()
|
||||
{
|
||||
|
@ -53,5 +81,40 @@ namespace StardewModdingAPI.Events
|
|||
Log.Error("An exception occured in XNA UpdateTick: " + ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public static void InvokeSecondUpdateTick()
|
||||
{
|
||||
SecondUpdateTick.Invoke(null, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public static void InvokeFourthUpdateTick()
|
||||
{
|
||||
FourthUpdateTick.Invoke(null, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public static void InvokeEighthUpdateTick()
|
||||
{
|
||||
EighthUpdateTick.Invoke(null, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public static void InvokeQuarterSecondTick()
|
||||
{
|
||||
QuarterSecondTick.Invoke(null, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public static void InvokeHalfSecondTick()
|
||||
{
|
||||
HalfSecondTick.Invoke(null, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public static void InvokeOneSecondTick()
|
||||
{
|
||||
OneSecondTick.Invoke(null, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public static void InvokeFirstUpdateTick()
|
||||
{
|
||||
FirstUpdateTick.Invoke(null, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
@ -60,5 +61,41 @@ namespace StardewModdingAPI
|
|||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
public static T Cast<T>(this object o) where T : class
|
||||
{
|
||||
return o as T;
|
||||
}
|
||||
|
||||
public static FieldInfo[] GetPrivateFields(this object o)
|
||||
{
|
||||
return o.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
public static FieldInfo GetBaseFieldInfo(this Type t, string name)
|
||||
{
|
||||
return t.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
public static T GetBaseFieldValue<T>(this Type t, object o, string name) where T : class
|
||||
{
|
||||
return t.GetBaseFieldInfo(name).GetValue(o) as T;
|
||||
}
|
||||
|
||||
/*
|
||||
public static T GetBaseFieldValue<T>(this object o, string name) where T : class
|
||||
{
|
||||
return o.GetType().GetBaseFieldInfo(name).GetValue(o) as T;
|
||||
}*/
|
||||
|
||||
public static object GetBaseFieldValue(this object o, string name)
|
||||
{
|
||||
return o.GetType().GetBaseFieldInfo(name).GetValue(o);
|
||||
}
|
||||
|
||||
public static void SetBaseFieldValue (this object o, string name, object newValue)
|
||||
{
|
||||
o.GetType().GetBaseFieldInfo(name).SetValue(o, newValue);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Weavers>
|
||||
<Costura/>
|
||||
|
||||
</Weavers>
|
|
@ -173,6 +173,15 @@ namespace StardewModdingAPI.Inheritance
|
|||
|
||||
public Farmer PreviousFarmer { get; private set; }
|
||||
|
||||
public Int32 CurrentUpdateTick { get; private set; }
|
||||
public bool FirstUpdate { get; private set; }
|
||||
|
||||
public RenderTarget2D Screen
|
||||
{
|
||||
get { return typeof (Game1).GetBaseFieldValue<RenderTarget2D>(Program.gamePtr, "screen"); }
|
||||
set { typeof (Game1).SetBaseFieldValue("screen", value); }
|
||||
}
|
||||
|
||||
private static SGame instance;
|
||||
public static SGame Instance { get { return instance; } }
|
||||
|
||||
|
@ -181,7 +190,9 @@ namespace StardewModdingAPI.Inheritance
|
|||
public SGame()
|
||||
{
|
||||
instance = this;
|
||||
FirstUpdate = true;
|
||||
|
||||
/*
|
||||
#if DEBUG
|
||||
SaveGame.serializer = new XmlSerializer(typeof (SaveGame), new Type[28]
|
||||
{
|
||||
|
@ -215,6 +226,7 @@ namespace StardewModdingAPI.Inheritance
|
|||
typeof (SObject)
|
||||
});
|
||||
#endif
|
||||
*/
|
||||
}
|
||||
|
||||
protected override void Initialize()
|
||||
|
@ -251,6 +263,33 @@ namespace StardewModdingAPI.Inheritance
|
|||
}
|
||||
|
||||
Events.GameEvents.InvokeUpdateTick();
|
||||
if (FirstUpdate)
|
||||
{
|
||||
GameEvents.InvokeFirstUpdateTick();
|
||||
FirstUpdate = false;
|
||||
}
|
||||
|
||||
if (CurrentUpdateTick % 2 == 0)
|
||||
Events.GameEvents.InvokeSecondUpdateTick();
|
||||
|
||||
if (CurrentUpdateTick % 4 == 0)
|
||||
Events.GameEvents.InvokeFourthUpdateTick();
|
||||
|
||||
if (CurrentUpdateTick % 8 == 0)
|
||||
Events.GameEvents.InvokeEighthUpdateTick();
|
||||
|
||||
if (CurrentUpdateTick % 15 == 0)
|
||||
Events.GameEvents.InvokeQuarterSecondTick();
|
||||
|
||||
if (CurrentUpdateTick % 30 == 0)
|
||||
Events.GameEvents.InvokeHalfSecondTick();
|
||||
|
||||
if (CurrentUpdateTick % 60 == 0)
|
||||
Events.GameEvents.InvokeOneSecondTick();
|
||||
|
||||
CurrentUpdateTick += 1;
|
||||
if (CurrentUpdateTick >= 60)
|
||||
CurrentUpdateTick = 0;
|
||||
|
||||
PreviouslyPressedKeys = CurrentlyPressedKeys;
|
||||
for(PlayerIndex i = PlayerIndex.One; i <= PlayerIndex.Four; i++)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
|
@ -28,7 +29,7 @@ namespace StardewModdingAPI
|
|||
catch (Exception)
|
||||
{
|
||||
// TODO: not use general exception
|
||||
Log.Error("Could not initialize LogStream - Logging is disabled");
|
||||
Error("Could not initialize LogStream - Logging is disabled");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,11 +37,11 @@ namespace StardewModdingAPI
|
|||
/// Print provided parameters to the console/file as applicable
|
||||
/// </summary>
|
||||
/// <param name="message">Desired message</param>
|
||||
/// <param name="suppressMessage">When true, writes to ONLY console and not the log file.</param>
|
||||
/// <param name="disableLogging">When true, writes to ONLY console and not the log file.</param>
|
||||
/// <param name="values">Additional params to be added to the message</param>
|
||||
private static void PrintLog(object message, bool disableLogging, params object[] values)
|
||||
{
|
||||
string logOutput = string.Format("[{0}] {1}", System.DateTime.Now.ToLongTimeString(), String.Format(message.ToString(), values));
|
||||
string logOutput = $"[{DateTime.Now.ToLongTimeString()}] {string.Format(message.ToString(), values)}";
|
||||
Console.WriteLine(logOutput);
|
||||
|
||||
if (_logStream != null && !disableLogging)
|
||||
|
@ -58,7 +59,7 @@ namespace StardewModdingAPI
|
|||
public static void Success(object message, params object[] values)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
Log.PrintLog(message?.ToString(), false, values);
|
||||
PrintLog(message?.ToString(), false, values);
|
||||
Console.ForegroundColor = ConsoleColor.Gray;
|
||||
}
|
||||
|
||||
|
@ -69,7 +70,9 @@ namespace StardewModdingAPI
|
|||
/// <param name="values"></param>
|
||||
public static void Verbose(object message, params object[] values)
|
||||
{
|
||||
Log.PrintLog(message?.ToString(), false, values);
|
||||
Console.ForegroundColor = ConsoleColor.Gray;
|
||||
PrintLog(message?.ToString(), false, values);
|
||||
Console.ForegroundColor = ConsoleColor.Gray;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -80,7 +83,7 @@ namespace StardewModdingAPI
|
|||
public static void Comment(object message, params object[] values)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
Log.PrintLog(message?.ToString(), false, values);
|
||||
PrintLog(message?.ToString(), false, values);
|
||||
Console.ForegroundColor = ConsoleColor.Gray;
|
||||
}
|
||||
|
||||
|
@ -91,7 +94,9 @@ namespace StardewModdingAPI
|
|||
/// <param name="values"></param>
|
||||
public static void Info(object message, params object[] values)
|
||||
{
|
||||
Log.PrintLog(message.ToString(), true, values);
|
||||
Console.ForegroundColor = ConsoleColor.Gray;
|
||||
PrintLog(message?.ToString(), true, values);
|
||||
Console.ForegroundColor = ConsoleColor.Gray;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -102,7 +107,7 @@ namespace StardewModdingAPI
|
|||
public static void Error(object message, params object[] values)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Log.PrintLog(message.ToString(), false, values);
|
||||
PrintLog(message?.ToString(), false, values);
|
||||
Console.ForegroundColor = ConsoleColor.Gray;
|
||||
}
|
||||
|
||||
|
@ -127,7 +132,7 @@ namespace StardewModdingAPI
|
|||
public static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||
{
|
||||
Console.WriteLine("An exception has been caught");
|
||||
File.WriteAllText(_logPath + "\\MODDED_ErrorLog.Log_" + Extensions.Random.Next(100000000, 999999999) + ".txt", e.ExceptionObject.ToString());
|
||||
File.WriteAllText(_logPath + "\\MODDED_ErrorLog.Log_" + DateTime.UtcNow.Ticks + ".txt", e.ExceptionObject.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StardewModdingAPI
|
||||
{
|
||||
public class Manifest
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of your mod.
|
||||
/// </summary>
|
||||
public virtual string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the mod's authour.
|
||||
/// </summary>
|
||||
public virtual string Authour { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The version of the mod.
|
||||
/// </summary>
|
||||
public virtual string Version { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A description of the mod.
|
||||
/// </summary>
|
||||
public virtual string Description { get; set; }
|
||||
|
||||
public string EntryDll { get; set; }
|
||||
}
|
||||
}
|
|
@ -10,23 +10,42 @@ namespace StardewModdingAPI
|
|||
{
|
||||
/// <summary>
|
||||
/// The name of your mod.
|
||||
/// NOTE: THIS IS DEPRECATED AND WILL BE REMOVED IN THE NEXT VERSION OF SMAPI
|
||||
/// </summary>
|
||||
public virtual string Name { get; protected set; }
|
||||
[Obsolete]
|
||||
public virtual string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the mod's authour.
|
||||
/// NOTE: THIS IS DEPRECATED AND WILL BE REMOVED IN THE NEXT VERSION OF SMAPI
|
||||
/// </summary>
|
||||
public virtual string Authour { get; protected set; }
|
||||
[Obsolete]
|
||||
public virtual string Authour { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The version of the mod.
|
||||
/// NOTE: THIS IS DEPRECATED AND WILL BE REMOVED IN THE NEXT VERSION OF SMAPI
|
||||
/// </summary>
|
||||
public virtual string Version { get; protected set; }
|
||||
[Obsolete]
|
||||
public virtual string Version { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A description of the mod.
|
||||
/// NOTE: THIS IS DEPRECATED AND WILL BE REMOVED IN THE NEXT VERSION OF SMAPI
|
||||
/// </summary>
|
||||
public virtual string Description { get; protected set; }
|
||||
[Obsolete]
|
||||
public virtual string Description { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The mod's manifest
|
||||
/// </summary>
|
||||
public Manifest Manifest { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Where the mod is located on the disk.
|
||||
/// </summary>
|
||||
public string PathOnDisk { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// A basic method that is the entry-point of your mod. It will always be called once when the mod loads.
|
||||
|
|
|
@ -8,18 +8,20 @@ using StardewValley.Menus;
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace StardewModdingAPI
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
private static List<string> _modPaths;
|
||||
private static List<string> _modContentPaths;
|
||||
//private static List<string> _modContentPaths;
|
||||
|
||||
public static Texture2D DebugPixel { get; private set; }
|
||||
|
||||
|
@ -45,11 +47,12 @@ namespace StardewModdingAPI
|
|||
/// <param name="args"></param>
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
|
||||
|
||||
try
|
||||
{
|
||||
ConfigureUI();
|
||||
ConfigurePaths();
|
||||
ConfigureInjector();
|
||||
ConfigureSDV();
|
||||
|
||||
GameRunInvoker();
|
||||
|
@ -84,17 +87,19 @@ namespace StardewModdingAPI
|
|||
StardewModdingAPI.Log.Info("Validating api paths...");
|
||||
|
||||
_modPaths = new List<string>();
|
||||
_modContentPaths = new List<string>();
|
||||
//_modContentPaths = new List<string>();
|
||||
|
||||
//TODO: Have an app.config and put the paths inside it so users can define locations to load mods from
|
||||
_modPaths.Add(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley", "Mods"));
|
||||
_modPaths.Add(Path.Combine(Constants.ExecutionPath, "Mods"));
|
||||
_modContentPaths.Add(Path.Combine(Constants.ExecutionPath, "Mods", "Content"));
|
||||
_modContentPaths.Add(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley", "Mods", "Content"));
|
||||
|
||||
//Mods need to make their own content paths, since we're doing a different, manifest-driven, approach.
|
||||
//_modContentPaths.Add(Path.Combine(Constants.ExecutionPath, "Mods", "Content"));
|
||||
//_modContentPaths.Add(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley", "Mods", "Content"));
|
||||
|
||||
//Checks that all defined modpaths exist as directories
|
||||
_modPaths.ForEach(path => VerifyPath(path));
|
||||
_modContentPaths.ForEach(path => VerifyPath(path));
|
||||
//_modContentPaths.ForEach(path => VerifyPath(path));
|
||||
VerifyPath(Constants.LogPath);
|
||||
|
||||
StardewModdingAPI.Log.Initialize(Constants.LogPath);
|
||||
|
@ -105,49 +110,6 @@ namespace StardewModdingAPI
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load the injector.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This will load the injector before anything else if it sees it
|
||||
/// It doesn't matter though
|
||||
/// I'll leave it as a feature in case anyone in the community wants to tinker with it
|
||||
/// All you need is a DLL that inherits from mod and is called StardewInjector.dll with an Entry() method
|
||||
/// </remarks>
|
||||
private static void ConfigureInjector()
|
||||
{
|
||||
foreach (string ModPath in _modPaths)
|
||||
{
|
||||
foreach (String s in Directory.GetFiles(ModPath, "StardewInjector.dll"))
|
||||
{
|
||||
StardewModdingAPI.Log.Success(ConsoleColor.Green, "Found Stardew Injector DLL: " + s);
|
||||
try
|
||||
{
|
||||
Assembly mod = Assembly.UnsafeLoadFrom(s); //to combat internet-downloaded DLLs
|
||||
|
||||
if (mod.DefinedTypes.Count(x => x.BaseType == typeof(Mod)) > 0)
|
||||
{
|
||||
StardewModdingAPI.Log.Success("Loading Injector DLL...");
|
||||
TypeInfo tar = mod.DefinedTypes.First(x => x.BaseType == typeof(Mod));
|
||||
Mod m = (Mod)mod.CreateInstance(tar.ToString());
|
||||
Console.WriteLine("LOADED: {0} by {1} - Version {2} | Description: {3}", m.Name, m.Authour, m.Version, m.Description);
|
||||
m.Entry(false);
|
||||
StardewInjectorLoaded = true;
|
||||
StardewInjectorMod = m;
|
||||
}
|
||||
else
|
||||
{
|
||||
StardewModdingAPI.Log.Error("Invalid Mod DLL");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
StardewModdingAPI.Log.Error("Failed to load mod '{0}'. Exception details:\n" + ex, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load Stardev Valley and control features
|
||||
/// </summary>
|
||||
|
@ -260,6 +222,8 @@ namespace StardewModdingAPI
|
|||
StardewModdingAPI.Log.Verbose("Patching SDV Graphics Profile...");
|
||||
Game1.graphics.GraphicsProfile = GraphicsProfile.HiDef;
|
||||
LoadMods();
|
||||
//DEPRECATED WAY
|
||||
LoadMods_OldWay();
|
||||
|
||||
StardewForm = Control.FromHandle(Program.gamePtr.Window.Handle).FindForm();
|
||||
StardewForm.Closing += StardewForm_Closing;
|
||||
|
@ -309,6 +273,82 @@ namespace StardewModdingAPI
|
|||
StardewModdingAPI.Log.Verbose("LOADING MODS");
|
||||
int loadedMods = 0;
|
||||
foreach (string ModPath in _modPaths)
|
||||
{
|
||||
foreach (String d in Directory.GetDirectories(ModPath))
|
||||
{
|
||||
foreach (String s in Directory.GetFiles(d, "manifest.json"))
|
||||
{
|
||||
if (s.Contains("StardewInjector"))
|
||||
continue;
|
||||
StardewModdingAPI.Log.Success("Found Manifest: " + s);
|
||||
Manifest manifest = new Manifest();
|
||||
try
|
||||
{
|
||||
string t = File.ReadAllText(s);
|
||||
if (string.IsNullOrEmpty(t))
|
||||
{
|
||||
StardewModdingAPI.Log.Error("Failed to read mod manifest '{0}'. Manifest is empty!", s);
|
||||
continue;
|
||||
}
|
||||
manifest = JsonConvert.DeserializeObject<Manifest>(t);
|
||||
if (string.IsNullOrEmpty(manifest.EntryDll))
|
||||
{
|
||||
StardewModdingAPI.Log.Error("Failed to read mod manifest '{0}'. EntryDll is empty!", s);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
StardewModdingAPI.Log.Error("Failed to read mod manifest '{0}'. Exception details:\n" + ex, s);
|
||||
continue;
|
||||
}
|
||||
try
|
||||
{
|
||||
string targDll = Path.Combine(Path.GetDirectoryName(s), manifest.EntryDll);
|
||||
if (!File.Exists(targDll))
|
||||
{
|
||||
StardewModdingAPI.Log.Error("Failed to load mod '{0}'. File {1} does not exist!", s, targDll);
|
||||
continue;
|
||||
}
|
||||
|
||||
Assembly mod = Assembly.UnsafeLoadFrom(targDll);
|
||||
|
||||
if (mod.DefinedTypes.Count(x => x.BaseType == typeof (Mod)) > 0)
|
||||
{
|
||||
StardewModdingAPI.Log.Verbose("Loading Mod DLL...");
|
||||
TypeInfo tar = mod.DefinedTypes.First(x => x.BaseType == typeof (Mod));
|
||||
Mod m = (Mod) mod.CreateInstance(tar.ToString());
|
||||
m.PathOnDisk = Path.GetDirectoryName(s);
|
||||
m.Manifest = manifest;
|
||||
StardewModdingAPI.Log.Success("LOADED MOD: {0} by {1} - Version {2} | Description: {3} (@ {4})", m.Manifest.Name, m.Manifest.Authour, m.Manifest.Version, m.Manifest.Description, targDll);
|
||||
loadedMods += 1;
|
||||
m.Entry();
|
||||
}
|
||||
else
|
||||
{
|
||||
StardewModdingAPI.Log.Error("Invalid Mod DLL");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
StardewModdingAPI.Log.Error("Failed to load mod '{0}'. Exception details:\n" + ex, s);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
StardewModdingAPI.Log.Success("LOADED {0} MODS", loadedMods);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DEPRECATED. REMOVE
|
||||
/// </summary>
|
||||
[Obsolete]
|
||||
public static void LoadMods_OldWay()
|
||||
{
|
||||
StardewModdingAPI.Log.Error("LOADING MODS (OLD WAY - DEPRECATED. ANY MODS LOADED THIS WAY NEED TO UPDATE)");
|
||||
int loadedMods = 0;
|
||||
foreach (string ModPath in _modPaths)
|
||||
{
|
||||
foreach (String s in Directory.GetFiles(ModPath, "*.dll"))
|
||||
{
|
||||
|
@ -324,6 +364,8 @@ namespace StardewModdingAPI
|
|||
StardewModdingAPI.Log.Verbose("Loading Mod DLL...");
|
||||
TypeInfo tar = mod.DefinedTypes.First(x => x.BaseType == typeof(Mod));
|
||||
Mod m = (Mod)mod.CreateInstance(tar.ToString());
|
||||
m.Manifest = null;
|
||||
m.PathOnDisk = Path.GetDirectoryName(s);
|
||||
Console.WriteLine("LOADED MOD: {0} by {1} - Version {2} | Description: {3}", m.Name, m.Authour, m.Version, m.Description);
|
||||
loadedMods += 1;
|
||||
m.Entry();
|
||||
|
@ -339,9 +381,10 @@ namespace StardewModdingAPI
|
|||
}
|
||||
}
|
||||
}
|
||||
StardewModdingAPI.Log.Success("LOADED {0} MODS", loadedMods);
|
||||
StardewModdingAPI.Log.Error("LOADED {0} MODS THAT NEED TO UPDATE", loadedMods);
|
||||
}
|
||||
|
||||
|
||||
public static void ConsoleInputThread()
|
||||
{
|
||||
string input = string.Empty;
|
||||
|
@ -397,7 +440,6 @@ namespace StardewModdingAPI
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void Events_LocationsChanged(List<GameLocation> newLocations)
|
||||
{
|
||||
#if DEBUG
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
</SccAuxPath>
|
||||
<SccProvider>
|
||||
</SccProvider>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<TargetFrameworkProfile />
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
|
@ -31,10 +33,10 @@
|
|||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<TargetFrameworkProfile />
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<Choose>
|
||||
<When Condition="'$(SteamInstallPath)' != ''">
|
||||
|
@ -44,7 +46,7 @@
|
|||
</When>
|
||||
<Otherwise>
|
||||
<PropertyGroup>
|
||||
<SteamPath>..\..\..\..\Games\SteamLibrary</SteamPath>
|
||||
<SteamPath>..\</SteamPath>
|
||||
</PropertyGroup>
|
||||
</Otherwise>
|
||||
</Choose>
|
||||
|
@ -87,13 +89,26 @@
|
|||
<ApplicationIcon>icon.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
|
||||
<Reference Include="Microsoft.Xna.Framework.Game, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
|
||||
<Reference Include="Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
|
||||
<Reference Include="Microsoft.Xna.Framework.Xact, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
|
||||
<Reference Include="Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Xna.Framework.Game, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Xna.Framework.Xact, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Stardew Valley, Version=1.0.5905.5747, Culture=neutral, processorArchitecture=x86">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>$(SteamPath)\steamapps\common\Stardew Valley\Stardew Valley.exe</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
|
@ -107,10 +122,12 @@
|
|||
<Reference Include="xTile, Version=2.0.4.0, Culture=neutral, processorArchitecture=x86">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>$(SteamPath)\steamapps\common\Stardew Valley\xTile.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Command.cs" />
|
||||
<Compile Include="Config.cs" />
|
||||
<Compile Include="Constants.cs" />
|
||||
<Compile Include="Entities\SCharacter.cs" />
|
||||
<Compile Include="Entities\SFarm.cs" />
|
||||
|
@ -135,6 +152,7 @@
|
|||
<Compile Include="Inheritance\SGameLocation.cs" />
|
||||
<Compile Include="Inheritance\SObject.cs" />
|
||||
<Compile Include="Log.cs" />
|
||||
<Compile Include="Manifest.cs" />
|
||||
<Compile Include="Mod.cs" />
|
||||
<Compile Include="ModItem.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
|
@ -143,8 +161,10 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="FodyWeavers.xml" />
|
||||
<Content Include="icon.ico" />
|
||||
<Content Include="steam_appid.txt" />
|
||||
</ItemGroup>
|
||||
|
@ -165,6 +185,13 @@
|
|||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\packages\Fody.1.28.3\build\Fody.targets" Condition="Exists('..\packages\Fody.1.28.3\build\Fody.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\Fody.1.28.3\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.1.28.3\build\Fody.targets'))" />
|
||||
</Target>
|
||||
<!-- 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">
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Costura.Fody" version="1.3.3.0" targetFramework="net45" developmentDependency="true" />
|
||||
<package id="Fody" version="1.28.3" targetFramework="net45" developmentDependency="true" />
|
||||
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net45" />
|
||||
</packages>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Weavers>
|
||||
|
||||
</Weavers>
|
|
@ -16,6 +16,7 @@ namespace TrainerMod
|
|||
{
|
||||
public class TrainerMod : Mod
|
||||
{
|
||||
/*
|
||||
public override string Name
|
||||
{
|
||||
get { return "Trainer Mod"; }
|
||||
|
@ -35,6 +36,7 @@ namespace TrainerMod
|
|||
{
|
||||
get { return "Registers several commands to use. Most commands are trainer-like in that they offer forms of cheating."; }
|
||||
}
|
||||
*/
|
||||
|
||||
public static int frozenTime;
|
||||
public static bool infHealth, infStamina, infMoney, freezeTime;
|
||||
|
|
|
@ -12,12 +12,14 @@
|
|||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\StardewModdingAPI\bin\x86\Debug\Mods\</OutputPath>
|
||||
<OutputPath>..\StardewModdingAPI\bin\x86\Debug\Mods\TrainerMod\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
|
@ -34,16 +36,16 @@
|
|||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<Choose>
|
||||
<When Condition="'$(SteamInstallPath)' != ''">
|
||||
<PropertyGroup>
|
||||
<SteamPath>$(SteamInstallPath)</SteamPath>
|
||||
<When Condition="'$(SteamInstallPath)' != ''">
|
||||
<PropertyGroup>
|
||||
<SteamPath>$(SteamInstallPath)</SteamPath>
|
||||
</PropertyGroup>
|
||||
</When>
|
||||
<Otherwise>
|
||||
<PropertyGroup>
|
||||
<SteamPath>..\..\..\..\Games\SteamLibrary</SteamPath>
|
||||
</PropertyGroup>
|
||||
</Otherwise>
|
||||
</When>
|
||||
<Otherwise>
|
||||
<PropertyGroup>
|
||||
<SteamPath>..\</SteamPath>
|
||||
</PropertyGroup>
|
||||
</Otherwise>
|
||||
</Choose>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
|
||||
|
@ -80,6 +82,15 @@
|
|||
<Private>False</Private>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="manifest.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="FodyWeavers.xml" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"Name": "Trainer Mod",
|
||||
"Authour": "Zoryn",
|
||||
"Version": "1.0",
|
||||
"Description": "Registers several commands to use. Most commands are trainer-like in that they offer forms of cheating.",
|
||||
"EntryDll": "TrainerMod.dll"
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net45" />
|
||||
</packages>
|
Loading…
Reference in New Issue