Hey guys! First post here.

I'm currently working on a custom webstatus page but I'm having troubles finding a way to sort players in the list by criterias, ie: kills.

Is there a system which implements this function already? So I can use it as a guide. I had no luck using the search function.

I want to make several custom "top 10" pages for murderers, pvp, pvm, etc.

Also, how make a list of all the playermobiles in the Shard? even counting offline playermobiles.
 
Hi David.

You have not said if you are building the web in php or in asp, but if you use the first, maybe this link can help.

https://github.com/tazmanyak/myPaperdollGenerator/tree/master/myPaperdoll

It is a fairly simple web, but it works and is very easy to modify.

Besides, in order to use it you have to enable a Mysql database, maybe u need install ODBC connector too, and "activate" the MyRunuo system on the server.

If you need more functionality, the code of MyRuno system in the services folder may help you in the development.
 
Get all your players in a list like this or how ever you like.
var players = new List<Mobile>();
foreach(var ns in NetState.Instances)
{
players.Add(ns.Mobile);
}

Then just use OrderBy or OrderByDescending to sort as you wish like
players.OrderBy(p => p.Kills);

Dont forget to add using System.Linq; to the top of your file too.
 
Good suggestion lotus. I believe a netstate can have a null mobile if the player hasn't logged in a character yet so it would be something to watch out for.

I would suggest to get all players in the world to use something like

var players = new List<Mobile>(World.Mobiles.Values.Where(x=>x is PlayerMobile));

Then you can order them the same way darklotus suggested. You'll need to assign the return value of OrderBy to something as Linq will not order the existing list.
 
Hi David.

You have not said if you are building the web in php or in asp, but if you use the first, maybe this link can help.

https://github.com/tazmanyak/myPaperdollGenerator/tree/master/myPaperdoll

It is a fairly simple web, but it works and is very easy to modify.

Besides, in order to use it you have to enable a Mysql database, maybe u need install ODBC connector too, and "activate" the MyRunuo system on the server.

If you need more functionality, the code of MyRuno system in the services folder may help you in the development.

Get all your players in a list like this or how ever you like.
var players = new List<Mobile>();
foreach(var ns in NetState.Instances)
{
players.Add(ns.Mobile);
}

Then just use OrderBy or OrderByDescending to sort as you wish like
players.OrderBy(p => p.Kills);

Dont forget to add using System.Linq; to the top of your file too.

Good suggestion lotus. I believe a netstate can have a null mobile if the player hasn't logged in a character yet so it would be something to watch out for.

I would suggest to get all players in the world to use something like

var players = new List<Mobile>(World.Mobiles.Values.Where(x=>x is PlayerMobile));

Then you can order them the same way darklotus suggested. You'll need to assign the return value of OrderBy to something as Linq will not order the existing list.

Thank you all four your replies!

I'm using the standart WebStatus.cs as base, using the tools you gave me I wrote (pasted :D) this little code, but it's not working properly, it does get a list of all the players in the world, it does list only 10, but is not sorting the list as it should, sorry if it's just a dumb mistake, it's my first time trying to sort lists.

Code:
using System;
using System.IO;
using System.Text;
using System.Linq;
using Server.Mobiles;
using System.Collections;
using System.Collections.Generic;
using Server;
using Server.Network;
using Server.Guilds;
namespace Server.Misc
{
public class StatusPage2 : Timer
{
  public static void Initialize()
  {
   new StatusPage2().Start();
  }
  public StatusPage2() : base( TimeSpan.FromSeconds( 30.0 ), TimeSpan.FromSeconds( 30.0 ) )
  {
   Priority = TimerPriority.FiveSeconds;
  }
  private static string Encode( string input )
  {
   StringBuilder sb = new StringBuilder( input );
   sb.Replace( "&", "&amp;" );
   sb.Replace( "<", "&lt;" );
   sb.Replace( ">", "&gt;" );
   sb.Replace( "\"", "&quot;" );
   sb.Replace( "'", "&apos;" );
   return sb.ToString();
  }
  protected override void OnTick()
  {
   //Not sure if this has to be modified, just make sure that you at least manually create the directory that you point this script to
   if ( !Directory.Exists( "web" ) )
    Directory.CreateDirectory( "web" );
   //use forward slashes or else your shard may crash the first time it writes that status.html page
   using ( StreamWriter op = new StreamWriter( "c:/web/index2.html" ) ) //If you do not use Reactor as a webserver, put your path to where you want the file created.
   {
    op.WriteLine( "<html>" );
    op.WriteLine( " <head>" );
    op.WriteLine( "  <title>Ultima Online: Titanes</title>" ); //Modify the address to your shard's hosting address
    op.WriteLine( "</head>" );
    op.WriteLine( "  <body background=\"fondo.JPG\" ");
    op.WriteLine( "   <h1 align=\"center\"><img border=\"0\" src=\"logo.jpg\" width=\"270\" height=\"50\"></h1>" ); //If you have a logo, put a copy of it in the same folder as the status.html (where it will be) then whatever your logo filename is just put that and the file ending. If you do not have a logo, either make one or comment this line out via a //
    op.WriteLine( "  <table width=\"100%\">" );
    op.WriteLine( "   <tr>" );
    op.WriteLine( "    <td bgcolor=\"#996633\"><font color=\"white\" face=\"Arial Narrow\" size=\"2\">Nombre</font></td><td bgcolor=\"#996633\"><font color=\"white\" face=\"Arial Narrow\" size=\"2\">Muertes</font></td><td bgcolor=\"#996633\"><font color=\"white\" face=\"Arial Narrow\" size=\"2\">Karma / Fama</font></td>" );
    op.WriteLine( "   </tr>" );
    //To Do: Style Sheet
        


        var players = new List<Mobile>(World.Mobiles.Values.Where(x=>x is PlayerMobile));
        players.OrderByDescending(p => p.Kills);


    for ( int i = 1; i < 11; ++i )
        {
                Mobile m = players[i];

        op.Write( "<tr><td>" );

        string namecolor = (m != null ? "#996633" : "#996633");
        op.Write( "<font color=" + namecolor + ">" );
        op.Write( m.Name );

        op.Write( "</td><td>" );

        string killscolor = (m != null ? "#996633" : "#996633");
        op.Write( "<font color=" + killscolor + ">" );
        op.Write( m.Kills );

        op.Write( "</td><td>" );

        string famecolor = (m != null ? "#996633" : "#996633");
        op.Write( "<font color=" + famecolor + ">" );
        op.Write( m.Karma );
                op.Write( " / " );
            op.Write( m.Fame );

        op.Write( "</td></tr> " );
        op.Write( "</font>" );  
    

      }
    op.WriteLine( "         <tr>" );
    op.WriteLine( "      </table>" );
    op.WriteLine( "   </body>" );
    op.WriteLine( "</html>" );
   }
  }
}
}
 
line 56
  1. players.OrderByDescending(p => p.Kills);
replace with
  1. players = players.OrderByDescending(p => p.Kills);
Thanks for your help Lotus
I did the trick creating a new list and filling with the sorted first list. (and changed the starting i to 0, it was ignoring the first player on top):


Code:
        var players = new List<Mobile>(World.Mobiles.Values.Where(x=>x is PlayerMobile));
        List<Mobile> SortedList = players.OrderByDescending(o=>o.Kills).ToList();


    for ( int i = 0; i < 10; ++i )
        {
                     Mobile m = SortedList[i];
                  if( m != null )
                  {
            op.Write( "<tr><td>" );

            string namecolor = (m != null ? "#996633" : "#996633");
            op.Write( "<font color=" + namecolor + ">" );
            op.Write( m.Name );

            op.Write( "</td><td>" );

            string killscolor = (m != null ? "#996633" : "#996633");
            op.Write( "<font color=" + killscolor + ">" );
            op.Write( m.Kills );

            op.Write( "</td><td>" );

            string famecolor = (m != null ? "#996633" : "#996633");
            op.Write( "<font color=" + famecolor + ">" );
            op.Write( m.Karma );
                       op.Write( " / " );
                   op.Write( m.Fame );

            op.Write( "</td></tr> " );
            op.Write( "</font>" );   
              }

      }
 
I have here a file that I was playing years ago when I started with Runuo, the code is pretty dirty and you can see my bad practices =), but if something of this file can help you, here it is.

PHP:
using System;
using System.IO;
using System.Text;
using System.Collections;
using Server;
using Server.Network;
using Server.Guilds;
using Server.Mobiles;

namespace Server.Misc
{
    public class StatusPages : Timer
    {
        public static bool Enabled = true;

        public static void Initialize()
        {
            if (Enabled)
                new StatusPages().Start();
        }

        public StatusPages() : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(10.0))
        {
            Priority = TimerPriority.FiveSeconds;
        }

        private static string Encode(string input)
        {
            StringBuilder sb = new StringBuilder(input);

            sb.Replace("&", "&amp;");
            sb.Replace("<", "&lt;");
            sb.Replace(">", "&gt;");
            sb.Replace("\"", "&quot;");
            sb.Replace("'", "&apos;");

            return sb.ToString();
        }

        protected override void OnTick()
        {
            if (!Directory.Exists("WEB"))
            Directory.CreateDirectory("WEB");

            using (StreamWriter op = new StreamWriter("WEB/Info.php"))
            {
                op.WriteLine("<?php define('_info_',true);    include_once 'registro.php'; ?>");
                op.WriteLine("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
                op.WriteLine("<meta http-equiv='content-type' content='text/html;charset=UTF-8'> ");
                op.WriteLine("<head><title>UO</title>");
                op.WriteLine("<link rel=\"shortcut icon\" href=\"images/favicon.ico\"/> ");
                op.WriteLine("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/> ");
                op.WriteLine("<meta name=\"keywords\" content=\"\"> ");
                op.WriteLine("<link href=\"/estilos/style.css\" type=\"text/css\" rel=\"stylesheet\"/></head>");
                op.WriteLine("<body> <div id=\"pagewrap\"><div id=\"flashwrap\" align=\"center\"></div><div id=\"mainwrap\"><div id=\"contentwrap-top\"></div><div id=\"contentwrap-center\"><div id=\"contentwrap\"> ");
                op.WriteLine("<div align=\"center\"><table border=\"0\" cellpadding=\"2\" width=\"680\" align=\"center\"><tr><td>&nbsp;&nbsp;&nbsp;<font color=\"white\" size=\"2\">Nombre</font></td><td><font color=\"white\" size=\"2\">Condición</font></td><td><font color=\"white\" size=\"2\">Estado</font></td><td><font color=\"white\" size=\"2\">Titulo</font></td><td><font color=\"white\" size=\"2\">Mapa</font></td><td><font color=\"white\" size=\"2\" align=\"center\">Región</font></td><td><font color=\"white\" size=\"2\">Victimas</font></td><td><font color=\"white\" size=\"2\">Karma/Fama</font></td><td><font color=\"white\" size=\"2\">Str</font></td><td><font color=\"white\" size=\"2\">Dex</font></td><td><font color=\"white\" size=\"2\">Int</font></td><td><font color=\"white\" size=\"2\"> Hits Max</font></td><td><font color=\"white\" size=\"2\">Mascotas</font></td><tr><tr></table>");
                op.WriteLine("</div>");

                foreach (NetState state in NetState.Instances)
                {
                    Mobile m = state.Mobile;

                    if (m != null && m.AccessLevel < AccessLevel.GameMaster)
                    {
                        string serial = m.Serial.Value.ToString();
                        Guild g = m.Guild as Guild;

                        op.Write("<tr><td><font color=\"darkblue\" size=\"2\">&nbsp;&nbsp;&nbsp;");

                        if (g != null)
                        {
                            op.Write("&nbsp;&nbsp;&nbsp;<a href =\"http://localhost/" + Encode(m.Name) + serial + "\"target=\"_self\">" + Encode(m.Name) + "</a>");
                            op.Write(" [");

                            string title = m.GuildTitle;

                            if (title != null)
                                title = title.Trim();
                            else
                                title = "";

                            if (title.Length > 0)
                            {
                                op.Write(Encode(title));
                                op.Write(", ");
                            }

                            op.Write(Encode(g.Abbreviation));

                            op.Write(']');
                        }
                        else
                        {
                            op.Write("&nbsp;&nbsp;&nbsp;<a href =\"http://localhost/" + Encode(m.Name) + serial + "\"target=\"_self\">" + Encode(m.Name) + "</a>");
                        }

                        op.Write("</td><td>");
                        if (m is PlayerMobile && ((PlayerMobile)m).Young)
                        {
                            op.Write("<font color=\"purple\" size=\"2\">");
                            op.Write("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(Novato)");
                        }
                        else if (m is PlayerMobile && !((PlayerMobile)m).Young)
                        {
                            op.Write("<font color=\"green\" size=\"2\">");
                            op.Write("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(Veterano)");
                        }

                        op.Write("</td><td>");
                        if (m is PlayerMobile && m.Alive)
                        {
                            op.Write("<font color=\"white\" size=\"2\" align=\"center\">");
                            op.Write("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Vivo");
                        }
                        else if (m is PlayerMobile && !m.Alive)
                        {
                            op.Write("<font color=\"red\" size=\"2\" align=\"center\">");
                            op.Write("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Muerto");
                        }

                        op.Write("</td><td>");
                        op.Write("<font color=\"gold\" size=\"2\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
                        op.Write(m.Title);
                        op.Write("</td><td>");
                        op.Write("<font color=\"darkorange\" size=\"2\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
                        op.Write(m.Map);
                        op.Write("</td><td>");
                        op.Write("<font color=\"darkorange\" size=\"2\">&nbsp;&nbsp;&nbsp;");
                        op.Write(m.Region);
                        op.Write("</td><td>");
                        op.Write("<font color=\"green\" size=\"2\" align=\"center\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
                        op.Write(m.Kills);
                        op.Write("</td><td>");
                        op.Write("<font color=\"yellow\" size=\"2\" align=\"center\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
                        op.Write(m.Karma);
                        op.Write("/<font color=\"yellow\" size=\"2\">");
                        op.Write(m.Fame);
                        op.WriteLine("</td></td>");
                        op.Write("</td><td>");
                        op.Write("<font color=\"cyan\" size=\"2\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
                        op.Write(m.RawStr);
                        op.Write("</td><td>");
                        op.Write("<font color=\"cyan\" size=\"2\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
                        op.Write(m.RawDex);
                        op.Write("</td><td>");
                        op.Write("<font color=\"cyan\" size=\"2\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
                        op.Write(m.RawInt);
                        op.Write("</td><td>");
                        op.Write("<font color=\"blue\" size=\"2\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
                        op.Write(m.Hits);
                        op.Write("/<font color=\"blue\" size=\"2\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
                        op.Write(m.HitsMax);
                        op.Write("</td><td align=\"center\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
                        op.Write("<font color=\"tan\" size=\"2\">&nbsp;&nbsp;&nbsp;&nbsp;");
                        op.Write(m.Followers);
                        op.WriteLine("</td><br></tr>");
                    }
                }

                op.WriteLine("<tr></table>");
                op.WriteLine("</div></div><div id=\"contentwrap-bottom\"></div></div><div id=\"menuwrap\"><div id=\"menupad\"><div id=\"menumodule\"><table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr align=\"left\"><td><a href=\"http://localhost/inicio\" class=\"menulink\">Inicio</a></td></tr><tr align=\"left\"><td><a href=\"http://localhost/jugar\" class=\"menulink\">Jugar</a></td></tr><tr align=\"left\"><td><a href=\"http://localhost/info\" class=\"menulink\">Información</a></td></tr></table></div> ");
                op.WriteLine("<div id=\"menumodule\"><img src=\"http://localhost/images/caballero.png\"></div><div id=\"menumodule\"></td></tr></td><td bgcolor=\"#000000\" width=\"95%\"></td></tr></div></div><br/></div><div id=\"footerwrap\" class=\"clearfix\"><p align=\"center\"><font color=\"green\" size=2><b>UO</b></font></p></div></div>");
                op.WriteLine("<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"10\"> ");
                op.WriteLine("   </body>");
                op.WriteLine( "</html>" );
            }
        }
    }
}
 
Hey guys! it's me again.

I'm facing a new problem sorting my players list, I'm currently using the code bellow, it works to sort mobiles which where added to the list checking the Player bool, the problem itself is when I try to use a Variable which is playermobile exclusive to sort the list, ie CompassionPoints, KnownRecipes, etc.

Code:
                                        var players = new List<Mobile>(World.Mobiles.Values.Where(x=>x is PlayerMobile));
                            List<Mobile> SortedKillers = players.OrderByDescending(e=>e.Kills).ToList();

I've tried this one:

Code:
                                        var players = new List<Mobile>(World.Mobiles.Values.Where(x=>x is PlayerMobile));
                            List<Mobile> SortedDuelists = players.OrderByDescending(e=>e.PvpPoints).ToList();

But it returns an error saying it doen'st contains a definition for PvpPoints, as its not reading "e" as PlayerMobile.

Hope you can help me.
 
Code:
public enum OrderBy
{
    None,
    Kills
}

Code:
var orderBy = OrderBy.Kills; // Sort by kills
var desc = Utility.RandomBool( ); // Random ascending or descending

// fetch initial enumeration of PlayerMobiles
var players = World.Mobiles.Values.OfType<PlayerMobile>(); // filter only PlayerMobiles

// pick a sorting method, check ascending or descending
switch( orderBy )
{
    case OrderBy.Kills:
        players = desc ? players.OrderByDescending( pm => pm.Kills ) : players.OrderBy( pm => pm.Kills );
    break;
}

players = players.Take( 10 ); // take the first 10

foreach( var pm in players ) // iterate the results
{
   // do output
}

The beauty about Linq is you don't need to instantiate new collections like List<T> or T[] (which ultimately consume a ton of memory)
 
you could try
Code:
players.OrderByDescending(e=>(e as PlayerMobile).PvpPoints).ToList();
That's what I needed! Thanks PyrO

Code:
public enum OrderBy
{
    None,
    Kills
}

Code:
var orderBy = OrderBy.Kills; // Sort by kills
var desc = Utility.RandomBool( ); // Random ascending or descending

// fetch initial enumeration of PlayerMobiles
var players = World.Mobiles.Values.OfType<PlayerMobile>(); // filter only PlayerMobiles

// pick a sorting method, check ascending or descending
switch( orderBy )
{
    case OrderBy.Kills:
        players = desc ? players.OrderByDescending( pm => pm.Kills ) : players.OrderBy( pm => pm.Kills );
    break;
}

players = players.Take( 10 ); // take the first 10

foreach( var pm in players ) // iterate the results
{
   // do output
}

The beauty about Linq is you don't need to instantiate new collections like List<T> or T[] (which ultimately consume a ton of memory)

Thanks Voxpire, I knew there was a cleaner method to do the task, I just lack of knowledge about the matter.

Thank you all!
 
Back