Perenthia Source Code

I uploaded the source for Perenthia. I am not sure if everything will compile but it is all there. Perenthia on GitHub

4/20/16


Perenthia–Development Diary #2

I have made some decent progress on scaling Perenthia down and re-tooling it for more basic HTML/mobile access. I have the server core complete and am working on the UI components. The first step will be to get the adventuring/combat piece finished and then move on to the crafting system.

The abstract core server pieces I decided to put into a separate library and made the source available on GitHub. I call it “Leo” and it provides the basic game server and provides some interfaces and associated libraries for processing input through the server. Since I am using SignalR for client to server communication I included some code in Leo to provide a input processor and PersistentConnection. The TestConsole project was something I used to initially setup the game libraries. They are now linked into my Perenthia solution and will be updated as I find the need while working on Perenthia.

The Leo source is very early stages and is subject to change frequently. It is also intended primarily for low traffic games such as iOS, Facebook, etc. I will up some instructions once it gets a little more stable.

Here is a screenshot of Perenthia’s new progress so far:

perenthia-ss1

5/4/12


Perenthia–Development Diary #1

I am working on Perenthia again, doing some re-design work to try and make the game fun but also maintainable by one person, me. I am going to catalog my development journey and the design decisions made along the way. I am trying to take what I learned from the prototype/alpha stage and improve upon it with realistic goals and tasks. Since it is just me working on it, other than contracting out the artwork pieces, I need to stay focused on making it fun and trying to implement the features that I think will be fun.

I have actually already started working on a re-usable library to host multi-player games. I have the basic framework in place which includes a base GameObject that provides a dictionary or properties and implements a behaviors system to allow custom behaviors to be created and attached to objects. I also have a master Game class that can be started and runs the server frame loop, updating the world and any loaded objects, behaviors or game components. I used MEF to define externally loaded components and data libraries. The Game class expects an IWorld implementation, some repositories for objects and users and optionally a list of IGameComponents. The IGameComponents are updated with each frame loop so I figured those would be good for creating things like a weather component, pack AI, etc. The IWorld is also a game component but has a few specific methods defined to access data contained within the world from the Game object. Behaviors are simple objects that can be attached to a game object and also contain and Update method that is called during the game object’s update method.

All this is server side code intended to run a virtual world. In addition to the re-usable game server I have a Perenthia specific library built on top of it that defines the aspects that are unique to Perenthia itself. For instance, Perenthia contains a Skill and Race object and loads that data during the world initialization. The underlying virtual world framework is not aware that skills and races exist, just that game objects are being added, removed and updated.

For data storage I put all world data that loads with the world initialization into SQL tables and a few external flat files. User and player data I am going to store in MongoDb to take advantage of the document storage mechanic and store an entire player object as one record. After using relational data for years to store objects and wiring up code to handle the relationships, etc. I find the document storage a refreshing change. I took a look at EF and code first but could not obtain the same level of ease of use as with a document store. I ended up having to code way too much logic specific to how the objects are stored rather than just saving them.

For the initial game client I decided to go the Html5/Javascript route to be able to present to the majority of players. I am using SignalR for the client to server communication and worked out some generic interfaces in the underlying server framework to allow for switching the communication technology. I am also using ScriptSharp to build the client side game logic. I find that using ScriptSharp is helpful as you get compile time errors and can resolve some issues up front without having to use console.log statements for everything. The string typing of objects does help to catch some case typos, etc. that are common for me when doing Javascript.

I have also created a world building tool for use with Perenthia. It allows me to draw the tiles that make up the world and save them as flat files for world initialization on the server. Using ScriptSharp I also coded some logic on the client to retrieve and load the maps. I can manage some of the SQL table stuff using the world build but want to get it to the point where I can add objects. My plan is to drop objects onto the map where an object resides within a tile, so not completely to scale or anything. My initial thoughts are to be able to add things like shops, taverns, etc. I also want to be able to add things like trees that can be cut down or a rock quarry for mining. I just not have not gotten to fleshing out all those details as of yet but that is the general plan.

What I am currently working on is randomization of creature encounters. I created a table to hold creature templates and then cataloged them by terrain. So for instance, in grass one might encounter a rat or kobold. In addition to that I created a feature in the world builder for editing creature zones. I store some zones in the database and then draw them on the world tiles to create the creature zones. So what I am working on is when a player moves onto a tile, if an encounter should happen I check to see if any creatures exist for the current terrain. If creatures exist I randomly get one with the level range marked by the zone. I am also thinking I may not return any creatures that are too low level for the player so you are not bogged down by encounters in low level areas and can move more freely into higher level areas. Once I get to where I have some decent encounters I am going to move on to the item system.

11/21/11


Perenthia in the Cloud

Part of the Perenthia re-birth is to get the game running in the cloud on Windows Azure. I started an Azure 1.2 web role project to handle the game. I got some of the basic stuff working like authentication and character creation. With the release of Azure 1.3 SDK I had to install IIS 7.5 components. Since I did not install it previously I had to run “aspnet_regiis –iru” to setup the IIS mappings for .NET 4 and I had to install the “HTTP Redirection” component for IIS 7. After getting all that setup I am up and running with Azure 1.3.

Because I am scaling the game down a bit and restructuring it to run with basic html and a variety of devices I am essentially re-building the game. I have a lot of code to work from and the concepts are already defined but I do have to do some new things. With running in the cloud some of the previous in-memory stuff I was doing has to be setup to store that in-memory data either in the database or in Azure Storage. For instance, when you connect to the game you get a token or session that identifies you. That token contains a reference to an in-memory object that stores the user id and currently selected character of the player. While I could setup and use .NET Sessions with some providers to store the data in Azure Storage I am going to continue to use the existing system I had in place and store in the in-memory data in Azure Table Storage.

I have some additional in-memory data that will either scale back to database driven queries or work the same way as tokens/sessions with table storage.

12/1/10


Perenthia Chapter 2

After many months of not working on Perenthia I find myself once again desiring to see it complete. The last revision I did on Perenthia was some time ago and involved a Silverlight UI with a C#/SQL 2008 backend.

During the course of development on Perenthia I discovered some of the pitfalls of attempting to develop a role playing game by one self. Mainly, the inability to handle content creation on a large enough scale as to appeal to players and have enough interactivity to make the game fun. I have been thinking lately of ways to reduce that load and still keep the game fun. I have some new ideas I want to put into place and re-release Perenthia with these concepts.

Among the changes I plan to implement will be scaling the game down to function solely in an HTML environment. This will enable me to provide a mobile version that works on all phones with a browser and keep the feature set the same for both phone and web.

I have begun to refactor pieces of the code and am making heavy use of jquery for the character creation screen.

11/30/10


Game Objects - My Design

I thought I would share one of the core concepts I implemented in Perenthia that has been working quite well. Early on in development I decided to create templates and instances in regards to game objects. A template would define common, unchangable properties of an object whereas an instance would be the opposite. An example would be a Sword; there is a template for a Sword that defines its damage value, price, required skill level, etc. 

I have one table that stores all the objects for the game. Since objects being actively used are loaded into memory and the table is indexed for those queries it runs pretty fast. Since I store all of the objects into one table I make heavy use of the XML data type in SQL 2005 to provide a bunch of XML Serialized Key/Value pairs that define the properties of an object. On the code side of things a dictionary provides the underlying data store for properties of the object. For instance, the Sword example above has a Power property that is used in combination with the wielder's skill in swords to determine damage. The Power property just fetches the Power value from the properties dictionary using the property name. This works a lot like the dependency properties, just my collection serializes to XML for database storage. When an object is loaded from the database the xml from the template is retrieved and added to the object, then the object instance xml is dropped into the object, overriding any template properties of the same name.

This property dictionary also allows me to store whether or not the property belongs to a template or instance. If the property belongs to a template then when the instance is serialized and saved to the database those template properties are excluded. Likewise saving a template does not serialize and save the instance properties. This structure allows for a lot of flexibility with my objects and has been working out quite well. I probably would not have used serialization and xml the way I am if I was doing a typical call to the database qith each request as the extra overhead would not have been worth the effort. However, since my objects are loaded into memory and my saves are background threaded I experience a lot of benefit of an easy to use object.

I shuld note that players character data is stored in a separate table from the core objects table. It follows the same design buy allows me to migrate and change data in the objects table without overwriting player data, since players are essentially the same as mobiles. 

5/15/09


Perenthia World Builder in Silverlight

I have been working to modify the tool I wrote for building the Perenthia world. The tool started life as a WinForms application, migrated to a WPF application but is now a part of the Silverlight Client UI. Since all of the actions are role based and controlled with permission on the server having it in the main client UI allows me to make use of all of the framework already in place for Perenthia.

The world builder UI connects to the server via WCF services tailored for world building. What this will also give me is the ability to open up the world builder to allow users to create custom dungeons, towns, etc.

Some features of the world builder are a background map of the world so I know where to place rooms, zoom capabilities that scale the map, draggable map and the ability to drag items, creatures, NPCs, etc. onto rooms on the map and configure the properties of each.

4/29/09


Silverlight Window Control

Here is a draggable Window control I wrote in Silverlight for Perenthia. A screen shot of the Window being used can be seen at http://cameronalbert.com/post/2008/11/19/Silverlight-Game-Controls.aspx

Here is the XAML from my generics.xaml file:

 

<!-- Default style for Lionsguard.Window -->
	<Style TargetType="lg:Window">
		<Setter Property="Background" Value="#99000000" />
		<Setter Property="Foreground" Value="#FFFFFFFF" />
		<Setter Property="BorderBrush" Value="#FFC38312" />
		<Setter Property="Template">
			<Setter.Value>
				<ControlTemplate TargetType="lg:Window">
					<Grid x:Name="RootElement">
						<Border HorizontalAlignment="Stretch" Margin="0,24,0,0" Padding="4,4,4,4" VerticalAlignment="Stretch" BorderThickness="2,2,2,2" CornerRadius="0,0,4,4">
							<ContentControl x:Name="ContentElement" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"/>
						</Border>
						<Border Height="24" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Top" CornerRadius="4,4,0,0" BorderThickness="2,2,2,0" x:Name="TitleBarElement" />
						<Button Height="20" HorizontalAlignment="Right" Margin="0,3,3,0" VerticalAlignment="Top" Width="20" Content="X" FontWeight="Bold" FontFamily="Trebuchet MS" FontSize="14" x:Name="CloseButtonElement"/>
						<TextBlock Height="20" Margin="8,3,27,0" VerticalAlignment="Top" Text="Title" TextWrapping="Wrap" x:Name="TitleLabelElement" FontFamily="Georgia" FontSize="16" FontWeight="Bold" HorizontalAlignment="Left"/>
					</Grid>
				</ControlTemplate>
			</Setter.Value>
		</Setter>
	</Style>

 

And here is the code for the class:

 

using System;
using System.Collections.Generic;
using System.Net;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Lionsguard
{
	[TemplatePart(Name = "RootElement", Type = typeof(FrameworkElement))]
	[TemplatePart(Name = "ContentElement", Type = typeof(ContentControl))]
	[TemplatePart(Name = "TitleBarElement", Type = typeof(Border))]
	[TemplatePart(Name = "CloseButtonElement", Type = typeof(Button))]
	[TemplatePart(Name = "TitleLabelElement", Type = typeof(TextBlock))]
	[ContentProperty("Content")]
	public class Window : Control
	{
		public FrameworkElement RootElement { get; set; }
		private ContentControl ContentElement { get; set; }
		private Border TitleBarElement { get; set; }
		private Button CloseButtonElement { get; set; }
		private TextBlock TitleLabelElement { get; set; }

		private Point MousePosition { get; set; }

		/// <summary>
		/// Gets or sets the Content of the Window.
		/// </summary>
		public UIElement Content
		{
			get { return (UIElement)GetValue(ContentProperty); }
			set { SetValue(ContentProperty, value); }
		}
		public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(UIElement), typeof(Window), new PropertyMetadata(null, new PropertyChangedCallback(Window.OnContentPropertyChanged)));
		private static void OnContentPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
		{
			(obj as Window).SetControlValues();
		}

		/// <summary>
		/// Gets or sets the Title displayed in the title bar of the window.
		/// </summary>
		public string Title
		{
			get { return (string)GetValue(TitleProperty); }
			set { SetValue(TitleProperty, value); }
		}
		public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(Window), new PropertyMetadata("Title", new PropertyChangedCallback(Window.OnTitlePropertyChanged)));
		private static void OnTitlePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
		{
			(obj as Window).SetControlValues();
		}

		/// <summary>
		/// Gets or sets a value indicating whether or not the close button of the title bar should be displayed.
		/// </summary>
		public bool ShowCloseButton
		{
			get { return (bool)GetValue(ShowCloseButtonProperty); }
			set { SetValue(ShowCloseButtonProperty, value); }	
		}
		public static readonly DependencyProperty ShowCloseButtonProperty = DependencyProperty.Register("ShowCloseButton", typeof(bool), typeof(Window), new PropertyMetadata(true, new PropertyChangedCallback(Window.OnShowCloseButtonPropertyChanged)));
		private static void OnShowCloseButtonPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
		{
			(obj as Window).SetControlValues();
		}

		/// <summary>
		/// Gets a value indicating whether or not the window is currently open and visible.
		/// </summary>
		public bool IsOpen
		{
			get { return this.Visibility == Visibility.Visible; }
		}

		/// <summary>
		/// An event that is raised when the window is closed.
		/// </summary>
		public event EventHandler Closed = delegate { };

		/// <summary>
		/// Initializes a new instance of the Lionsguard.Window class.
		/// </summary>
		public Window()
		{
			this.DefaultStyleKey = typeof(Window);
		}

		public override void OnApplyTemplate()
		{
			base.OnApplyTemplate();

			this.RootElement = base.GetTemplateChild("RootElement") as FrameworkElement;
			this.ContentElement = base.GetTemplateChild("ContentElement") as ContentControl;
			this.TitleBarElement = base.GetTemplateChild("TitleBarElement") as Border;
			this.CloseButtonElement = base.GetTemplateChild("CloseButtonElement") as Button;
			this.TitleLabelElement = base.GetTemplateChild("TitleLabelElement") as TextBlock;
			
			if (this.RootElement != null)
			{
				this.RootElement.MouseLeftButtonDown += new MouseButtonEventHandler(OnRootElementMouseLeftButtonDown);

				this.TitleBarElement.MouseLeftButtonDown += new MouseButtonEventHandler(OnTitleBarMouseLeftButtonDown);
				this.TitleBarElement.MouseEnter += new MouseEventHandler(OnTitleBarMouseEnter);
				this.TitleBarElement.MouseLeave += new MouseEventHandler(OnTitleBarMouseLeave);

				this.TitleLabelElement.MouseLeftButtonDown += new MouseButtonEventHandler(OnTitleBarMouseLeftButtonDown);
				this.TitleLabelElement.MouseEnter += new MouseEventHandler(OnTitleBarMouseEnter);
				this.TitleLabelElement.MouseLeave += new MouseEventHandler(OnTitleBarMouseLeave);

				this.CloseButtonElement.Click += new RoutedEventHandler(OnCloseButtonClick);

				this.SetControlValues();
			}
		}

		private void SetControlValues()
		{
			if (this.ContentElement != null && this.Content != null)
			{
				this.ContentElement.Content = this.Content;
			}
			if (this.TitleLabelElement != null)
			{
				this.TitleLabelElement.Text = this.Title;
				ToolTipService.SetToolTip(this.TitleLabelElement, this.Title);
			}
			if (this.CloseButtonElement != null)
			{
				if (this.ShowCloseButton) this.CloseButtonElement.Visibility = Visibility.Visible;
				else this.CloseButtonElement.Visibility = Visibility.Collapsed;
			}
		}

		private void OnRootElementMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
		{
			// Set the Z-Index of the window to the top most position.
			this.BringToFront();
		}

		private void OnCloseButtonClick(object sender, RoutedEventArgs e)
		{
			this.Close();
		}

		private void OnTitleBarMouseLeave(object sender, MouseEventArgs e)
		{
			this.Cursor = Cursors.Arrow;
		}

		private void OnTitleBarMouseEnter(object sender, MouseEventArgs e)
		{
			this.Cursor = Cursors.Hand;
		}

		private void OnTitleBarMouseMove(object sender, MouseEventArgs e)
		{
			Point position = e.GetPosition(null);

			// Prevent the mouse from moving outside the bounds of the parent canvas.
			if (position.X <= 30) position.X = 30;
			if (position.Y <= 30) position.Y = 30;

			Canvas parent = this.Parent as Canvas;
			if (parent != null)
			{
				if (position.X >= (parent.Width - 30)) position.X = parent.Width - 30;
				if (position.Y >= (parent.Height - 30)) position.Y = parent.Height - 30;
			}

			System.Diagnostics.Debug.WriteLine("position = {0}", position);

			double deltaX = position.X - this.MousePosition.X;
			double deltaY = position.Y - this.MousePosition.Y;
			
			Point newPosition = new Point(
				((double)this.GetValue(Canvas.LeftProperty)) + deltaX,
				((double)this.GetValue(Canvas.TopProperty)) + deltaY);

			this.SetValue(Canvas.LeftProperty, newPosition.X);
			this.SetValue(Canvas.TopProperty, newPosition.Y);

			this.MousePosition = position;
		}

		private void OnTitleBarMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
		{
			((UIElement)sender).ReleaseMouseCapture();

			this.Cursor = Cursors.Arrow;

			this.TitleBarElement.MouseLeftButtonUp -= new MouseButtonEventHandler(OnTitleBarMouseLeftButtonUp);
			this.TitleBarElement.MouseMove -= new MouseEventHandler(OnTitleBarMouseMove);
			this.TitleLabelElement.MouseLeftButtonUp -= new MouseButtonEventHandler(OnTitleBarMouseLeftButtonUp);
			this.TitleLabelElement.MouseMove -= new MouseEventHandler(OnTitleBarMouseMove);
		}

		private void OnTitleBarMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
		{
			this.MousePosition = e.GetPosition(null);
			this.Cursor = Cursors.Hand;

			((UIElement)sender).CaptureMouse();

			this.TitleBarElement.MouseLeftButtonUp += new MouseButtonEventHandler(OnTitleBarMouseLeftButtonUp);
			this.TitleBarElement.MouseMove += new MouseEventHandler(OnTitleBarMouseMove);
			this.TitleLabelElement.MouseLeftButtonUp += new MouseButtonEventHandler(OnTitleBarMouseLeftButtonUp);
			this.TitleLabelElement.MouseMove += new MouseEventHandler(OnTitleBarMouseMove);
		}

		/// <summary>
		/// Causes the current window to be re-z-indexed to the top most window.
		/// </summary>
		protected void BringToFront()
		{
			// Search the top most "Window" and swap z-indexes.
			Panel parent = this.Parent as Panel; // Panel is the base for Canvas, Grid and StackPanel.
			if (parent != null)
			{
				int currentZIndex = (int)this.GetValue(Canvas.ZIndexProperty);
				var child = (from c in parent.Children where c is Window select c as Window).OrderByDescending(c => (int)c.GetValue(Canvas.ZIndexProperty)).FirstOrDefault();
				if (child != null)
				{
					int topZIndex = (int)child.GetValue(Canvas.ZIndexProperty);
					if (topZIndex == 0) topZIndex = 1; // If the value has not been set then just default it to 1.
					if (topZIndex > currentZIndex)
					{
						this.SetValue(Canvas.ZIndexProperty, topZIndex);
						child.SetValue(Canvas.ZIndexProperty, currentZIndex);
					}
				}
			}
		}

		public void Show()
		{
			this.Visibility = Visibility.Visible;
			// If content is present show that as well.
			if (this.Content != null) this.Content.Visibility = Visibility.Visible;
		}

		public void Close()
		{
			this.Visibility = Visibility.Collapsed;
			// If content is present hide that as well.
			if (this.Content != null) this.Content.Visibility = Visibility.Collapsed;
			this.Closed(this, EventArgs.Empty);
		}

		public void ToggleWindow()
		{
			if (this.Visibility == Visibility.Visible)
			{
				this.Close();
			}
			else
			{
				this.Show();
			}
		}
	}
}

 

This is how I am using it within the Pernethia UI (The content of window is actually the Character Sheet as displayed in the screenshot from above):

Namespace: xmlns:Lionsguard="clr-namespace:Lionsguard;assembly=Lionsguard.Silverlight"

 

<Lionsguard:Window Height="375" x:Name="diagCharacterSheet" Visibility="Collapsed" Width="634" Canvas.Left="8" Canvas.Top="19" Title="Character Sheet" Style="{StaticResource WindowStyle}" d:IsLocked="True">
    		<Perenthia_Dialogs:CharacterSheetDialog x:Name="diagCharacterSheetContent" SkillChanged="diagCharacterSheetContent_SkillChanged"/>
		</Lionsguard:Window>

 

Enjoy!

 

4/22/09


Working on a Silverlight Multi-Player Library

I have been porting out the multi-player aspects of Perenthia into a separate library I hope to get up on CodePlex before too long. What the library will provide is some interfaces and classes related to handling multi-player environments. A central static class will manage connected clients and three protocol classes for HTTP, Polling Duplex and Sockets will use the static class to retrieve connected clients and push information down to them. A simple set of "tags" are used to send information back and forth and some providers allow for defining your own implementation of handling commands and encrypting data.

The library will be focused on providing an easy way to get setup and implement a multi-player structure. You will still need our own game engine and associated components.

As soon as I get it cleaned up a little and tested out I will put it up on CodePlex and provide a tutorial and sample application showing how to implement and use the component.

3/12/09


Silverlight for Multi-Player Games

I am hoping to start writing some articles about building multi-player games in Silverlight. I am planning on charting my development progress and ideas in my design and development of Perenthia.

Silverlight is a great platform for .NET developers to be able to write multi-player browser based games. You get a great tool for building a UI, animations, sounds, etc. and can program everything in your .NET language of choice. Silverlight 3 is supposed to support 3D so that will open it up even more for some great games.

Over the next few months, in between working on Perenthia, I am going to work on the first of a series of articles outlining how I built Perenthia. I will start with the Server component, outlining the core communication architecture and design decisions.

Keep checking back for more information.

2/16/09


Perenthia Armorial Version 1.0

I uploaded the Perenthia Armorial Version 1.0 to the Perenthia Alpha site tonight. The Perenthia Armorial is a way to provide external access to Perenthia information. The first version includes the Player Bar feature, where you pass a player name to the service and renders back HTML with player details.

The call to http://alpha.perenthia.com/Armorial/Armorial.ashx?n=Aldarian renders the following:

1/18/09


Perenthia Alpha Testing

I did a Character Creation, Movement and Chat test last night with the Perenthia Alpha players. The tests went well, I chatted with a few players, found some bugs and was very encouraged by the whole thing. The next test should start next weekend and will include some combat/spell tests. After that we will do some questing tests, travel tests (boats and stuff) and then I will open up more of the world for the alpha players to help resolve other issues not covered by the main feature tests.

I am enjoying Silverlight as the client UI, it provides a Windows like interface with ability to be run in a browser.

1/16/09


Client/Server Communication Data Formats

While developing Perenthia I tried several different communication formats from sending JSON serialized objects back and forth to sending byte arrays containing mostly integers indicating what should be loaded and displayed, what commands to execute etc. What I eventually settled on was a bit of a hybrid. I've created a simple set of "tags" that can be sent to and from the server. The tags are nothing more than pipe delimited strings contained within curly braces and there are a limited number of tags that provide simplicity yet flexibility with the data that is transmitted. The tags are represented in C# by tag objects allow me to create them, query them, etc.

A simple command tag for the SAY command might look like this: {CMD|SAY|"Hello World!"}

I wrote a custom tag writer class that parses the tag objects into strings to be sent to the client and likewise a tag reader that reads the strings sent from the client and parses them into tag objects.

The client can only send commands to the server but the server sends commands, messages and objects to the client. The commands are all the same, the CMD text then the one word name of the command and then a list of arguments, messages are system, chat and tell messages but objects have a bit more information. For instance, an object tag encompasses several different types starting with a base ACTOR, a PLACE, a PLAYER and a PROP or property. The ACTOR, PLACE and PLAYER tags all define the ID, Name and Descriptions of the objects, with some additional data per type but the PROP tag defines the object id of its owner and a name/value pair. An example of a PLAYER tag with properties for x, y and z coordinates might be:

{OBJ|PLAYER|3756|"Aldarian"|"My character description..."}

{OBJ|PROP|3756|"X"|45}

{OBJ|PROP|3756|"Y"|26}

{OBJ|PROP|3756|"Z"|0}

The client can find and parse the player tag and then find the properties associated with that player instance. The way the server works now it will send the full player tag once logged in and a character is selected and then from then on out it just sends property updates.

Using this type of tag structure allows quite a bit of flexibility for the client. I could choose to write a very simple client that only displays MSG tags, much like a MUD, I could write a simple 2D interface client and display and move sprites about the map using the properties from the server, etc. Once Perenthia is up and running I will probably post some information on the tags and how to talk with the server should someone feel the need to write their own client. :)

1/5/09


Almost Alpha Time!

For those waiting, Perenthia is almost ready for alpha. I have a few more things to complete and then the first phase of the Alpha will be ready. Hopefully you have had time to look over the various races, attributes and skills on the Perenthia web site and will be ready to create a character and begin your journey.

Here is a list of the remaining tasks I need to complete before Alpha, this does not include testing and fixing bugs with these features, just implementing them:

  • Spellcasting (Basic framework is in place, just need to define some spells and test them out)
  • Monster drops, including currency, gold, silver, etc. (They don't drop anything right now, stingy)
  • Help (Just need the framework in place as the help will get compiled during the alpha)
  • Quests (May not finish these for the first phase of alpha, want to try and keep it simple to start)
  • Some UI cleanup (got some windows not responding to updates from the server)
  • Content (Need to finish adding monsters to the dungeon, just the one dungeon for alpha)

I thought I would include a couple of screen shots along with this update. The first is a shot of the map window of the world builder tool I wrote for managing the places and things within the Perenthia world. This is the shot of the Alpha testing area, a small village called "Delcor". This view is actually a windows forms application with a WPF (ElementHost) control for rendering the map. The little red dots are NPCs that I can actually drag around into other rooms on the map after I create them, makes for moving the monsters in the dungeon a lot easier. :)

This second shot is the game user interface showing the same map that I was working on in the screen shot above.


12/24/08


Evolution of a Game UI

As I have been working on the Silverlight UI for Perenthia I find myself constantly adding little things here there to provide more information or easier click-to-action type of functionality. The UI has evolved, for the better I hope, over the past few months from my original design as I have discovered something else that needed to be displayed while hooking it into the server. This seems to be the natural progression of things, at least with the way I work. :)

Here is the latest UI screen shot, this one shows my character viewing the items a merchant has for sale, with my inventory items on the left and the ones the merchant offers on the right. I will do a development update again soon, had to backtrack a bit with the UI.

11/29/08


Silverlight Game Controls

While building the Silverlight UI for Perenthia I have been building some re-usable game controls that I plan on posting before too long. One of the controls I created is a Window control that is just a control that provides a title bar with a close button and provides a Content section to add custom controls. I needed it to provide menu windows or panels but it could be used outside of games for just about anything. The control is draggable, as long as the parent control is a Canvas and will position itself as the top window when clicked, provided other windows exist in the same parent.

The Window control is featured in the screen shot below, the "Spellbook", "Character Sheet" and "Adenturer's"** are the windows. They contain custom controls that determine the content of the windows. The small icons at the very bottom of the screen shot are Slot controls that allow for a background image, primary image and object Item to be set on them. They also respond to clicks so click events can be handled on them. The ChatPanel under the windows is also a re-usable control and allows for adding any type of UIElement as content for the main chat area, not just text.

I hope to get these controls commented and the source up soon.

** The "Adventurer's" window is actually "Adventurer's Backpack", have a font sizing issue :)

11/19/08


Silverlight 2 Release

Silverlight 2 has officially been released. I've upgraded both Joust and Cameron's Dungeon as well as the Perenthia client. Work on Perenthia continues, albeit a little slow but it does continue. :)

10/14/08


Scripting for Games

Scripting in games is not a new concept, most games do this on some level. Scripting allows game objects to execute code that is not compiled as part of the object. In the realm of roe playing games scripting gives objects the ability to react to the world around them. For instance, an object could execute script whenever a player gets near it, allowing a vender to hawk their wares, creatures to attack, etc. There are a variety of scripting languages currently being implement in games such as Lua and Python. Recently I have been researching these two for possible addition to Perenthia to provide me the ability to add custom behavior to objects and NPCs.

Edit: Thanks to some helpful insight and information from Michael Foord I was able to get an IronPython sample working. The sample adds scripting support to an object; the code is very basic but accomplishes the task. Thanks Michael!

Here is a snippet of a console app using the latest IronPython Beta4:

using System;using System.Collections;using System.Collections.Generic;using System.IO;using System.Reflection;using System.Scripting;using IronPython;using IronPython.Hosting;using IronPython.Runtime;using IronPython.Runtime.Exceptions;using Microsoft.Scripting;using Microsoft.Scripting.Hosting;namespace IronPythonGameScripting{    class Program    {        static void Main(string[] args)        {            try            {                Actor player = new Actor("Cam");                Actor mob = new Actor("Mob");                mob.Script = @"class Mob:    def onEncounter(self, *value):        value[0].Name = ""Mr Groovy""";                Console.WriteLine("Player name was '{0}'", player.Name);                mob.Execute(Actor.EVENT_ON_ENCOUNTER, player);                Console.WriteLine("Player name is now '{0}'", player.Name);                mob.Execute("Test", player);            }            catch (Exception ex)            {                Console.WriteLine(ex.ToString());            }            finally            {                Console.WriteLine("Press any key to exit...");                Console.ReadKey();            }        }    }    public static class Engine    {        private static ScriptEngine _engine;        private static ScriptScope _scope;        static Engine()        {            _engine = PythonEngine.CurrentEngine;            _scope = _engine.CreateScope();        }        public static void Initialize()        {        }        public static void Execute(string script)        {            ScriptSource source = _engine.CreateScriptSourceFromString(script, SourceCodeKind.Statements);            source.Execute(_scope);        }        public static void Execute(string script, string className, string methodName, params object[] args)        {            ObjectOperations ops = _engine.Operations;            ScriptSource source = _engine.CreateScriptSourceFromString(script, SourceCodeKind.Statements);            source.Execute(_scope);            if (_scope.ContainsVariable(className))            {                object @class = _scope.GetVariable(className);                object instance = ops.Call(@class);                if (instance != null)                {                    if (ops.ContainsMember(instance, methodName))                    {                        object method = ops.GetMember(instance, methodName);                        ops.Call(method, args);                    }                }            }        }    }    public class Actor    {        public const string EVENT_ON_ENCOUNTER = "onEncounter";        public string Name { get; set; }        public string Script { get; set; }        public Actor(string name)        {            this.Name = name;        }        public void Execute(string methodName, params object[] args)        {            Engine.Execute(this.Script, "Mob", methodName, args);        }    }}

 

As it turns out I was attempting to use the IronPython libraries compiled against the Silverlight framework rather than the libraries compiled against the normal .NET framework. I was also using an older beta 1 version of the IronPython library which may have attributed to the exceptions I was seeing. Got to make sure you reference the correct assemblies when working in both .NET and Silverlight. Surprised this is the first time I've done this...

I reviewed IronPython because it has Silverlight support with the DLR but it is really designed to be used instead of C# not as a scripting language executed from within C#. With Lua though I may be able to get it working although it still seems like everything was designed to simply execute the game in lua scripts using C# as the core instead of augmenting C# classes.

I really want to just be able to raise events on the mobile objects and have instances handle those events in a custom way. I certainly don't want to compile C# on the fly either as that has its own set of issues. Compiling C# on the fly is like running an exe for each script that is executed and would be way too costly in both execution time to compile and memory consumption.

Also, since both the client and server will need to execute scripts the scripting language needs to work in both Silverlight and ASP.NET.

Perenthia currently handles commands using a Dictionary<int, Command> where the int is command value, from a list of constants, and the Command is a method pointer (delegate). When the game loads up the first time the list of commands is constructed and the methods pointers are set to methods that related to the command. An example would be a chat command. When the command comes in and is validated the method pointer is found using this dictionary and then executed in the context of the connected player. I was thinking of doing the same thing with mobiles and the actions they can take and respond to based on the world around them. It is a bit more complex with mobiles than commands since commands do a specific thing whereas every mobile could execute a different block of code for a given event. I still have some work to do on it but this will probably be what I use in place of scripting. I loose the flexibility of writing quick scripts, changing them on the fly, etc. but gain the ability to have it work within my code framework, rely on only .NET and work in both Silverlight and ASP.NET.

8/26/08


More Perenthia Screen Shots

Here are a few more screen shots of the Perenthia UI. The three screen shots are dialog windows that popup as a result of clicking on icons or buttons in UI. They are use a reusable control I created that has the title bar and X button and then just has a ContentControl for the guts of the dialog. The dialog window is draggable and does the hide and show thing. I need to do some cleanup on it and then I will post the source. I will also post the source for the stat bars shown on the skills dialog screen shot.

Also, I am hoping to have some time to blog about some of what I am doing with the overall game engine. I wanted to provide a development update but haven't moved the development along all that much due to working out some networking issues and trying to clean up some of the code.

The goal for Alpha is to get a working zone complete with quests, monsters, npcs, etc. However, I may do some smaller tests with the alpha registrants before all of this is complete. I was thinking of setting up a tiny zone just for testing where players could login, create a Character and accept a quest, which would be to enter a room where enemies spawn randomly and in various numbers. This would allow me to test a lot of things in one place; Character Creation, Quests, Spawning, Combat and NPC interaction.

Anyway, here are the screen shots; this first one is the Character Sheet that will display your character stats, equipped items and skills. The empty box will show the skills once I bind them to it. :)

This next screen is the actual skills screen where you can see you skill rank and all available skills. If you have Skill Points you can increase or learn new skills from this window.

This last image is just the backpack dialog, all I have is a starting candle right now. :)

8/9/08


Perenthia UI Screen Shot

As promised here is a screen shot of the main game UI, click on the image for a full size version. The top left is the current player's avatar and details. The map in the top right corner shows you the current zone, in relation to your z-index. The icons scattered around open other windows that allow you to view your character sheet, skills, spells, backpack, etc. The interface is built in Silverlight 2 Beta 2.

Perenthia UI

7/27/08


Quests

For those unfamiliar with the fantasy role playing genre; quests are simple to complex tasks that players complete in order to advance, get sweet gear, etc. They usually involved raiding a dungeon, slaying some terrible beast and wondering about the countryside trying to find the entrance to the hidden caverns.

What I hope to accomplish with quests is to provide a goal beyond just slaying monsters. Quests will actually move your Character through the game, while training and advancing them along the way.

One of my primary goals with Perenthia is to provide a different game play experience as players mature within the game. The first phases of the game will include some of the normal grind, killing monsters to get better gear, to level up, to kill monsters, etc. This gives the players immediate satisfaction while getting them used to moving around, using commands, spells, equipping items, buying and selling and everything else that goes along with eradication of the demon beasts of the underworld. The second phase of the game will follow a bit of a storyline, requiring players to venture into dungeons and caverns to retrieve special items they will need in order to move into the next phase of the game. While this involves a lot of the same type of situation, you have a reason to go into the dungeon and complete it, rather than just killing 10 rats because some dude is freaking out. The third phase will require the player to use the items created from the previous phase to solve puzzles, riddles and the like, which will take them into the next phase. The fourth phase will require the player to purchase some form of transportation in order to visit very far off places and located individuals who can further their progress with quests of their own. This will continue in this manner for the remainder of the game. I currently have 4 phases planned and ideas for 3 more that I hope to get written down and planned out before too long, although I will probably wait until after the alpha an beta test phases.

I want to try and provide a fun game and I feel that doing this phased game progress could provide an enjoyable gaming experience. I know when playing other games of the genre I usually burn out in the high levels because I worked so hard to get there and it is just more of the same. I would also like the world to progress forward around the players so that new challenges are introduced to both high and low level characters that are in keeping with the overall storyline. I want players to have as much fun playing the game as I am having making it. :)

I hope to provide a robust questing system that can handle these phases and still maintain a clean and easy way for players to know what to do next. For the alpha I have planned out some quests that take you around the alpha starting area and should advance the alpha players enough so that the next area will introduce another phase in the game experience.

I will do another development update after this weekend.

7/23/08


Perenthia World Builder Screen Shots

I am not quite ready to post the screen shots of the actual game UI, still need to do some cleanup. So, since I promised I would post some screen shots here are a few of my world builder tool. This is a windows application that just reads and writes to the database.

This first screen is the map builder and as you can see I can draw the actual places/rooms in which players will adventure. The map that is displayed will be the Alpha starting map, it consists of a small town, a forest and a small sewer system. The sewer nodes are not displayed because they are one level down.

This is the creature manager window that allows me to create creature "templates", from which actual creature instances can be created and placed onto the map from above. (Using the Add Mobile button).

This is just a shot of the item manager window, displaying some of the items I've added so far, got a long way to go on these. The items also follow the same "template" pattern that the creatures do. I still need to add in support for placing the drop items on Mobiles.

I hope to have the game UI screen shots ready soon.

7/22/08


Perenthia - Pre-Alpha Details

I have made so many changes to Perenthia since the alpha/beta release I did last year that I am actually going to take the game back to Alpha and go through the whole process again. Most of the data elements remain the same, the story is the same, the goals, etc. but the server and client pieces have been modified so much its not really the same code base.

Anyway, I am hoping to get a pre-alpha signup form on the site this weekend and get the closed Alpha live by the end of summer.

7/10/08


Just an Update

I am still plugging along on my games, working mostly on Perenthia and checking out the new stuff in Silverlight 2 beta 2. I want to try and get the Perenthia beta 2 up and running by the middle or end of the summer, free time permitting.

 I haven't blogged much lately but I have been working on a lot of stuff. I will try and get some posts together to outline some of the stuff I have taken advantage of in developing Perenthia such as adding files as links in Visual Studio and then using partial classes to separate server and client logic and multi-threading in Silverlight and how to avoid cross thread access, which you will get exceptions on now in SL 2 beta 2. I will also try and get some screen shots of Perenthia, quite a bit has changed since the last screen shot I posted and I would like to get some of the new ones up.

6/10/08


Perenthia Map

I thought I would post an image of the map I have been working on for Perenthia. I made this in Photoshop using a variety of brushes and layers. I still have some more that I want to do with it but I am pretty happy with it so far.

4/11/08


Perenthia Screen Shot

OK, I decided to post a screen shot of the Perenthia interface so far. Keep in mind this is still under development. The main sprite is not the final, just a ripped image from a Flash game called Exile and the background is just a sample I created so I could tell if the camera was following my player.

 

4/9/08


Perenthia and Pirates

After surviving the flu I am back to working on Perenthia. I did some work on Pirates but I am still having some positioning issues that I can't seem to get worked out and may have to rebuild a good portion of the game.

I should have a screen shot or two of the progress on Perenthia in another few days, I will see how it goes.

I have a good portion or rather the majority of the Perenthia Server finished and have been working on the Silverlight front end. I am still not sure whether or not I will be using sockets for communication or a custom IHttpHandler implementation.

4/8/08


Silverlight 2.0 and My Game Engine

I got the chat portion of the game engine working with Silverlight 2.0 tonight. I am just using web services to send the commands back and forth for now. Once I complete incorporating the other portions of the engine into Silverlight I will start playing around with sockets. 

3/7/08


Data Format for Socket Server Packets

For my PBBG Engine I started off programming it all for the web and AJAX. Recently I added support for sockets by porting over my socket server code I wrote for a Flash server and incorporating the code into the PBBG Engine. In a previous post about my PBBG Engine Architecture I outlined my plans for how the socket and web pieces would work together. I spent some time today refining my command pipeline and server protocol for the socket side of the engine and will probably utilize that on the web side as well.

I decided on the following format for the data packets that will go to and from the server and client. Since it is just bytes going back and forth and I wanted to keep the data streams as small as possible I decided to abandon the string based command protocol and use this instead:

The first 2 bytes of the packet will be used to store an Int16 (short) value that indicates the command to execute. I have an event being raised from the game engine that allows the implementing libraries to set the game commands. This was a Dictionary<string, ICommand> but I am going to change it to a Dictionary<short, ICommand>. That will save me some bytes back and forth without passing the command names. I can have the clientsend the proper short value for the command typed into the console or just have the links and events in the client supply the proper short value.

The next 4 bytes will be the integer length value of the message. This will allow me to know when this message ends and the next one begins.

All the bytes following up to the length value will be the actual message sent to the client or sent to the server.

The server is already validating commands, I will just need to modify to validate these bytes and watch for buffer over runs. I still need to work out validating that a logged in user is sending the information but I will work out something, maybe have the client send the encrypted authentication key to the server after a connection is opened but before commands can be processed. 

 

3/2/08


PBBG Engine Architecture

Thought I would go ahead and post a little about the architecture I have set up for my PBBG engine so far. Basically, the engine is a library that other projects can reference to make building PBBGs a little easier. All of the logic for handling incoming requests and parsing commands is contained within the engine. My PBBG engine is kind of like a MUD driver, it requires a MUDLib to define objects, persist data, etc. Some interfaces are defined within the engine library to make it extensible while it also contains base class implementations of those interfaces to make building on top of working logic possible. When the engine starts up it raises a set of events and when it processes commands it also raises events to allow the implementing application to control loading of commands, determining the server implementation and creating command instances.

 

Not the best diagram in the world but kind of gives you the idea of how it works. The column down the middle are the interfaces defined by then engine, which also define base classes, except for the CommandManager which is just a static class for processing commands.

In addition to the classes here are the Verb abstract class, the ICommand interface and the Command<Verb> instance for creating commands from Verbs. The CommandManager raises an event when it finds the command text that allows an external library to set the ICommand instance that will execute the current command. When the engine starts up though it raises an event that will allow the implementation library to set all the commands into memory rather than creating a new instance with each command.

The IServer interface defines an IConnectionManager property where connections into the server are managed, either socket or http.

On the WEB side, which is actually a namespace ".Web"; the "Server" instance writes out a JavaScript reference to an embedded js file containing the script required to submit commands to the engine using AJAX. A separate RequestHandler class actually parses the input from the AJAX call and then attempts to locate or create an IConnection instance on the Server's IConnectionManager instance. The Server in this namespace actually sends the command to the CommandManager.

On the NET side, which is actually a namespace ".Net"; the "Server" instance actually contains the socket used to listen for incoming connections on a port specified during startup. From there the individual IConnection instances contained in the IConnectionManager instance handle processing the input and formatting it into a command. The IConnection instance contains the connected socket and will send the command to the CommandManager.

Both IConnection instances in both namespaces allow messages to be sent to the client along with custom data such as stats, gold, map data, etc. The difference between the two is that the WEB instance sends all of this back as JSON in the HTTP response and the NET instance sends the messages down the socket as they are added to the IConnection instance and then sends the additional data once the command completes execution.

That is all I have completed at this point on the engine side, it processes commands from the web and the implementation library sitting on top of it handles the commands and persists the data. There is plenty of work on the implementation library side still yet to be completed.

2/26/08


Perenthia Update

I haven't decided yet but am considering using Silverlight 2.0 with the next release of Perenthia. I've completed a good portion of my PBBG engine that will drive Perenthia but want to be able to take advantage of some the features of Silverlight 2.0 to provide better user experience. One of the features that really interests me is the socket support for 2.0. Once I get the 2.0 beta 1 bits I am going to start playing around with running my PBBG engine on a socket server application I wrote for Flash. If all goes well I should be able to provide some better multiplayer features in Perenthia such as real time chat and possibly player vs player combat.

Perenthia will still primarily be a text-based game but Silverlight could allow me to bridge the gap between web and client software. 

2/24/08


Processing Commands

I might have mentioned it before but my PBBG engine is basically a commands processor. In other words it accepts commands from the client, processes the information on the server and sends the response back to the clients as JSON. Not really different from a normal web request except it is specific to my PBBG engine and you don't request documents from the server you are telling the server you want your Character to "do" something.

My PBBG engine is essentially just the command processor and the classes surrounding processing commands. I have abstracted it completely from the data source. There are no data providers or data connections at all in the engine. Instead, if it needs to get data it raises events that a deriving library can handle and pass back the required data in the form of simple interfaces. Some assumptions I did make such as ID values defined in interfaces are int values rather than object since I don't design databases with primary keys other than int. :)

One of the things I also did for the CommandManager was to created an abstract Verb class that I can derive from to create command verbs such as move, say, attack, etc. These command verbs can be defined in the deriving library and set in the CommandManager when the game starts up. Another class to assist with commands was a generic Command<T> class where T has to be a derived Verb value. So I can create Command<Move>() and the call an Execute method on the class which in turn creates the Verb instance and executes the code in the Verb class.

This has been working pretty well so far and since the CommandManager raises an event each time if processes a command I can have any number of derived libraries executing their own commands. 

2/13/08


Wilderness Adventuring

Perenthia currently provides "wilderness" areas where monsters roam around waiting to attack players who wander beyond the safety of the towns. I had originally wanted the wilderness to auto generate instead of how it works now where all the wilderness "tiles" are stored in the database. This caused over 150,000 records to have to be entered into the table and really limits expanding the word since I have to basically draw all the tiles.

For the Perenthia Beta 2 I worked out a "Regions" table to store a rectangle x,y,z value. The Regions table also stores the min and max levels required to venture into the region. Towns located within regions also carry a safe indicator so that monsters will not auto generate. Using this concept I only have to create the towns or places of importance and can let the "wilderness" be auto generated. 

The auto generated wilderness is infinite in that each wilderness place visited is created and stored on the player record. Wilderness is also exclusive to the player so that monsters generated will be available only to the adventurer. A lot of games have done this with dungeon instances and I thought it was a good idea to implement in Perenthia. There will be ways to interact with others and I still have some work to do to handle group play but wilderness is intended for solo players. Now, given that wilderness is infinite I don't want players getting lost so, the last non-wilderness place they visit will be stored on their player record and if they log out and log back in they will be reset to the previous non-wilderness place. It's kind of a fast way to cheat your way back to town if you get into trouble but I am OK with that. I would rather players leap back to town before their character dies than wander aimlessly around thousands of tiles from civilization. I want the wilderness adventuring to be a fun way to earn gold, not a potential for grief.

Quests may require adventuring through the wilderness to find hidden places so logging out when you are in trouble will cause your quest to take even longer. I think this will be a good trade off because quests will offer greater rewards than adventuring and should require a higher level of mastery. 

2/8/08


Perenthia UI

Spent some time today working on the UI for Perenthia. For now it will remain AJAX based but in the future I will probably add a Silverlight front end as well. I will post some screenshots of it soon, I want to get the layout complete first.

I also spent some time working through my data model for quests. I still need to do some work but I think it will be flexible enough to allow for adding all manner of quests and adventures. 

2/1/08


Place Manager

In my previous post Memory Management I was talking about storing character and room data in server memory.

For the Character memory management I basically just use a DateTime value that gets updated each time a request is made by the connected player. If the DateTime exceeds a certain limit such as 20 minutes then the character data is saved and removed from memory. If the player just has a long pause between requests their character data will be reloaded if they make another request after the cleanup.

For the Room or Place data I've though about doing the same thing, just store a DateTime value and update it whenever a player performs an action in the room. I am not sure this is the best approach since the only commands that reference the Place object are movement, looking, some inventory and buying commands. Other actions such as casting spells, viewing stats, private chat, etc. do not reference the Place object. Of course, I guess if you are not accessing the Place object no need to have it in memory but once a player attempts to move again I would need to reload the Place. I might just maintain a list in the Place object of all the players currently located there and only remove the object once those references have been removed. I'll try a few things and record what I find.

1/30/08


Memory Management

For Perenthia I am planning on utilizing server memory as much as possible without crippling the web server. To do that I am going to be maintaining player data and room data in memory for fast access and quicker responses from the interface.

The basic idea is that players login, choose a character and begin playing. This character information will be loaded into memory and persisted to the database when the data is changed, such as when commands are executed. As players move around the rooms they enter will also be persisted into memory to make loading and re-loading rooms faster.

The trick will be effective management of these resources. Character data will be removed after inactivity but I haven't figured out a good scheme for removal of the room data. Hope to have that working before too long though.

Anyway, that is the plan, we'll see how it works out. :) 

1/29/08


Adventures in LINQ to SQL

I've been playing around a little with LINQ to SQL for Perenthia and wanted to share a kind of nasty query I just wrote. In Perenthia the typical RPG classes are called Professions. To track these professions I have the following database tables:

The players table links over to the rad_ProfessionLevels table via the ProfessionLevelId foreign key. The rad_ProfessionLevels table also links over the rad_Levels table on the LeveId foreign key. This layout allows me to have professions, define custom names for the levels and give certain levels titles.

When loading up a player record I need to go and get the level number, level name, profession name and title prefix and suffix values from the database. Since I am using LINQ to SQL for my entity classes I wrote the following query to retrieve this information:

 

var titleQuery = from pl in db.ProfessionLevelsjoin p in db.Professions on pl.ProfessionId equals p.ProfessionIdjoin plt in db.ProfessionLevelTitles on pl.ProfessionLevelId equals plt.ProfessionLevelId into profLevelsfrom x in profLevels.DefaultIfEmpty()join t in db.Titles on x.TitleId equals t.TitleId into titlesfrom y in titles.DefaultIfEmpty()join l in db.Levels on pl.LevelId equals l.LevelId into levelsfrom z in levels.DefaultIfEmpty()where pl.ProfessionLevelId == avatar.ProfessionLevelIdselect new { p.ProfessionName, z.LevelNumber, pl.LevelName, y.Prefix, y.Suffix };
 

It's kind of a nasty beast but produces the following SQL query:

 

SELECT [t1].[ProfessionName],[t4].[LevelNumber] AS [LevelNumber],[t0].[LevelName], [t3].[Prefix] AS [Prefix],[t3].[Suffix] AS [Suffix]FROM [dbo].[rad_ProfessionLevels] AS [t0]INNER JOIN [dbo].[rad_Professions] AS [t1]ON [t0].[ProfessionId] = [t1].[ProfessionId]LEFT OUTER JOIN [dbo].[rad_ProfessionLevelTitles] AS [t2]ON [t0].[ProfessionLevelId] = [t2].[ProfessionLevelId]LEFT OUTER JOIN [dbo].[rad_Titles] AS [t3]ON [t2].[TitleId] = [t3].[TitleId]LEFT OUTER JOIN [dbo].[rad_Levels] AS [t4]ON [t0].[LevelId] = [t4].[LevelId]WHERE [t0].[ProfessionLevelId] = @p0
 

The @p0 value is the ProfessionLevelId value stored with the player record.

The LINQ query is nasty because of the three outer joins I have to perform because not all profession levels have titles. It doesn't look pretty but it does work; as I get into more LINQ writing I will probably find a better way to write this but at least I got my data. :)

1/25/08


PBBG Engine Update

Work continues on Perenthia and my PBBG Engine. I think I got the core PBBG engine framework complete, at least complete enough to start porting over the content items from Perenthia. My goal is to get a small area working with a few items, monsters, etc. before I port over the entire database.

I am hoping to improve performance in this new version as well as complete several of the features I didn't get implemented in Beta 1. The engine uses a lof of in memory objects while still persisting the world to the database. Running a lot of this in memory will eat of memory on the web server but will hopefully improve performance in regards to interactions from users. The main bulk of the places or rooms will be loaded up into memory when the application starts. Along with this load will be a load of NPCs and items located in towns and designated areas. Then, whenever a player logs in and begins playing their player object will be loaded into memory as well. At regular intervals the world state will be updated and player objects persisted to the database. Inactive player objects will be saved and then discarded from memory until the next time the player logs in.

Loading these objects into memory will keep the database connection initialization and IO traffic to a minimum and help speed up actions such as moving around and engaging NPCs. Since I don't know of anyone actually doing this I'm not completely sure it will work. :) My testing so far is working great and at most I may need to beef up the RAM on the web server.

I am still planning for a January release of Beta 2 and depending on how that beta goes; a full release in the early Spring.

11/27/07


SQL 2005 XML Data Type, Stored Procedures and Lists

I've seen a lot of stuff out there regarding the SQL 2005 XML data type but most of it is just regurgitates the MSDN documentation. That's fine and all but what about practical uses of it? Well, I have a practical use sample. In building my persistent browser based game Perenthia I have a concept of a Place. A place is a virtual space in which objects are stored. For Perenthia the places represent the various rooms or tiles players move around on. The place or room has exits defined that allow the player to move from one place to the next. The exits are the typical directions; north, south, up, down, etc. In the database I have a Places table and a PlaceExits table. The Places table stores all the information regarding a place and the PlaceExits table stores the placeId along with a directionId and destinationId so I know what exits are available in any room and what rooms they lead to.

The simplified schema for the places would be:

 Places Tables

 In the stored procedure that retrieves the place information I use the following query snippet in the select clause:

    SELECT

        p.*,

    (
            SELECT
                e.DirectionId        AS "@directionId",
                e.DestinationId        AS "@destinationId"
            FROM
                dbo.PlaceExits e
            WHERE
                e.PlaceId = p.PlaceId
            FOR XML PATH('exit'), ROOT('exits')
        ) AS ExitsXml

    FROM dbo.Places p 

 This creates an XML fragment I can then parse in the application to fill a collection of Exits on the Place object.

When saving place information I pass XML generated from the Exits collection in a stored procedure like so:

CREATE PROCEDURE dbo.Places_SavePlace  (@PlaceId int, @ExitsXml xml)

From within the save procedure I perform an update or insert of the place data and then execute the following sql to insert and update the exits for the current place:

    -- Exits

    -- Process the existing exits first

    UPDATE
        dbo.PlaceExits
    SET
        DestinationId    = e.ex.value('(@destinationId)[1]', 'int')
    FROM
        @ExitsXml.nodes('/exits/exit') as e(ex)
    WHERE
        PlaceId = @PlaceId
        AND DirectionId = e.ex.value('(@directionId)[1]', 'tinyint')

    -- Process any new exits

    INSERT INTO dbo.PlaceExits
    (
        ObjectId, DirectionId, DestinationId
    )
    SELECT
        @PlaceId,
        e.ex.value('(@directionId)[1]', 'tinyint'),
        e.ex.value('(@destinationId)[1]', 'int')
    FROM
        @ExitsXml.nodes('/exits/exit') as e(ex)
    WHERE
        e.ex.value('(@directionId)[1]', 'tinyint') NOT IN
        (
            SELECT DirectionId FROM dbo.PlaceExits WHERE PlaceId = @PlaceId
        )

This is working pretty well and keeps me from having to loop through the exits in the application and make multiple database calls. 

11/14/07


Database Model for a PBBG

I've worked on some large projects in the past with 500+ database tables but I have yet to see any persistent browser based games or any games get up that kind of table count. I only have 61 tables in Perenthia right now with a few more features to add which could possibly add another 10 tables. I would be curious to see a larger model, to see what kinds of things are handled. Right now I have tables for users, roles, places, things, avatars, skills, attributes, quests, guilds, professions and an assortment of lookup tables for things like item conditions, materials, titles, levels, etc.

11/9/07


Some New Stat Panel Designs

Here are some of the new stat panels I have been working on for the persistent browser based game Perenthia. I may use these for other games just depends on the game. I am making these into server controls that will render divs without the INamingContainer scheme of naming so they can be accessed a little easier via JavaScript and my AJAX calls.

Perenthia Stat Panels 

 

11/1/07


Command Processor

For my PBBG Engine I am developing a command processor independent of the client interface. The reason for this is that I want to be able to build different interfaces such as a mobile interface, silverlight and/or flash interface. I want all the interfaces to process the same commands and be able to handle the same output from the server in order to update the UI components.

What I have come up with for the command request to the server is a simple pipe delimited string:

CMD|AUTHKEY

Where CMD would be the command to send to the server and the AUTHKEY would be a key generated when the player logs in through the authentication service that uniquely identifies the player for that session.

The response from the server will be JSON formatted objects and I still have not figured out the complete structure yet. The things I need to send back to the client would be:  An array of messages to display to the player, player's new position should they move, the player stats when in combat, their current target and any other players or mobiles they encounter. Could end up being a large set of data for certain actions so we'll see about performance there.

10/23/07


PBBGs and Performance

One of the main things I am concentrating on for Perenthia and my PBBG Engine is performance. A lot has to go on in a game, each action be it movement, combat, etc. causes a lot of code to be executed and database calls to be made. What I am striving for in Perenthia and ultimately in my PBBG Engine will be as few database calls per command as I can get away with. Right now Perenthia makes several calls, one to load the Character and depending on the action 1-4 more database calls and then the final save Character call.

For Perenthia, I was able to get movement into the Character load call, then make one call to determine if the player can move and if any monsters are encountered, then a final call to save the character. That is probably as small as I can get movement but it still does not perform the way that it should.

I thought about caching or storing the map in memory but with over 150,000 records in the table storing the map data that is just not a good idea. Just not sure of the best approach for this. The database procedure for movement runs in under a second so I don't think that is the bottle neck, I think the bottle neck is sending all that data from the server to the client. I may try to asnychronously download the map data to the client while they are playing and just send smaller amounts of data for the map. Maybe a JavaScript file that can be auto generated using custom handlers that would contain the entire map structure with X,Y,Z and Terrain values. Then I can just use the player's current location to position them on the map. since I validate their position on the server I can still perform the monster check and move check and just not send the whole map down the pipe.

Attack is another performance bottle neck that I plan to devote some time to once I get the map movement sped up. 

10/19/07


.NET PBBG Engine

In between updating Perenthia and adding new features I have been pulling parts of the code base into a more generic PBBG Engine I am writing in C#. I started working on it when I upgraded the Knights of the Realm game and used parts of it for Perenthia. I am hoping to put Knights of the Realm Beta 2 on the new engine once I get it finished.

I am building the engine as generic as I can but it will incorporate a base rules set and some basic concepts. The base objects will be Avatars, Places and Things. These objects will contain the properties required to function within the rules set and all objects will derive from a base GameObject class that will provide a properties collection for creating custom properties on derived game objects.

The game will be driven by commands sent from the client. Some objects will handle the commands in the engine framework while other commands will cause events to be raised that deriving implementations can handle and provide custom execution or additional execution of the commands.

The egnine will basically be a commands/rules processor that I will hopefully be able to build a variety of games on. I have plans and ideas for several types of games and do not want to continually build the same thing over and over, hence the PBBG engine. 

10/17/07


ASP.NET AJAX Server Controls and PBBGs

I ran into a major performance issue with the ASP.NET AJAX Server Controls while testing my persistent browser based game Perenthia. I had initially used update panels fro the various regions on the main game interface such as the player stats, map and chat window. Programming this was simple as I could do everything in the server side code and just send back the results. With the partial page rendering feature of the ASP.NET AJAX Extensions only the update panel html was sent back to the browser.

Once I moved the application into a production environment and had people on there playing and testing the web starting running out of memory, the application was consuming the server memory at an alarming rate. What was happening was that IIS would jump 1 to 2 MB of RAM for each request made by the client, that means every time someone moved on the game map 1 to 2 MB of RAM were being held and not released. I tried a bunch of different stuff from optimizing stored procedures to caching the map data but none of it helped.

I used Firebug to watch the AJAX request and response and to see if I could reduce that down some. The response was simply HTML fragments so I wasn't too worried about that but the request sent the entire ViewState up to the server with each post. The ViewState for the game page could be quite large since I was appending messages to the chat window which was a server control.

I was able to eliminate the ViewState issue with the chat window but the app was still consuming RAM and not releasing it.

I decided to try just a simple JavaScript only AJAX post using the Microsoft AJAX Client Libraries. After doing some basic tests on the chat window I decided to rebuild the game interface using only client side AJAX calls, no update panels. This has resolved the server memory issue, why, I am still not sure, must be something with the way the resources are handled in .NET. I have not encountered the slow downs or crashes from before and the app is actually running a little smoother on the front end as well.

What I settled on was a custom ASHX handler class that handles the commands from the client and returns JSON strings that the UI can then translate and use to update the interface components. I had to rebuild some of the interface components as JavaScript objects but overall it was the right choice. Not too mention that I can now use that same handler with other interfaces such as Flash or Silverlight.

In conclusion, while the AJAX Server Controls might work great for most web sites they are definitely not optimal for a persistent browser based game (PPBG).

10/1/07


Perenthia PBBG Post-Beta Release

I released the persistent browser based game Perenthia last week into a public BETA. Got some great folks on there testing stuff out, finding bugs and overall just providing great feedback. It's funny how much can get past your unit testing when you are the one who wrote the code.

Anyway, got a game refresh and loads of bug fixes coming either tonight or tomorrow and then hopefully I can move on to getting quests ready to go. 

9/21/07


Upload started..

I have started the database upload for Perenthia and will move the files shortly thereafter. Once everything is tested up on the server to ensure it is working properly I will open up the game.

9/14/07


Perenthia PBBG Release Tomorrow

The persistent browser based game Perenthia will open for a public Beta tomorrow evening. Some of the quests have yet to be completed but they are higher level quests so I still have time to map them all out.

Banks and Households are not complete and although you may see references to them they do not function as of yet. Banks will allow you to borrow money and store items and gold and Households are player run groups that will feature private messaging, group events and quests and could possibly include Household vs Household competitions.

Since banks are not complete you can pretty much carry as much stuff as you want. Once banks are complete you will find yourself restricted if you carry too much.  

9/13/07


Perenthia Release Update

Not sure what time of day I will open up Perenthia on Friday the 14th. Probably sometime in the morning, depends on how my last testing goes. I am finishing up testing out the quests and auto generated dungeons. If everything goes well, which it never does, the game will be live Friday morning. If I run into snags could be later in the day or worse case Saturday.

For those who don't know, Perenthia is a persistent browser based game set in a fantasy world and will feature Character Profiles, Live Chat, Quests, Forums, Households and hopefully Player vs Player combat.

Character Profiles will allow you to upload an avatar image, provide a description about your Character and even maintain a journal where other players can leave you comments and you can catalog your adventures.

Live Chat is built into the interface and will allow you to chat with other players in the game.

Quests are an important part of the game and the main storyline drives several key quests that will send you all across the landscape.

Forums allow you to interact with other players, helping each other on quests, reporting bugs, etc.

Households have yet to be completed but will be player run and allow the head of household to assign special titles to levels and create a unique experience for members. 

9/11/07


PBBG Mapper

Here is a screenshot of the PBBG mapping tool I wrote for creating the Perenthia world. The screenshot is the City of Angarath, a starting point in the game. The mapper is a  Windows application written in C# 2.0.

PBBG Mapper 

9/11/07


Perenthia PBBG AJAX Screenshot

Here is a screenshot of the AJAX interface for my PBBG Perenthia, which is scheduled for a beta release this Friday September 14th. This will be the main game screen where all actions related to game play will take place.

Perenthia PBBG AJAX UI 

9/10/07


Perenthia PBBG Update

Making good progress toward the Beta release of my PBBG Perenthia on September 14th. Not sure what time of day I will open the site up, probably in the morning some time on the 14th. Anyway, the AJAX game interface is working great after I scaled it down a little. I am still working on a more advanced interface in Silverlight 1.1, might be a little while before that is finished though, I want to get the game up and running first.

 

9/7/07


Perenthia Release Date

Alright, it is looking like the first initial release of Perenthia will be September 14th 2007. The initial release will feature an AJAX based user interface, kind of looks like a MUD client, with a new Silverlight interface to follow in the coming months, once Silverlight 1.1 goes into Beta with a Go Live license.

Players will be able to create Characters with a special profile page where they can describe their Characters and even upload an avatar image. A friends list on the Character Profile page will allow players to link to their friends and simple Character blog will allow the player to keep visitors up-to-date on their progress. Some other features of Perenthia will include player run Households, where players can make up advancement ranks, various length quests for all levels of play that will focus and determine the main story line, a different kind of magic system consisting of runes of power that you can combine to create spell effects and of course adventuring into wilderness to defeat scary monsters.

For those unaware, Perenthia is a persistent browser based game (PBBG) set in a fantasy medieval world. 

9/3/07


Perenthia Update - Release Soon

I am hoping to release Perenthia around the end of August. Everything is mostly complete and ready to go, I have a few UI element issues to work out and then the game will go live with a public beta.

8/13/07