2016-02-28 19:55:35 +08:00
using System ;
2016-03-02 07:44:41 +08:00
using System.CodeDom.Compiler ;
2016-02-28 19:55:35 +08:00
using System.Collections.Generic ;
using System.ComponentModel ;
using System.IO ;
using System.Linq ;
using System.Reflection ;
2016-03-01 14:35:52 +08:00
using System.Reflection.Emit ;
2016-02-28 19:55:35 +08:00
using System.Text ;
using System.Threading ;
using System.Threading.Tasks ;
using System.Windows.Forms ;
2016-03-02 07:44:41 +08:00
using Microsoft.CSharp ;
2016-02-28 19:55:35 +08:00
using Microsoft.Xna.Framework ;
using Microsoft.Xna.Framework.Graphics ;
using Microsoft.Xna.Framework.Input ;
2016-02-29 11:16:32 +08:00
using StardewModdingAPI.Inheritance ;
2016-03-01 14:35:52 +08:00
using StardewModdingAPI.Inheritance.Menus ;
2016-02-28 19:55:35 +08:00
using StardewValley ;
using StardewValley.Menus ;
2016-02-29 09:26:36 +08:00
using StardewValley.Minigames ;
2016-02-28 19:55:35 +08:00
using StardewValley.Network ;
2016-02-29 18:21:45 +08:00
using StardewValley.Tools ;
2016-02-28 19:55:35 +08:00
using Keys = Microsoft . Xna . Framework . Input . Keys ;
2016-02-29 18:21:45 +08:00
using Object = StardewValley . Object ;
2016-03-04 22:05:36 +08:00
using StardewModdingAPI.Events ;
2016-02-28 19:55:35 +08:00
namespace StardewModdingAPI
{
public class Program
{
2016-03-01 02:22:24 +08:00
public static string ExecutionPath { get ; private set ; }
2016-02-28 19:55:35 +08:00
public static string DataPath = Path . Combine ( Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . ApplicationData ) , "StardewValley" ) ) ;
2016-03-02 07:44:41 +08:00
public static List < string > ModPaths = new List < string > ( ) ;
public static List < string > ModContentPaths = new List < string > ( ) ;
2016-03-01 02:39:21 +08:00
public static string LogPath = Path . Combine ( Path . Combine ( Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . ApplicationData ) , "StardewValley" ) ) , "ErrorLogs" ) ;
2016-03-01 04:01:41 +08:00
public static string CurrentLog { get ; private set ; }
public static StreamWriter LogStream { get ; private set ; }
2016-02-28 19:55:35 +08:00
2016-03-01 15:16:35 +08:00
public static Texture2D DebugPixel { get ; private set ; }
2016-02-29 09:26:36 +08:00
public static SGame gamePtr ;
2016-02-28 19:55:35 +08:00
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 ;
2016-03-03 12:38:51 +08:00
public const string Version = "0.36 Alpha" ;
2016-03-05 04:20:58 +08:00
public const bool debug = false ;
2016-03-02 21:28:20 +08:00
public static bool disableLogging { get ; private set ; }
2016-03-02 08:36:12 +08:00
2016-03-04 03:01:32 +08:00
public static bool StardewInjectorLoaded { get ; private set ; }
public static Mod StardewInjectorMod { get ; private set ; }
2016-02-28 19:55:35 +08:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2016-03-03 11:54:37 +08:00
2016-02-28 19:55:35 +08:00
private static void Main ( string [ ] args )
{
Console . Title = "Stardew Modding API Console" ;
2016-03-02 08:36:12 +08:00
Console . Title + = " - Version " + Version ;
if ( debug )
2016-03-03 12:38:51 +08:00
Console . Title + = " - DEBUG IS NOT FALSE, AUTHOUR NEEDS TO REUPLOAD THIS VERSION" ;
2016-03-03 01:24:15 +08:00
//TODO: Have an app.config and put the paths inside it so users can define locations to load mods from
2016-03-01 02:22:24 +08:00
ExecutionPath = Path . GetDirectoryName ( Assembly . GetExecutingAssembly ( ) . Location ) ;
2016-03-02 07:44:41 +08:00
ModPaths . Add ( Path . Combine ( Path . Combine ( Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . ApplicationData ) , "StardewValley" ) ) , "Mods" ) ) ;
ModPaths . Add ( Path . Combine ( ExecutionPath , "Mods" ) ) ;
2016-03-02 12:12:19 +08:00
ModPaths . Add ( Path . Combine ( Path . Combine ( ExecutionPath , "Mods" ) , "Content" ) ) ;
2016-03-02 07:44:41 +08:00
ModContentPaths . Add ( Path . Combine ( Path . Combine ( Path . Combine ( Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . ApplicationData ) , "StardewValley" ) ) , "Mods" ) , "Content" ) ) ;
2016-03-03 01:24:15 +08:00
//Checks that all defined modpaths exist as directories
2016-03-02 07:44:41 +08:00
foreach ( string ModPath in ModPaths )
{
2016-03-02 12:12:19 +08:00
try
{
if ( File . Exists ( ModPath ) )
File . Delete ( ModPath ) ;
if ( ! Directory . Exists ( ModPath ) )
Directory . CreateDirectory ( ModPath ) ;
}
catch ( Exception ex )
{
LogError ( "Could not create a missing ModPath: " + ModPath + "\n\n" + ex ) ;
}
2016-03-02 07:44:41 +08:00
}
2016-03-03 01:24:15 +08:00
//Same for content
2016-03-02 07:44:41 +08:00
foreach ( string ModContentPath in ModContentPaths )
{
2016-03-02 12:12:19 +08:00
try
{
if ( ! Directory . Exists ( ModContentPath ) )
Directory . CreateDirectory ( ModContentPath ) ;
}
catch ( Exception ex )
{
LogError ( "Could not create a missing ModContentPath: " + ModContentPath + "\n\n" + ex ) ;
}
}
2016-03-03 01:24:15 +08:00
//And then make sure we have an errorlog dir
2016-03-02 12:12:19 +08:00
try
{
2016-03-02 21:28:20 +08:00
if ( ! Directory . Exists ( LogPath ) )
2016-03-02 12:12:19 +08:00
Directory . CreateDirectory ( LogPath ) ;
}
catch ( Exception ex )
{
LogError ( "Could not create the missing ErrorLogs path: " + LogPath + "\n\n" + ex ) ;
2016-03-02 07:44:41 +08:00
}
2016-03-03 01:24:15 +08:00
//Define the path to the current log file
CurrentLog = LogPath + "\\MODDED_ProgramLog_LATEST" /* + System.DateTime.Now.Ticks + */ + ".txt" ;
2016-03-01 04:01:41 +08:00
Log ( ExecutionPath , false ) ;
2016-03-03 01:24:15 +08:00
//Create a writer to the log file
2016-03-02 21:28:20 +08:00
try
{
LogStream = new StreamWriter ( CurrentLog , false ) ;
}
catch ( Exception ex )
{
disableLogging = true ;
LogError ( "Could not initialize LogStream - Logging is disabled" ) ;
}
2016-03-01 04:01:41 +08:00
2016-03-03 01:24:15 +08:00
2016-02-28 19:55:35 +08:00
LogInfo ( "Initializing SDV Assembly..." ) ;
2016-03-01 04:01:41 +08:00
if ( ! File . Exists ( ExecutionPath + "\\Stardew Valley.exe" ) )
{
2016-03-03 01:24:15 +08:00
//If the api isn't next to SDV.exe then terminate. Though it'll crash before we even get here w/o sdv.exe. Perplexing.
2016-03-01 04:01:41 +08:00
LogError ( "Could not find: " + ExecutionPath + "\\Stardew Valley.exe" ) ;
LogError ( "The API will now terminate." ) ;
Console . ReadKey ( ) ;
Environment . Exit ( - 4 ) ;
}
2016-03-01 14:35:52 +08:00
2016-03-03 01:24:15 +08:00
//Load in that assembly. Also, ignore security :D
StardewAssembly = Assembly . UnsafeLoadFrom ( ExecutionPath + "\\Stardew Valley.exe" ) ;
2016-03-04 03:01:32 +08:00
2016-03-04 06:08:40 +08:00
//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
2016-03-04 03:01:32 +08:00
foreach ( string ModPath in ModPaths )
{
foreach ( String s in Directory . GetFiles ( ModPath , "StardewInjector.dll" ) )
{
LogColour ( ConsoleColor . Green , "Found Stardew Injector DLL: " + s ) ;
try
{
Assembly mod = Assembly . UnsafeLoadFrom ( s ) ; //to combat internet-downloaded DLLs
2016-03-04 06:08:40 +08:00
if ( mod . DefinedTypes . Count ( x = > x . BaseType = = typeof ( Mod ) ) > 0 )
2016-03-04 03:01:32 +08:00
{
LogColour ( ConsoleColor . Green , "Loading Injector DLL..." ) ;
2016-03-04 06:08:40 +08:00
TypeInfo tar = mod . DefinedTypes . First ( x = > x . BaseType = = typeof ( Mod ) ) ;
Mod m = ( Mod ) mod . CreateInstance ( tar . ToString ( ) ) ;
2016-03-04 03:01:32 +08:00
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
{
LogError ( "Invalid Mod DLL" ) ;
}
}
catch ( Exception ex )
{
LogError ( "Failed to load mod '{0}'. Exception details:\n" + ex , s ) ;
}
}
}
2016-02-28 19:55:35 +08:00
StardewProgramType = StardewAssembly . GetType ( "StardewValley.Program" , true ) ;
StardewGameInfo = StardewProgramType . GetField ( "gamePtr" ) ;
2016-03-04 06:08:40 +08:00
#region deprecated
2016-03-04 03:01:32 +08:00
/ *
2016-03-04 06:08:40 +08:00
* Lol no . I tried though .
2016-03-04 03:01:32 +08:00
if ( File . Exists ( ExecutionPath + "\\Stardew_Injector.exe" ) )
{
//Stardew_Injector Mode
StardewInjectorLoaded = true ;
Program . LogInfo ( "STARDEW_INJECTOR DETECTED, LAUNCHING USING INJECTOR CALLS" ) ;
Assembly inj = Assembly . UnsafeLoadFrom ( ExecutionPath + "\\Stardew_Injector.exe" ) ;
Type prog = inj . GetType ( "Stardew_Injector.Program" , true ) ;
FieldInfo hooker = prog . GetField ( "hooker" , BindingFlags . NonPublic | BindingFlags . Static ) ;
//hook.GetMethod("Initialize").Invoke(hooker.GetValue(null), null);
//customize the initialize method for SGame instead of Game
Assembly cecil = Assembly . UnsafeLoadFrom ( ExecutionPath + "\\Mono.Cecil.dll" ) ;
Type assDef = cecil . GetType ( "Mono.Cecil.AssemblyDefinition" ) ;
var aDefs = assDef . GetMethods ( BindingFlags . Public | BindingFlags . Static ) ;
var aDef = aDefs . First ( x = > x . ToString ( ) . Contains ( "ReadAssembly(System.String)" ) ) ;
var theAssDef = aDef . Invoke ( null , new object [ ] { Assembly . GetExecutingAssembly ( ) . Location } ) ;
var modDef = assDef . GetProperty ( "MainModule" , BindingFlags . Public | BindingFlags . Instance ) ;
var theModDef = modDef . GetValue ( theAssDef ) ;
Console . WriteLine ( "MODDEF: " + theModDef ) ;
Type hook = inj . GetType ( "Stardew_Injector.Stardew_Hooker" , true ) ;
hook . GetField ( "m_vAsmDefinition" , BindingFlags . NonPublic | BindingFlags . Instance ) . SetValue ( hooker . GetValue ( null ) , theAssDef ) ;
hook . GetField ( "m_vModDefinition" , BindingFlags . NonPublic | BindingFlags . Instance ) . SetValue ( hooker . GetValue ( null ) , theModDef ) ;
//hook.GetMethod("Initialize").Invoke(hooker.GetValue(null), null);
hook . GetMethod ( "ApplyHooks" ) . Invoke ( hooker . GetValue ( null ) , null ) ;
//hook.GetMethod("Finalize").Invoke(hooker.GetValue(null), null);
//hook.GetMethod("Run").Invoke(hooker.GetValue(null), null);
Console . ReadKey ( ) ;
//Now go back and load Stardew through SMAPI
}
* /
2016-03-04 06:08:40 +08:00
#endregion
2016-03-04 03:01:32 +08:00
2016-03-03 01:24:15 +08:00
//Change the game's version
2016-02-28 19:55:35 +08:00
LogInfo ( "Injecting New SDV Version..." ) ;
2016-03-02 12:12:19 +08:00
Game1 . version + = "-Z_MODDED | SMAPI " + Version ;
2016-02-28 19:55:35 +08:00
2016-03-03 01:24:15 +08:00
//Create the thread for the game to run in.
2016-02-28 19:55:35 +08:00
gameThread = new Thread ( RunGame ) ;
LogInfo ( "Starting SDV..." ) ;
gameThread . Start ( ) ;
2016-03-03 01:24:15 +08:00
//I forget.
2016-03-01 14:35:52 +08:00
SGame . GetStaticFields ( ) ;
2016-02-28 19:55:35 +08:00
while ( ! ready )
{
2016-03-03 01:24:15 +08:00
//Wait for the game to load up
2016-02-28 19:55:35 +08:00
}
2016-03-03 01:24:15 +08:00
//SDV is running
2016-02-28 19:55:35 +08:00
Log ( "SDV Loaded Into Memory" ) ;
2016-03-03 01:24:15 +08:00
//Create definition to listen for input
2016-02-28 19:55:35 +08:00
LogInfo ( "Initializing Console Input Thread..." ) ;
2016-03-03 01:24:15 +08:00
consoleInputThread = new Thread ( ConsoleInputThread ) ;
2016-03-02 05:16:51 +08:00
2016-03-04 04:06:25 +08:00
//The only command in the API (at least it should be, for now)\
2016-03-02 05:16:51 +08:00
Command . RegisterCommand ( "help" , "Lists all commands | 'help <cmd>' returns command description" ) . CommandFired + = help_CommandFired ;
2016-03-03 01:24:15 +08:00
//Command.RegisterCommand("crash", "crashes sdv").CommandFired += delegate { Game1.player.draw(null); };
2016-02-28 19:55:35 +08:00
2016-03-03 01:24:15 +08:00
//Subscribe to events
2016-03-04 22:05:36 +08:00
Events . ControlEvents . KeyPressed + = Events_KeyPressed ;
Events . GameEvents . LoadContent + = Events_LoadContent ;
2016-03-03 01:24:15 +08:00
//Events.MenuChanged += Events_MenuChanged; //Idk right now
if ( debug )
{
//Experimental
2016-03-03 11:54:37 +08:00
//Events.LocationsChanged += Events_LocationsChanged;
//Events.CurrentLocationChanged += Events_CurrentLocationChanged;
2016-03-03 01:24:15 +08:00
}
2016-02-28 19:55:35 +08:00
2016-03-03 01:24:15 +08:00
//Do tweaks using winforms invoke because I'm lazy
2016-02-28 19:55:35 +08:00
LogInfo ( "Applying Final SDV Tweaks..." ) ;
StardewInvoke ( ( ) = >
{
gamePtr . IsMouseVisible = false ;
2016-03-01 04:04:39 +08:00
gamePtr . Window . Title = "Stardew Valley - Version " + Game1 . version ;
2016-03-04 22:05:36 +08:00
StardewForm . Resize + = Events . GraphicsEvents . InvokeResize ;
2016-02-28 19:55:35 +08:00
} ) ;
2016-03-03 01:24:15 +08:00
//Game's in memory now, send the event
2016-02-28 19:55:35 +08:00
LogInfo ( "Game Loaded" ) ;
2016-03-04 22:05:36 +08:00
Events . GameEvents . InvokeGameLoaded ( ) ;
2016-03-01 04:01:41 +08:00
2016-03-01 14:35:52 +08:00
LogColour ( ConsoleColor . Cyan , "Type 'help' for help, or 'help <cmd>' for a command's usage" ) ;
2016-03-03 01:24:15 +08:00
//Begin listening to input
consoleInputThread . Start ( ) ;
2016-03-01 14:35:52 +08:00
2016-03-01 04:01:41 +08:00
while ( ready )
{
//Check if the game is still running 10 times a second
Thread . Sleep ( 1000 / 10 ) ;
}
2016-03-03 01:24:15 +08:00
//abort the thread, we're closing
2016-03-01 04:01:41 +08:00
if ( consoleInputThread ! = null & & consoleInputThread . ThreadState = = ThreadState . Running )
consoleInputThread . Abort ( ) ;
LogInfo ( "Game Execution Finished" ) ;
LogInfo ( "Shutting Down..." ) ;
2016-03-03 01:24:15 +08:00
Thread . Sleep ( 100 ) ;
/ *
2016-03-01 04:01:41 +08:00
int time = 0 ;
int step = 100 ;
2016-03-01 14:35:52 +08:00
int target = 1000 ;
2016-03-01 04:01:41 +08:00
while ( true )
{
time + = step ;
Thread . Sleep ( step ) ;
Console . Write ( "." ) ;
if ( time > = target )
break ;
}
2016-03-03 01:24:15 +08:00
* /
2016-03-01 04:01:41 +08:00
Environment . Exit ( 0 ) ;
2016-02-28 19:55:35 +08:00
}
2016-03-01 14:35:52 +08:00
2016-03-01 02:39:21 +08:00
2016-02-28 19:55:35 +08:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2016-02-29 05:01:24 +08:00
2016-02-28 19:55:35 +08:00
public static void RunGame ( )
{
2016-03-03 01:24:15 +08:00
//Does this even do anything???
Application . ThreadException + = Application_ThreadException ;
Application . SetUnhandledExceptionMode ( UnhandledExceptionMode . CatchException ) ;
AppDomain . CurrentDomain . UnhandledException + = CurrentDomain_UnhandledException ;
//I've yet to see it called :|
2016-02-28 19:55:35 +08:00
try
{
2016-02-29 09:26:36 +08:00
gamePtr = new SGame ( ) ;
2016-03-01 04:01:41 +08:00
LogInfo ( "Patching SDV Graphics Profile..." ) ;
2016-02-28 19:55:35 +08:00
Game1 . graphics . GraphicsProfile = GraphicsProfile . HiDef ;
LoadMods ( ) ;
StardewForm = Control . FromHandle ( Program . gamePtr . Window . Handle ) . FindForm ( ) ;
2016-03-01 04:01:41 +08:00
StardewForm . Closing + = StardewForm_Closing ;
2016-02-28 19:55:35 +08:00
ready = true ;
2016-03-04 06:08:40 +08:00
StardewGameInfo . SetValue ( StardewProgramType , gamePtr ) ;
gamePtr . Run ( ) ;
#region deprecated
if ( false )
2016-03-04 03:01:32 +08:00
{
2016-03-04 06:08:40 +08:00
//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
2016-03-04 03:01:32 +08:00
//StardewInjectorMod.Entry(true);
2016-03-04 06:08:40 +08:00
Type gt = StardewAssembly . GetType ( "StardewValley.Game1" , true ) ;
gamePtr = ( SGame ) Activator . CreateInstance ( gt ) ;
ready = true ;
2016-03-04 04:06:25 +08:00
StardewGameInfo . SetValue ( StardewProgramType , gamePtr ) ;
gamePtr . Run ( ) ;
2016-03-04 03:04:29 +08:00
}
2016-03-04 06:08:40 +08:00
#endregion
2016-03-04 03:04:29 +08:00
}
catch ( Exception ex )
{
LogError ( "Game failed to start: " + ex ) ;
}
}
static void StardewForm_Closing ( object sender , CancelEventArgs e )
{
e . Cancel = true ;
2016-03-04 06:08:40 +08:00
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 ;
}
2016-03-04 03:04:29 +08:00
}
public static void LoadMods ( )
{
LogColour ( ConsoleColor . Green , "LOADING MODS" ) ;
int loadedMods = 0 ;
foreach ( string ModPath in ModPaths )
{
foreach ( String s in Directory . GetFiles ( ModPath , "*.dll" ) )
{
2016-03-04 04:06:25 +08:00
if ( s . Contains ( "StardewInjector" ) )
continue ;
2016-03-04 03:04:29 +08:00
LogColour ( ConsoleColor . Green , "Found DLL: " + s ) ;
try
{
Assembly mod = Assembly . UnsafeLoadFrom ( s ) ; //to combat internet-downloaded DLLs
if ( mod . DefinedTypes . Count ( x = > x . BaseType = = typeof ( Mod ) ) > 0 )
{
LogColour ( ConsoleColor . Green , "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
{
LogError ( "Invalid Mod DLL" ) ;
}
}
catch ( Exception ex )
{
LogError ( "Failed to load mod '{0}'. Exception details:\n" + ex , s ) ;
}
}
}
LogColour ( ConsoleColor . Green , "LOADED {0} MODS" , loadedMods ) ;
}
public static void ConsoleInputThread ( )
{
string input = string . Empty ;
while ( true )
{
Command . CallCommand ( Console . ReadLine ( ) ) ;
}
}
2016-03-04 04:06:25 +08:00
static void Events_LoadContent ( object o , EventArgs e )
2016-03-04 03:04:29 +08:00
{
LogInfo ( "Initializing Debug Assets..." ) ;
DebugPixel = new Texture2D ( Game1 . graphics . GraphicsDevice , 1 , 1 ) ;
DebugPixel . SetData ( new Color [ ] { Color . White } ) ;
if ( debug )
{
LogColour ( ConsoleColor . Magenta , "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 ;
LogColour ( ConsoleColor . Cyan , "REGISTERED WITH ID OF: " + SGame . RegisterModItem ( so ) ) ;
LogColour ( ConsoleColor . Magenta , "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 ;
LogColour ( ConsoleColor . Cyan , "REGISTERED WITH ID OF: " + SGame . RegisterModItem ( so2 ) ) ;
}
if ( debug )
Command . CallCommand ( "load" ) ;
}
2016-03-04 04:06:25 +08:00
static void Events_KeyPressed ( object o , EventArgsKeyPressed e )
2016-03-04 03:04:29 +08:00
{
}
static void Events_MenuChanged ( IClickableMenu newMenu )
{
LogInfo ( "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 ) ;
}
}
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 ) ;
}
//Game1.currentLocation = SGame.CurrentLocation;
//LogInfo(((SGameLocation) newLocation).name);
//LogInfo("LOC CHANGED: " + SGame.currentLocation.name);
}
public static void StardewInvoke ( Action a )
{
StardewForm . Invoke ( a ) ;
}
static void CurrentDomain_UnhandledException ( object sender , UnhandledExceptionEventArgs e )
{
Console . WriteLine ( "An exception has been caught" ) ;
File . WriteAllText ( Program . LogPath + "\\MODDED_ErrorLog_" + Extensions . Random . Next ( 100000000 , 999999999 ) + ".txt" , e . ExceptionObject . ToString ( ) ) ;
}
static void Application_ThreadException ( object sender , ThreadExceptionEventArgs e )
{
Console . WriteLine ( "A thread exception has been caught" ) ;
File . WriteAllText ( Program . LogPath + "\\MODDED_ErrorLog_" + Extensions . Random . Next ( 100000000 , 999999999 ) + ".txt" , e . Exception . ToString ( ) ) ;
}
2016-03-04 04:06:25 +08:00
static void help_CommandFired ( object o , EventArgsCommand e )
2016-03-04 03:04:29 +08:00
{
2016-03-04 04:06:25 +08:00
if ( e . Command . CalledArgs . Length > 0 )
2016-03-04 03:04:29 +08:00
{
2016-03-04 04:06:25 +08:00
Command fnd = Command . FindCommand ( e . Command . CalledArgs [ 0 ] ) ;
2016-03-04 03:04:29 +08:00
if ( fnd = = null )
LogError ( "The command specified could not be found" ) ;
else
{
if ( fnd . CommandArgs . Length > 0 )
LogInfo ( "{0}: {1} - {2}" , fnd . CommandName , fnd . CommandDesc , fnd . CommandArgs . ToSingular ( ) ) ;
else
LogInfo ( "{0}: {1}" , fnd . CommandName , fnd . CommandDesc ) ;
}
}
else
LogInfo ( "Commands: " + Command . RegisteredCommands . Select ( x = > x . CommandName ) . ToSingular ( ) ) ;
}
#region Logging
public static void Log ( object o , params object [ ] format )
{
if ( format . Length > 0 )
{
if ( format [ 0 ] is bool )
{
if ( ( bool ) format [ 0 ] = = false )
{
//suppress logging to file
Console . WriteLine ( "[{0}] {1}" , System . DateTime . Now . ToLongTimeString ( ) , String . Format ( o . ToString ( ) , format ) ) ;
return ;
}
}
}
string toLog = string . Format ( "[{0}] {1}" , System . DateTime . Now . ToLongTimeString ( ) , String . Format ( o . ToString ( ) , format ) ) ;
Console . WriteLine ( toLog ) ;
if ( ! disableLogging )
{
LogStream . WriteLine ( toLog ) ;
LogStream . Flush ( ) ;
}
}
public static void LogColour ( ConsoleColor c , object o , params object [ ] format )
{
Console . ForegroundColor = c ;
Log ( o . ToString ( ) , format ) ;
Console . ForegroundColor = ConsoleColor . Gray ;
}
public static void LogInfo ( object o , params object [ ] format )
{
Console . ForegroundColor = ConsoleColor . Yellow ;
Log ( o . ToString ( ) , format ) ;
Console . ForegroundColor = ConsoleColor . Gray ;
}
public static void LogError ( object o , params object [ ] format )
{
Console . ForegroundColor = ConsoleColor . Red ;
Log ( o . ToString ( ) , format ) ;
Console . ForegroundColor = ConsoleColor . Gray ;
}
public static void LogDebug ( object o , params object [ ] format )
{
if ( ! debug )
return ;
Console . ForegroundColor = ConsoleColor . DarkYellow ;
Log ( o . ToString ( ) , format ) ;
Console . ForegroundColor = ConsoleColor . Gray ;
}
public static void LogValueNotSpecified ( )
{
LogError ( "<value> must be specified" ) ;
}
public static void LogObjectValueNotSpecified ( )
{
LogError ( "<object> and <value> must be specified" ) ;
}
public static void LogValueInvalid ( )
{
LogError ( "<value> is invalid" ) ;
}
public static void LogObjectInvalid ( )
{
LogError ( "<object> is invalid" ) ;
}
public static void LogValueNotInt32 ( )
{
LogError ( "<value> must be a whole number (Int32)" ) ;
}
#endregion
}
2016-03-04 04:06:25 +08:00
}