AvatarsConquest/Scripts/Items/Books/BaseBook.cs

510 lines
No EOL
12 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Server;
using Server.ContextMenus;
using Server.Network;
using Server.Gumps;
using Server.Multis;
namespace Server.Items
{
public class BookPageInfo
{
private string[] m_Lines;
public string[] Lines
{
get
{
return m_Lines;
}
set
{
m_Lines = value;
}
}
public BookPageInfo()
{
m_Lines = new string[0];
}
public BookPageInfo( params string[] lines )
{
m_Lines = lines;
}
public BookPageInfo( GenericReader reader )
{
int length = reader.ReadInt();
m_Lines = new string[length];
for ( int i = 0; i < m_Lines.Length; ++i )
m_Lines[i] = Utility.Intern( reader.ReadString() );
}
public void Serialize( GenericWriter writer )
{
writer.Write( m_Lines.Length );
for ( int i = 0; i < m_Lines.Length; ++i )
writer.Write( m_Lines[i] );
}
}
public class BaseBook : Item, ISecurable
{
private string m_Title;
private string m_Author;
private BookPageInfo[] m_Pages;
private bool m_Writable;
private SecureLevel m_SecureLevel;
[CommandProperty( AccessLevel.GameMaster )]
public string Title
{
get { return m_Title; }
set { m_Title = value; InvalidateProperties(); }
}
[CommandProperty( AccessLevel.GameMaster )]
public string Author
{
get { return m_Author; }
set { m_Author = value; InvalidateProperties(); }
}
[CommandProperty( AccessLevel.GameMaster )]
public bool Writable
{
get { return m_Writable; }
set { m_Writable = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public int PagesCount
{
get { return m_Pages.Length; }
}
public BookPageInfo[] Pages
{
get { return m_Pages; }
}
[Constructable]
public BaseBook( int itemID ) : this( itemID, 20, true )
{
}
[Constructable]
public BaseBook( int itemID, int pageCount, bool writable ) : this( itemID, null, null, pageCount, writable )
{
}
[Constructable]
public BaseBook( int itemID, string title, string author, int pageCount, bool writable ) : base( itemID )
{
Name = "book";
m_Title = title;
m_Author = author;
m_Writable = writable;
BookContent content = this.DefaultContent;
if ( content == null )
{
m_Pages = new BookPageInfo[pageCount];
for ( int i = 0; i < m_Pages.Length; ++i )
m_Pages[i] = new BookPageInfo();
}
else
{
m_Pages = content.Copy();
}
}
// Intended for defined books only
public BaseBook( int itemID, bool writable ) : base( itemID )
{
m_Writable = writable;
BookContent content = this.DefaultContent;
if ( content == null )
{
m_Pages = new BookPageInfo[0];
}
else
{
m_Title = content.Title;
m_Author = content.Author;
m_Pages = content.Copy();
}
}
public virtual BookContent DefaultContent{ get{ return null; } }
public BaseBook( Serial serial ) : base( serial )
{
}
[Flags]
private enum SaveFlags
{
None = 0x00,
Title = 0x01,
Author = 0x02,
Writable = 0x04,
Content = 0x08
}
public override void GetContextMenuEntries( Mobile from, List<ContextMenuEntry> list )
{
base.GetContextMenuEntries( from, list );
SetSecureLevelEntry.AddTo( from, this, list );
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
BookContent content = this.DefaultContent;
SaveFlags flags = SaveFlags.None;
if ( m_Title != ( content == null ? null : content.Title ) )
flags |= SaveFlags.Title;
if ( m_Author != ( content == null ? null : content.Author ) )
flags |= SaveFlags.Author;
if ( m_Writable )
flags |= SaveFlags.Writable;
if ( content == null || !content.IsMatch( m_Pages ) )
flags |= SaveFlags.Content;
writer.Write( (int) 4 ); // version
writer.Write( (int)m_SecureLevel );
writer.Write( (byte) flags );
if ( (flags & SaveFlags.Title) != 0 )
writer.Write( m_Title );
if ( (flags & SaveFlags.Author) != 0 )
writer.Write( m_Author );
if ( (flags & SaveFlags.Content) != 0 )
{
writer.WriteEncodedInt( m_Pages.Length );
for ( int i = 0; i < m_Pages.Length; ++i )
m_Pages[i].Serialize( writer );
}
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
switch ( version )
{
case 4:
{
m_SecureLevel = (SecureLevel)reader.ReadInt();
goto case 3;
}
case 3:
case 2:
{
BookContent content = this.DefaultContent;
SaveFlags flags = (SaveFlags) reader.ReadByte();
if ( (flags & SaveFlags.Title) != 0 )
m_Title = Utility.Intern( reader.ReadString() );
else if ( content != null )
m_Title = content.Title;
if ( (flags & SaveFlags.Author) != 0 )
m_Author = reader.ReadString();
else if ( content != null )
m_Author = content.Author;
m_Writable = ( flags & SaveFlags.Writable ) != 0;
if ( (flags & SaveFlags.Content) != 0 )
{
m_Pages = new BookPageInfo[reader.ReadEncodedInt()];
for ( int i = 0; i < m_Pages.Length; ++i )
m_Pages[i] = new BookPageInfo( reader );
}
else
{
if ( content != null )
m_Pages = content.Copy();
else
m_Pages = new BookPageInfo[0];
}
break;
}
case 1:
case 0:
{
m_Title = reader.ReadString();
m_Author = reader.ReadString();
m_Writable = reader.ReadBool();
if ( version == 0 || reader.ReadBool() )
{
m_Pages = new BookPageInfo[reader.ReadInt()];
for ( int i = 0; i < m_Pages.Length; ++i )
m_Pages[i] = new BookPageInfo( reader );
}
else
{
BookContent content = this.DefaultContent;
if ( content != null )
m_Pages = content.Copy();
else
m_Pages = new BookPageInfo[0];
}
break;
}
}
if ( version < 3 && ( Weight == 1 || Weight == 2 ) )
Weight = -1;
}
public override void AddNameProperty( ObjectPropertyList list )
{
if ( m_Title != null && m_Title.Length > 0 )
{
list.Add( m_Title );
if ( !String.IsNullOrEmpty( m_SpecialName ) )
list.Add( 1062613, m_SpecialName );
}
else
base.AddNameProperty( list );
}
/*public override void GetProperties( ObjectPropertyList list )
{
base.GetProperties( list );
if ( m_Title != null && m_Title.Length > 0 )
list.Add( 1060658, "Title\t{0}", m_Title ); // ~1_val~: ~2_val~
if ( m_Author != null && m_Author.Length > 0 )
list.Add( 1060659, "Author\t{0}", m_Author ); // ~1_val~: ~2_val~
if ( m_Pages != null && m_Pages.Length > 0 )
list.Add( 1060660, "Pages\t{0}", m_Pages.Length ); // ~1_val~: ~2_val~
}*/
public override void OnSingleClick ( Mobile from )
{
LabelTo( from, "{0} by {1}", m_Title, m_Author );
LabelTo( from, "[{0} pages]", m_Pages.Length );
}
public override void OnDoubleClick ( Mobile from )
{
if ( m_Title == null && m_Author == null && m_Writable == true )
{
Title = "a book";
Author = from.Name;
}
from.Send( new BookHeader( from, this ) );
from.Send( new BookPageDetails( this ) );
}
public static void Initialize()
{
PacketHandlers.Register( 0xD4, 0, true, new OnPacketReceive( HeaderChange ) );
PacketHandlers.Register( 0x66, 0, true, new OnPacketReceive( ContentChange ) );
PacketHandlers.Register( 0x93, 99, true, new OnPacketReceive( OldHeaderChange ) );
}
public static void OldHeaderChange( NetState state, PacketReader pvSrc )
{
Mobile from = state.Mobile;
BaseBook book = World.FindItem( pvSrc.ReadInt32() ) as BaseBook;
if ( book == null || !book.Writable || !from.InRange( book.GetWorldLocation(), 1 ) || !book.IsAccessibleTo( from ) )
return;
pvSrc.Seek( 4, SeekOrigin.Current ); // Skip flags and page count
string title = pvSrc.ReadStringSafe( 60 );
string author = pvSrc.ReadStringSafe( 30 );
book.Title = Utility.FixHtml( title );
book.Author = Utility.FixHtml( author );
}
public static void HeaderChange( NetState state, PacketReader pvSrc )
{
Mobile from = state.Mobile;
BaseBook book = World.FindItem( pvSrc.ReadInt32() ) as BaseBook;
if ( book == null || !book.Writable || !from.InRange( book.GetWorldLocation(), 1 ) || !book.IsAccessibleTo( from ) )
return;
pvSrc.Seek( 4, SeekOrigin.Current ); // Skip flags and page count
int titleLength = pvSrc.ReadUInt16();
if ( titleLength > 60 )
return;
string title = pvSrc.ReadUTF8StringSafe( titleLength );
int authorLength = pvSrc.ReadUInt16();
if ( authorLength > 30 )
return;
string author = pvSrc.ReadUTF8StringSafe( authorLength );
book.Title = Utility.FixHtml( title );
book.Author = Utility.FixHtml( author );
}
public static void ContentChange( NetState state, PacketReader pvSrc )
{
Mobile from = state.Mobile;
BaseBook book = World.FindItem( pvSrc.ReadInt32() ) as BaseBook;
if ( book == null || !book.Writable || !from.InRange( book.GetWorldLocation(), 1 ) || !book.IsAccessibleTo( from ) )
return;
int pageCount = pvSrc.ReadUInt16();
if ( pageCount > book.PagesCount )
return;
for ( int i = 0; i < pageCount; ++i )
{
int index = pvSrc.ReadUInt16();
if ( index >= 1 && index <= book.PagesCount )
{
--index;
int lineCount = pvSrc.ReadUInt16();
if ( lineCount <= 8 )
{
string[] lines = new string[lineCount];
for ( int j = 0; j < lineCount; ++j )
if ( (lines[j] = pvSrc.ReadUTF8StringSafe()).Length >= 80 )
return;
book.Pages[index].Lines = lines;
}
else
{
return;
}
}
else
{
return;
}
}
}
#region ISecurable Members
[CommandProperty( AccessLevel.GameMaster )]
public SecureLevel Level
{
get
{
return m_SecureLevel;
}
set
{
m_SecureLevel = value;
}
}
#endregion
}
public sealed class BookPageDetails : Packet
{
public BookPageDetails( BaseBook book ) : base( 0x66 )
{
EnsureCapacity( 256 );
m_Stream.Write( (int) book.Serial );
m_Stream.Write( (ushort) book.PagesCount );
for ( int i = 0; i < book.PagesCount; ++i )
{
BookPageInfo page = book.Pages[i];
m_Stream.Write( (ushort) (i + 1) );
m_Stream.Write( (ushort) page.Lines.Length );
for ( int j = 0; j < page.Lines.Length; ++j )
{
byte[] buffer = Utility.UTF8.GetBytes( page.Lines[j] );
m_Stream.Write( buffer, 0, buffer.Length );
m_Stream.Write( (byte) 0 );
}
}
}
}
public sealed class BookHeader : Packet
{
public BookHeader( Mobile from, BaseBook book ) : base ( 0xD4 )
{
string title = book.Title == null ? "" : book.Title;
string author = book.Author == null ? "" : book.Author;
byte[] titleBuffer = Utility.UTF8.GetBytes( title );
byte[] authorBuffer = Utility.UTF8.GetBytes( author );
EnsureCapacity( 15 + titleBuffer.Length + authorBuffer.Length );
m_Stream.Write( (int) book.Serial );
m_Stream.Write( (bool) true );
m_Stream.Write( (bool) book.Writable && from.InRange( book.GetWorldLocation(), 1 ) );
m_Stream.Write( (ushort) book.PagesCount );
m_Stream.Write( (ushort) (titleBuffer.Length + 1) );
m_Stream.Write( titleBuffer, 0, titleBuffer.Length );
m_Stream.Write( (byte) 0 ); // terminate
m_Stream.Write( (ushort) (authorBuffer.Length + 1) );
m_Stream.Write( authorBuffer, 0, authorBuffer.Length );
m_Stream.Write( (byte) 0 ); // terminate
}
}
}