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 two runuo servers on one computer?

Safera

Page
Is it possible to run two runuo server instances on one computer (at the same time)?

I assume I would have to change the ports it is listening on is all?

Anyone know if/how this is possible?
 

Soteric

Knight
If you don't need them both to be listed on the same login screen then yes, you only need to change listening port.
 

Vorspire

Knight
I'll just throw this in as it doesn't seem to be noted in that linked thread;

It is highly recommended that each instance of RunUO has it's own dedicated set of UO files, or full UO installation.

For example;
Server 1: C:/Program Files (x86)/EA Games/Ultima Online Classic/Server1
Server 2: C:/Program Files (x86)/EA Games/Ultima Online Classic/Server2

This will stop any file access violation issues that may occur now or in the future when you've developed your shard a bit.

You will need to modify DataPath.cs and provide the relevant path for that server instance.

You don't have to do this, but it's better to be safe than sorry.
 

Safera

Page
ooh, good call, Vorspire. I wouldn't have thought of that now.

Thanks everyone for the help!

In laymen's terms for anyone who wants the basic jist of running 2 runuo shards at once:

Go to: Scripts > Misc >SocketOptions.cs

On line 17:
Code:
new IPEndPoint( IPAddress.Any, 2593 ), // Default: Listen on port 2593 on all IP addresses

Edit the number 2593 to a different port number.​
 
Mr Fixit Callandor2k PappaSmurf
serverlist 2 allows multiple shards to be listed on same screen vorspire said also two seperate uo installs work best for this. be advised.
 

Attachments

  • ServerList2.cs
    16.9 KB · Views: 43

Bittiez

Sorceror
Edited.

Now all you need to change is the server names and ports in the ServerList.cs file:
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 = "Main Server";    // Server Name Goes Here
        public const string ServerNameA = "[Development]";  // 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 = "";
        // public static string Address = "";
        // ==================================================================================
        public const bool InternetIPAutodetect = true;
        public const int MinutesBetweenIPAutodetect = 14400;
        public static string Address = "192.168.1.122";        // Server Address Goes Here
        public static string AddressA = "192.168.1.122";
        public const int Port = 2593;
        public const int PortA = 2590;    //Only one port listing.....????
        // ==================================================================================
        // 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 The Grove");
           
            // ----------------------------------------------------
            // 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, Port ));//  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
        // ==================================================================================
                private static string FindInternetIP()
        {
            try {
                WebRequest req = HttpWebRequest.Create( "http://www.runuo.com/ip.php" );
                req.Timeout = 15000;
 
                WebResponse res = req.GetResponse();
 
                Stream s = res.GetResponseStream();
 
                StreamReader sr = new StreamReader( s );
 
                IPAddress ip = IPAddress.Parse( sr.ReadLine() );
 
                sr.Close();
                s.Close();
                res.Close();
 
                return ip.ToString();
            } catch {
                return null;
            }
        }
                public static string FindInternetIP( bool old )
        {
 
            // ----------------------------------------------------
            // 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" ); //* changed 174.56.47.161 to 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();
        }
    }
}

And change one of your servers ports(SocketOptions.cs)
 

Ryan

RunUO Founder
Staff member
We currently do this on UOGamers with Demise and Hybrid in production (its a chore but it works) but we have two IP's on the server.

In order to do this with one IP all you need to do is the following (SocketOptions.cs - https://code.google.com/p/runuo/source/browse/devel/Scripts/Misc/SocketOptions.cs):

C#:
                private static IPEndPoint[] m_ListenerEndPoints = new IPEndPoint[] {
                        new IPEndPoint( IPAddress.Any, 2593 ), // Shard One will Listen on 2593 
                   
                        // Examples:
                        // new IPEndPoint( IPAddress.Any, 80 ), // Listen on port 80 on all IP addresses
                        // new IPEndPoint( IPAddress.Parse( "1.2.3.4" ), 2593 ), // Listen on port 2593 on IP address 1.2.3.4
                };



C#:
                private static IPEndPoint[] m_ListenerEndPoints = new IPEndPoint[] {
                        new IPEndPoint( IPAddress.Any, 2594 ), // Shard Two will Listen on 2594
                     
                        // Examples:
                        // new IPEndPoint( IPAddress.Any, 80 ), // Listen on port 80 on all IP addresses
                        // new IPEndPoint( IPAddress.Parse( "1.2.3.4" ), 2593 ), // Listen on port 2593 on IP address 1.2.3.4
                };
 

Khaz

Knight
We currently do this on UOGamers with Demise and Hybrid in production (its a chore but it works) but we have two IP's on the server.
...

Ryan, is the account info shared between Demise and Hybrid? I'm currently trying a configuration similar to what you described, but new accounts are not able to get past the serverlist when the second server is selected.

e.g.
ServerA is configured to run on 2593 and provide the serverlist to connecting clients
ServerB is configured to run on 3000, same IP

Connecting all the way through to either server works fine if the account is already existing on both servers. If it's a new account, ServerB drops the connection when it is selected. ServerA handles the new account fine, and I can see in the console the account is created on ServerA (not ServerB) - so I'm curious as to how you solved this problem on UOGamers.

As a side note, this machine does have multiple IPs available, if that helps, though I don't think it'd affect this particular problem.
 

Simon Omega

Traveler
I've had a setup where I had Stable and Development servers. I also had a connection entry for local lan and external connections... Some Place...
I've got nots on how I set it up.

Everyone else seems to have covered the details here. If you run into problems shoot a message and we can look into it for you.
 

Khaz

Knight
I've had a setup where I had Stable and Development servers. I also had a connection entry for local lan and external connections... Some Place...
I've got nots on how I set it up.

Everyone else seems to have covered the details here. If you run into problems shoot a message and we can look into it for you.


The details covered here only address networking, which is very straightforward. Zippy shared a mysql/php accounting solution and FingersMcSteal has talked about sql-based accounting in a few places, and I'm not really worried about that. Technically this is all very feasible and not a big challenge, but I would like to know how UOG have solves the problem, because those guys have put in a lot of time and effort that is worth hearing about! :)

Anyway, I answered my own question last night through those threads and looking at what the second server is doing when it receives a character list request for an account it doesn't know about. The rest is all just information-sharing.
 

zolo888

Sorceror
Now I may be stupid but....... If i wanted to run a Test and Prod shard on the same server and I had 2 IP addresses ..... What do I do?

I want to get it so that Players get the choice upon login eg just like OSI do.

Sorry if its a dumb question. Head hurts today.
 
Top