first commit

This commit is contained in:
Beyhan Oğur
2026-09-03 04:45:36 +03:00
commit d5f52cc3d3
1038 changed files with 169579 additions and 0 deletions
@@ -0,0 +1,891 @@
/* Copyright (C) 2009 Matthew Geyer
*
* This file is part of UO Machine.
*
* UO Machine is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* UO Machine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with UO Machine. If not, see <http://www.gnu.org/licenses/>. */
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using ClassicAssist.Shared;
using ClassicAssist.Shared.UO;
using ClassicAssist.UO.Data;
namespace ClassicAssist.UO.Objects.Gumps
{
public class Gump
{
private static readonly Random _random = new Random();
private static readonly byte[] BeginLayout = StringToBuffer( "{ " );
private static readonly byte[] EndLayout = StringToBuffer( " }" );
private static readonly byte[] NoMove = StringToBuffer( "{ nomove }" );
private static readonly byte[] NoClose = StringToBuffer( "{ noclose }" );
private static readonly byte[] NoDispose = StringToBuffer( "{ nodispose }" );
private static readonly byte[] NoResize = StringToBuffer( "{ noresize }" );
private static readonly byte[] True = StringToBuffer( " 1" );
private static readonly byte[] False = StringToBuffer( " 0" );
private static readonly byte[] BeginTextSeparator = StringToBuffer( " @" );
private static readonly byte[] EndTextSeparator = StringToBuffer( "@" );
public readonly string Layout;
public readonly GumpPage[] Pages;
private List<GumpElement> _elements;
private List<string> _strings;
public int Serial;
public int X;
public int Y;
public Gump( int x, int y, uint id, int serial, string layout, string[] strings, GumpElement[] elements,
GumpPage[] pages )
{
X = x;
Y = y;
ID = id;
Serial = serial;
Layout = layout;
Strings = strings;
GumpElements = elements;
Pages = pages;
foreach ( GumpPage gp in pages )
{
gp.ParentGump = this;
}
}
public Gump( int x, int y, int serial = 0, uint id = 0 )
{
X = x;
Y = y;
Serial = serial;
ID = id;
string fullName = GetType().FullName;
if ( ID == 0 && fullName != null )
{
ID = (uint) fullName.GetHashCode();
}
if ( Serial == 0 && fullName != null )
{
uint hashCode = (uint) fullName.GetHashCode();
hashCode &= 0x0000FFFF;
hashCode <<= 8;
hashCode |= (uint) 0xFF << 24;
Serial = (int) ( hashCode + _random.Next( 0, 0xFF ) );
}
_elements = new List<GumpElement>();
_strings = new List<string>();
}
public bool Closable { get; set; }
public bool Disposable { get; set; }
public GumpElement[] GumpElements
{
get => _elements.ToArray();
set
{
_elements = new List<GumpElement>();
for ( int i = 0; i < value.Length; i++ )
{
_elements.Add( value[i] );
}
}
}
public uint ID { get; }
public bool Movable { get; set; }
public bool Resizable { get; set; }
public string[] Strings
{
get => _strings.ToArray();
set
{
_strings = new List<string>();
for ( int i = 0; i < value.Length; i++ )
{
_strings.Add( value[i] );
}
}
}
/// <summary>
/// Get array of GumpElements which match the specified ElementType from all pages.
/// </summary>
public GumpElement[] GetElementsByType( ElementType type )
{
List<GumpElement> elementList = new List<GumpElement>();
if ( GumpElements != null )
{
elementList.AddRange( GumpElements.Where( ge => ge.Type == type ) );
}
if ( Pages != null )
{
elementList.AddRange( from p in Pages from ge in p.GumpElements where ge.Type == type select ge );
}
return elementList.ToArray();
}
/// <summary>
/// Get the GumpElement with the specified ID. Searches all pages/elements.
/// </summary>
/// <returns>True on success.</returns>
public bool GetElementByID( int id, out GumpElement element )
{
if ( GumpElements != null )
{
foreach ( GumpElement ge in GumpElements )
{
if ( ge.ElementID == id )
{
element = ge;
return true;
}
}
}
if ( Pages != null )
{
foreach ( GumpPage p in Pages )
{
foreach ( GumpElement ge in p.GumpElements )
{
if ( ge.ElementID == id )
{
element = ge;
return true;
}
}
}
}
element = null;
return false;
}
/// <summary>
/// Get the GumpElement nearest to the specified GumpElement.
/// </summary>
/// <returns>True on success.</returns>
public bool GetNearestElement( GumpElement source, out GumpElement element )
{
GumpElement nearest = null;
double closest = 0;
if ( source.ParentPage != null )
{
return source.ParentPage.GetNearestElement( source, out element );
}
foreach ( GumpElement ge in GumpElements )
{
if ( ge == source )
{
continue;
}
double distance = UOMath.Distance( source.X, source.Y, ge.X, ge.Y );
if ( nearest == null )
{
closest = distance;
nearest = ge;
}
else
{
if ( distance < closest )
{
closest = distance;
nearest = ge;
}
}
}
element = nearest;
return nearest != null;
}
/// <summary>
/// Get nearest GumpElement to source, but only if it's ElementType is contained in the include list.
/// </summary>
/// <param name="source">Source GumpElement</param>
/// <param name="includeTypes">Array of ElementTypes which specifies valid GumpElements to search.</param>
/// <param name="element">GumpElement (out).</param>
/// <returns>True on success.</returns>
public bool GetNearestElement( GumpElement source, ElementType[] includeTypes, out GumpElement element )
{
GumpElement nearest = null;
double closest = 0;
if ( source.ParentPage != null )
{
return source.ParentPage.GetNearestElement( source, includeTypes, out element );
}
foreach ( GumpElement ge in GumpElements )
{
if ( ge == source )
{
continue;
}
bool found = includeTypes.Any( et => ge.Type == et );
if ( !found )
{
continue;
}
double distance = UOMath.Distance( source.X, source.Y, ge.X, ge.Y );
if ( nearest == null )
{
closest = distance;
nearest = ge;
}
else
{
if ( distance < closest )
{
closest = distance;
nearest = ge;
}
}
}
element = nearest;
return nearest != null;
}
public bool GetElementByXY( int x, int y, out GumpElement gumpElement )
{
gumpElement = null;
if ( GumpElements == null )
{
return false;
}
GumpElement element = GumpElements.FirstOrDefault( m => m.X == x && m.Y == y );
if ( element != null )
{
gumpElement = element;
}
return gumpElement != null;
}
public GumpElement GetElementByXY( int x, int y )
{
return GetElementByXY( x, y, out GumpElement element ) ? element : null;
}
public bool GetElementByCliloc( int cliloc, out GumpElement gumpElement )
{
gumpElement = null;
if ( GumpElements == null )
{
return false;
}
GumpElement element = GumpElements.FirstOrDefault( m => m.Cliloc == cliloc );
if ( element != null )
{
gumpElement = element;
}
return gumpElement != null;
}
public GumpElement GetElementByCliloc( int cliloc )
{
return GetElementByCliloc( cliloc, out GumpElement element ) ? element : null;
}
public override int GetHashCode()
{
return ID.GetHashCode() ^ Layout?.GetHashCode() ?? 0;
}
public virtual void OnResponse( int buttonID, int[] switches )
{
}
public virtual void SendGump()
{
byte[] bytes = Compile();
Engine.Gumps.Add( this );
Engine.SendPacketToClient( bytes, bytes.Length );
}
public void CloseGump()
{
Commands.CloseClientGump( ID );
}
public void Add( GumpElement e )
{
e.ParentGump = this;
_elements.Add( e );
}
public void AddPage( int page )
{
GumpElement ge = new GumpElement { Type = ElementType.page, PageNumber = page };
Add( ge );
}
public void AddAlphaRegion( int x, int y, int width, int height )
{
GumpElement ge = new GumpElement
{
Type = ElementType.checkertrans,
X = x,
Y = y,
Width = width,
Height = height
};
Add( ge );
}
public void AddBackground( int x, int y, int width, int height, int gumpID )
{
GumpElement ge = new GumpElement
{
Type = ElementType.resizepic,
X = x,
Y = y,
Width = width,
Height = height,
ElementID = gumpID
};
Add( ge );
}
public void AddButton( int x, int y, int normalID, int pressedID, int buttonID, GumpButtonType type, int param )
{
GumpElement ge = new GumpElement
{
Type = ElementType.button,
X = x,
Y = y,
InactiveID = normalID,
ActiveID = pressedID,
ButtonType = (int) type,
ElementID = buttonID,
Param = param
};
Add( ge );
}
public void AddCheck( int x, int y, int inactiveID, int activeID, bool initialState, int switchID )
{
GumpElement ge = new GumpElement
{
Type = ElementType.checkbox,
X = x,
Y = y,
InactiveID = inactiveID,
ActiveID = activeID,
InitialState = initialState,
ElementID = switchID
};
Add( ge );
}
public void AddGroup( int group )
{
GumpElement ge = new GumpElement { Type = ElementType.group, Group = group };
Add( ge );
}
public void AddTooltip( int number )
{
GumpElement ge = new GumpElement { Type = ElementType.tooltip, Cliloc = number };
Add( ge );
}
public void AddHtml( int x, int y, int width, int height, string text, bool background, bool scrollbar )
{
GumpElement ge = new GumpElement
{
Type = ElementType.htmlgump,
X = x,
Y = y,
Width = width,
Height = height,
Text = text,
ScrollBar = scrollbar,
Background = background
};
Add( ge );
}
public void AddHtmlLocalized( int x, int y, int width, int height, int number, bool background, bool scrollbar )
{
GumpElement ge = new GumpElement
{
Type = ElementType.xmfhtmlgump,
X = x,
Y = y,
Width = width,
Height = height,
Cliloc = number,
Background = background,
ScrollBar = scrollbar
};
Add( ge );
}
public void AddHtmlLocalized( int x, int y, int width, int height, int number, int color, bool background,
bool scrollbar )
{
GumpElement ge = new GumpElement
{
Type = ElementType.xmfhtmlgumpcolor,
X = x,
Y = y,
Width = width,
Height = height,
Cliloc = number,
Hue = color,
Background = background,
ScrollBar = scrollbar
};
Add( ge );
}
public void AddHtmlLocalized( int x, int y, int width, int height, int number, string args, int color,
bool background, bool scrollbar )
{
GumpElement ge = new GumpElement
{
Type = ElementType.xmfhtmltok,
X = x,
Y = y,
Width = width,
Height = height,
Cliloc = number,
Args = args,
Hue = color,
Background = background,
ScrollBar = scrollbar
};
Add( ge );
}
public void AddImage( int x, int y, int gumpID )
{
AddImage( x, y, gumpID, 0 );
}
public void AddImage( int x, int y, int gumpID, int hue )
{
GumpElement ge = new GumpElement
{
Type = ElementType.gumppic,
X = x,
Y = y,
ElementID = gumpID,
Hue = hue
};
Add( ge );
}
public void AddImageTiled( int x, int y, int width, int height, int gumpID )
{
GumpElement ge = new GumpElement
{
Type = ElementType.gumppictiled,
X = x,
Y = y,
Width = width,
Height = height,
ElementID = gumpID
};
Add( ge );
}
public void AddImageTiledButton( int x, int y, int normalID, int pressedID, int buttonID, GumpButtonType type,
int param, int itemID, int hue, int width, int height )
{
AddImageTiledButton( x, y, normalID, pressedID, buttonID, type, param, itemID, hue, width, height, -1 );
}
public void AddImageTiledButton( int x, int y, int normalID, int pressedID, int buttonID, GumpButtonType type,
int param, int itemID, int hue, int width, int height, int localizedTooltip )
{
GumpElement ge = new GumpElement
{
Type = ElementType.buttontileart,
X = x,
Y = y,
InactiveID = normalID,
ActiveID = pressedID,
ElementID = buttonID,
ButtonType = (int) type,
Param = param,
ItemID = itemID,
Hue = hue,
Height = height,
Width = width,
Cliloc = localizedTooltip
};
Add( ge );
}
public void AddItem( int x, int y, int itemID )
{
GumpElement ge = new GumpElement { Type = ElementType.tilepic, X = x, Y = y, ItemID = itemID };
Add( ge );
}
public void AddItem( int x, int y, int itemID, int hue )
{
GumpElement ge = new GumpElement
{
Type = ElementType.tilepic,
X = x,
Y = y,
ItemID = itemID,
Hue = hue
};
Add( ge );
}
public void AddLabel( int x, int y, int hue, string text )
{
GumpElement ge = new GumpElement
{
Type = ElementType.text,
X = x,
Y = y,
Hue = hue,
Text = text
};
Add( ge );
}
public void AddLabelCropped( int x, int y, int width, int height, int hue, string text )
{
GumpElement ge = new GumpElement
{
Type = ElementType.croppedtext,
X = x,
Y = y,
Width = width,
Height = height,
Hue = hue,
Text = text
};
Add( ge );
}
public void AddRadio( int x, int y, int inactiveID, int activeID, bool initialState, int switchID )
{
GumpElement ge = new GumpElement
{
Type = ElementType.radio,
X = x,
Y = y,
InactiveID = inactiveID,
ActiveID = activeID,
InitialState = initialState,
ElementID = switchID
};
Add( ge );
}
public void AddTextEntry( int x, int y, int width, int height, int hue, int entryID, string initialText )
{
GumpElement ge = new GumpElement
{
Type = ElementType.textentry,
X = x,
Y = y,
Width = width,
Height = height,
Hue = hue,
ElementID = entryID,
Text = initialText
};
Add( ge );
}
public void AddTextEntry( int x, int y, int width, int height, int hue, int entryID, string initialText,
int size )
{
GumpElement ge = new GumpElement
{
Type = ElementType.textentrylimited,
X = x,
Y = y,
Width = width,
Height = height,
Hue = hue,
ElementID = entryID,
Text = initialText,
Size = size
};
Add( ge );
}
public void AddItemProperty( int serial )
{
GumpElement ge = new GumpElement { Type = ElementType.itemproperty, Serial = serial };
Add( ge );
}
public int Intern( string value )
{
int indexOf = _strings.IndexOf( value );
if ( indexOf >= 0 )
{
return indexOf;
}
_strings.Add( value );
return _strings.Count - 1;
}
internal static byte[] StringToBuffer( string str )
{
return Encoding.ASCII.GetBytes( str );
}
private byte[] Compile()
{
IGumpWriter disp = new GumpWriter( this );
if ( !Movable )
{
disp.AppendLayout( NoMove );
}
if ( !Closable )
{
disp.AppendLayout( NoClose );
}
if ( !Disposable )
{
disp.AppendLayout( NoDispose );
}
if ( !Resizable )
{
disp.AppendLayout( NoResize );
}
int count = GumpElements.Length;
for ( int i = 0; i < count; ++i )
{
GumpElement e = GumpElements[i];
disp.AppendLayout( BeginLayout );
e.AppendTo( disp );
disp.AppendLayout( EndLayout );
}
List<string> strings = new List<string>();
if ( Strings != null )
{
for ( int i = 0; i < Strings.Length; i++ )
{
strings.Add( Strings[i] );
}
}
disp.WriteStrings( strings );
disp.Flush();
return disp.ToArray();
}
internal interface IGumpWriter
{
int Switches { get; set; }
int TextEntries { get; set; }
void AppendLayout( bool val );
void AppendLayout( int val );
void AppendLayoutNS( int val );
void AppendLayout( string text );
void AppendLayout( byte[] buffer );
void WriteStrings( List<string> strings );
void Flush();
byte[] ToArray();
}
internal class GumpWriter : IGumpWriter, IDisposable
{
private readonly byte[] _buffer = new byte[48];
private readonly PacketWriter _stream;
private int m_LayoutLength;
private int m_PacketLength;
private int m_StringsLength;
public GumpWriter( Gump g )
{
_stream = new PacketWriter( 4096 );
_buffer[0] = (byte) ' ';
_stream.Write( (byte) 0xB0 );
_stream.Write( (short) 0 );
_stream.Write( g.Serial );
_stream.Write( g.ID );
_stream.Write( g.X );
_stream.Write( g.Y );
_stream.Write( (ushort) 0xFFFF );
}
public int Switches { get; set; }
public int TextEntries { get; set; }
public void AppendLayout( byte[] buffer )
{
int length = buffer.Length;
_stream.Write( buffer, 0, length );
m_LayoutLength += length;
}
public void AppendLayout( string text )
{
AppendLayout( BeginTextSeparator );
int length = text.Length;
_stream.WriteAsciiFixed( text, length );
m_LayoutLength += length;
AppendLayout( EndTextSeparator );
}
public void AppendLayout( int val )
{
string toString = val.ToString();
int bytes = Encoding.ASCII.GetBytes( toString, 0, toString.Length, _buffer, 1 ) + 1;
_stream.Write( _buffer, 0, bytes );
m_LayoutLength += bytes;
}
public void AppendLayout( bool val )
{
AppendLayout( val ? True : False );
}
public void AppendLayoutNS( int val )
{
string toString = val.ToString();
int bytes = Encoding.ASCII.GetBytes( toString, 0, toString.Length, _buffer, 1 );
_stream.Write( _buffer, 1, bytes );
m_LayoutLength += bytes;
}
public void Flush()
{
int length = 23 + m_LayoutLength + m_StringsLength;
_stream.Seek( 1, SeekOrigin.Begin );
_stream.Write( (short) length );
m_PacketLength = length;
}
public void WriteStrings( List<string> text )
{
_stream.Seek( 19, SeekOrigin.Begin );
_stream.Write( (ushort) m_LayoutLength );
_stream.Seek( 0, SeekOrigin.End );
_stream.Write( (ushort) text.Count );
for ( int i = 0; i < text.Count; ++i )
{
string v = text[i] ?? string.Empty;
int length = (ushort) v.Length;
m_StringsLength += length * 2 + 2;
_stream.Write( (ushort) length );
_stream.WriteBigUniFixed( v, length );
}
}
public byte[] ToArray()
{
byte[] packet = new byte[m_PacketLength];
Buffer.BlockCopy( _stream.ToArray(), 0, packet, 0, m_PacketLength );
return packet;
}
#region IDisposable Support
private bool disposedValue; // To detect redundant calls
protected virtual void Dispose( bool disposing )
{
if ( disposedValue )
{
return;
}
if ( disposing )
{
_stream.Dispose();
}
disposedValue = true;
}
public void Dispose()
{
Dispose( true );
GC.SuppressFinalize( this );
}
#endregion
}
}
}
@@ -0,0 +1,8 @@
namespace ClassicAssist.UO.Objects.Gumps
{
public enum GumpButtonType
{
Page = 0,
Reply = 1
}
}
@@ -0,0 +1,346 @@
/* Copyright (C) 2009 Matthew Geyer
*
* This file is part of UO Machine.
*
* UO Machine is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* UO Machine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with UO Machine. If not, see <http://www.gnu.org/licenses/>. */
using System;
namespace ClassicAssist.UO.Objects.Gumps
{
public class GumpElement
{
private Gump _parentGump;
public int ActiveID { get; set; }
public string Args { get; set; }
public bool Background { get; set; }
public int ButtonType { get; set; }
public int Cliloc { get; set; }
public int ElementID { get; set; }
public int Group { get; set; }
public int Height { get; set; }
public int Hue { get; set; }
public int InactiveID { get; set; }
public bool InitialState { get; set; }
public int ItemID { get; set; }
public int PageNumber { get; set; }
public int Param { get; set; }
public Gump ParentGump
{
get => _parentGump ?? ParentPage?.ParentGump;
set => _parentGump = value;
}
public GumpPage ParentPage { get; set; }
public bool ScrollBar { get; set; }
public int Serial { get; set; }
public int Size { get; set; }
public string Text { get; set; }
public int Tooltip { get; set; }
public ElementType Type { get; set; }
public int Width { get; set; }
public int X { get; set; }
public int Y { get; set; }
/// <summary>
/// Get nearest GumpElement.
/// </summary>
/// <returns>True on success.</returns>
public bool GetNearestElement( out GumpElement element )
{
if ( ParentPage != null )
{
return ParentPage.GetNearestElement( this, out element );
}
element = null;
return false;
}
/// <summary>
/// Get nearest GumpElement, but only if it's ElementType is contained in the include list.
/// </summary>
/// <param name="includeTypes">Array of ElementTypes which specifies valid GumpElements to search.</param>
/// <param name="element">GumpElement (out).</param>
/// <returns>True on success.</returns>
public bool GetNearestElement( ElementType[] includeTypes, out GumpElement element )
{
if ( ParentPage != null )
{
return ParentPage.GetNearestElement( this, includeTypes, out element );
}
element = null;
return false;
}
public void Click()
{
Gump g = ParentGump;
if ( g != null && g.ID != 461 && Type == ElementType.button )
{
//TODO
//Macros.MacroEx.CloseClientGump( g.Client, g.ID );
//Macros.MacroEx.GumpButtonClick( g.Client, g.ID, g.Serial, this.ElementID );
}
}
internal void AppendTo( Gump.IGumpWriter disp )
{
switch ( Type )
{
case ElementType.textentrylimited:
{
disp.AppendLayout( Gump.StringToBuffer( "textentrylimited" ) );
disp.AppendLayout( X );
disp.AppendLayout( Y );
disp.AppendLayout( Width );
disp.AppendLayout( Height );
disp.AppendLayout( Hue );
disp.AppendLayout( ElementID );
disp.AppendLayout( ParentGump.Intern( Text ) );
disp.AppendLayout( Size );
disp.TextEntries++;
break;
}
case ElementType.textentry:
{
disp.AppendLayout( Gump.StringToBuffer( "textentry" ) );
disp.AppendLayout( X );
disp.AppendLayout( Y );
disp.AppendLayout( Width );
disp.AppendLayout( Height );
disp.AppendLayout( Hue );
disp.AppendLayout( ElementID );
disp.AppendLayout( ParentGump.Intern( Text ) );
disp.TextEntries++;
break;
}
case ElementType.radio:
{
disp.AppendLayout( Gump.StringToBuffer( "radio" ) );
disp.AppendLayout( X );
disp.AppendLayout( Y );
disp.AppendLayout( InactiveID );
disp.AppendLayout( ActiveID );
disp.AppendLayout( InitialState );
disp.AppendLayout( ElementID );
disp.Switches++;
break;
}
case ElementType.croppedtext:
{
disp.AppendLayout( Gump.StringToBuffer( "croppedtext" ) );
disp.AppendLayout( X );
disp.AppendLayout( Y );
disp.AppendLayout( Width );
disp.AppendLayout( Height );
disp.AppendLayout( Hue );
disp.AppendLayout( ParentGump.Intern( Text ) );
break;
}
case ElementType.buttontileart:
{
disp.AppendLayout( Gump.StringToBuffer( "buttontileart" ) );
disp.AppendLayout( X );
disp.AppendLayout( Y );
disp.AppendLayout( InactiveID );
disp.AppendLayout( ActiveID );
disp.AppendLayout( ButtonType );
disp.AppendLayout( Param );
disp.AppendLayout( ElementID );
disp.AppendLayout( ItemID );
disp.AppendLayout( Hue );
disp.AppendLayout( Width );
disp.AppendLayout( Height );
if ( Cliloc != -1 )
{
disp.AppendLayout( Gump.StringToBuffer( " }{ tooltip" ) );
disp.AppendLayout( Cliloc );
}
break;
}
case ElementType.tilepic:
case ElementType.tilepichue:
{
disp.AppendLayout( Gump.StringToBuffer( Hue == 0 ? "tilepic" : "tilepichue" ) );
disp.AppendLayout( X );
disp.AppendLayout( Y );
disp.AppendLayout( ItemID );
if ( Hue != 0 )
{
disp.AppendLayout( Hue );
}
break;
}
case ElementType.itemproperty:
{
disp.AppendLayout( Gump.StringToBuffer( "itemproperty" ) );
disp.AppendLayout( Serial );
break;
}
case ElementType.gumppictiled:
{
disp.AppendLayout( Gump.StringToBuffer( "gumppictiled" ) );
disp.AppendLayout( X );
disp.AppendLayout( Y );
disp.AppendLayout( Width );
disp.AppendLayout( Height );
disp.AppendLayout( ElementID );
break;
}
case ElementType.gumppic:
{
disp.AppendLayout( Gump.StringToBuffer( "gumppic" ) );
disp.AppendLayout( X );
disp.AppendLayout( Y );
disp.AppendLayout( ElementID );
if ( Hue != 0 )
{
disp.AppendLayout( Gump.StringToBuffer( " hue=" ) );
disp.AppendLayoutNS( Hue );
}
break;
}
case ElementType.xmfhtmlgump:
{
disp.AppendLayout( Gump.StringToBuffer( "xmfhtmlgump" ) );
disp.AppendLayout( X );
disp.AppendLayout( Y );
disp.AppendLayout( Width );
disp.AppendLayout( Height );
disp.AppendLayout( Cliloc );
disp.AppendLayout( Background );
disp.AppendLayout( ScrollBar );
break;
}
case ElementType.xmfhtmlgumpcolor:
{
disp.AppendLayout( Gump.StringToBuffer( "xmfhtmlgumpcolor" ) );
disp.AppendLayout( X );
disp.AppendLayout( Y );
disp.AppendLayout( Width );
disp.AppendLayout( Height );
disp.AppendLayout( Cliloc );
disp.AppendLayout( Background );
disp.AppendLayout( ScrollBar );
disp.AppendLayout( Hue );
break;
}
case ElementType.xmfhtmltok:
{
disp.AppendLayout( Gump.StringToBuffer( "xmfhtmltok" ) );
disp.AppendLayout( X );
disp.AppendLayout( Y );
disp.AppendLayout( Width );
disp.AppendLayout( Height );
disp.AppendLayout( Background );
disp.AppendLayout( ScrollBar );
disp.AppendLayout( Hue );
disp.AppendLayout( Cliloc );
disp.AppendLayout( Args );
break;
}
case ElementType.htmlgump:
{
disp.AppendLayout( Gump.StringToBuffer( "htmlgump" ) );
disp.AppendLayout( X );
disp.AppendLayout( Y );
disp.AppendLayout( Width );
disp.AppendLayout( Height );
disp.AppendLayout( ParentGump.Intern( Text ) );
disp.AppendLayout( Background );
disp.AppendLayout( ScrollBar );
break;
}
case ElementType.tooltip:
{
disp.AppendLayout( Gump.StringToBuffer( "tooltip" ) );
disp.AppendLayout( Cliloc );
break;
}
case ElementType.group:
{
disp.AppendLayout( Gump.StringToBuffer( "group" ) );
disp.AppendLayout( Group );
break;
}
case ElementType.resizepic:
{
disp.AppendLayout( Gump.StringToBuffer( "resizepic" ) );
disp.AppendLayout( X );
disp.AppendLayout( Y );
disp.AppendLayout( ElementID );
disp.AppendLayout( Width );
disp.AppendLayout( Height );
break;
}
case ElementType.checkertrans:
{
disp.AppendLayout( Gump.StringToBuffer( "checkertrans" ) );
disp.AppendLayout( X );
disp.AppendLayout( Y );
disp.AppendLayout( Width );
disp.AppendLayout( Height );
break;
}
case ElementType.page:
{
disp.AppendLayout( Gump.StringToBuffer( "page" ) );
disp.AppendLayout( PageNumber );
break;
}
case ElementType.button:
{
disp.AppendLayout( Gump.StringToBuffer( "button" ) );
disp.AppendLayout( X );
disp.AppendLayout( Y );
disp.AppendLayout( InactiveID );
disp.AppendLayout( ActiveID );
disp.AppendLayout( ButtonType );
disp.AppendLayout( Param );
disp.AppendLayout( ElementID );
break;
}
case ElementType.text:
{
disp.AppendLayout( Gump.StringToBuffer( "text" ) );
disp.AppendLayout( X );
disp.AppendLayout( Y );
disp.AppendLayout( Hue );
disp.AppendLayout( ParentGump.Intern( Text ) );
break;
}
case ElementType.invalid:
break;
case ElementType.checkbox:
break;
case ElementType.kr_xmfhtmlgump:
break;
case ElementType.mastergump:
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}
}
@@ -0,0 +1,177 @@
/* Copyright (C) 2009 Matthew Geyer
*
* This file is part of UO Machine.
*
* UO Machine is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* UO Machine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with UO Machine. If not, see <http://www.gnu.org/licenses/>. */
using System.Linq;
namespace ClassicAssist.UO.Objects.Gumps
{
public sealed class GumpPage
{
public GumpElement[] GumpElements { get; internal set; }
public int Page { get; internal set; }
public Gump ParentGump { get; internal set; }
/// <summary>
/// Get array of GumpElements which match the specified ElementType.
/// </summary>
public GumpElement[] GetElementsByType( ElementType type )
{
return GumpElements.Where( ge => ge.Type == type ).ToArray();
}
/// <summary>
/// Get nearest GumpElement to source, but only if it's ElementType is contained in the include list.
/// </summary>
/// <param name="source">Source element.</param>
/// <param name="includeTypes">Array of ElementTypes which specifies valid GumpElements to search.</param>
/// <param name="element">GumpElement (out).</param>
/// <returns>True on success.</returns>
public bool GetNearestElement( GumpElement source, ElementType[] includeTypes, out GumpElement element )
{
GumpElement nearest = null;
double closest = 0;
foreach ( GumpElement ge in GumpElements )
{
if ( ge == source )
{
continue;
}
bool found = includeTypes.Any( et => ge.Type == et );
if ( !found )
{
continue;
}
double distance = UOMath.Distance( source.X, source.Y, ge.X, ge.Y );
if ( nearest == null )
{
closest = distance;
nearest = ge;
}
else
{
if ( !( distance < closest ) )
{
continue;
}
closest = distance;
nearest = ge;
}
}
element = nearest;
return nearest != null;
}
/// <summary>
/// Get nearest GumpElement from source.
/// </summary>
/// <returns>True on success.</returns>
public bool GetNearestElement( GumpElement source, out GumpElement element )
{
GumpElement nearest = null;
double closest = 0;
foreach ( GumpElement ge in GumpElements )
{
if ( ge == source )
{
continue;
}
double distance = UOMath.Distance( source.X, source.Y, ge.X, ge.Y );
if ( nearest == null )
{
closest = distance;
nearest = ge;
}
else
{
if ( !( distance < closest ) )
{
continue;
}
closest = distance;
nearest = ge;
}
}
element = nearest;
return nearest != null;
}
public bool GetElementByXY( int x, int y, out GumpElement gumpElement )
{
gumpElement = null;
if ( GumpElements == null )
{
return false;
}
GumpElement element = GumpElements.FirstOrDefault( m => m.X == x && m.Y == y );
if ( element != null )
{
gumpElement = element;
}
return gumpElement != null;
}
public GumpElement GetElementByXY( int x, int y )
{
if ( GetElementByXY( x, y, out GumpElement element ) )
{
return element;
}
return null;
}
public bool GetElementByCliloc( int cliloc, out GumpElement gumpElement )
{
gumpElement = null;
if ( GumpElements == null )
{
return false;
}
GumpElement element = GumpElements.FirstOrDefault( m => m.Cliloc == cliloc );
if ( element != null )
{
gumpElement = element;
}
return gumpElement != null;
}
public GumpElement GetElementByCliloc( int cliloc )
{
return GetElementByCliloc( cliloc, out GumpElement element ) ? element : null;
}
}
}
@@ -0,0 +1,917 @@
/* Copyright (C) 2009 Matthew Geyer
*
* This file is part of UO Machine.
*
* UO Machine is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* UO Machine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with UO Machine. If not, see <http://www.gnu.org/licenses/>. */
using System;
using System.Collections.Generic;
using System.Text;
using ClassicAssist.UO.Data;
namespace ClassicAssist.UO.Objects.Gumps
{
public static class GumpParser
{
// Gump command reference: http://docs.polserver.com/pol098/guides.php?guidefile=gumpcmdlist#xmfhtmltok
private static void OnError( string elementName, string layout )
{
throw new InvalidOperationException(
$"Error parsing gump element {elementName} in layout:\r\n\r\n{layout}" );
}
private static string[] GetTokens( string input )
{
//@0@1@ = {"0","1"}
if ( input.Contains( "@" ) )
{
input = input.Trim( '@' );
if ( input.Contains( "@" ) )
{
return input.Split( '@' );
}
string[] output = new string[1];
output[0] = input;
return output;
}
return null;
}
private static bool GetInt( string input, out int output )
{
if ( input.Contains( "=" ) )
{
string[] strArray = input.Split( '=' );
return int.TryParse( strArray[1].Trim(), out output );
}
output = -1;
return false;
}
public static Gump Parse( int serial, uint ID, int x, int y, string layout, string[] text )
{
bool closable = true, movable = true, disposable = true, resizable = true;
List<GumpPage> pageList = new List<GumpPage>();
List<GumpElement> gumpElementList = new List<GumpElement>();
GumpElement lastGumpElement = null;
GumpPage currentPage = null;
if ( string.IsNullOrEmpty( layout ) )
{
return null;
}
string[] split = layout.Substring( layout.IndexOf( '{' ) ).TrimEnd( '}', ' ' )
.Split( new[] { '}' }, StringSplitOptions.RemoveEmptyEntries );
for ( int i = 0; i < split.Length; i++ )
{
split[i] = split[i].TrimStart( '{', ' ' ).Trim();
string[] formatted = split[i].Split( new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries );
for ( int j = 0; j < formatted.Length; j++ )
{
formatted[j] = formatted[j].Trim();
}
switch ( formatted[0] )
{
case "noclose":
closable = false;
break;
case "nodispose":
disposable = false;
break;
case "nomove":
movable = false;
break;
case "noresize":
resizable = false;
break;
case "kr_button":
case "button":
try
{
if ( int.TryParse( formatted[1], out int gbX ) &&
int.TryParse( formatted[2], out int gbY ) &&
int.TryParse( formatted[3], out int gbNormalID ) &&
int.TryParse( formatted[4], out int gbPressedID ) &&
int.TryParse( formatted[5], out int gbType ) &&
int.TryParse( formatted[6], out int gbParam ) &&
int.TryParse( formatted[7], out int gbID ) )
{
GumpElement ge = new GumpElement
{
Type = ElementType.button,
ParentPage = currentPage,
X = gbX,
Y = gbY,
InactiveID = gbNormalID,
ActiveID = gbPressedID,
ElementID = gbID,
ButtonType = gbType,
Param = gbParam
};
gumpElementList.Add( ge );
}
else
{
OnError( "button", layout );
}
}
catch
{
OnError( "button", layout );
}
break;
case "buttontileart":
try
{
if ( int.TryParse( formatted[1], out int btX ) &&
int.TryParse( formatted[2], out int btY ) &&
int.TryParse( formatted[3], out int btNormalID ) &&
int.TryParse( formatted[4], out int btPressedID ) &&
int.TryParse( formatted[5], out int btType ) &&
int.TryParse( formatted[6], out int btParam ) &&
int.TryParse( formatted[7], out int btID ) &&
int.TryParse( formatted[8], out int btItemID ) &&
int.TryParse( formatted[9], out int btHue ) &&
int.TryParse( formatted[10], out int btWidth ) &&
int.TryParse( formatted[11], out int btHeight ) )
{
GumpElement ge = new GumpElement
{
Type = ElementType.buttontileart,
ParentPage = currentPage,
X = btX,
Y = btY,
ElementID = btID,
ButtonType = btType,
Height = btHeight,
Width = btWidth,
Hue = btHue,
ItemID = btItemID,
InactiveID = btNormalID,
Param = btParam,
ActiveID = btPressedID
};
gumpElementList.Add( ge );
lastGumpElement = ge;
}
else
{
OnError( "buttontileart", layout );
}
}
catch
{
OnError( "buttontileart", layout );
}
break;
case "checkertrans":
try
{
if ( int.TryParse( formatted[1], out int ctX ) &&
int.TryParse( formatted[2], out int ctY ) &&
int.TryParse( formatted[3], out int ctWidth ) &&
int.TryParse( formatted[4], out int ctHeight ) )
{
GumpElement ge = new GumpElement
{
Type = ElementType.checkertrans,
ParentPage = currentPage,
X = ctX,
Y = ctY,
Width = ctWidth,
Height = ctHeight
};
gumpElementList.Add( ge );
}
else
{
OnError( "checkertrans", layout );
}
}
catch
{
OnError( "checkertrans", layout );
}
break;
case "croppedtext":
try
{
if ( int.TryParse( formatted[1], out int crX ) &&
int.TryParse( formatted[2], out int crY ) &&
int.TryParse( formatted[3], out int crWidth ) &&
int.TryParse( formatted[4], out int crHeight ) &&
int.TryParse( formatted[5], out int crHue ) &&
int.TryParse( formatted[6], out int crText ) )
{
GumpElement ge = new GumpElement
{
Type = ElementType.croppedtext,
ParentPage = currentPage,
X = crX,
Y = crY,
Height = crHeight,
Width = crWidth,
Hue = crHue,
Text = text[crText]
};
gumpElementList.Add( ge );
}
else
{
OnError( "croppedtext", layout );
}
}
catch
{
OnError( "croppedtext", layout );
}
break;
case "checkbox":
try
{
if ( int.TryParse( formatted[1], out int cbX ) &&
int.TryParse( formatted[2], out int cbY ) &&
int.TryParse( formatted[3], out int cbInactiveID ) &&
int.TryParse( formatted[4], out int cbActiveID ) &&
int.TryParse( formatted[5], out int cbState ) &&
int.TryParse( formatted[6], out int cbID ) )
{
GumpElement ge = new GumpElement
{
Type = ElementType.checkbox,
ParentPage = currentPage,
X = cbX,
Y = cbY,
InactiveID = cbInactiveID,
ActiveID = cbActiveID,
ElementID = cbID,
InitialState = cbState == 1
};
gumpElementList.Add( ge );
}
else
{
OnError( "checkbox", layout );
}
}
catch
{
OnError( "checkbox", layout );
}
break;
case "page":
if ( currentPage == null )
{
currentPage = new GumpPage();
}
else
{
currentPage.GumpElements = gumpElementList.ToArray();
pageList.Add( currentPage );
currentPage = new GumpPage();
gumpElementList = new List<GumpElement>();
}
if ( int.TryParse( formatted[1], out int page ) )
{
currentPage.Page = page;
}
else
{
OnError( "page", layout );
}
break;
case "kr_gumppic":
case "gumppic":
try
{
if ( int.TryParse( formatted[1], out int gpX ) &&
int.TryParse( formatted[2], out int gpY ) &&
int.TryParse( formatted[3], out int gpID ) )
{
GumpElement ge = new GumpElement
{
Type = ElementType.gumppic, ParentPage = currentPage
};
if ( formatted.Length > 4 )
{
for ( int gp = 4; gp < formatted.Length; gp++ )
{
if ( formatted[gp].Contains( "hue" ) )
{
if ( GetInt( formatted[gp], out int gpHue ) )
{
ge.Hue = gpHue;
}
else
{
OnError( "gumppic", layout );
}
}
else
{
ge.Args = formatted[gp];
}
}
}
ge.X = gpX;
ge.Y = gpY;
ge.ElementID = gpID;
gumpElementList.Add( ge );
}
else
{
OnError( "gumppic", layout );
}
}
catch
{
OnError( "gumppic", layout );
}
break;
case "gumppictiled":
try
{
if ( int.TryParse( formatted[1], out int gtX ) &&
int.TryParse( formatted[2], out int gtY ) &&
int.TryParse( formatted[3], out int gtWidth ) &&
int.TryParse( formatted[4], out int gtHeight ) &&
int.TryParse( formatted[5], out int gtID ) )
{
GumpElement ge = new GumpElement
{
Type = ElementType.gumppictiled,
ParentPage = currentPage,
X = gtX,
Y = gtY,
Width = gtWidth,
Height = gtHeight,
ElementID = gtID
};
gumpElementList.Add( ge );
}
else
{
OnError( "gumppictiled", layout );
}
}
catch
{
OnError( "gumppictiled", layout );
}
break;
case "kr_xmfhtmlgump":
try
{
if ( int.TryParse( formatted[1], out int xgX ) &&
int.TryParse( formatted[2], out int xgY ) &&
int.TryParse( formatted[3], out int xgWidth ) &&
int.TryParse( formatted[4], out int xgHeight ) &&
int.TryParse( formatted[5], out int xgCliloc ) &&
int.TryParse( formatted[6], out int xgBackground ) &&
int.TryParse( formatted[7], out int xgScrollbar ) )
{
GumpElement ge = new GumpElement
{
Type = ElementType.kr_xmfhtmlgump,
ParentPage = currentPage,
X = xgX,
Y = xgY,
Width = xgWidth,
Height = xgHeight,
Cliloc = xgCliloc,
Background = xgBackground == 1,
ScrollBar = xgScrollbar == 1
};
if ( xgCliloc != 0 )
{
ge.Text = Cliloc.GetProperty( xgCliloc );
}
gumpElementList.Add( ge );
}
else
{
OnError( "kr_xmfhtmlgump", layout );
}
}
catch
{
OnError( "kr_xmfhtmlgump", layout );
}
break;
case "mastergump":
try
{
if ( int.TryParse( formatted[1], out int mgID ) )
{
GumpElement ge = new GumpElement
{
Type = ElementType.mastergump, ParentPage = currentPage, ElementID = mgID
};
gumpElementList.Add( ge );
}
else
{
OnError( "mastergump", layout );
}
}
catch
{
OnError( "mastergump", layout );
}
break;
case "radio":
try
{
if ( int.TryParse( formatted[1], out int rX ) && int.TryParse( formatted[2], out int rY ) &&
int.TryParse( formatted[3], out int rInactiveID ) &&
int.TryParse( formatted[4], out int rActiveID ) &&
int.TryParse( formatted[5], out int rState ) &&
int.TryParse( formatted[6], out int rID ) )
{
GumpElement ge = new GumpElement
{
Type = ElementType.radio,
ParentPage = currentPage,
X = rX,
Y = rY,
InactiveID = rInactiveID,
ActiveID = rActiveID,
ElementID = rID,
InitialState = rState == 1
};
gumpElementList.Add( ge );
}
else
{
OnError( "radio", layout );
}
}
catch
{
OnError( "radio", layout );
}
break;
case "resizepic":
try
{
if ( int.TryParse( formatted[1], out int rpX ) &&
int.TryParse( formatted[2], out int rpY ) &&
int.TryParse( formatted[3], out int rpID ) &&
int.TryParse( formatted[4], out int rpWidth ) &&
int.TryParse( formatted[5], out int _ ) )
{
GumpElement ge = new GumpElement
{
Type = ElementType.resizepic,
ParentPage = currentPage,
X = rpX,
Y = rpY,
Width = rpWidth,
Height = rpWidth,
ElementID = rpID
};
gumpElementList.Add( ge );
}
else
{
OnError( "resizepic", layout );
}
}
catch
{
OnError( "resizepic", layout );
}
break;
case "text":
try
{
if ( int.TryParse( formatted[1], out int tX ) && int.TryParse( formatted[2], out int tY ) &&
int.TryParse( formatted[3], out int tHue ) &&
int.TryParse( formatted[4], out int tText ) )
{
GumpElement ge = new GumpElement
{
Type = ElementType.text,
ParentPage = currentPage,
X = tX,
Y = tY,
Hue = tHue,
Text = text[tText]
};
gumpElementList.Add( ge );
}
else
{
OnError( "text", layout );
}
}
catch
{
OnError( "text", layout );
}
break;
case "tooltip":
try
{
if ( int.TryParse( formatted[1], out int tooltip ) /* && lastGumpElement != null */ )
{
if ( lastGumpElement != null )
{
lastGumpElement.Tooltip = tooltip;
lastGumpElement.Text = Cliloc.GetProperty( tooltip );
}
}
else
{
OnError( "tooltip", layout );
}
}
catch
{
OnError( "tooltip", layout );
}
break;
case "htmlgump":
try
{
if ( int.TryParse( formatted[1], out int hgX ) &&
int.TryParse( formatted[2], out int hgY ) &&
int.TryParse( formatted[3], out int hgWidth ) &&
int.TryParse( formatted[4], out int hgHeight ) &&
int.TryParse( formatted[5], out int hgText ) &&
int.TryParse( formatted[6], out int hgBackground ) &&
int.TryParse( formatted[7], out int hgScrollbar ) )
{
GumpElement ge = new GumpElement
{
Type = ElementType.htmlgump,
ParentPage = currentPage,
X = hgX,
Y = hgY,
Width = hgWidth,
Height = hgHeight,
Text = text[hgText],
ScrollBar = hgScrollbar == 1,
Background = hgBackground == 1
};
gumpElementList.Add( ge );
}
else
{
OnError( "htmlgump", layout );
}
}
catch
{
OnError( "htmlgump", layout );
}
break;
case "textentry":
try
{
if ( int.TryParse( formatted[1], out int teX ) &&
int.TryParse( formatted[2], out int teY ) &&
int.TryParse( formatted[3], out int teWidth ) &&
int.TryParse( formatted[4], out int teHeight ) &&
int.TryParse( formatted[5], out int teHue ) &&
int.TryParse( formatted[6], out int teID ) &&
int.TryParse( formatted[7], out int teText ) )
{
GumpElement ge = new GumpElement
{
Type = ElementType.textentry,
ParentPage = currentPage,
X = teX,
Y = teY,
Height = teHeight,
Width = teWidth,
Hue = teHue,
ElementID = teID,
Text = text[teText]
};
gumpElementList.Add( ge );
}
else
{
OnError( "textentry", layout );
}
}
catch
{
OnError( "textentry", layout );
}
break;
case "textentrylimited":
try
{
if ( int.TryParse( formatted[1], out int tlX ) &&
int.TryParse( formatted[2], out int tlY ) &&
int.TryParse( formatted[3], out int tlWidth ) &&
int.TryParse( formatted[4], out int tlHeight ) &&
int.TryParse( formatted[5], out int tlHue ) &&
int.TryParse( formatted[6], out int tlID ) &&
int.TryParse( formatted[7], out int tlText ) &&
int.TryParse( formatted[8], out int tlSize ) )
{
GumpElement ge = new GumpElement
{
Type = ElementType.textentrylimited,
ParentPage = currentPage,
X = tlX,
Y = tlY,
Height = tlHeight,
Width = tlWidth,
Hue = tlHue,
ElementID = tlID,
Text = text[tlText],
Size = tlSize
};
gumpElementList.Add( ge );
}
else
{
OnError( "textentrylimited", layout );
}
}
catch
{
OnError( "textentrylimited", layout );
}
break;
case "tilepic":
try
{
if ( int.TryParse( formatted[1], out int tpX ) &&
int.TryParse( formatted[2], out int tpY ) && int.TryParse(
formatted[3].Split( new[] { ',' }, StringSplitOptions.RemoveEmptyEntries )?[0] ??
"0", out int tpID ) )
{
GumpElement ge = new GumpElement
{
Type = ElementType.tilepic,
ParentPage = currentPage,
X = tpX,
Y = tpY,
ElementID = tpID
};
gumpElementList.Add( ge );
}
else
{
OnError( "tilepic", layout );
}
}
catch
{
OnError( "tilepic", layout );
}
break;
case "tilepichue":
try
{
if ( int.TryParse( formatted[1], out int tpX ) &&
int.TryParse( formatted[2], out int tpY ) &&
int.TryParse( formatted[3], out int tpID ) &&
int.TryParse( formatted[4], out int tpHue ) )
{
GumpElement ge = new GumpElement
{
Type = ElementType.tilepichue,
ParentPage = currentPage,
X = tpX,
Y = tpY,
ElementID = tpID,
Hue = tpHue
};
gumpElementList.Add( ge );
}
else
{
OnError( "tilepichue", layout );
}
}
catch
{
OnError( "tilepichue", layout );
}
break;
case "xmfhtmlgump":
try
{
if ( int.TryParse( formatted[1], out int xgX ) &&
int.TryParse( formatted[2], out int xgY ) &&
int.TryParse( formatted[3], out int xgWidth ) &&
int.TryParse( formatted[4], out int xgHeight ) &&
int.TryParse( formatted[5], out int xgCliloc ) &&
int.TryParse( formatted[6], out int xgBackground ) &&
int.TryParse( formatted[7], out int xgScrollbar ) )
{
GumpElement ge = new GumpElement
{
Type = ElementType.xmfhtmlgump,
ParentPage = currentPage,
X = xgX,
Y = xgY,
Width = xgWidth,
Height = xgHeight,
Cliloc = xgCliloc,
Background = xgBackground == 1,
ScrollBar = xgScrollbar == 1
};
if ( xgCliloc != 0 )
{
ge.Text = Cliloc.GetProperty( xgCliloc );
}
gumpElementList.Add( ge );
}
else
{
OnError( "xmfhtmlgump", layout );
}
}
catch
{
OnError( "xmfhtmlgump", layout );
}
break;
case "xmfhtmlgumpcolor":
try
{
if ( int.TryParse( formatted[1], out int xcX ) &&
int.TryParse( formatted[2], out int xcY ) &&
int.TryParse( formatted[3], out int xcWidth ) &&
int.TryParse( formatted[4], out int xcHeight ) &&
int.TryParse( formatted[5], out int xcCliloc ) &&
int.TryParse( formatted[6], out int xcBackground ) &&
int.TryParse( formatted[7], out int xcScrollbar ) &&
int.TryParse( formatted[8], out int xcHue ) )
{
GumpElement ge = new GumpElement
{
Type = ElementType.xmfhtmlgumpcolor,
ParentPage = currentPage,
X = xcX,
Y = xcY,
Width = xcWidth,
Height = xcHeight,
Cliloc = xcCliloc,
Background = xcBackground == 1,
ScrollBar = xcScrollbar == 1,
Hue = xcHue
};
if ( xcCliloc != 0 )
{
ge.Text = Cliloc.GetProperty( xcCliloc );
}
gumpElementList.Add( ge );
}
else
{
OnError( "xmfhtmlgumpcolor", layout );
}
}
catch
{
OnError( "xmfhtmlgumpcolor", layout );
}
break;
case "xmfhtmltok":
try
{
if ( int.TryParse( formatted[1], out int xtX ) &&
int.TryParse( formatted[2], out int xtY ) &&
int.TryParse( formatted[3], out int xtWidth ) &&
int.TryParse( formatted[4], out int xtHeight ) &&
int.TryParse( formatted[5], out int xtBackground ) &&
int.TryParse( formatted[6], out int xtScrollbar ) &&
int.TryParse( formatted[7], out int xtHue ) &&
int.TryParse( formatted[8], out int xtCliloc ) )
{
GumpElement ge = new GumpElement
{
Type = ElementType.xmfhtmltok, ParentPage = currentPage
};
string[] args = null;
StringBuilder sb = new StringBuilder();
if ( formatted.Length > 9 )
{
sb.Append( formatted[9] );
for ( int a = 10; a < formatted.Length; a++ )
{
sb.Append( ' ' );
sb.Append( formatted[a] );
}
args = GetTokens( sb.ToString() );
}
ge.Text = Cliloc.GetLocalString( xtCliloc, args );
ge.Args = args != null ? string.Join( "\t", args ) : string.Empty;
ge.X = xtX;
ge.Y = xtY;
ge.Width = xtWidth;
ge.Height = xtHeight;
ge.Hue = xtHue;
ge.Cliloc = xtCliloc;
ge.ScrollBar = xtScrollbar == 1;
ge.Background = xtBackground == 1;
gumpElementList.Add( ge );
}
else
{
OnError( "xmfhtmltok", layout );
}
}
catch
{
OnError( "xmfhtmltok", layout );
}
break;
case "itemproperty":
int itemserial;
if ( int.TryParse( formatted[1], out itemserial ) )
{
GumpElement ge = new GumpElement { Type = ElementType.itemproperty, Serial = itemserial };
gumpElementList.Add( ge );
}
break;
case "echandleinput":
//TODO
break;
//default:
// throw new InvalidOperationException(
// $"Unknown element \"{formatted[0]}\" in custom gump layout:\r\n\r\n{layout}" );
}
}
if ( currentPage != null )
{
currentPage.GumpElements = gumpElementList.ToArray();
pageList.Add( currentPage );
}
Gump g = new Gump( x, y, ID, serial, layout, text, gumpElementList.ToArray(), pageList.ToArray() )
{
Closable = closable, Disposable = disposable, Movable = movable, Resizable = resizable
};
return g;
}
}
}
@@ -0,0 +1,48 @@
/* Copyright (C) 2009 Matthew Geyer
*
* This file is part of UO Machine.
*
* UO Machine is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* UO Machine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with UO Machine. If not, see <http://www.gnu.org/licenses/>. */
namespace ClassicAssist.UO.Objects.Gumps
{
public enum ElementType : byte
{
invalid,
button,
buttontileart,
checkbox,
checkertrans,
croppedtext,
gumppic,
gumppictiled,
htmlgump,
kr_xmfhtmlgump,
mastergump,
radio,
resizepic,
text,
textentry,
textentrylimited,
tilepic,
tilepichue,
xmfhtmlgump,
xmfhtmlgumpcolor,
xmfhtmltok,
itemproperty,
page,
group,
tooltip
}
}