Merge branch 'master'

This commit is contained in:
Zoryn Aaron 2016-03-21 21:07:37 -04:00
commit c73c1a0ec7
19 changed files with 863 additions and 435 deletions

1
.gitignore vendored
View File

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

View File

@ -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
@ -27,4 +26,4 @@ To install mods:
## Mod Developers!
Mod developers would work off the release branch. The master branch will contain mid-version updates which could make your mods incompatable with both the current release and the upcoming releases.
Mod developers would work off the release branch. The master branch will contain mid-version updates which could make your mods incompatable with both the current release and the upcoming releases.

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

@ -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";

View File

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

View File

@ -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;
@ -59,6 +60,42 @@ namespace StardewModdingAPI
hash ^= v.GetHashCode();
}
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);
}
}
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Weavers>
<Costura/>
</Weavers>

View File

@ -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++)

View File

@ -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>

View File

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

View File

@ -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.

View File

@ -1,55 +1,58 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using StardewModdingAPI.Events;
using StardewModdingAPI.Inheritance;
using StardewModdingAPI.Inheritance.Menus;
using StardewValley;
using StardewValley.Menus;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
using StardewModdingAPI.Inheritance;
using StardewModdingAPI.Inheritance.Menus;
using StardewValley;
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;
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>
/// Main method holding the API execution
/// </summary>
/// <param name="args"></param>
private static void Main(string[] args)
{
/// <param name="args"></param>
private static void Main(string[] args)
{
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
try
{
ConfigureUI();
ConfigurePaths();
ConfigureInjector();
ConfigureSDV();
GameRunInvoker();
@ -62,16 +65,16 @@ namespace StardewModdingAPI
StardewModdingAPI.Log.Comment("The API will now terminate. Press any key to continue...");
Console.ReadKey();
}
}
/// <summary>
/// Set up the console properties
/// </summary>
/// </summary>
private static void ConfigureUI()
{
{
Console.Title = Constants.ConsoleTitle;
#if DEBUG
#if DEBUG
Console.Title += " - DEBUG IS NOT FALSE, AUTHOUR NEEDS TO REUPLOAD THIS VERSION";
#endif
}
@ -81,150 +84,109 @@ namespace StardewModdingAPI
/// </summary>
private static void ConfigurePaths()
{
StardewModdingAPI.Log.Info("Validating api paths...");
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"));
//Checks that all defined modpaths exist as directories
_modPaths.ForEach(path => VerifyPath(path));
_modContentPaths.ForEach(path => VerifyPath(path));
VerifyPath(Constants.LogPath);
_modPaths.Add(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley", "Mods"));
_modPaths.Add(Path.Combine(Constants.ExecutionPath, "Mods"));
//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));
VerifyPath(Constants.LogPath);
StardewModdingAPI.Log.Initialize(Constants.LogPath);
if (!File.Exists(Constants.ExecutionPath + "\\Stardew Valley.exe"))
{
{
throw new FileNotFoundException(string.Format("Could not found: {0}\\Stardew Valley.exe", Constants.ExecutionPath));
}
}
/// <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>
/// </summary>
private static void ConfigureSDV()
{
StardewModdingAPI.Log.Info("Initializing SDV Assembly...");
// Load in the assembly - ignores security
StardewAssembly = Assembly.UnsafeLoadFrom(Constants.ExecutionPath + "\\Stardew Valley.exe");
StardewProgramType = StardewAssembly.GetType("StardewValley.Program", true);
StardewGameInfo = StardewProgramType.GetField("gamePtr");
// Change the game's version
StardewModdingAPI.Log.Verbose("Injecting New SDV Version...");
{
StardewModdingAPI.Log.Info("Initializing SDV Assembly...");
// Load in the assembly - ignores security
StardewAssembly = Assembly.UnsafeLoadFrom(Constants.ExecutionPath + "\\Stardew Valley.exe");
StardewProgramType = StardewAssembly.GetType("StardewValley.Program", true);
StardewGameInfo = StardewProgramType.GetField("gamePtr");
// Change the game's version
StardewModdingAPI.Log.Verbose("Injecting New SDV Version...");
Game1.version += string.Format("-Z_MODDED | SMAPI {0}", Constants.VersionString);
// Create the thread for the game to run in.
gameThread = new Thread(RunGame);
StardewModdingAPI.Log.Info("Starting SDV...");
// Create the thread for the game to run in.
gameThread = new Thread(RunGame);
StardewModdingAPI.Log.Info("Starting SDV...");
gameThread.Start();
// Wait for the game to load up
while (!ready) ;
//SDV is running
StardewModdingAPI.Log.Comment("SDV Loaded Into Memory");
//Create definition to listen for input
StardewModdingAPI.Log.Verbose("Initializing Console Input Thread...");
consoleInputThread = new Thread(ConsoleInputThread);
// 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("crash", "crashes sdv").CommandFired += delegate { Game1.player.draw(null); };
//Subscribe to events
Events.ControlEvents.KeyPressed += Events_KeyPressed;
while (!ready) ;
//SDV is running
StardewModdingAPI.Log.Comment("SDV Loaded Into Memory");
//Create definition to listen for input
StardewModdingAPI.Log.Verbose("Initializing Console Input Thread...");
consoleInputThread = new Thread(ConsoleInputThread);
// 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("crash", "crashes sdv").CommandFired += delegate { Game1.player.draw(null); };
//Subscribe to events
Events.ControlEvents.KeyPressed += Events_KeyPressed;
Events.GameEvents.LoadContent += Events_LoadContent;
//Events.MenuChanged += Events_MenuChanged; //Idk right now
StardewModdingAPI.Log.Verbose("Applying Final SDV Tweaks...");
StardewInvoke(() =>
//Events.MenuChanged += Events_MenuChanged; //Idk right now
StardewModdingAPI.Log.Verbose("Applying Final SDV Tweaks...");
StardewInvoke(() =>
{
gamePtr.IsMouseVisible = false;
gamePtr.Window.Title = "Stardew Valley - Version " + Game1.version;
StardewForm.Resize += Events.GraphicsEvents.InvokeResize;
});
}
StardewForm.Resize += Events.GraphicsEvents.InvokeResize;
});
}
/// <summary>
/// Wrap the 'RunGame' method for console output
/// </summary>
/// </summary>
private static void GameRunInvoker()
{
//Game's in memory now, send the event
StardewModdingAPI.Log.Verbose("Game Loaded");
Events.GameEvents.InvokeGameLoaded();
{
//Game's in memory now, send the event
StardewModdingAPI.Log.Verbose("Game Loaded");
Events.GameEvents.InvokeGameLoaded();
StardewModdingAPI.Log.Comment("Type 'help' for help, or 'help <cmd>' for a command's usage");
//Begin listening to input
consoleInputThread.Start();
while (ready)
{
//Check if the game is still running 10 times a second
Thread.Sleep(1000 / 10);
}
//abort the thread, we're closing
if (consoleInputThread != null && consoleInputThread.ThreadState == ThreadState.Running)
consoleInputThread.Abort();
StardewModdingAPI.Log.Verbose("Game Execution Finished");
StardewModdingAPI.Log.Verbose("Shutting Down...");
Thread.Sleep(100);
Environment.Exit(0);
//Begin listening to input
consoleInputThread.Start();
while (ready)
{
//Check if the game is still running 10 times a second
Thread.Sleep(1000 / 10);
}
//abort the thread, we're closing
if (consoleInputThread != null && consoleInputThread.ThreadState == ThreadState.Running)
consoleInputThread.Abort();
StardewModdingAPI.Log.Verbose("Game Execution Finished");
StardewModdingAPI.Log.Verbose("Shutting Down...");
Thread.Sleep(100);
Environment.Exit(0);
}
/// <summary>
@ -241,186 +203,266 @@ namespace StardewModdingAPI
}
}
catch (Exception ex)
{
{
StardewModdingAPI.Log.Error("Could not create a path: " + path + "\n\n" + ex);
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static void RunGame()
{
Application.ThreadException += StardewModdingAPI.Log.Application_ThreadException;
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
AppDomain.CurrentDomain.UnhandledException += StardewModdingAPI.Log.CurrentDomain_UnhandledException;
try
{
gamePtr = new SGame();
StardewModdingAPI.Log.Verbose("Patching SDV Graphics Profile...");
Game1.graphics.GraphicsProfile = GraphicsProfile.HiDef;
LoadMods();
StardewForm = Control.FromHandle(Program.gamePtr.Window.Handle).FindForm();
StardewForm.Closing += StardewForm_Closing;
ready = true;
StardewGameInfo.SetValue(StardewProgramType, gamePtr);
gamePtr.Run();
#region deprecated
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
//I'm leaving this here in case the community is interested
//StardewInjectorMod.Entry(true);
Type gt = StardewAssembly.GetType("StardewValley.Game1", true);
gamePtr = (SGame)Activator.CreateInstance(gt);
ready = true;
StardewGameInfo.SetValue(StardewProgramType, gamePtr);
gamePtr.Run();
}
#endregion
}
catch (Exception ex)
{
StardewModdingAPI.Log.Error("Game failed to start: " + ex);
}
}
static void StardewForm_Closing(object sender, CancelEventArgs e)
{
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)
{
gamePtr.Exit();
gamePtr.Dispose();
StardewForm.Hide();
ready = false;
}
}
public static void LoadMods()
{
StardewModdingAPI.Log.Verbose("LOADING MODS");
int loadedMods = 0;
foreach (string ModPath in _modPaths)
{
foreach (String s in Directory.GetFiles(ModPath, "*.dll"))
{
if (s.Contains("StardewInjector"))
continue;
StardewModdingAPI.Log.Success("Found 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.Verbose("Loading Mod DLL...");
TypeInfo tar = mod.DefinedTypes.First(x => x.BaseType == typeof(Mod));
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);
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);
}
}
}
StardewModdingAPI.Log.Success("LOADED {0} MODS", loadedMods);
}
public static void ConsoleInputThread()
{
string input = string.Empty;
while (true)
{
Command.CallCommand(Console.ReadLine());
}
}
static void Events_LoadContent(object o, EventArgs e)
{
StardewModdingAPI.Log.Info("Initializing Debug Assets...");
DebugPixel = new Texture2D(Game1.graphics.GraphicsDevice, 1, 1);
public static void RunGame()
{
Application.ThreadException += StardewModdingAPI.Log.Application_ThreadException;
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
AppDomain.CurrentDomain.UnhandledException += StardewModdingAPI.Log.CurrentDomain_UnhandledException;
try
{
gamePtr = new SGame();
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;
ready = true;
StardewGameInfo.SetValue(StardewProgramType, gamePtr);
gamePtr.Run();
#region deprecated
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
//I'm leaving this here in case the community is interested
//StardewInjectorMod.Entry(true);
Type gt = StardewAssembly.GetType("StardewValley.Game1", true);
gamePtr = (SGame)Activator.CreateInstance(gt);
ready = true;
StardewGameInfo.SetValue(StardewProgramType, gamePtr);
gamePtr.Run();
}
#endregion
}
catch (Exception ex)
{
StardewModdingAPI.Log.Error("Game failed to start: " + ex);
}
}
static void StardewForm_Closing(object sender, CancelEventArgs e)
{
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)
{
gamePtr.Exit();
gamePtr.Dispose();
StardewForm.Hide();
ready = false;
}
}
public static void LoadMods()
{
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"))
{
if (s.Contains("StardewInjector"))
continue;
StardewModdingAPI.Log.Success("Found 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.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();
}
else
{
StardewModdingAPI.Log.Error("Invalid Mod DLL");
}
}
catch (Exception ex)
{
StardewModdingAPI.Log.Error("Failed to load mod '{0}'. Exception details:\n" + ex, s);
}
}
}
StardewModdingAPI.Log.Error("LOADED {0} MODS THAT NEED TO UPDATE", loadedMods);
}
public static void ConsoleInputThread()
{
string input = string.Empty;
while (true)
{
Command.CallCommand(Console.ReadLine());
}
}
static void Events_LoadContent(object o, EventArgs e)
{
StardewModdingAPI.Log.Info("Initializing Debug Assets...");
DebugPixel = new Texture2D(Game1.graphics.GraphicsDevice, 1, 1);
DebugPixel.SetData(new Color[] { Color.White });
#if DEBUG
StardewModdingAPI.Log.Verbose("REGISTERING BASE CUSTOM ITEM");
SObject so = new SObject();
so.Name = "Mario Block";
so.CategoryName = "SMAPI Test Mod";
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.IsPassable = true;
so.IsPlaceable = true;
StardewModdingAPI.Log.Verbose("REGISTERED WITH ID OF: " + SGame.RegisterModItem(so));
//StardewModdingAPI.Log.Verbose("REGISTERING SECOND CUSTOM ITEM");
//SObject so2 = new SObject();
//so2.Name = "Mario Painting";
//so2.CategoryName = "SMAPI Test Mod";
//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.IsPassable = true;
//so2.IsPlaceable = true;
//StardewModdingAPI.Log.Verbose("REGISTERED WITH ID OF: " + SGame.RegisterModItem(so2));
Command.CallCommand("load");
#endif
}
static void Events_KeyPressed(object o, EventArgsKeyPressed e)
#if DEBUG
StardewModdingAPI.Log.Verbose("REGISTERING BASE CUSTOM ITEM");
SObject so = new SObject();
so.Name = "Mario Block";
so.CategoryName = "SMAPI Test Mod";
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.IsPassable = true;
so.IsPlaceable = true;
StardewModdingAPI.Log.Verbose("REGISTERED WITH ID OF: " + SGame.RegisterModItem(so));
//StardewModdingAPI.Log.Verbose("REGISTERING SECOND CUSTOM ITEM");
//SObject so2 = new SObject();
//so2.Name = "Mario Painting";
//so2.CategoryName = "SMAPI Test Mod";
//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.IsPassable = true;
//so2.IsPlaceable = true;
//StardewModdingAPI.Log.Verbose("REGISTERED WITH ID OF: " + SGame.RegisterModItem(so2));
Command.CallCommand("load");
#endif
}
static void Events_KeyPressed(object o, EventArgsKeyPressed e)
{
}
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)
}
static void Events_MenuChanged(IClickableMenu newMenu)
{
#if DEBUG
SGame.ModLocations = SGameLocation.ConstructFromBaseClasses(Game1.locations);
#endif
}
static void Events_CurrentLocationChanged(GameLocation newLocation)
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
SGame.ModLocations = SGameLocation.ConstructFromBaseClasses(Game1.locations);
#endif
}
static void Events_CurrentLocationChanged(GameLocation newLocation)
{
//SGame.CurrentLocation = null;
//System.Threading.Thread.Sleep(10);
#if DEBUG
Console.WriteLine(newLocation.name);
SGame.CurrentLocation = SGame.LoadOrCreateSGameLocationFromName(newLocation.name);
#endif
//Game1.currentLocation = SGame.CurrentLocation;
//Log.LogComment(((SGameLocation) newLocation).name);
//Log.LogComment("LOC CHANGED: " + SGame.currentLocation.name);
}
public static void StardewInvoke(Action a)
{
StardewForm.Invoke(a);
#if DEBUG
Console.WriteLine(newLocation.name);
SGame.CurrentLocation = SGame.LoadOrCreateSGameLocationFromName(newLocation.name);
#endif
//Game1.currentLocation = SGame.CurrentLocation;
//Log.LogComment(((SGameLocation) newLocation).name);
//Log.LogComment("LOC CHANGED: " + SGame.currentLocation.name);
}
public static void StardewInvoke(Action a)
{
StardewForm.Invoke(a);
}
static void help_CommandFired(object o, EventArgsCommand e)
@ -442,66 +484,66 @@ namespace StardewModdingAPI
StardewModdingAPI.Log.Info("Commands: " + Command.RegisteredCommands.Select(x => x.CommandName).ToSingular());
}
#region Logging
[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)
#region Logging
[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)
{
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")]
public static void LogColour(ConsoleColor c, object o, params object[] 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")]
public static void LogInfo(object o, params object[] 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")]
public static void LogError(object o, params object[] 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")]
public static void LogDebug(object o, params object[] 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")]
public static void LogValueNotSpecified()
{
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")]
public static void LogObjectValueNotSpecified()
{
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")]
public static void LogValueInvalid()
{
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")]
public static void LogObjectInvalid()
{
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")]
public static void LogValueNotInt32()
{
StardewModdingAPI.Log.Error("<value> must be a whole number (Int32)");
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")]
public static void LogColour(ConsoleColor c, object o, params object[] 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")]
public static void LogInfo(object o, params object[] 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")]
public static void LogError(object o, params object[] 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")]
public static void LogDebug(object o, params object[] 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")]
public static void LogValueNotSpecified()
{
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")]
public static void LogObjectValueNotSpecified()
{
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")]
public static void LogValueInvalid()
{
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")]
public static void LogObjectInvalid()
{
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")]
public static void LogValueNotInt32()
{
StardewModdingAPI.Log.Error("<value> must be a whole number (Int32)");
}
#endregion
}
}
}

View File

@ -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">

View File

@ -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>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Weavers>
</Weavers>

View File

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

View File

@ -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>

7
TrainerMod/manifest.json Normal file
View File

@ -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"
}

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>