Zoryn returns. Added JSON. Added Config.cs.

This commit is contained in:
Zoryn Aaron 2016-03-20 15:43:31 -04:00
parent d367b0a7bc
commit c50891a093
8 changed files with 550 additions and 398 deletions

1
.gitignore vendored
View File

@ -6,6 +6,7 @@ TrainerMod/obj/
StardewInjector/bin/ StardewInjector/bin/
StardewInjector/obj/ StardewInjector/obj/
packages/ packages/
steamapps/
*.symlink *.symlink
*.lnk *.lnk

124
StardewModdingAPI/Config.cs Normal file
View File

@ -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);
}
}
}

View File

@ -28,6 +28,11 @@ namespace StardewModdingAPI
/// </summary> /// </summary>
public virtual string Description { get; protected set; } public virtual string Description { get; protected set; }
/// <summary>
/// Where the mod is located on the disk.
/// </summary>
public string PathOnDisk { get; internal set; }
/// <summary> /// <summary>
/// A basic method that is the entry-point of your mod. It will always be called once when the mod loads. /// A basic method that is the entry-point of your mod. It will always be called once when the mod loads.
/// </summary> /// </summary>

View File

@ -1,50 +1,50 @@
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using StardewModdingAPI.Events; using StardewModdingAPI.Events;
using StardewModdingAPI.Inheritance; using StardewModdingAPI.Inheritance;
using StardewModdingAPI.Inheritance.Menus; using StardewModdingAPI.Inheritance.Menus;
using StardewValley; using StardewValley;
using StardewValley.Menus; using StardewValley.Menus;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
using System.Windows.Forms; using System.Windows.Forms;
namespace StardewModdingAPI
{
public class Program
{
private static List<string> _modPaths;
private static List<string> _modContentPaths;
public static Texture2D DebugPixel { get; private set; }
public static SGame gamePtr;
public static bool ready;
public static Assembly StardewAssembly;
public static Type StardewProgramType;
public static FieldInfo StardewGameInfo;
public static Form StardewForm;
public static Thread gameThread;
public static Thread consoleInputThread;
public static bool StardewInjectorLoaded { get; private set; }
public static Mod StardewInjectorMod { get; private set; }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace StardewModdingAPI
{
public class Program
{
private static List<string> _modPaths;
private static List<string> _modContentPaths;
public static Texture2D DebugPixel { get; private set; }
public static SGame gamePtr;
public static bool ready;
public static Assembly StardewAssembly;
public static Type StardewProgramType;
public static FieldInfo StardewGameInfo;
public static Form StardewForm;
public static Thread gameThread;
public static Thread consoleInputThread;
public static bool StardewInjectorLoaded { get; private set; }
public static Mod StardewInjectorMod { get; private set; }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> /// <summary>
/// Main method holding the API execution /// Main method holding the API execution
/// </summary> /// </summary>
/// <param name="args"></param> /// <param name="args"></param>
private static void Main(string[] args) private static void Main(string[] args)
{ {
try try
{ {
ConfigureUI(); ConfigureUI();
@ -62,16 +62,16 @@ namespace StardewModdingAPI
StardewModdingAPI.Log.Comment("The API will now terminate. Press any key to continue..."); StardewModdingAPI.Log.Comment("The API will now terminate. Press any key to continue...");
Console.ReadKey(); Console.ReadKey();
} }
/// <summary> /// <summary>
/// Set up the console properties /// Set up the console properties
/// </summary> /// </summary>
private static void ConfigureUI() private static void ConfigureUI()
{ {
Console.Title = Constants.ConsoleTitle; Console.Title = Constants.ConsoleTitle;
#if DEBUG #if DEBUG
Console.Title += " - DEBUG IS NOT FALSE, AUTHOUR NEEDS TO REUPLOAD THIS VERSION"; Console.Title += " - DEBUG IS NOT FALSE, AUTHOUR NEEDS TO REUPLOAD THIS VERSION";
#endif #endif
} }
@ -81,150 +81,151 @@ namespace StardewModdingAPI
/// </summary> /// </summary>
private static void ConfigurePaths() private static void ConfigurePaths()
{ {
StardewModdingAPI.Log.Info("Validating api paths..."); StardewModdingAPI.Log.Info("Validating api paths...");
_modPaths = new List<string>(); _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 //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(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley", "Mods"));
_modPaths.Add(Path.Combine(Constants.ExecutionPath, "Mods")); _modPaths.Add(Path.Combine(Constants.ExecutionPath, "Mods"));
_modContentPaths.Add(Path.Combine(Constants.ExecutionPath, "Mods", "Content")); _modContentPaths.Add(Path.Combine(Constants.ExecutionPath, "Mods", "Content"));
_modContentPaths.Add(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley", "Mods", "Content")); _modContentPaths.Add(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley", "Mods", "Content"));
//Checks that all defined modpaths exist as directories //Checks that all defined modpaths exist as directories
_modPaths.ForEach(path => VerifyPath(path)); _modPaths.ForEach(path => VerifyPath(path));
_modContentPaths.ForEach(path => VerifyPath(path)); _modContentPaths.ForEach(path => VerifyPath(path));
VerifyPath(Constants.LogPath); VerifyPath(Constants.LogPath);
StardewModdingAPI.Log.Initialize(Constants.LogPath); StardewModdingAPI.Log.Initialize(Constants.LogPath);
if (!File.Exists(Constants.ExecutionPath + "\\Stardew Valley.exe")) if (!File.Exists(Constants.ExecutionPath + "\\Stardew Valley.exe"))
{ {
throw new FileNotFoundException(string.Format("Could not found: {0}\\Stardew Valley.exe", Constants.ExecutionPath)); throw new FileNotFoundException(string.Format("Could not found: {0}\\Stardew Valley.exe", Constants.ExecutionPath));
} }
} }
/// <summary> /// <summary>
/// Load the injector. /// Load the injector.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This will load the injector before anything else if it sees it /// This will load the injector before anything else if it sees it
/// It doesn't matter though /// It doesn't matter though
/// I'll leave it as a feature in case anyone in the community wants to tinker with it /// 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 /// All you need is a DLL that inherits from mod and is called StardewInjector.dll with an Entry() method
/// </remarks> /// </remarks>
private static void ConfigureInjector() private static void ConfigureInjector()
{ {
foreach (string ModPath in _modPaths) foreach (string ModPath in _modPaths)
{ {
foreach (String s in Directory.GetFiles(ModPath, "StardewInjector.dll")) foreach (String s in Directory.GetFiles(ModPath, "StardewInjector.dll"))
{ {
StardewModdingAPI.Log.Success(ConsoleColor.Green, "Found Stardew Injector DLL: " + s); StardewModdingAPI.Log.Success(ConsoleColor.Green, "Found Stardew Injector DLL: " + s);
try try
{ {
Assembly mod = Assembly.UnsafeLoadFrom(s); //to combat internet-downloaded DLLs Assembly mod = Assembly.UnsafeLoadFrom(s); //to combat internet-downloaded DLLs
if (mod.DefinedTypes.Count(x => x.BaseType == typeof(Mod)) > 0) if (mod.DefinedTypes.Count(x => x.BaseType == typeof(Mod)) > 0)
{ {
StardewModdingAPI.Log.Success("Loading Injector DLL..."); StardewModdingAPI.Log.Success("Loading Injector DLL...");
TypeInfo tar = mod.DefinedTypes.First(x => x.BaseType == typeof(Mod)); TypeInfo tar = mod.DefinedTypes.First(x => x.BaseType == typeof(Mod));
Mod m = (Mod)mod.CreateInstance(tar.ToString()); 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); Console.WriteLine("LOADED: {0} by {1} - Version {2} | Description: {3}", m.Name, m.Authour, m.Version, m.Description);
m.Entry(false); m.PathOnDisk = Path.GetDirectoryName(ModPath);
StardewInjectorLoaded = true; m.Entry(false);
StardewInjectorMod = m; StardewInjectorLoaded = true;
} StardewInjectorMod = m;
else }
{ else
StardewModdingAPI.Log.Error("Invalid Mod DLL"); {
} StardewModdingAPI.Log.Error("Invalid Mod DLL");
} }
catch (Exception ex) }
{ catch (Exception ex)
StardewModdingAPI.Log.Error("Failed to load mod '{0}'. Exception details:\n" + ex, s); {
} StardewModdingAPI.Log.Error("Failed to load mod '{0}'. Exception details:\n" + ex, s);
} }
} }
} }
}
/// <summary> /// <summary>
/// Load Stardev Valley and control features /// Load Stardev Valley and control features
/// </summary> /// </summary>
private static void ConfigureSDV() private static void ConfigureSDV()
{ {
StardewModdingAPI.Log.Info("Initializing SDV Assembly..."); StardewModdingAPI.Log.Info("Initializing SDV Assembly...");
// Load in the assembly - ignores security // Load in the assembly - ignores security
StardewAssembly = Assembly.UnsafeLoadFrom(Constants.ExecutionPath + "\\Stardew Valley.exe"); StardewAssembly = Assembly.UnsafeLoadFrom(Constants.ExecutionPath + "\\Stardew Valley.exe");
StardewProgramType = StardewAssembly.GetType("StardewValley.Program", true); StardewProgramType = StardewAssembly.GetType("StardewValley.Program", true);
StardewGameInfo = StardewProgramType.GetField("gamePtr"); StardewGameInfo = StardewProgramType.GetField("gamePtr");
// Change the game's version // Change the game's version
StardewModdingAPI.Log.Verbose("Injecting New SDV Version..."); StardewModdingAPI.Log.Verbose("Injecting New SDV Version...");
Game1.version += string.Format("-Z_MODDED | SMAPI {0}", Constants.VersionString); Game1.version += string.Format("-Z_MODDED | SMAPI {0}", Constants.VersionString);
// Create the thread for the game to run in. // Create the thread for the game to run in.
gameThread = new Thread(RunGame); gameThread = new Thread(RunGame);
StardewModdingAPI.Log.Info("Starting SDV..."); StardewModdingAPI.Log.Info("Starting SDV...");
gameThread.Start(); gameThread.Start();
// Wait for the game to load up // Wait for the game to load up
while (!ready) ; while (!ready) ;
//SDV is running //SDV is running
StardewModdingAPI.Log.Comment("SDV Loaded Into Memory"); StardewModdingAPI.Log.Comment("SDV Loaded Into Memory");
//Create definition to listen for input //Create definition to listen for input
StardewModdingAPI.Log.Verbose("Initializing Console Input Thread..."); StardewModdingAPI.Log.Verbose("Initializing Console Input Thread...");
consoleInputThread = new Thread(ConsoleInputThread); consoleInputThread = new Thread(ConsoleInputThread);
// The only command in the API (at least it should be, for now) // The only command in the API (at least it should be, for now)
Command.RegisterCommand("help", "Lists all commands | 'help <cmd>' returns command description").CommandFired += help_CommandFired; Command.RegisterCommand("help", "Lists all commands | 'help <cmd>' returns command description").CommandFired += help_CommandFired;
//Command.RegisterCommand("crash", "crashes sdv").CommandFired += delegate { Game1.player.draw(null); }; //Command.RegisterCommand("crash", "crashes sdv").CommandFired += delegate { Game1.player.draw(null); };
//Subscribe to events //Subscribe to events
Events.ControlEvents.KeyPressed += Events_KeyPressed; Events.ControlEvents.KeyPressed += Events_KeyPressed;
Events.GameEvents.LoadContent += Events_LoadContent; Events.GameEvents.LoadContent += Events_LoadContent;
//Events.MenuChanged += Events_MenuChanged; //Idk right now //Events.MenuChanged += Events_MenuChanged; //Idk right now
StardewModdingAPI.Log.Verbose("Applying Final SDV Tweaks..."); StardewModdingAPI.Log.Verbose("Applying Final SDV Tweaks...");
StardewInvoke(() => StardewInvoke(() =>
{ {
gamePtr.IsMouseVisible = false; gamePtr.IsMouseVisible = false;
gamePtr.Window.Title = "Stardew Valley - Version " + Game1.version; gamePtr.Window.Title = "Stardew Valley - Version " + Game1.version;
StardewForm.Resize += Events.GraphicsEvents.InvokeResize; StardewForm.Resize += Events.GraphicsEvents.InvokeResize;
}); });
} }
/// <summary> /// <summary>
/// Wrap the 'RunGame' method for console output /// Wrap the 'RunGame' method for console output
/// </summary> /// </summary>
private static void GameRunInvoker() private static void GameRunInvoker()
{ {
//Game's in memory now, send the event //Game's in memory now, send the event
StardewModdingAPI.Log.Verbose("Game Loaded"); StardewModdingAPI.Log.Verbose("Game Loaded");
Events.GameEvents.InvokeGameLoaded(); Events.GameEvents.InvokeGameLoaded();
StardewModdingAPI.Log.Comment("Type 'help' for help, or 'help <cmd>' for a command's usage"); StardewModdingAPI.Log.Comment("Type 'help' for help, or 'help <cmd>' for a command's usage");
//Begin listening to input //Begin listening to input
consoleInputThread.Start(); consoleInputThread.Start();
while (ready) while (ready)
{ {
//Check if the game is still running 10 times a second //Check if the game is still running 10 times a second
Thread.Sleep(1000 / 10); Thread.Sleep(1000 / 10);
} }
//abort the thread, we're closing //abort the thread, we're closing
if (consoleInputThread != null && consoleInputThread.ThreadState == ThreadState.Running) if (consoleInputThread != null && consoleInputThread.ThreadState == ThreadState.Running)
consoleInputThread.Abort(); consoleInputThread.Abort();
StardewModdingAPI.Log.Verbose("Game Execution Finished"); StardewModdingAPI.Log.Verbose("Game Execution Finished");
StardewModdingAPI.Log.Verbose("Shutting Down..."); StardewModdingAPI.Log.Verbose("Shutting Down...");
Thread.Sleep(100); Thread.Sleep(100);
Environment.Exit(0); Environment.Exit(0);
} }
/// <summary> /// <summary>
@ -241,186 +242,186 @@ namespace StardewModdingAPI
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
StardewModdingAPI.Log.Error("Could not create a path: " + path + "\n\n" + ex); StardewModdingAPI.Log.Error("Could not create a path: " + path + "\n\n" + ex);
} }
} }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static void RunGame() public static void RunGame()
{ {
Application.ThreadException += StardewModdingAPI.Log.Application_ThreadException; Application.ThreadException += StardewModdingAPI.Log.Application_ThreadException;
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
AppDomain.CurrentDomain.UnhandledException += StardewModdingAPI.Log.CurrentDomain_UnhandledException; AppDomain.CurrentDomain.UnhandledException += StardewModdingAPI.Log.CurrentDomain_UnhandledException;
try try
{ {
gamePtr = new SGame(); gamePtr = new SGame();
StardewModdingAPI.Log.Verbose("Patching SDV Graphics Profile..."); StardewModdingAPI.Log.Verbose("Patching SDV Graphics Profile...");
Game1.graphics.GraphicsProfile = GraphicsProfile.HiDef; Game1.graphics.GraphicsProfile = GraphicsProfile.HiDef;
LoadMods(); LoadMods();
StardewForm = Control.FromHandle(Program.gamePtr.Window.Handle).FindForm(); StardewForm = Control.FromHandle(Program.gamePtr.Window.Handle).FindForm();
StardewForm.Closing += StardewForm_Closing; StardewForm.Closing += StardewForm_Closing;
ready = true; ready = true;
StardewGameInfo.SetValue(StardewProgramType, gamePtr); StardewGameInfo.SetValue(StardewProgramType, gamePtr);
gamePtr.Run(); gamePtr.Run();
#region deprecated #region deprecated
if (false) if (false)
{ {
//Nope, I can't get it to work. I depend on Game1 being an SGame, and can't cast a parent to a child //Nope, I can't get it to work. I depend on Game1 being an SGame, and can't cast a parent to a child
//I'm leaving this here in case the community is interested //I'm leaving this here in case the community is interested
//StardewInjectorMod.Entry(true); //StardewInjectorMod.Entry(true);
Type gt = StardewAssembly.GetType("StardewValley.Game1", true); Type gt = StardewAssembly.GetType("StardewValley.Game1", true);
gamePtr = (SGame)Activator.CreateInstance(gt); gamePtr = (SGame)Activator.CreateInstance(gt);
ready = true; ready = true;
StardewGameInfo.SetValue(StardewProgramType, gamePtr); StardewGameInfo.SetValue(StardewProgramType, gamePtr);
gamePtr.Run(); gamePtr.Run();
} }
#endregion #endregion
} }
catch (Exception ex) catch (Exception ex)
{ {
StardewModdingAPI.Log.Error("Game failed to start: " + ex); StardewModdingAPI.Log.Error("Game failed to start: " + ex);
} }
} }
static void StardewForm_Closing(object sender, CancelEventArgs e) static void StardewForm_Closing(object sender, CancelEventArgs e)
{ {
e.Cancel = true; e.Cancel = true;
if (true || MessageBox.Show("Are you sure you would like to quit Stardew Valley?\nUnsaved progress will be lost!", "Confirm Exit", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes) if (true || MessageBox.Show("Are you sure you would like to quit Stardew Valley?\nUnsaved progress will be lost!", "Confirm Exit", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes)
{ {
gamePtr.Exit(); gamePtr.Exit();
gamePtr.Dispose(); gamePtr.Dispose();
StardewForm.Hide(); StardewForm.Hide();
ready = false; ready = false;
} }
} }
public static void LoadMods() public static void LoadMods()
{ {
StardewModdingAPI.Log.Verbose("LOADING MODS"); StardewModdingAPI.Log.Verbose("LOADING MODS");
int loadedMods = 0; int loadedMods = 0;
foreach (string ModPath in _modPaths) foreach (string ModPath in _modPaths)
{ {
foreach (String s in Directory.GetFiles(ModPath, "*.dll")) foreach (String s in Directory.GetFiles(ModPath, "*.dll"))
{ {
if (s.Contains("StardewInjector")) if (s.Contains("StardewInjector"))
continue; continue;
StardewModdingAPI.Log.Success("Found DLL: " + s); StardewModdingAPI.Log.Success("Found DLL: " + s);
try try
{ {
Assembly mod = Assembly.UnsafeLoadFrom(s); //to combat internet-downloaded DLLs Assembly mod = Assembly.UnsafeLoadFrom(s); //to combat internet-downloaded DLLs
if (mod.DefinedTypes.Count(x => x.BaseType == typeof(Mod)) > 0) if (mod.DefinedTypes.Count(x => x.BaseType == typeof(Mod)) > 0)
{ {
StardewModdingAPI.Log.Verbose("Loading Mod DLL..."); StardewModdingAPI.Log.Verbose("Loading Mod DLL...");
TypeInfo tar = mod.DefinedTypes.First(x => x.BaseType == typeof(Mod)); TypeInfo tar = mod.DefinedTypes.First(x => x.BaseType == typeof(Mod));
Mod m = (Mod)mod.CreateInstance(tar.ToString()); Mod m = (Mod)mod.CreateInstance(tar.ToString());
Console.WriteLine("LOADED MOD: {0} by {1} - Version {2} | Description: {3}", m.Name, m.Authour, m.Version, m.Description); Console.WriteLine("LOADED MOD: {0} by {1} - Version {2} | Description: {3}", m.Name, m.Authour, m.Version, m.Description);
loadedMods += 1; loadedMods += 1;
m.Entry(); m.Entry();
} }
else else
{ {
StardewModdingAPI.Log.Error("Invalid Mod DLL"); StardewModdingAPI.Log.Error("Invalid Mod DLL");
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
StardewModdingAPI.Log.Error("Failed to load mod '{0}'. Exception details:\n" + ex, s); StardewModdingAPI.Log.Error("Failed to load mod '{0}'. Exception details:\n" + ex, s);
} }
} }
} }
StardewModdingAPI.Log.Success("LOADED {0} MODS", loadedMods); StardewModdingAPI.Log.Success("LOADED {0} MODS", loadedMods);
} }
public static void ConsoleInputThread() public static void ConsoleInputThread()
{ {
string input = string.Empty; string input = string.Empty;
while (true) while (true)
{ {
Command.CallCommand(Console.ReadLine()); Command.CallCommand(Console.ReadLine());
} }
} }
static void Events_LoadContent(object o, EventArgs e) static void Events_LoadContent(object o, EventArgs e)
{ {
StardewModdingAPI.Log.Info("Initializing Debug Assets..."); StardewModdingAPI.Log.Info("Initializing Debug Assets...");
DebugPixel = new Texture2D(Game1.graphics.GraphicsDevice, 1, 1); DebugPixel = new Texture2D(Game1.graphics.GraphicsDevice, 1, 1);
DebugPixel.SetData(new Color[] { Color.White }); DebugPixel.SetData(new Color[] { Color.White });
#if DEBUG #if DEBUG
StardewModdingAPI.Log.Verbose("REGISTERING BASE CUSTOM ITEM"); StardewModdingAPI.Log.Verbose("REGISTERING BASE CUSTOM ITEM");
SObject so = new SObject(); SObject so = new SObject();
so.Name = "Mario Block"; so.Name = "Mario Block";
so.CategoryName = "SMAPI Test Mod"; so.CategoryName = "SMAPI Test Mod";
so.Description = "It's a block from Mario!\nLoaded in realtime by SMAPI."; so.Description = "It's a block from Mario!\nLoaded in realtime by SMAPI.";
so.Texture = Texture2D.FromStream(Game1.graphics.GraphicsDevice, new FileStream(_modContentPaths[0] + "\\Test.png", FileMode.Open)); so.Texture = Texture2D.FromStream(Game1.graphics.GraphicsDevice, new FileStream(_modContentPaths[0] + "\\Test.png", FileMode.Open));
so.IsPassable = true; so.IsPassable = true;
so.IsPlaceable = true; so.IsPlaceable = true;
StardewModdingAPI.Log.Verbose("REGISTERED WITH ID OF: " + SGame.RegisterModItem(so)); StardewModdingAPI.Log.Verbose("REGISTERED WITH ID OF: " + SGame.RegisterModItem(so));
//StardewModdingAPI.Log.Verbose("REGISTERING SECOND CUSTOM ITEM"); //StardewModdingAPI.Log.Verbose("REGISTERING SECOND CUSTOM ITEM");
//SObject so2 = new SObject(); //SObject so2 = new SObject();
//so2.Name = "Mario Painting"; //so2.Name = "Mario Painting";
//so2.CategoryName = "SMAPI Test Mod"; //so2.CategoryName = "SMAPI Test Mod";
//so2.Description = "It's a painting of a creature from Mario!\nLoaded in realtime by SMAPI."; //so2.Description = "It's a painting of a creature from Mario!\nLoaded in realtime by SMAPI.";
//so2.Texture = Texture2D.FromStream(Game1.graphics.GraphicsDevice, new FileStream(_modContentPaths[0] + "\\PaintingTest.png", FileMode.Open)); //so2.Texture = Texture2D.FromStream(Game1.graphics.GraphicsDevice, new FileStream(_modContentPaths[0] + "\\PaintingTest.png", FileMode.Open));
//so2.IsPassable = true; //so2.IsPassable = true;
//so2.IsPlaceable = true; //so2.IsPlaceable = true;
//StardewModdingAPI.Log.Verbose("REGISTERED WITH ID OF: " + SGame.RegisterModItem(so2)); //StardewModdingAPI.Log.Verbose("REGISTERED WITH ID OF: " + SGame.RegisterModItem(so2));
Command.CallCommand("load"); Command.CallCommand("load");
#endif #endif
} }
static void Events_KeyPressed(object o, EventArgsKeyPressed e) static void Events_KeyPressed(object o, EventArgsKeyPressed e)
{ {
} }
static void Events_MenuChanged(IClickableMenu newMenu) static void Events_MenuChanged(IClickableMenu newMenu)
{
StardewModdingAPI.Log.Verbose("NEW MENU: " + newMenu.GetType());
if (newMenu is GameMenu)
{
Game1.activeClickableMenu = SGameMenu.ConstructFromBaseClass(Game1.activeClickableMenu as GameMenu);
}
}
static void Events_LocationsChanged(List<GameLocation> newLocations)
{ {
#if DEBUG StardewModdingAPI.Log.Verbose("NEW MENU: " + newMenu.GetType());
SGame.ModLocations = SGameLocation.ConstructFromBaseClasses(Game1.locations); if (newMenu is GameMenu)
#endif {
} Game1.activeClickableMenu = SGameMenu.ConstructFromBaseClass(Game1.activeClickableMenu as GameMenu);
}
static void Events_CurrentLocationChanged(GameLocation newLocation) }
static void Events_LocationsChanged(List<GameLocation> newLocations)
{
#if DEBUG
SGame.ModLocations = SGameLocation.ConstructFromBaseClasses(Game1.locations);
#endif
}
static void Events_CurrentLocationChanged(GameLocation newLocation)
{ {
//SGame.CurrentLocation = null; //SGame.CurrentLocation = null;
//System.Threading.Thread.Sleep(10); //System.Threading.Thread.Sleep(10);
#if DEBUG #if DEBUG
Console.WriteLine(newLocation.name); Console.WriteLine(newLocation.name);
SGame.CurrentLocation = SGame.LoadOrCreateSGameLocationFromName(newLocation.name); SGame.CurrentLocation = SGame.LoadOrCreateSGameLocationFromName(newLocation.name);
#endif #endif
//Game1.currentLocation = SGame.CurrentLocation; //Game1.currentLocation = SGame.CurrentLocation;
//Log.LogComment(((SGameLocation) newLocation).name); //Log.LogComment(((SGameLocation) newLocation).name);
//Log.LogComment("LOC CHANGED: " + SGame.currentLocation.name); //Log.LogComment("LOC CHANGED: " + SGame.currentLocation.name);
} }
public static void StardewInvoke(Action a) public static void StardewInvoke(Action a)
{ {
StardewForm.Invoke(a); StardewForm.Invoke(a);
} }
static void help_CommandFired(object o, EventArgsCommand e) static void help_CommandFired(object o, EventArgsCommand e)
@ -442,66 +443,66 @@ namespace StardewModdingAPI
StardewModdingAPI.Log.Info("Commands: " + Command.RegisteredCommands.Select(x => x.CommandName).ToSingular()); StardewModdingAPI.Log.Info("Commands: " + Command.RegisteredCommands.Select(x => x.CommandName).ToSingular());
} }
#region Logging #region Logging
[Obsolete("This method is obsolete and will be removed in v0.39, please use the appropriate methods in the Log class")] [Obsolete("This method is obsolete and will be removed in v0.39, please use the appropriate methods in the Log class")]
public static void Log(object o, params object[] format) public static void Log(object o, params object[] format)
{ {
StardewModdingAPI.Log.Info(o, format); StardewModdingAPI.Log.Info(o, format);
} }
[Obsolete("This method is obsolete and will be removed in v0.39, please use the appropriate methods in the Log class")] [Obsolete("This method is obsolete and will be removed in v0.39, please use the appropriate methods in the Log class")]
public static void LogColour(ConsoleColor c, object o, params object[] format) public static void LogColour(ConsoleColor c, object o, params object[] format)
{ {
StardewModdingAPI.Log.Info(o, format); StardewModdingAPI.Log.Info(o, format);
} }
[Obsolete("This method is obsolete and will be removed in v0.39, please use the appropriate methods in the Log class")] [Obsolete("This method is obsolete and will be removed in v0.39, please use the appropriate methods in the Log class")]
public static void LogInfo(object o, params object[] format) public static void LogInfo(object o, params object[] format)
{ {
StardewModdingAPI.Log.Info(o, format); StardewModdingAPI.Log.Info(o, format);
} }
[Obsolete("This method is obsolete and will be removed in v0.39, please use the appropriate methods in the Log class")] [Obsolete("This method is obsolete and will be removed in v0.39, please use the appropriate methods in the Log class")]
public static void LogError(object o, params object[] format) public static void LogError(object o, params object[] format)
{ {
StardewModdingAPI.Log.Error(o, format); StardewModdingAPI.Log.Error(o, format);
} }
[Obsolete("This method is obsolete and will be removed in v0.39, please use the appropriate methods in the Log class")] [Obsolete("This method is obsolete and will be removed in v0.39, please use the appropriate methods in the Log class")]
public static void LogDebug(object o, params object[] format) public static void LogDebug(object o, params object[] format)
{ {
StardewModdingAPI.Log.Debug(o, format); StardewModdingAPI.Log.Debug(o, format);
} }
[Obsolete("This method is obsolete and will be removed in v0.39, please use the appropriate methods in the Log class")] [Obsolete("This method is obsolete and will be removed in v0.39, please use the appropriate methods in the Log class")]
public static void LogValueNotSpecified() public static void LogValueNotSpecified()
{ {
StardewModdingAPI.Log.Error("<value> must be specified"); StardewModdingAPI.Log.Error("<value> must be specified");
} }
[Obsolete("This method is obsolete and will be removed in v0.39, please use the appropriate methods in the Log class")] [Obsolete("This method is obsolete and will be removed in v0.39, please use the appropriate methods in the Log class")]
public static void LogObjectValueNotSpecified() public static void LogObjectValueNotSpecified()
{ {
StardewModdingAPI.Log.Error("<object> and <value> must be specified"); StardewModdingAPI.Log.Error("<object> and <value> must be specified");
} }
[Obsolete("This method is obsolete and will be removed in v0.39, please use the appropriate methods in the Log class")] [Obsolete("This method is obsolete and will be removed in v0.39, please use the appropriate methods in the Log class")]
public static void LogValueInvalid() public static void LogValueInvalid()
{ {
StardewModdingAPI.Log.Error("<value> is invalid"); StardewModdingAPI.Log.Error("<value> is invalid");
} }
[Obsolete("This method is obsolete and will be removed in v0.39, please use the appropriate methods in the Log class")] [Obsolete("This method is obsolete and will be removed in v0.39, please use the appropriate methods in the Log class")]
public static void LogObjectInvalid() public static void LogObjectInvalid()
{ {
StardewModdingAPI.Log.Error("<object> is invalid"); StardewModdingAPI.Log.Error("<object> is invalid");
} }
[Obsolete("This method is obsolete and will be removed in v0.39, please use the appropriate methods in the Log class")] [Obsolete("This method is obsolete and will be removed in v0.39, please use the appropriate methods in the Log class")]
public static void LogValueNotInt32() public static void LogValueNotInt32()
{ {
StardewModdingAPI.Log.Error("<value> must be a whole number (Int32)"); StardewModdingAPI.Log.Error("<value> must be a whole number (Int32)");
} }
#endregion #endregion
} }
} }

View File

@ -44,7 +44,7 @@
</When> </When>
<Otherwise> <Otherwise>
<PropertyGroup> <PropertyGroup>
<SteamPath>..\..\..\..\Games\SteamLibrary</SteamPath> <SteamPath>..\</SteamPath>
</PropertyGroup> </PropertyGroup>
</Otherwise> </Otherwise>
</Choose> </Choose>
@ -91,6 +91,10 @@
<Reference Include="Microsoft.Xna.Framework.Game, 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.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.Xact, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Stardew Valley, Version=1.0.5905.5747, Culture=neutral, processorArchitecture=x86"> <Reference Include="Stardew Valley, Version=1.0.5905.5747, Culture=neutral, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>$(SteamPath)\steamapps\common\Stardew Valley\Stardew Valley.exe</HintPath> <HintPath>$(SteamPath)\steamapps\common\Stardew Valley\Stardew Valley.exe</HintPath>
@ -111,6 +115,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Command.cs" /> <Compile Include="Command.cs" />
<Compile Include="Config.cs" />
<Compile Include="Constants.cs" /> <Compile Include="Constants.cs" />
<Compile Include="Entities\SCharacter.cs" /> <Compile Include="Entities\SCharacter.cs" />
<Compile Include="Entities\SFarm.cs" /> <Compile Include="Entities\SFarm.cs" />
@ -143,6 +148,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="App.config" /> <None Include="App.config" />
<None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="icon.ico" /> <Content Include="icon.ico" />

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="8.0.2" targetFramework="net45" />
</packages>

View File

@ -34,16 +34,16 @@
<Prefer32Bit>false</Prefer32Bit> <Prefer32Bit>false</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<Choose> <Choose>
<When Condition="'$(SteamInstallPath)' != ''"> <When Condition="'$(SteamInstallPath)' != ''">
<PropertyGroup> <PropertyGroup>
<SteamPath>$(SteamInstallPath)</SteamPath> <SteamPath>$(SteamInstallPath)</SteamPath>
</PropertyGroup> </PropertyGroup>
</When> </When>
<Otherwise> <Otherwise>
<PropertyGroup> <PropertyGroup>
<SteamPath>..\..\..\..\Games\SteamLibrary</SteamPath> <SteamPath>..\</SteamPath>
</PropertyGroup> </PropertyGroup>
</Otherwise> </Otherwise>
</Choose> </Choose>
<ItemGroup> <ItemGroup>
<Reference Include="Microsoft.Xna.Framework, 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">
@ -52,6 +52,10 @@
<Reference Include="Microsoft.Xna.Framework.Game, 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">
<Private>False</Private> <Private>False</Private>
</Reference> </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"> <Reference Include="Stardew Valley">
<HintPath>$(SteamPath)\steamapps\common\Stardew Valley\Stardew Valley.exe</HintPath> <HintPath>$(SteamPath)\steamapps\common\Stardew Valley\Stardew Valley.exe</HintPath>
<Private>False</Private> <Private>False</Private>
@ -80,6 +84,9 @@
<Private>False</Private> <Private>False</Private>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup> <PropertyGroup>
<PostBuildEvent> <PostBuildEvent>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net45" />
</packages>