muddesigner/MudEngine/GameManagement/Game.cs
Scionwest_cp c3c2d22ec7 MudEngine:
- Login command now automatically disconnects a user if they are currently logged into the server when another user attempts to login with the same credentials.
 - Login command now loads saved players when a character name is entered that has previously been saved.
 - FileManager.GetData() now supports ignoring simi-colons in data files. These can be used as comments if needed.
 - MudEngine.GameManagement.Game.TimeOfDayOptions has been removed from the Game Type. It is now just MudEngine.GameManagement.TimeOfDayOptions.
 - BaseCharacter will no longer try to save the character if the supplied filename is blank
 - BaseCharacter will now send a disconnect message of 'Goodbye!' upon the player being disconnected from the server.
 - ScriptEngine.ScriptPath now returns a absolute path.
 - Script File compilation within ScriptEngine.Initialization is now supported. This allows developers to write their MUD's using Scripts and letting the server compile them during server startup rather than use the ScriptCompiler.exe to pre-compile scripts now.
 - Custom Game Types are now supported. Only 1 Type may inherit from MudEngine.GameManagement.Game at a time. To use, create a file, write a script that inherits from Game and run the server.
 - ScriptEngine.GetObjectOf(string) method adding. Returns a object that inherits from the Type supplied in the parameter.
 - Deleted StartupObject.cs
 - Deleted Startup.dat 

MudOfflineExample:
 - Updated to reflect the TimeOfDayOptions change in MudEngine.csproj

MudServer:
 - Added MyGame.cs inside Debug/bin/scripts. This is a example script showing how to inherit from Game and write a custom Game Type. This Type is used when the Server runs rather than the Engine Game Type.
 - Server startup re-wrote to compile scripts during startup, scan them via the script engine for any custom Types that inherit from Game, and use the if needed instead of the default Engine Type.
 - Server now uses a Settings.ini file to allow configuration of the Script Engine by users. Provides them the ability to now customize where scripts are stored and their file extension.
 - Deleted Scripts.dll, as the Server now generates one at runtime each time it is ran.

As of this commit, users will not need to use C# to compile their MUD's any longer. Compile the Server and run it. Scripts are now fully implemented (however not fully tested).
2010-08-05 17:46:30 -07:00

374 lines
13 KiB
C#

//Microsoft .NET Framework
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Xml.Serialization;
using System.Xml;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
//MUD Engine
using MudEngine.FileSystem;
using MudEngine.GameObjects;
using MudEngine.GameObjects.Characters;
using MudEngine.GameObjects.Environment;
using MudEngine.Scripting;
namespace MudEngine.GameManagement
{
#region Custom Types
public enum TimeOfDayOptions
{
AlwaysDay,
AlwaysNight,
Transition,
}
#endregion
/// <summary>
/// Manages all of the projects settings.
/// </summary>
[XmlInclude(typeof(StartingLocation))]
[XmlInclude(typeof(Currency))]
public class Game
{
#region ==== Properties & Types ====
#region Game Object Setup
/// <summary>
/// Gets or Sets if this game is running in debug mode. Additional information is sent to the log if enabled.
/// </summary>
public static bool IsDebug { get; set; }
/// <summary>
/// Gets or Sets if the game will run with a server or not.
/// </summary>
public bool IsMultiplayer { get; set; }
/// <summary>
/// Gets or Sets if this game is currently running.
/// </summary>
[Browsable(false)]
public bool IsRunning { get; internal set; }
/// <summary>
/// Gets or Sets if all objects will be laoded during server startup. Enabling this results in a slower server start time, but faster object access.
/// </summary>
[Category("Project Settings")]
[Description("If enabled, all objects will be loaded during server startup resulting in a slower server start time, but faster load time during gameplay")]
public bool PreCacheObjects { get; set; }
/// <summary>
/// Gets or Sets the path to the current project
/// </summary>
[Browsable(false)]
public string ProjectPath { get; set; }
/// <summary>
/// Gets or Sets the paths to various project related objects.
/// </summary>
public SaveDataPaths DataPaths { get; set; }
/// <summary>
/// Gets the scripting engine used by the game.
/// </summary>
public ScriptEngine scriptEngine { get; internal set; }
#endregion
#region Game Information
[Category("Company Settings")]
[Description("The name of the Company or Author building the game.")]
/// <summary>
/// Gets or Sets the name of the company
/// </summary>
public string CompanyName { get; set; }
[Category("Company Settings")]
[Description("The website URL that a player can visit to view additional information related to the game")]
/// <summary>
/// Gets or Sets the companies website for this project
/// </summary>
public string Website { get; set; }
[Category("Project Settings")]
[Description("The name of the game displayed to the users, and title bar of the runtime.")]
public string GameTitle { get; set; }
/// <summary>
/// Gets or Sets the current working version of the game.
/// </summary>
[Category("Project Settings")]
[Description("The current working version of the game.")]
public string Version { get; set; }
[Category("Project Settings")]
[Description("Enable or Disable Auto-saving of players when the player travels")]
/// <summary>
/// Gets or Sets if the game autosaves when the player changes locations.
/// </summary>
public bool AutoSave { get; set; }
[Category("Project Settings")]
[Description("Hide Room names from being outputted to the console.")]
/// <summary>
/// Gets or Sets if room names are hidden during console output.
/// </summary>
public bool HideRoomNames { get; set; }
/// <summary>
/// Gets or Sets what time of day the world is currently in.
/// </summary>
[Category("Day Management")]
[Description("Set what time of day the world will take place in.")]
public TimeOfDayOptions TimeOfDay { get; set; }
/// <summary>
/// Gets or Sets how long in minutes it takes to transition from day to night.
/// </summary>
[Category("Day Management")]
[Description("Set how long in minutes it takes to transition from day to night.")]
public int TimeOfDayTransition { get; set; }
/// <summary>
/// Gets or Sets how long in minutes a day lasts in the game world.
/// </summary>
[Category("Day Management")]
[Description("Sets how long in minutes a day lasts in the game world.")]
public int DayLength { get; set; }
[Category("Game Currency")]
[DefaultValue(1)]
[Description("Sets the amount that the base currency is valued at.")]
public uint BaseCurrencyAmount { get; set; }
[Category("Game Currency")]
[DefaultValue("Copper")]
public string BaseCurrencyName { get; set; }
[Browsable(false)]
public List<Currency> CurrencyList { get; set; }
[Category("Environment Settings")]
[ReadOnly(true)]
public Realm InitialRealm
{
get;
private set;
}
/// <summary>
/// Gets the collection of Realms currently stored in the Game.
/// </summary>
public List<Realm> RealmCollection { get; private set; }
/// <summary>
/// The Story that is displayed on initial player entry into the game
/// </summary>
public string Story { get; set; }
#endregion
#region Networking
//TODO: This should be internal only; C# property using get; internal set; so only MudEngine.dll may edit this collection
/// <summary>
/// Collection of players currently running on the server.
/// </summary>
internal BaseCharacter[] PlayerCollection;
/// <summary>
/// Gets the current running Server object.
/// </summary>
public MudEngine.Networking.Server Server { get; internal set; }
/// <summary>
/// Gets or Sets the protocol used by the server.
/// </summary>
public ProtocolType ServerType { get; set; }
/// <summary>
/// Gets or Sets the port that the server will run on
/// </summary>
public int ServerPort { get; set; }
/// <summary>
/// Gets or Sets the maximum number of Players permitted to run on this Games server.
/// </summary>
public int MaximumPlayers { get; set; }
#endregion
#endregion
#region ==== Constructors ====
public Game()
{
//Instance all of the Games Objects.
CurrencyList = new List<Currency>();
scriptEngine = new Scripting.ScriptEngine(this);
RealmCollection = new List<Realm>();
//Prepare the Save Paths for all of our Game objects.
SaveDataPaths paths = new SaveDataPaths();
paths.Environment = FileManager.GetDataPath(SaveDataTypes.Realms);
paths.Players = FileManager.GetDataPath(SaveDataTypes.Player);
DataPaths = paths;
//Setup default settings for the Game
GameTitle = "New Game";
BaseCurrencyAmount = 1;
BaseCurrencyName = "Copper";
Version = "1.0";
Story = "";
//Setup default Networking settings
IsMultiplayer = true;
ServerType = ProtocolType.Tcp;
ServerPort = 555;
MaximumPlayers = 1000;
}
#endregion
#region ==== Methods ====
/// <summary>
/// Starts the game and runs the server if IsMultiplayer is true
/// </summary>
public bool Start()
{
Log.Write("Game Initializing...");
//Setup the scripting engine and load our script library
scriptEngine.Initialize();
/*
* If a custom player script is loaded in the script engine, then the base commands are
* loaded when the script is instanced automatically. If there is no script then these
* don't get loaded and will need to be forced.
* This prevents a duplicate "Loading Commands" message in the server console if the
* player script exists and pre-loads the commands during script instancing in ScriptEngine.Initialize()
*/
Log.Write("Initializing Command Engine...");
if ((CommandEngine.CommandCollection == null) || (CommandEngine.CommandCollection.Count == 0))
CommandEngine.LoadBaseCommands();
if (IsDebug)
{
foreach (string command in CommandEngine.CommandCollection.Keys)
Log.Write("Command Loaded: " + command);
}
//See if we have an Initial Realm set
//TODO: Check for saved Realm files and load
Log.Write("Initializing World...");
foreach (Realm r in RealmCollection)
{
if (r.IsInitialRealm)
{
InitialRealm = r;
break;
}
}
//Check if any the initial room exists or not.
if ((InitialRealm == null) || (InitialRealm.InitialZone == null) || (InitialRealm.InitialZone.InitialRoom == null))
{
Log.Write("ERROR: No initial location defined. Game startup failed!");
return false;
}
else
Log.Write("Initial Location loaded-> " + InitialRealm.Name + "." + InitialRealm.InitialZone.Name + "." + InitialRealm.InitialZone.InitialRoom.Name);
//Start the Telnet server
if (IsMultiplayer)
{
Log.Write("Starting Server...");
this.StartServer();
}
//Game is running now.
IsRunning = true;
Log.Write("Game startup complete.");
return true;
}
/// <summary>
/// Shuts down the Game and Server.
/// </summary>
public void Shutdown()
{
Log.Write("Server shutdown requested...");
//Place ending code here for game shut down.
//TODO: Save content on shutdown.
if (IsMultiplayer)
Server.EndServer();
IsRunning = false;
Log.Write("Shutdown completed...");
}
/// <summary>
/// Adds a Realm to the Games current list of Realms.
/// </summary>
/// <param name="realm"></param>
public void AddRealm(Realm realm)
{
//If this Realm is set as Initial then we need to disable any previously
//set Realms to avoid conflict.
if (realm.IsInitialRealm)
{
foreach (Realm r in RealmCollection)
{
if (r.IsInitialRealm)
{
r.IsInitialRealm = false;
break;
}
}
}
//Set this Realm as the Games initial Realm
if (realm.IsInitialRealm)
InitialRealm = realm;
//TODO: Check for duplicate Realms.
RealmCollection.Add(realm);
}
/// <summary>
/// Gets a Realm currently stored in the Games collection of Realms.
/// </summary>
/// <param name="realmName"></param>
/// <returns></returns>
public Realm GetRealm(string realmName)
{
foreach (Realm realm in RealmCollection)
{
if (realm.Name == realmName)
return realm;
}
return null;
}
/// <summary>
/// Starts the Server.
/// </summary>
private void StartServer()
{
//This is handled by the Game() Constructor
//PlayerCollection = new List<BaseCharacter>(MaximumPlayers);
PlayerCollection = new BaseCharacter[MaximumPlayers];
for (int i = 0; i < MaximumPlayers; i++)
PlayerCollection[i] = new BaseCharacter(this);
Server = new Networking.Server();
Server.Initialize(ServerPort, ref PlayerCollection);
Server.Start();
}
#endregion
}
}