RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

[RUO 2.0] Integrated Web-Server

Vorspire

Knight
[RUO 2.0] Integrated Web-Server


----------
SYSTEM REQUIREMENTS
----------

For Use
  • Windows User Account with Administrator rights
  • Windows XP Home Edition
  • Windows XP Professional x64 Edition
  • Windows Server 2003
  • Windows Service Pack 2
  • .NET Framework 2.0
  • RunUO 2.0 ***
  • Ultima Online SDK 2.X ***

For Development

  • Windows XP Home Edition
  • Windows XP Professional x64 Edition
  • Windows Server 2003
  • Windows Service Pack 2
  • .NET Framework 2.0
  • RunUO 2.0 ***
  • Ultima Online SDK 2.X ***

*** Only required for custom WebObjects and/or CoreModules that are supplied in the "Custom" directory with the initial download.


----------
PACKAGE:
----------
namsepace WebServer
namsepace WebServer.HTDOCS
namsepace WebServer.Modules
----------

The time has come, to finally integrate some sort of web-server service into RunUO. One that is easy modded and can deliver the performance and security required to make this all worth-while.

While the current DLL I have wrote is quite powerful in terms of dynamics, I am releasing it here with one simple function;
To provide any shard with a reliable, fast and real-time "Shard Status" service, without the need for writing complicated PHP scripts.

I will have more information to come and possibly many updates, plugins and custom pages to expand this little package into something that allows you to have complete control over your shard from your web-browser.

----------
The Basics
----------
Code:
Thanks for taking interest in this project.

Here are the simple installation instructions for RunUO 2.0+

1)
Copy the entire contents of this package to the local relative directory for RunUO.exe, so that RunUO.exe and WebServer.dll are in the same directory.

2)
Browse to your RunUO "Scripts" directory and create a new directory named "WebServer".
The resulting path should be;
RunUO.exe/Scripts/WebServer/

3)
Browse to the "Custom" directory; "RunUO.exe/WebServer/Custom/" and >>MOVE<< the entire contents, including the script files, to the new "WebServer" folder you just created.
The resulting paths should be;
RunUO.exe/Scripts/WebServer/Modules/
RunUO.exe/Scripts/WebServer/WebObjects/

4)
Remove the trailing dash from the end of these files:
Initializer.cs-
StatusPage.wsobj.cs-
ItemCatalog.wsobj.cs-
Paperdoll.wsobj.cs-

5)
Check Initializer.cs to see if the configuration options are to your liking.

6)
Browse to your RunUO data folder; "RunUO.exe/Data/" and open "Assemblies.cfg".
Add a new line to the list; "WebServer.dll", save and close.

7)
Everything should be ready to go. Boot up your shard and test your WebServer by visitng;
http://localhost/index.html
Alternatively, visit www.whatismyip.com to find out your IP address and do the following:
http://<your_ip_address>/index.html

8)
If that works, then you have successfully set up your WebServer system, congratulations :)

----------

This WebServer comes with (almost) full documentation, with as accurate descriptions as I could manage.
Over 250 comments and annotations to help you develop your own special custom virtual pages.

----------
Hints and Tips
----------

WebObjects:

Virtual WebObjects are WebObjects that can be dynamically called into memory, serve an HttpRequest and transport the requested data back to the HttpResponse, they act exactly as any Web-Page should.

All physical files located in "RunUO.exe/WebServer/HTDOCS/" are also called into memory as Physical WebObjects.
This means that any "web page" that may be requested, can be served with a physical file in the "RunUO.exe/WebServer/HTDOCS/" directory, or by a >>CUSTOM<< WebObject script located in the "RunUO.exe/Scripts/WebServer/" directory.

The VirtualName is responsible for directing the request to the right file and as long as you set the right ContentType, you can use any file extension you wish, or none at all :) For example: "status.vor" still produces XML data.

The WebObjects were partly inspired by the way the RunUO Gumps system works and uses 3 main methods for inserting data into the body of a custom WebObject;
"AddHTML", "AddText" and "AddByte".

The Status Page can be accessed via; http://<host>/RunUO/status.vor
The Test Image Page can be accessed via; http://<host>/RunUO/test_image.jpg
Code:
************************
************************
[B]ALL WebObjects MUST be assigned to the WebServer.HTDOCS namespace in order to be accessed by the WebServer HttpRequest handling system.

However, you may assign additional names to the namespace, which will represent the URL you use in your browser.

For example, "namespace WebServer.HTDOCS.Public" would be the 'relative' path for the URL "http://<host>/Public/"

Any WebObject class assigned to the custom namespace will be accessed from that same URL appended with the WebObjects' VirtualName, IE; "http://<host>/Public/HelloWorld.obj"[/B]
************************
************************
Core Modules:

These Core Modules are important to the WebServer system, there are currently 6 embedded Core Modules in the program that handle common tasks such as Flood Protection, Garbage Collection, WebObjects Registry and even the actual HttpListener service itself.

Core Modules are basically a 'plug-in' class for the WebServer system, that are loaded before the main Listener and are used to handle special tasks.

Custom Core Modules can be plugged into the WebServer system by adding the relevant scripts to the "RunUO.exe/Scripts/WebServer/Modules/", there is a sample Core Module supplied that is the main set-up to use when creating any custom Core Module.

Core Modules are started in a prioritized order, which you can select in the CoreModuleAttribute arguments.
You can not change the priority of the 6 core WebServer Core Modules.

When using the CoreModuleAttribute, you must always supply the Type argument with the relevant Type of the class you are attaching the attribute to.

For example, if you were to create a custom Core Module named "HelloWorld", the Type argument of the CoreModuleAttribute should also be "HelloWorld".
The Name argument is completely custom and can be anything you wish.
Code:
************************
************************
[B]ALL Core Modules should be assigned to the "WebServer.Modules" namepsace to avoid any unwanted ambiguity between WebServer and RunUO assemblies.[/B]
************************
************************

I hope that's enough to get you started.

Please remember that this software is currently in the UNSTABLE-BETA stage and I am not responsible for any damage or data loss as a result of using this system, although I can *almost* guarantee that no damage or data-loss could possibly happen ;)

I will be working on and updating this project quite frequently, however, I can not exactly say when new updates may become available on the RunUO Forums.

I hope you enjoy this package, the next release will yield many new features and more custom Core Modules and advanced custom WebObjects.

WEBSERVER_LITE_README.TXT said:
WebServerLite.exe is an application host for the WebServer DLL assembly, which can allow the WebServer to run as a stand-alone application.

If you run WebServerLite.exe, it will not include any of the custom Core Modules or WebObjects from your "RunUO.exe/Scripts/" directory, as it is defaulted to the local "WebServer/Custom/" directory.

WebServer.cfg was specifically created to provide a RunTime configuraton for WebServerLite.exe and will not, in any way, affect the RunUO-WebServer configuration.

To find out how to edit the RunUO-WebServer configuration, please refer to "RUNUO_INSTALL.TXT".

-Vorspire


Extra Information
 
K

KevinEvans

Guest
SWEET! Thanks Vorspire! <3

and does it share the same port as the shard? or does it listen on port 80?
 

Vorspire

Knight
KevinEvans;814621 said:
SWEET! Thanks Vorspire! <3

and does it share the same port as the shard? or does it listen on port 80?

It listens on all available IP Addresses on Port 80 currently.

You can add your own host names in the Initializer:

Code:
[COLOR="SeaGreen"]/// <summary>
/// Register a Listener Host that requires a Port. Hosts must be registered before the Core is initialized, if a host is added while the Core is running, the Core must be restarted for the changes to take effect.
/// </summary>
/// <param name="host">Host-Name, IPv4, IPv6 or '+' for all available IP Addresses</param>
/// <param name="port">Listener Port, this port should be public and configured to accept incomming connections</param>[/COLOR]
public static void Add(string host, int port)
{
	string hostName = String.Format("http://{0}:{1}/", host, port);

	if (!_Hosts.Contains(hostName))
	{ _Hosts.Add(hostName); }
}

[COLOR="SeaGreen"]/// <summary>
/// Register a Listener Host that does not require a Port. Hosts must be registered before the Core is initialized, if a host is added while the Core is running, the Core must be restarted for the changes to take effect.
/// </summary>
/// <param name="host">Host-Name, IPv4, IPv6 or '+' for all available IP Addresses</param>[/COLOR]
public static void Add(string host)
{
	string hostName = String.Format("http://{0}/", host);

	if (!_Hosts.Contains(hostName))
	{ _Hosts.Add(hostName); }
}

Code:
Listener.Add("xxx.xxx.xxx.xxx", 1234);
 

Kamon

Wanderer
RunUO doesn't find System.Linq, what could I do? :confused:
Using RunUO SVN 339 with Mondian's Legacy SVN 48

Edit: It seems that I have to install dotnet framework 3.5 :p
Edit2: It didn't fix the problem, RunUO keeps using framework 2.0 :S
 

Vorspire

Knight
It could be a possibility with this system if you were to write the virtual web-pages correctly, I suppose it can be done :)
 

Vorspire

Knight
I have "downgraded" the project to 2.0 and I could release it now, but one problem still remains, the damn thing won't serve images for some reason and I'm still tweaking the flood filter amongst other things :)

Won't be long now...
 

old_school

Wanderer
Thats awsome man when u get it done can u also include a basic setup giude for us whom want to set it up on a web page using php Thanks.
 

Vorspire

Knight
HOME: http://projects.vita-nex.com/webserverlite/index.php/topic,6.msg6

Yes of course, I will provide all relevant documentation and tutorials to help out :D

In most cases, you may not need to use an external website as there is the unique ability with this system to write your own WebObjects - A class that provides methods that can virtually compile any web element, such as Images, providing that it is scripted properly.

Here is an example of the WebObject that is a page-type element which loads the shard status:
Accessable via http://<host>/RunUO/status.vor - The file extension does not matter when it comes to these virtual WebObjects, and can be anything you wish, as long as the correct MimeType is set. (Default MimeType is text/plain.
Code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Net;

using Server;
using Server.Network;
using Server.Accounting;
using Server.Gumps;
using Server.Items;
using Server.Mobiles;

using WebServer;
using WebServer.Modules;

namespace WebServer.HTDOCS.RunUO
{
	public sealed class StatusPage : WebObject
	{
		public override string VirtualName { get { return "status.vor"; } }

		public StatusPage(HttpListenerContext ctx, Client client, Uri url)
			: base(ctx, client, url)
		{
			Name = "Status Page";

			int[] totals = new int[]
			{
				Accounts.Table.Count,		//Accounts
				NetState.Instances.Count,	//Online Clients
				World.Items.Count,			//World Items
				World.Mobiles.Count,		//World Mobiles
				Server.Core.ScriptItems,	//Item Scripts
				Server.Core.ScriptMobiles,	//Mobile Scripts
			};

			double upTime = (DateTime.Now - Clock.ServerStart).TotalMilliseconds;	//Up-Time
			long memory = GC.GetTotalMemory(false);									//Memory Usage (bytes)

			string mode = "xml";

			if (GetQuery("mode") != null)
				mode = GetQuery("mode");

			switch (mode)
			{
				default: { goto case "xml"; }
				case "xml":
					{
						ContentType = "text/xml";

						AddHTML("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");

						AddHTML("<STATUS>");

						AddHTML("<TOTALS>");
						AddHTML("<ACCOUNTS>{0}</ACCOUNTS>", totals[0]);
						AddHTML("<CLIENTS>{0}</CLIENTS>", totals[1]);
						AddHTML("<ITEMS>{0}</ITEMS>", totals[2]);
						AddHTML("<MOBILES>{0}</MOBILES>", totals[3]);
						AddHTML("</TOTALS>");

						AddHTML("<SCRIPTS>");
						AddHTML("<ITEMS>{0}</ITEMS>", totals[4]);
						AddHTML("<MOBILES>{0}</MOBILES>", totals[5]);
						AddHTML("</SCRIPTS>");

						AddHTML("<SERVER>");
						AddHTML("<UPTIME>{0}</UPTIME>", upTime);
						AddHTML("<MEMORY>{0}</MEMORY>", memory);
						AddHTML("<FRAMEWORK>{0}</FRAMEWORK>", Environment.Version);
						AddHTML("<OSVERSION>{0}</OSVERSION>", Environment.OSVersion);
						AddHTML("</SERVER>");

						AddHTML("</STATUS>");
					} break;
				case "html":
					{
						ContentType = "text/html";

						AddHTML("<HTML>");
						AddHTML("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
						AddHTML("<HEAD><TITLE>STATUS</TITLE></HEAD>");
						AddHTML("<BODY>");

						AddHTML("<table border=\"1\" cellpadding=\"2\" cellspacing=\"0\">");
						AddHTML("<tr><td>");

						AddHTML("<table border=\"1\" cellpadding=\"2\" cellspacing=\"0\" width=\"100%\">");
						AddHTML("<tr><td colspan=\"2\">STATUS</td></tr>");
						AddHTML("<tr><td>ACCOUNTS</td><td>{0}</td></tr>", totals[0]);
						AddHTML("<tr><td>CLIENTS</td><td>{0}</td></tr>", totals[1]);
						AddHTML("<tr><td>ITEMS</td><td>{0}</td></tr>", totals[2]);
						AddHTML("<tr><td>MOBILES</td><td>{0}</td></tr>", totals[3]);
						AddHTML("</table>");

						AddHTML("</td></tr>");
						AddHTML("<tr><td>");

						AddHTML("<table border=\"1\" cellpadding=\"2\" cellspacing=\"0\" width=\"100%\">");
						AddHTML("<tr><td colspan=\"2\">SCRIPTS</td></tr>");
						AddHTML("<tr><td>ITEMS</td><td>{0}</td></tr>", totals[4]);
						AddHTML("<tr><td>MOBILES</td><td>{0}</td></tr>", totals[5]);
						AddHTML("</table>");

						AddHTML("</td></tr>");
						AddHTML("<tr><td>");

						AddHTML("<table border=\"1\" cellpadding=\"2\" cellspacing=\"0\" width=\"100%\">");
						AddHTML("<tr><td colspan=\"2\">SERVER</td></tr>");
						AddHTML("<tr><td>UPTIME</td><td>{0}</td></tr>", AdminGump.FormatTimeSpan(TimeSpan.FromMilliseconds(upTime)));
						AddHTML("<tr><td>MEMORY USAGE</td><td>{0}</td></tr>", AdminGump.FormatByteAmount(memory));
						AddHTML("<tr><td>FRAMEWORK</td><td>{0}</td></tr>",Environment.Version);
						AddHTML("<tr><td>OPERATING SYSTEM</td><td>{0}</td></tr>", Environment.OSVersion);
						AddHTML("</table>");

						AddHTML("</td></tr>");
						AddHTML("</table>");

						AddHTML("</BODY>");
						AddHTML("</HTML>");
					} break;
				case "plain":
					{
						ContentType = "text/plain";

						AddHTML("STATUS");
						AddHTML("ACCOUNTS: {0}", totals[0]);
						AddHTML("CLIENTS: {0}", totals[1]);
						AddHTML("ITEMS: {0}", totals[2]);
						AddHTML("MOBILES: {0}", totals[3]);

						AddHTML("");

						AddHTML("SCRIPTS");
						AddHTML("ITEMS: {0}", totals[4]);
						AddHTML("MOBILES: {0}", totals[5]);

						AddHTML("");

						AddHTML("SERVER");
						AddHTML("UPTIME: {0}", AdminGump.FormatTimeSpan(TimeSpan.FromMilliseconds(upTime)));
						AddHTML("MEMORY USAGE: {0}", AdminGump.FormatByteAmount(memory));
						AddHTML("FRAMEWORK: {0}", Environment.Version);
						AddHTML("OPERATING SYSTEM: {0}", Environment.OSVersion);
					} break;
			}
		}
			
		public StatusPage(UID uid)
			: base(uid)
		{ }
	}
}

The StatusPage inherits the WebObject class, which in turn, inherits the IWebObject interface used to reply to requests.
The WebObject has underlying overridable methods that compile all of the given data when the page is requested, the data contained within a page (as you can see) can be modified against the client who is loading the page and the URL arguments that are passed, by accessing the string[] Queries property.
To generate an image is just as simple, as all WebObjects are compiled into a byte[] format and sent with the correct encoding to the request output stream. All you'd need to do is use the System.Drawing.Bitmap class to load a new image file and then use the AddByte( byte[] bytes ) method provided by the WebObject class to insert the information ready for the final compilation process.

Hope that wasn't too much of an essay :p
 

Vorspire

Knight
I have managed to impliment ASP.NET hosting into the WebServer application for the next release. PHP should also be supported. Watch this space.
 

old_school

Wanderer
Well I have a PHP web site An Ill def be looking to install this. So in theory how does this work? I mean in short. I just set up the script to run off my web page? An people just connect to my web page and play? Or do they need a copy of UO first?
 

Vorspire

Knight
old_school;816003 said:
Well I have a PHP web site An Ill def be looking to install this. So in theory how does this work? I mean in short. I just set up the script to run off my web page? An people just connect to my web page and play? Or do they need a copy of UO first?

It's not intended for that reason (to be playable from the browser), it is more aimed at enabling you to host your own websites from inside the RunUO directory with all the custom code you like.

Being able to display a tatus page is one of many things you could do with this.
Another impimentation would be to create a website with UO that allowed you to access the configuration files for anything, script things remotely, send commands and view the console window from within the browser.

You can even generate images on-the-fly using the System.Drawing.Bitmap class to handle image files, this means you could generate an image of every body-ID from your shard's mul files for use with monster descriptions.

You could even create an entire real-time library for your shard, like a sort of knowledge-base that is updated in real-time as the server runs.

You could impliment a web-accounting type system that required you to verify your account details before you could create the account.

The MAIN purpose of this Integrated WebServer is to provide a platform to connect with RunUO to skip out the MySQL or other data source connections that you may need to use to get the information you want.

Many possible uses :)
 

Vorspire

Knight
KevinEvans;816015 said:
Does it have any advantages over Apache? :p

Yes, the main difference being that my WebServer can operate from the same application as RunUO by simply importing the DLL and initializing the WebServer Core with WebServer.Core.Start() method.

This means that you don't have to write a 3rd party interface or website to interact with RunUO.
Infact, the only other way to communicate directly with your shard is to use the RemoteAdmin system, which is limited in what you can do, unless you develop a website with it's own set of packets that is capable of making a connections to RunUO and sending those packets.

As far as I'm aware, Apache does not come with standard support for the ASP.NET Framework :)
 

StaticZ

Sorceror
It's seems interesting, I want to look at this. When the link to download Integrated Web-Server will be back?
 

Vorspire

Knight
StaticZ;816076 said:
It's seems interesting, I want to look at this. When the link to download Integrated Web-Server will be back?

As soon as I've implimented PHP and other standard web-server services. Won't be long :)

Thanks for the continued interest in this project :)
 
Top