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!

RunUO Remote Administrator

Jeff

Lord
RunUO Remote Administrator

So, ya, its been done, but nothing lately. I've started working on a Remote Adminsitration application for RunUO created using WPF and .Net 3.5sp1. You might ask, why? Well recently at work I've been doing alot of work with Silverlight and WPF, and to be completely honest, I will never make another app using standard windows forms ever again. WPF is just to cool, easy to use and convenient.

Anyway, back on topic. I want everyone's input as to what is needed, cool to have, ideas for this application. Right now it will login and show you the console, allow you to search for accounts, but thats about it. I've not implemented to much strictly because I'm not sure what is truely needed. I've not actually played UO in a good 3 years, and haven't touched RunUO in probably 1 - 2 years. So I'm asking for your input. No flaming, no being rude, everyone is entitled to their opinions and ideas.

Let the discussions begin!!!

P.S. Here is the project RunUO Administrator It is open source, and will stay that way. Hope everyone can learn from it. It uses the MVVM (Model View ViewModel) design pattern, which I've found to be extremely efficient with WPF and Silverlight and most likely will not stray from it.

P.S.S It is very crude and early in its development, so if it doesn't run on your machine, Sorry but I'm not going to support issues right now. Wait for a true release!

Enjoy!!!
 

Thilgon

Sorceror
For the moment, the most important thing that comes to my mind is the ability to turn on and off the server via remoteadmin, dunno if it's already done... I'll keep thinking about this, thanks :)
 

FingersMcSteal

Sorceror
I'd guess at access to accounts and characters, maybe able to remote change / edit character & account details, after that maybe server control's, shutdown's / restart's forced saves etc.

Older remote tools i've seen myself were mainly for the account side of things but i'm sure with more idea's and suggestions it could become bigger and better.
 

Thagoras

Sorceror
I really liked that Console Command app that BeneathTheStars wrote. That in mind, I think it might be useful to be able to send messages (global or individual) to players/staff.

Perhaps get statistics from the server...number of players logged in, number of mobiles, number of items.
 

Jeff

Lord
Thagoras;829898 said:
I really liked that Console Command app that BeneathTheStars wrote. That in mind, I think it might be useful to be able to send messages (global or individual) to players/staff.

Perhaps get statistics from the server...number of players logged in, number of mobiles, number of items.

Those statistics already exist in the current version ;)
 

Jeff

Lord
Thilgon;829891 said:
For the moment, the most important thing that comes to my mind is the ability to turn on and off the server via remoteadmin, dunno if it's already done... I'll keep thinking about this, thanks :)

Turning off and restarting should be doable, but as for turning it on, when it is off, not possible without an additional application (service).
 

Vorspire

Knight
Direct console command API would be a great addition to RunUO, allowing any command to be invoked from an admin panel without the need to login with the UO client.
But that would require a modification or new implimentation on the server-side as well as your client-side interface.
If you could impliment this kind of interface, there's really no limit as to the functions you could add to your app.

Another great feature I would love to see (I was going to impliment it in WebServerLite - RunUO Edition) is Statics editing, where a portion of the map is loaded into your remote GUI as if you were logged into the UO client. - The objects that qualify as statics could be easily manipulated, frozen/unfrozen etc.
In addition to this, you could actually add a modification that allows you to track players and see what they see and maybe interact with them too.

Sounds like, yet another, great project you're working on Jeff :)
 

Jeff

Lord
I'm not worried to much about server side modification. It already has some modification to the Remote Admin scripts.

As for statics editing, for now this will be low priority on my list.

Remote console commands (or just remote commands) are already on my todo list. I should probably put this up on the codeplex site.

As for tracking players, I was trying to envision something like this, not entirely sure how I would go about that. I would like to be able to make a UOAM type of view perhaps, and the ability to actually login to your character via the remote admin tool and interact with players through that. However, I also do not want to be tied down with a limitation of having to need UO installed to use this. So I might need to come up with a hybrid approach of this... lots of consideration and thinking will be involved in this feature.

I also do not currently have UO installed, and do not plan on installing it. I''m seriously over the client itself haha.
 

Vorspire

Knight
Jeff;829915 said:
As for tracking players, I was trying to envision something like this, not entirely sure how I would go about that. I would like to be able to make a UOAM type of view perhaps, and the ability to actually login to your character via the remote admin tool and interact with players through that. However, I also do not want to be tied down with a limitation of having to need UO installed to use this. So I might need to come up with a hybrid approach of this... lots of consideration and thinking will be involved in this feature.

I also do not currently have UO installed, and do not plan on installing it. I''m seriously over the client itself haha.

You could always have the server stream compressed Bitmap data to your client, then decode and recompile the data back into valid Bitmaps.

I understand this could be laggy, but for the most part, only one or two people will be using it at any given time and you will always see exactly what your server supports, avoiding mis-matched UO installs, etc.
-There is also the option for Multi-Threading, so the process does not directly affect anyone's game-play.

Pre-processing a 9 sector, 3x3 grid, each approx 18x24x100 tiles around your viewable area of 18x24x100 tiles.

[-][-][-]
[-][-][-]
[-][-][-]


You are here.
Pre-processed sectors.

18x24x100 is my estimate of the viewable game-screen, not sure if it is correct though.


IMO though, I would bite my lip, close my eyes and just install UO (then pretend I didn't), or at least make it portable to use a localized installation, for the sake of the end user :)
 

Jeff

Lord
Vorspire;829959 said:
IMO though, I would bite my lip, close my eyes and just install UO (then pretend I didn't), or at least make it portable to use a localized installation, for the sake of the end user :)

NEVER!!! UO is like the plague, if i install it, i risk contamination. ;)

But seriously, i had thought about this, but I think I have a better idea. I don't want even the look of UO in this client. It's seriously time for something new!!! But ya, the whole sending a compressed bitmap idea did cross my mind, so did sending radarcol.mul, and then using id lookups send from the server (which would be smaller then a bitmap). I'm on to something a tad different now, but ill have to do some testing.
 

Vorspire

Knight
Sounds good :) Could you explain a little more about the Radarcol file and how it works, or perhaps provide a link to a good source of info? (Never looked into this before)

Nontheless, here is the script I was writing for the WebServerLite implimentation, if you decide to go with Bitmaps, this should speed up some of the work, the tile grid algorithms are in there.
Don't get me wrong, this code need to be finalized and fine-tuned hehe.
I just hope it helps...

Code:
using System;
using System.Net;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;

using Server;
using Server.Items;
using Server.Misc;

using WebServer;
using WebServer.Modules;

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

		private Size _ImageSize = new Size(800, 600);
		private Rectangle2D _Bounds = new Rectangle2D(0, 0, 18, 18);
		private Point3D _Location = new Point3D(0, 0, 0);
		private Map _Map = Map.Felucca;
		private int _Width = 18;
		private int _Height = 18;
		private int _LayerCount = 18;

		public StaticTileSector(HttpListenerContext ctx, Client client, Uri url)
			: base(ctx, client, url)
		{
			string loc = GetQuery("location");
			_Location = ParseLocation(loc);

			string map = GetQuery("map");
			_Map = ParseMap(map);

			int width;
			if (Int32.TryParse(GetQuery("width"), out width))
				_Width = width;

			int height;
			if (Int32.TryParse(GetQuery("height"), out height))
				_Height = height;

			int layers;
			if (Int32.TryParse(GetQuery("layers"), out layers))
				_LayerCount = layers;

			Point2D topLeft = new Point2D(_Location.X - (int)(_Width / 2), _Location.Y - (int)(_Height / 2));
			Point2D bottomRight = new Point2D(_Location.X + (int)(_Width / 2), _Location.Y + (int)(_Height / 2));
			_Bounds = new Rectangle2D(topLeft, bottomRight);

			//RealTime = true;
			Name = "StaticTileSector Location: " + _Location.ToString() + " - Map: " + _Map.Name + " (" + _Map.MapID + ")";
			ContentType = "image/png";

			using (Bitmap grid = GenerateGrid())
			{
				byte[] buffer = new byte[0];

				using (MemoryStream ms = new MemoryStream())
				{
					grid.Save(ms, ImageFormat.Png);
					buffer = ms.ToArray();
				}

				AddByte(buffer);
				buffer = new byte[0];
			}
		}

		private List<Tile> GetTilesAt(Point2D p)
		{
			List<Tile> list = new List<Tile>();

			foreach (Tile tile in _Map.GetTilesAt(p, true, true, true))
			{
				if (!list.Contains(tile))
					list.Add(tile);
			}

			list.Sort(new TileComparer());

			return list;
		}

		internal class TileComparer : Comparer<Tile>
		{
			public override int Compare(Tile x, Tile y)
			{
				if (x.Z < y.Z)
					return -1;

				if (x.Z > y.Z)
					return 1;

				return 0;
			}

			public override int GetHashCode()
			{ return base.GetHashCode(); }

			public override bool Equals(object obj)
			{ return base.Equals(obj); }

			public override string ToString()
			{ return base.ToString(); }
		}

		private Bitmap GenerateGrid()
		{
			Bitmap grid = new Bitmap(_ImageSize.Width, _ImageSize.Height);

			for (int z = _Location.Z; z < _Location.Z + 50; z++)
			{
				for (int y = _Bounds.Start.Y; y < _Bounds.End.Y; y++)
				{
					for (int x = _Bounds.Start.X; x < _Bounds.End.X; x++)
					{
						Point2D p = new Point2D(x, y);
						List<Tile> tiles = GetTilesAt(p);
					}
				}
			}

			using (Graphics g = Graphics.FromImage(grid))
			{

				/*foreach (Item item in _Map.(_Location, 16))
				{
					byte[] rawData = Import("http://localhost/RunUO/Interactive/StaticTile.vor?id=" + item.ItemID + "&hue=" + item.Hue, false);

					using (MemoryStream ms = new MemoryStream())
					{
						ms.Write(rawData, 0, rawData.Length);
						g.DrawImage(new Bitmap(ms), curX, curY);
						g.Save();
					}

					curX += 16;
					curY += 16;
				}*/
			}

			return grid;
		}

		public Point3D ParseLocation(string loc)
		{
			string[] split = loc.Split(new char[] { ',' }, 3, StringSplitOptions.RemoveEmptyEntries);

			if (split.Length == 3)
			{
				int x, y, z;
				if (Int32.TryParse(split[0], out x) && Int32.TryParse(split[1], out y) && Int32.TryParse(split[2], out z))
				{ return new Point3D(x, y, z); }
			}

			return new Point3D(0, 0, 0);
		}

		public Map ParseMap(string map)
		{
			int mapID;
			if (Int32.TryParse(map, out mapID))
			{ return Map.Maps.GetValue(mapID) as Map; }

			foreach (Map m in Map.Maps)
			{
				if (m == null)
					continue;

				if (m.Name.ToUpper() == map.ToUpper())
					return m;
			}

			return Map.Felucca;
		}

		public StaticTileSector(UID uid)
			: base(uid)
		{ }
	}

	public sealed class StaticTile : WebObject
	{
		/// <summary>
		/// Initialize the UO-SDK with a custom path to a directory where ARTIDX.MUL and ART.MUL can be found.
		/// If this throws errors when you install it, make sure the CustomPath variable is set to public in DataPath.cs
		/// Otherwise, simply type your own custom path in place of DataPath.Custom
		/// </summary>
		public static void Initialize() { Ultima.Client.Directories.Add(DataPath.CustomPath); }

		public override string VirtualName { get { return "StaticTile.vor"; } }

		public StaticTile(HttpListenerContext ctx, Client client, Uri url)
			: base(ctx, client, url)
		{
			ContentType = "image/png";

			string id = GetQuery("id");
			string hue = GetQuery("hue");
			string onlygrey = GetQuery("only-grey");
			string landtile = GetQuery("land-tile");

			int itemID = 0, itemHue = 0;
			bool onlyGrey = true, landTile = false;

			Int32.TryParse(id, out itemID);
			Int32.TryParse(hue, out itemHue);
			Boolean.TryParse(onlygrey, out onlyGrey);

			if (itemID < 0)
				itemID = 0;

			if (itemID > 16144)
				itemID = 16144;

			if (itemHue < 0)
				itemHue = 0;

			if (itemHue > 2999)
				itemHue = 2999;

			if (TileData.ItemTable.Length > itemID)
				Name = TileData.ItemTable[itemID].Name;

			using (Bitmap bmp = GenerateItem(itemID, itemHue, onlyGrey, landTile))
			{
				byte[] buffer = new byte[0];

				using (MemoryStream ms = new MemoryStream())
				{
					bmp.Save(ms, ImageFormat.Png);
					buffer = ms.ToArray();
				}

				AddByte(buffer);
				buffer = new byte[0];
			}
		}

		public static Bitmap GenerateItem(int itemID, int itemHue, bool onlyGrey, bool landTile)
		{
			Bitmap bmp = landTile ? Ultima.Art.GetLand(itemID, false) : Ultima.Art.GetStatic(itemID, false);

			if (bmp == null)
				bmp = new Bitmap(16, 16);
			else
				Hues.GetHue(itemHue).ApplyTo(bmp, onlyGrey);

			return bmp;
		}

		public StaticTile(UID uid)
			: base(uid)
		{ }
	}
}

BTW... UO-SDK... Epic win.
 

Jeff

Lord
Vorspire;829967 said:
Sounds good :) Could you explain a little more about the Radarcol file and how it works, or perhaps provide a link to a good source of info? (Never looked into this before)
UO File Formats

I would really like to not use bitmaps.
 

Thagoras

Sorceror
You ever play Nethack, Rogue or Angband? What if you just had a VERY primitive display of things? Players would be represented by the @ symbol. Land and water tiles could just be different colored ascii symbols (used in those days as shading).
 

Jeff

Lord
Thagoras;829969 said:
You ever play Nethack, Rogue or Angband? What if you just had a VERY primitive display of things? Players would be represented by the @ symbol. Land and water tiles could just be different colored ascii symbols (used in those days as shading).

Right. i have a similar idea, only not SOOO primitive.
 

Jeff

Lord
Vorspire;829972 said:
Care to share, so we can avoid suggesting any more ideas you've already thought of? xD

Not until i have all the details ironed out. I'm not big on proposing idea's that may not work. :)
 

Vorspire

Knight
Jeff;829975 said:
Not until i have all the details ironed out. I'm not big on proposing idea's that may not work. :)

Ahh that's where we become opposites :D

I love to have input and ideas on hypotheses, even if it may fail.

To each their own, good luck Jeff :)
 

Lichbane

Wanderer
Show Active Accounts
Show Active Characters

Display Last Save Date/Time
Display Last Backup Date/Time

Stop Server (with or without save)
Restart Server (with or without save)
Start Server

EDIT: I forgot ...

Display Santa
 
Top