using System; using ModernUO.Serialization; using Server.Collections; using Server.ContextMenus; using Server.Gumps; using Server.Multis; using Server.Text; namespace Server.Items { [SerializationGenerator(5, false)] public partial class BaseBook : Item, ISecurable { [SerializedIgnoreDupe] [SerializableField(0)] [SerializedCommandProperty(AccessLevel.GameMaster)] private SecureLevel _level; [InternString] [InvalidateProperties] [SerializableField(1)] [SaveFlag(nameof(ShouldSerializeTitle), nameof(TitleDefaultValue))] [SerializedCommandProperty(AccessLevel.GameMaster)] private string _title; private bool ShouldSerializeTitle() => _title != DefaultContent?.Title; private string TitleDefaultValue() => DefaultContent?.Title; [InvalidateProperties] [SerializableField(2)] [SaveFlag(nameof(ShouldSerializeAuthor), nameof(AuthorDefaultValue))] [SerializedCommandProperty(AccessLevel.GameMaster)] private string _author; private bool ShouldSerializeAuthor() => _author != DefaultContent?.Author; private string AuthorDefaultValue() => DefaultContent?.Author; [SerializableField(3)] [SaveFlag(nameof(ShouldSerializeWritable))] [SerializedCommandProperty(AccessLevel.GameMaster)] private bool _writable; private bool ShouldSerializeWritable() => _writable; [SerializedIgnoreDupe] [SerializableField(4, setter: "protected")] [SaveFlag(nameof(ShouldSerializePages), nameof(PagesDefaultValue))] private BookPageInfo[] _pages; private bool ShouldSerializePages() => DefaultContent?.IsMatch(_pages) != true; private BookPageInfo[] PagesDefaultValue() => DefaultContent?.Copy() ?? Array.Empty(); [Constructible] public BaseBook(int itemID, int pageCount = 20, bool writable = true) : this(itemID, null, null, pageCount, writable) { } [Constructible] public BaseBook(int itemID, string title, string author, int pageCount, bool writable) : base(itemID) { var content = DefaultContent; _title = title ?? content?.Title; _author = author ?? content?.Author; _writable = writable; if (content == null) { _pages = new BookPageInfo[pageCount]; for (var i = 0; i < _pages.Length; ++i) { _pages[i] = new BookPageInfo(); } } else { _pages = content.Copy(); } } // Intended for defined books only public BaseBook(int itemID, bool writable) : this(itemID, 0, writable) { } [CommandProperty(AccessLevel.GameMaster)] public int PagesCount => _pages.Length; public override void OnAfterDuped(Item newItem) { if (newItem is not BaseBook book) { return; } book.Pages = new BookPageInfo[book.PagesCount]; for (var i = 0; i < _pages.Length; ++i) { var oldPage = _pages[i]; var oldLines = _pages[i].Lines; var lines = new string[oldPage.Lines.Length]; for (var j = 0; j < oldLines.Length; j++) { lines[j] = oldLines[j]; } book._pages[i] = new BookPageInfo(lines); } } public virtual BookContent DefaultContent => null; public string ContentAsString { get { using var sb = new ValueStringBuilder(stackalloc char[256]); foreach (var bpi in Pages) { foreach (var line in bpi.Lines) { sb.AppendLine(line); } } return sb.ToString(); } } public string[] ContentAsStringArray { get { using var lines = PooledRefQueue.Create(256); for (var i = 0; i < Pages.Length; i++) { var bpi = Pages[i]; for (var j = 0; j < bpi.Lines.Length; j++) { lines.Enqueue(bpi.Lines[j]); } } return lines.ToArray(); } } public override void GetContextMenuEntries(Mobile from, ref PooledRefList list) { base.GetContextMenuEntries(from, ref list); SetSecureLevelEntry.AddTo(from, this, ref list); } private void Deserialize(IGenericReader reader, int version) { Level = (SecureLevel)reader.ReadInt(); var content = DefaultContent; var flags = (OldSaveFlags)reader.ReadEncodedInt(); if ((flags & OldSaveFlags.Title) != 0) { _title = reader.ReadString().Intern(); } else if (content != null) { _title = content.Title; } if ((flags & OldSaveFlags.Author) != 0) { _author = reader.ReadString(); } else if (content != null) { _author = content.Author; } Writable = (flags & OldSaveFlags.Writable) != 0; if ((flags & OldSaveFlags.Content) != 0) { Pages = new BookPageInfo[reader.ReadEncodedInt()]; for (var i = 0; i < Pages.Length; ++i) { Pages[i] = new BookPageInfo(reader); } } else { Pages = content?.Copy() ?? Array.Empty(); } } public override void AddNameProperty(IPropertyList list) { if (!string.IsNullOrEmpty(_title)) { list.Add(_title); } else { base.AddNameProperty(list); } } /*public override void GetProperties( ObjectPropertyList list ) { base.GetProperties( list ); if (_title?.Length > 0) list.Add( 1060658, "Title\t{0}", _title ); // ~1_val~: ~2_val~ if (_author?.Length > 0) list.Add( 1060659, "Author\t{0}", _author ); // ~1_val~: ~2_val~ if (_pages?.Length > 0) list.Add( 1060660, "Pages\t{0}", _pages.Length ); // ~1_val~: ~2_val~ }*/ public override void OnSingleClick(Mobile from) { LabelTo(from, $"{_title} by {_author}"); LabelTo(from, $"[{_pages.Length} pages]"); } public override void OnDoubleClick(Mobile from) { if (_title == null && _author == null && Writable) { Title = "a book"; Author = from.Name; } from.NetState.SendBookCover(from, this); from.NetState.SendBookContent(this); } [Flags] private enum OldSaveFlags { None = 0x00, Title = 0x01, Author = 0x02, Writable = 0x04, Content = 0x08 } } }