MudEngine:

- Player login now creates the directories needed if they don't exist.
 - Added Update method that serves as the game loop now.
 - Added additional save code to Game.Save() now saves all realms, zones, rooms and players. Called during server shutdown (Game.Shutdown())
 - Began work on implementing a Unique Identifier system for all game objects. 
 - Renamed GetRealm() and GetZone() to GetRealmByID() and GetZoneByID. Now accepts a Int32 instead of a string as the parameter, returning a reference to the object.
 - Added GetRealmByName() and GetZoneByName(). Similar to the old GetRealm and GetZone methods. Accepts a string as a parameter, however it returns a list<> collection of the found objects due to objects with duplicate names are allowed to co-exist in the game world.
 - Temp directory that was being generated during server startup within Game.Start() is now deleted once script compilation is completed.
 - Added GameTime.cs; contains all the properties and methods needed to have a working time system built into the engine for the game world. Not fully complete.
 - Added CommandGetTime.cs which prints the current date and time to the players console. Prints the GameTime.DayNames and GameTime.MonthNames to the player. Defaults to real-world names, however these can be configured and changed, along with the number of days per week, weeks per month, months per year, seconds per minute, minutes per hour and hours per day.

MudGame:
 - Now supports Game.AutoSave. If AutoSave is true, then the server loop will call Game.Save() automatically.
 - Server Game Loop now calls Game.Update() every loop cycle.
This commit is contained in:
Scionwest_cp 2010-08-10 15:10:25 -07:00
parent a2181572d0
commit d212f5b854
12 changed files with 417 additions and 63 deletions

View file

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MudEngine.GameObjects.Characters;
namespace MudEngine.Commands
{
public class CommandGetTime : MudEngine.GameManagement.IGameCommand
{
public string Name { get; set; }
public bool Override { get; set; }
public MudEngine.GameManagement.CommandResults Execute(string command, BaseCharacter player)
{
player.Send(player.ActiveGame.WorldTime.GetCurrentWorldTime());
return new GameManagement.CommandResults();
}
}
}

View file

@ -31,6 +31,9 @@ namespace MudEngine.Commands
string savedFile = "";
//See if this character already exists.
if (!Directory.Exists(player.ActiveGame.DataPaths.Players))
Directory.CreateDirectory(player.ActiveGame.DataPaths.Players);
foreach (string filename in Directory.GetFiles(player.ActiveGame.DataPaths.Players))
{
if (Path.GetFileNameWithoutExtension(filename).ToLower() == input.ToLower())

View file

@ -20,16 +20,6 @@ using MudEngine.Scripting;
namespace MudEngine.GameManagement
{
#region Custom Types
public enum TimeOfDayOptions
{
AlwaysDay,
AlwaysNight,
Transition,
}
#endregion
/// <summary>
/// Manages all of the projects settings.
/// </summary>
@ -78,6 +68,11 @@ namespace MudEngine.GameManagement
[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 a copy of all identifiers being used in the game.
/// </summary>
internal List<Int32> ObjectIdentifierCollection { get; private set; }
#endregion
#region Game Information
@ -141,27 +136,6 @@ namespace MudEngine.GameManagement
/// </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.")]
@ -171,6 +145,8 @@ namespace MudEngine.GameManagement
[Category("Game Currency")]
[DefaultValue("Copper")]
public string BaseCurrencyName { get; set; }
public GameTime WorldTime { get; set; }
#endregion
#region Networking
@ -209,6 +185,7 @@ namespace MudEngine.GameManagement
CurrencyList = new List<Currency>();
scriptEngine = new Scripting.ScriptEngine(this);
RealmCollection = new List<Realm>();
WorldTime = new GameTime(this);
//Prepare the Save Paths for all of our Game objects.
SaveDataPaths paths = new SaveDataPaths();
@ -234,6 +211,20 @@ namespace MudEngine.GameManagement
PlayerCollection = new BaseCharacter[MaximumPlayers];
for (int i = 0; i < MaximumPlayers; i++)
PlayerCollection[i] = new BaseCharacter(this);
GameTime.Time t = new GameTime.Time();
t.Hour = 8;
t.Minute = 0;
t.Second = 0;
t.Day = 1;
t.Month = 1;
t.Year = 2010;
WorldTime.InitialGameTime = t;
WorldTime.DaysPerMonth = 7;
WorldTime.MonthsPerYear = 12;
WorldTime.HoursPerDay = 23;
WorldTime.MinutesPerHour = 59;
WorldTime.SecondsPerMinute = 59;
}
#endregion
@ -307,6 +298,8 @@ namespace MudEngine.GameManagement
PlayerCollection[0].Initialize();
}
WorldTime.Initialize();
//Game is running now.
IsRunning = true;
@ -331,7 +324,12 @@ namespace MudEngine.GameManagement
Log.Write("Shutdown completed...");
}
public void Save()
public virtual void Update()
{
WorldTime.Update();
}
public virtual void Save()
{
Log.Write("Saving Game world....");
@ -344,9 +342,47 @@ namespace MudEngine.GameManagement
Log.Write("Saving " + PlayerCollection[i].Name);
PlayerCollection[i].Save(Path.Combine(DataPaths.Players, PlayerCollection[i].Filename));
}
//Delete the last saved version of the World. We will dump the current version onto disk.
if (Directory.Exists(DataPaths.Environment))
Directory.Delete(DataPaths.Environment, true);
//Re-create the environment directory
Directory.CreateDirectory(DataPaths.Environment);
//Loop through each Realm and save it.
for (int x = 0; x <= RealmCollection.Count - 1; x++)
{
string realmFile = Path.Combine(DataPaths.Environment, RealmCollection[x].Filename);
//Save the Realm
RealmCollection[x].Save(realmFile);
//Loop through each Zone in the Realm and save it.
for (int y = 0; y <= RealmCollection[x].ZoneCollection.Count - 1; y++)
{
string zonePath = Path.Combine(DataPaths.Environment, Path.GetFileNameWithoutExtension(RealmCollection[x].Filename), Path.GetFileNameWithoutExtension(RealmCollection[x].ZoneCollection[y].Filename));
if (!Directory.Exists(zonePath))
Directory.CreateDirectory(zonePath);
//Save the Zone.
RealmCollection[x].ZoneCollection[y].Save(Path.Combine(zonePath, RealmCollection[x].ZoneCollection[y].Filename));
for (int z = 0; z <= RealmCollection[x].ZoneCollection[y].RoomCollection.Count - 1; z++)
{
if (!Directory.Exists(Path.Combine(zonePath, "Rooms")))
Directory.CreateDirectory(Path.Combine(zonePath, "Rooms"));
string roomPath = Path.Combine(zonePath, "Rooms");
RealmCollection[x].ZoneCollection[y].RoomCollection[z].Save(Path.Combine(roomPath, RealmCollection[x].ZoneCollection[y].RoomCollection[z].Filename));
}
}
}
}
public void Load()
public virtual void Load()
{
}
@ -383,12 +419,25 @@ namespace MudEngine.GameManagement
/// </summary>
/// <param name="realmName"></param>
/// <returns></returns>
public Realm GetRealm(string realmName)
public List<Realm> GetRealmByName(string realmName)
{
List<Realm> realms = new List<Realm>();
foreach (Realm realm in RealmCollection)
{
if (realm.Name == realmName)
return realm;
realms.Add(realm);
}
return realms;
}
public Realm GetRealmByID(Guid id)
{
foreach (Realm r in RealmCollection)
{
if (r.ID == id)
return r;
}
return null;

View file

@ -0,0 +1,260 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MudEngine.GameManagement
{
public class GameTime
{
public struct Time
{
public int Year { get; set; }
public int Month { get; set; }
public int Day { get; set; }
public int Hour { get; set; }
public int Minute { get; set; }
public int Second { get; set; }
private GameTime gameTime;
}
public enum TimeOfDayOptions
{
AlwaysDay,
AlwaysNight,
Transition,
}
internal Game ActiveGame { get; private set; }
/// <summary>
/// The time of day that the server actually started up.
/// </summary>
internal DateTime ServerStartTime { get; private set; }
/// <summary>
/// Gets the current World Time.
/// </summary>
public Time CurrentWorldTime { get; internal set; }
/// <summary>
/// Gets or Sets the current Time of the System
/// </summary>
private DateTime CurrentTime { get; set; }
/// <summary>
/// Gets or Sets how many Hours it takes to make a full day in the World
/// </summary>
public int HoursPerDay { get; set; }
/// <summary>
/// Gets or Sets how many minutes it takes to make a full Hour
/// </summary>
public int MinutesPerHour { get; set; }
/// <summary>
/// Gets or Sets how many seconds it takes to make a full minute
/// </summary>
public int SecondsPerMinute { get; set; }
/// <summary>
/// Gets or Sets how many Days it takes to make a full month in the world
/// </summary>
public int DaysPerMonth { get; set; }
/// <summary>
/// Gets or Sets how many Months it takes to make a full Year in the world
/// </summary>
public int MonthsPerYear { get; set; }
/// <summary>
/// Gets or Sets the name of each Day in a Week.
/// </summary>
public List<string> DayNames { get; set; }
/// <summary>
/// Gets or Sets the name of each Month in a Year.
/// </summary>
public List<string> MonthNames { get; set; }
/// <summary>
/// Gets or Sets what time of day the world is currently in.
/// </summary>
public TimeOfDayOptions DayTransitions { get; set; }
/// <summary>
/// Gets or Sets what time of day that it begins to transition to night.
/// </summary>
public int DawnTime { get; set; }
/// <summary>
/// /Gets or Sets what time of day that it begins to transition into day time.
/// </summary>
public int SunriseTime { get; set; }
/// <summary>
/// Gets or Sets the initial Time that the world starts in.
/// </summary>
public Time InitialGameTime { get; set; }
public GameTime(Game game)
{
ActiveGame = game;
ServerStartTime = DateTime.Now;
DayNames = new List<string>();
MonthNames = new List<string>();
DayNames.Add("Monday");
DayNames.Add("Tuesday");
DayNames.Add("Wednesday");
DayNames.Add("Thursday");
DayNames.Add("Friday");
DayNames.Add("Saturday");
DayNames.Add("Sunday");
MonthNames.Add("January");
MonthNames.Add("February");
MonthNames.Add("March");
MonthNames.Add("April");
MonthNames.Add("May");
MonthNames.Add("June");
MonthNames.Add("July");
MonthNames.Add("August");
MonthNames.Add("September");
MonthNames.Add("October");
MonthNames.Add("November");
MonthNames.Add("December");
}
public void Initialize()
{
Time t = InitialGameTime;
CurrentWorldTime = t;
}
public virtual void Update()
{
TimeSpan ts = CurrentTime - DateTime.Now;
//If the seconds that has passed inbetween the last Update call is greater than 0
//Then we need to increment a Second, which will start a domino effect if it needs to
//in order to increment minute/hours/days/months and years.
if (ts.Seconds != 0)
{
IncrementSecond();
}
CurrentTime = DateTime.Now;
}
public void IncrementSecond()
{
Time t = new Time();
t = CurrentWorldTime;
if (CurrentWorldTime.Second == SecondsPerMinute)
{
t.Second = 0;
IncrementMinute();
}
else
t.Second++;
CurrentWorldTime = t;
}
public void IncrementMinute()
{
Time t = new Time();
t = CurrentWorldTime;
if (CurrentWorldTime.Minute == MinutesPerHour)
{
t.Minute = 0;
IncrementHour();
}
else
t.Minute++;
CurrentWorldTime = t;
}
public void IncrementHour()
{
Time t = new Time();
t = CurrentWorldTime;
if (CurrentWorldTime.Hour == HoursPerDay)
{
t.Hour = 0;
IncrementDay();
}
else
t.Hour++;
CurrentWorldTime = t;
}
public void IncrementDay()
{
Time t = new Time();
t = CurrentWorldTime;
if (CurrentWorldTime.Day == DaysPerMonth)
{
t.Day = 1;
IncrementMonth();
}
else
t.Day++;
CurrentWorldTime = t;
}
public void IncrementMonth()
{
Time t = new Time();
t = CurrentWorldTime;
if (CurrentWorldTime.Month == MonthsPerYear)
{
t.Month = 1;
IncrementYear();
}
else
t.Month++;
CurrentWorldTime = t;
}
public void IncrementYear()
{
Time t = new Time();
t = CurrentWorldTime;
t.Year++;
CurrentWorldTime = t;
}
public string GetCurrentWorldTime()
{
if (DayNames.Count < CurrentWorldTime.Day)
{
return "Not enough Day Names specified to match up with DaysPerMonth property.";
}
else if (MonthNames.Count < CurrentWorldTime.Month)
{
return "Not enough Month names specified to match up with MonthsPerYear property.";
}
string day = DayNames[CurrentWorldTime.Day - 1];
string month = MonthNames[CurrentWorldTime.Month - 1];
return day + ", " + month + " " + CurrentWorldTime.Day + ", " + CurrentWorldTime.Year + ": " + CurrentWorldTime.Hour + ":" + CurrentWorldTime.Minute + ":" + CurrentWorldTime.Second;
}
}
}

View file

@ -21,6 +21,8 @@ namespace MudEngine.GameObjects
[RefreshProperties(RefreshProperties.All)]
public string Name { get; set; }
public Guid ID { get; internal set; }
[Category("Object Setup")]
[Description("A brief description of this object. The description is displayed to users when they use a command for investigating an object")]
public string Description { get; set; }
@ -39,12 +41,7 @@ namespace MudEngine.GameObjects
//Filenames are generated by the class itself, users can not assign it.
get
{
if (this.GetType().Name.StartsWith("Base"))
{
return this.Name + "." + GetType().Name.Substring("Base".Length);
}
else
return this.Name + "." + GetType().Name;
return this.ID + "." + GetType().Name;
}
}
@ -65,13 +62,6 @@ namespace MudEngine.GameObjects
public Game ActiveGame { get; set; }
/// <summary>
/// used for serialization only.
/// </summary>
internal BaseObject()
{
}
/// <summary>
/// Initializes the base object
/// </summary>
@ -85,6 +75,13 @@ namespace MudEngine.GameObjects
this.Listen = "You hear nothing of interest.";
this.Smell = "You don't smell anything unsual.";
this.Name = DefaultName();
//This must be called on instancing of the object.
//It is unique and will be used for saving the object.
//Allows for multiple objects with the same Name property
//but different Identifiers. Letting there be multiple versions
//of the same object.
this.ID = Guid.NewGuid();
}
private bool ShouldSerializeName()
@ -151,6 +148,7 @@ namespace MudEngine.GameObjects
File.Delete(filename);
FileManager.WriteLine(filename, this.Name, "Name");
FileManager.WriteLine(filename, this.ID.ToString(), "Identifier");
FileManager.WriteLine(filename, this.Description, "Description");
FileManager.WriteLine(filename, this.Feel, "Feel");
FileManager.WriteLine(filename, this.Listen, "Listen");

View file

@ -89,21 +89,23 @@ namespace MudEngine.GameObjects.Characters
}
//Restore the users current Room.
Realm realm= ActiveGame.GetRealm(FileManager.GetData(filename, "CurrentRealm"));
Realm realm = ActiveGame.GetRealmByID(Guid.Parse(FileManager.GetData(filename, "CurrentRealm")));
if (realm == null)
{
realm = new Realm(ActiveGame);
return;
}
Zone zone = realm.GetZone(FileManager.GetData(filename, "CurrentZone"));
Zone zone = realm.GetZoneByID(Guid.Parse(FileManager.GetData(filename, "CurrentZone")));
if (zone == null)
{
zone = new Zone(ActiveGame);
return;
}
CurrentRoom = zone.GetRoom(FileManager.GetData(filename, "CurrentRoom"));
CurrentRoom = zone.GetRoomByID(Guid.Parse(FileManager.GetData(filename, "CurrentRoom")));
if (CurrentRoom == null)
{
CurrentRoom = new Room(ActiveGame);
@ -123,9 +125,9 @@ namespace MudEngine.GameObjects.Characters
FileManager.WriteLine(filename, this.IsControlled.ToString(), "IsControlled");
FileManager.WriteLine(filename, this.Role.ToString(), "Role");
FileManager.WriteLine(filename, this.CurrentRoom.Name, "CurrentRoom");
FileManager.WriteLine(filename, this.CurrentRoom.Zone, "CurrentZone");
FileManager.WriteLine(filename, this.CurrentRoom.Realm, "CurrentRealm");
FileManager.WriteLine(filename, this.CurrentRoom.ID.ToString(), "CurrentRoom");
FileManager.WriteLine(filename, this.CurrentRoom.ID.ToString(), "CurrentZone");
FileManager.WriteLine(filename, this.CurrentRoom.ID.ToString(), "CurrentRealm");
}
/// <summary>

View file

@ -40,17 +40,31 @@ namespace MudEngine.GameObjects.Environment
/// </summary>
/// <param name="zoneName"></param>
/// <returns></returns>
public Zone GetZone(string name)
public Zone GetZoneByID(Guid id)
{
foreach (Zone zone in ZoneCollection)
{
if (zone.Name == name)
if (zone.ID == id)
return zone;
}
return null;
}
public List<Zone> GetZoneByName(string name)
{
List<Zone> zones = new List<Zone>();
foreach (Zone zone in ZoneCollection)
{
if (zone.Name == name)
zones.Add(zone);
}
return zones;
}
public void AddZone(Zone zone)
{
if (zone.IsInitialZone)

View file

@ -88,11 +88,11 @@ namespace MudEngine.GameObjects.Environment
/// </summary>
/// <param name="RoomName"></param>
/// <returns></returns>
public Room GetRoom(string name)
public Room GetRoomByID(Guid id)
{
foreach (Room room in RoomCollection)
{
if (room.Name == name)
if (room.ID == id)
return room;
}
return null;

View file

@ -51,6 +51,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Commands\CommandExit.cs" />
<Compile Include="Commands\CommandGetTime.cs" />
<Compile Include="Commands\CommandLook.cs" />
<Compile Include="Commands\CommandRestart.cs" />
<Compile Include="Commands\CommandSave.cs" />
@ -60,6 +61,7 @@
<Compile Include="FileSystem\SaveDataPaths.cs" />
<Compile Include="GameManagement\CommandEngine.cs" />
<Compile Include="GameManagement\CommandResults.cs" />
<Compile Include="GameManagement\GameTime.cs" />
<Compile Include="GameManagement\ICommand.cs" />
<Compile Include="FileSystem\FileManager.cs" />
<Compile Include="FileSystem\SaveDataTypes.cs" />

View file

@ -178,7 +178,7 @@ namespace MudEngine.Scripting
results = codeProvider.CompileAssemblyFromFile(param, scripts);
//Delete the temp folder
//Directory.Delete("temp", true);
Directory.Delete("temp", true);
ScriptPath = oldPath;
//if we encountered errors we need to log them to our ErrorMessages property

View file

@ -121,10 +121,12 @@ namespace MudGame
{
if (lastSaveGap == 30)
{
if (game.AutoSave)
game.Save();
lastSaveGap = 0;
}
//ServerTime holds the last minute prior to our current minute.
if (serverTime.Minute != DateTime.Now.Minute)
{
serverTime = DateTime.Now;
@ -141,6 +143,7 @@ namespace MudGame
{
game.PlayerCollection[0].ExecuteCommand(Console.ReadLine());
}
game.Update();
}
}
}

View file

@ -1,3 +1,2 @@
ScriptPath=Scripts
ScriptExtension=.cs
ServerEnabled=True