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!

Running Multiple Servers off a Single Host Machine with 1 Login

PappaSmurf

Knight
Running Multiple Servers off a Single Host Machine with 1 Login

This is a question that comes up every once in a while, and I know searching can find the answer but, it's easier to just post up a FAQ about it and be done with it.

You'll need a few things...
Mr. Fixits ServerList.cs which Calandor2K updated a while back for use with RunUO 2.0 and I've added additional updates for multi-shard connectivity.
And you'll need to update your SocketOptions.cs on one of your servers.

To Start off Copy the following and save it as your now ServerList.cs

Code:
// ==================================================================================================
// ServerList.cs
// ==================================================================================================
//    	1.0 	RunUO Beta 36	    Initial version
//    	1.1 	Mr Fixit	        Now automaticly detects if you are connecting localy and uses the
//				                    servers local ip in the client serverlist.
//	    1.2	    Mr Fixit	        Internet IP autodetection using www.whatismyip.com.
//  	1.3	    Mr Fixit	        If script fails to find the internet ip, keep the old one and try
//				                    again in # minutes.
//      1.4	    Mr Fixit	        You can now add AutoIP mirrors. Added whatismyip.com and myip.com.
//      1.5	    Mr Fixit	        Adjusted the AutoIP mirror engine so it supports more mirrors.
//				                    Added findmyip.com and ipaddy.com.
//      1.6	    Mr Fixit	        IP is now trimmed (Just in case). Added simflex.com, edpsciences.com,
//				                    ipid.shat.net and checkip.dyndns.org.
//      1.7     Mr Fixit            Removed www.whatismyip.com is it seems to be out of buisness.
//      1.8     Mr Fixit            Added a message to the console with ServerList.cs version when server loads.
//				                    Now detects the internet ip when the server starts.
//				                    Now checks if the ip has changed every 60 minutes instead of 30 minutes.
//      1.9     Mr Fixit            Removed noip.com mirror as it isnt working anymore.
//      2.0     Mr Fixit            Now only renews the ip every 24 hours (1440 minutes).
//      2.1     Callandor2k         Made compatible with svn 278.
//              AKA                 Changed the way it writes to console and added a few console lines. 
//              Shai'Tan Malkier    Removed findmyip.com. 3 edits are required. ServerName, Address and Local Lan IP.
//                                  Check the port address on line 208 to make sure its the one you use in SocketOptions.cs.
//      2.2     PappaSmurf          Modified to allow Multiple Servers to Run on One Machine.
// ==================================================================================================

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using Server;
using Server.Misc;
using Server.Network;

namespace Server.Misc
{
	public class ServerList
	{
		 
		// ==================================================================================
		// YOUR SERVERS NAME
		// ==================================================================================
        public const string ServerName = "[COLOR="Blue"]*Your Choice of Name*[/COLOR]";    // Server Name Goes Here
        public const string ServerNameA = "[COLOR="Purple"]*Your Choice of Name*[/COLOR]";  // Other Sever Name Goes Here


		// ==================================================================================
		// YOUR INTERNET IP OR DNS NAME
		// Here you can select to autodetect your internet ip, or manualy specify
		// Examples:
		// public static string Address = "12.34.56.78";
		// public static string Address = "shard.host.com";
		// ==================================================================================
		public const bool InternetIPAutodetect = true;
		public const int MinutesBetweenIPAutodetect = 14400;
        public static string Address = null;         // Server Address Goes Here
        public static string AddressA = null;
        public const int PortA = [COLOR="Red"]2593[/COLOR];
		// ==================================================================================
		// Here are some values stored
		// ==================================================================================
		private static LocalLanIPRange[] LocalLanIPRanges = new LocalLanIPRange[10];		
		private static UInt32 LocalLanIPRangesCount;
		private static AutoIPMirror[] AutoIPMirrors = new AutoIPMirror[10];	
		private static UInt32 AutoIPMirrorsCount;
		private static DateTime InternetIPAutodetectLast;
		
		// ==================================================================================
		// Initialization
		// ==================================================================================
		public static void Initialize()
		{
			// ----------------------------------------------------
			// Load the local LAN ip ranges. 
            // Remove the // on section you need or create your own
			// ----------------------------------------------------
			//AddLocalLANIPRange("10.0.0.0", "10.255.255.255");
			//AddLocalLANIPRange("192.168.1.100", "192.168.1.110");
			//AddLocalLANIPRange("172.16.0.0", "172.32.255.255");
			//AddLocalLANIPRange("169.254.0.0", "169.254.255.255");

			// ----------------------------------------------------
			// Load the Auto IP mirros
			// ----------------------------------------------------
            AddAutoIPMirror("http://www.ipaddy.com/", "Your IP address is: ", "<br>");
            AddAutoIPMirror("http://checkip.dyndns.org/", "Current IP Address: ", "</body>");
            AddAutoIPMirror("http://ipid.shat.net/iponly/", "<title>", "</title>");
            AddAutoIPMirror("http://www.edpsciences.com/htbin/ipaddress", "Your IP address is  <B> ", " </B>");
			
			// ----------------------------------------------------
			// Create the event
			// ----------------------------------------------------
			EventSink.ServerList += new ServerListEventHandler( EventSink_ServerList );

            // ----------------------------------------------------
            // Show info in console
            // ----------------------------------------------------
            Console.WriteLine("ServerList 2.2");
            Console.WriteLine("Welcome to Server 2");
			
			// ----------------------------------------------------
			// Lets find internet ip
			// ----------------------------------------------------
			DetectInternetIP();
		}

		// ==================================================================================
		// Add a range of local lan ips
		// ==================================================================================
		private static void AddLocalLANIPRange(string RangeFrom, string	RangeTo)
		{
			LocalLanIPRanges[LocalLanIPRangesCount] = new LocalLanIPRange();
			LocalLanIPRanges[LocalLanIPRangesCount].RangeFrom = StringIPToUInt32IP(RangeFrom);
			LocalLanIPRanges[LocalLanIPRangesCount].RangeTo = StringIPToUInt32IP(RangeTo);
			LocalLanIPRangesCount = LocalLanIPRangesCount + 1;
		}
		
		// ==================================================================================
		// Convert a ip string to a binary unsigned int
		// ==================================================================================
		private static UInt32 StringIPToUInt32IP(string addr)
		{
			byte[] byteArray1 = IPAddress.Parse(addr).GetAddressBytes();
			byte[] byteArray2 = IPAddress.Parse(addr).GetAddressBytes();
			byteArray1[0] = byteArray2[3];
			byteArray1[1] = byteArray2[2];
			byteArray1[2] = byteArray2[1];
			byteArray1[3] = byteArray2[0];
			return  BitConverter.ToUInt32( byteArray1, 0);
		}
		
		// ==================================================================================
		// Used to store the local lan ip ranges
		// ==================================================================================
		private class LocalLanIPRange
		{
			public UInt32			RangeFrom;
			public UInt32			RangeTo;
		}	

		// ==================================================================================
		// Add a AutoIP mirror
		// ==================================================================================
		private static void AddAutoIPMirror(string sURL, string	sStart, string sEnd)
		{
			AutoIPMirrors[AutoIPMirrorsCount] = new AutoIPMirror();
			AutoIPMirrors[AutoIPMirrorsCount].sURL = sURL;
			AutoIPMirrors[AutoIPMirrorsCount].sStart = sStart;
			AutoIPMirrors[AutoIPMirrorsCount].sEnd = sEnd;
			AutoIPMirrorsCount = AutoIPMirrorsCount + 1;
		}

		// ==================================================================================
		// Used to store the Auto IP mirrors
		// ==================================================================================
		private class AutoIPMirror
		{
			public string			sURL;
			public string			sStart;
			public string			sEnd;
			public UInt32			iFailures;
		}

		// ==================================================================================
		// Detect ip
		// ==================================================================================
		public static void DetectInternetIP()
		{

			// ----------------------------------------------------
			// Autodetect the Internet IP
			// ----------------------------------------------------
			if (InternetIPAutodetect) {
				DateTime UpdateTime = InternetIPAutodetectLast;
				UpdateTime = UpdateTime.AddMinutes(MinutesBetweenIPAutodetect);
				if (UpdateTime<DateTime.Now) {
					string NewAddress = null;
					NewAddress = FindInternetIP();
					InternetIPAutodetectLast = DateTime.Now;
					if (NewAddress!=null) 
					{
						Address = NewAddress;
					}
				}
			}
		}

		// ==================================================================================
		// The serverlist event
		// ==================================================================================
		public static void EventSink_ServerList( ServerListEventArgs e )
		{
			try
			{

				// ----------------------------------------------------
				// Lets find internet ip
				// ----------------------------------------------------
				DetectInternetIP();
				
				// ----------------------------------------------------
				// Find the server ip to use for this user
				// ----------------------------------------------------
				IPAddress ipAddr = FindMachineIP(e);
				
				// ----------------------------------------------------
				// Send serverlist
				// ----------------------------------------------------
				if (ipAddr != null)
				{
                    e.AddServer(ServerName, new IPEndPoint(ipAddr, 2593 ));//  Place the port that you are using here.
                    e.AddServer(ServerNameA, new IPEndPoint(ipAddr, PortA));
				} else {
					e.Rejected = true;
				}
			}
			catch
			{
				e.Rejected = true;
			}
		}

		// ==================================================================================
		// Connects to a webserver that gives you your internet ip
		// ==================================================================================
                public static string FindInternetIP( )
		{

			// ----------------------------------------------------
			// Pick a random mirror
			// ----------------------------------------------------
			Random rnd = new Random();
			int UseMirror = (int)( rnd.NextDouble() * AutoIPMirrorsCount);
			string MyIP = "";
			
			// ----------------------------------------------------
			// Catch if the mirror is down
			// ----------------------------------------------------
			try
			{
				// ----------------------------------------------------
				// Get the webpage
				// ----------------------------------------------------
        	    		WebClient client = new WebClient();
            			byte[] pageData = client.DownloadData(AutoIPMirrors[UseMirror].sURL);
            			MyIP = System.Text.Encoding.ASCII.GetString(pageData);
            		
				// ----------------------------------------------------
				// Find the string
				// ----------------------------------------------------
                        	int iStart = MyIP.LastIndexOf(AutoIPMirrors[UseMirror].sStart);   
                        	int iEnd = MyIP.IndexOf(AutoIPMirrors[UseMirror].sEnd, iStart+AutoIPMirrors[UseMirror].sStart.Length);
                        	MyIP = MyIP.Substring(iStart+AutoIPMirrors[UseMirror].sStart.Length, iEnd-iStart-AutoIPMirrors[UseMirror].sStart.Length );
                        	MyIP = MyIP.Trim();
                        	
				// ----------------------------------------------------
				// Return value
				// ----------------------------------------------------
                            Console.WriteLine("-------------------------------------------------------------------------------");
                            Console.WriteLine("Serverlist.cs: 2.1");
                            Console.WriteLine("{0} ({1})", ServerName, Address);
                            Console.WriteLine("You are using Internet IP : {0}", MyIP);
                            Console.WriteLine("IP found by: ({0})", AutoIPMirrors[UseMirror].sURL);
                            Console.WriteLine("-------------------------------------------------------------------------------");
        	                return MyIP;
			}
			catch
			{
				Console.WriteLine("Unable to autoupdate the Internet IP from {0}!", AutoIPMirrors[UseMirror].sURL);
				Console.WriteLine("----------------------------------------------------------------------");
				Console.WriteLine(MyIP);
				Console.WriteLine("----------------------------------------------------------------------");
				return null;
			}
        	}

		// ==================================================================================
		// Calculates what server IP to use
		// ==================================================================================
                public static IPAddress FindMachineIP( ServerListEventArgs e )
		{
			// ----------------------------------------------------
			// Find the IP of the connecting user
			// ----------------------------------------------------
			Socket sock = e.State.Socket;
			IPAddress theirAddress = ((IPEndPoint)sock.RemoteEndPoint).Address;				
			IPAddress serverAddress;

			// ----------------------------------------------------
			// Is it Loopback?
			// ----------------------------------------------------
			if ( IPAddress.IsLoopback( theirAddress ) )
			{
				return IPAddress.Parse( "127.0.0.1" );
			}

			// ----------------------------------------------------
			// Local
			// ----------------------------------------------------
			UInt32 uint32Address = StringIPToUInt32IP(theirAddress.ToString());
			for (UInt32 LocalLanIPRangesLoop = 0 ; LocalLanIPRangesLoop < LocalLanIPRangesCount; LocalLanIPRangesLoop++)
			{	
				if ( (LocalLanIPRanges[LocalLanIPRangesLoop].RangeFrom <= uint32Address) && (LocalLanIPRanges[LocalLanIPRangesLoop].RangeTo >= uint32Address) )
				{
					Resolve(Dns.GetHostName(), out serverAddress);
					
					Console.WriteLine("Player is reconnecting to " + serverAddress.ToString());
					return serverAddress;
				}
			}

			// ----------------------------------------------------
			// Internet addresses
			// ----------------------------------------------------
			if (Address!=null)
			{
				Resolve(Address, out serverAddress);	
			} else {
				Resolve(Dns.GetHostName(), out serverAddress);	
			}
			
			Console.WriteLine("Player is reconnecting to " + serverAddress.ToString());
			return serverAddress;
		}
		
		// ==================================================================================
		// Resolves dns names
		// ==================================================================================
		public static bool Resolve( string addr, out IPAddress outValue )
		{
			try
			{
				outValue = IPAddress.Parse( addr );
				return true;
			}
			catch
			{
				try
				{
				IPHostEntry iphe = Dns.GetHostEntry( addr );

					if ( iphe.AddressList.Length > 0 )
					{
						outValue = iphe.AddressList[iphe.AddressList.Length - 1];
						return true;
					}
				}
				catch
				{
				}
			}
			outValue = IPAddress.None;
			return false;
		}
	}
}
namespace Server.Network
{
    public class APH
    {
        public static void Initialize()
        {
            PacketHandlers.Register(145, 65, false, new OnPacketReceive(GameLogin));
        }

        public static void GameLogin(NetState state, PacketReader pvSrc)
        {
            if (state.SentFirstPacket)
            {
                state.Dispose();
                return;
            }
            state.SentFirstPacket = true;
            int SecurityID = pvSrc.ReadInt32();

            string un = pvSrc.ReadString(30);
            string pw = pvSrc.ReadString(30);
            GameLoginEventArgs loginevents = new GameLoginEventArgs(state, un, pw);
            EventSink.InvokeGameLogin(loginevents);
            if (loginevents.Accepted)
            {
                state.CityInfo = loginevents.CityInfo;
                state.CompressionEnabled = true;
                /*if (Core.AOS)
                {
                    state.Send(SupportedFeatures.Instantiate());
                }*/
                state.Send(new CharacterList(state.Account, state.CityInfo));
                return;
            }
            state.Dispose();
        }
    }
}

Replace the Blue text with the name of the Server you are using this file with, Replace the Purpler Text with the Name of the other server.

For Example. I have two server builds, one is standard ML the other is Siege Perilous ML Rules..
For me I use the following
RunUO ML Build
RunUO Siege Perilous Build

Still With me?

Ok Now make a Second copy of this to replace the ServerList.cs in your second Servers Scripts/Misc folder
This Time when you change the Server Names it should look like this
RunUO Siege Perilous Build
RunUO ML Build

Now on this server and only on this server (the second one) you'll need a different Port Number
Change the Text in Red to what every port you wish to use, and then find the following line in SocketOptions.cs

SocketOptions.cs
Code:
private static IPEndPoint[] m_ListenerEndPoints = new IPEndPoint[] {
			new IPEndPoint( IPAddress.Any, [COLOR="Red"]2593 [/COLOR]), // Default: Listen on port 2593 on all IP addresses

The Port Number listed in Red should match the Port Number you assigned to your second Server, if not (and it won't I promise) change it to match. Save all your Files and Restart your servers.

When You go to log in you should have both on a single Login Screen.
 
Top