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 2.0] ReadBookFromTxt.cs Convert text files to RunUO book scripts

Lokai

Knight
[RunUO 2.0] ReadBookFromTxt.cs Convert text files to RunUO book scripts

/*********** ReadBookFromTxt.cs ***********
*
* (C) 2008, Lokai
*
* Description: Command that allows you
* to read a text file book into a
* script for RunUO that can be used
* in the game.
*
* Usage: ReadBookFrom {filename}
* {filename} is optional. If given,
* it will read the text file located
* at Data/Books/{filename}. If not
* given, it will use the file at
* Data/Books/default.txt
*
* Input: Text file must have the first
* line be the title, the second line
* be the author, and the rest be the
* body of the book. Quotes in the
* text should be written like this:
* He said, \"I will not go!\"
* Blank lines are ignored. Too many
* special characters in the title
* might cause the script to fail.
*
* Output: New scripts are saved as the
* title of the book, without spaces
* or special characters. Filenames
* are the name of the class plus
* the .cs extension. Files are
* saved to the Data/Books/ folder.
*
*******************************************/

Included in the zip file is an example text file I was able to successfully read and convert to a book script. It is only included to give you an idea of how your text files can look. Notice that line lengths are varied, and there are some blank lines.

UPDATE 5/3/2008 1:42PM EDT: Please download the latest zip. I fixed the error when using the command without the {filename} specified.
 

Attachments

  • ReadBookFromTxt.zip
    14.7 KB · Views: 140
  • ReadBookFromTxt-704pm.zip
    14.7 KB · Views: 140
Question, soon as I use the command ReadBookFrom, the server crashes. I have the included text file in data/books. Suggestions?

here is crash log:

Server Crash Report
===================

RunUO Version 2.0, Build 2959.20979
Operating System: Microsoft Windows NT 5.1.2600 Service Pack 2
.NET Framework: 2.0.50727.1433
Time: 5/3/2008 12:47:35 PM
Mobiles: 3973
Items: 197444
Exception:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at Server.Custom.ReadBookFromTxt.ReadBookFrom_OnCommand(CommandEventArgs e)
at Server.Commands.CommandSystem.Handle(Mobile from, String text, MessageType type)
at Server.Mobile.DoSpeech(String text, Int32[] keywords, MessageType type, Int32 hue)
at Server.Mobiles.PlayerMobile.DoSpeech(String text, Int32[] keywords, MessageType type, Int32 hue)
at Server.Network.PacketHandlers.UnicodeSpeech(NetState state, PacketReader pvSrc)
at Server.Network.MessagePump.HandleReceive(NetState ns)
at Server.Network.MessagePump.Slice()
at Server.Core.Main(String[] args)

Clients:
- Count: 1
+ 66.66.89.206: (account = Gotzhaus Tur) (mobile = 0x22 'GM Tur')
 

Lokai

Knight
Sorry about that.

Did you by any chance use the command without specifying the name of the file?
 

Lokai

Knight
NEW FILE RELEASED:

Please download the latest zip. I fixed the error when using the command without the {filename} specified.
 

datguy

Sorceror
I got it to work
[readbookfrom Illiad.txt


if I don't put in the .txt or have nothing after the command it crashes
 

Lokai

Knight
Strange, I tried it with and without the filename, and it worked. It also worked when I put a filename there that did not exist. It just politely tells me "Bad File Name".

Did you both download the file again and replace the previous one?
 

datguy

Sorceror
I had no previous, I downloaded from top post 5 min before I posted :)
Did your upload work?
Code:
/*********** ReadBookFromTxt.cs ***********
 *
 *            (C) 2008, Lokai
 * 
 * Description: Command that allows you
 *      to read a text file book into a
 *      script for RunUO that can be used
 *      in the game.
 * 
 * Usage: ReadBookFrom {filename}
 *      {filename} is optional. If given,
 *      it will read the text file located
 *      at Data/Books/{filename}. If not 
 *      given, it will use the file at
 *      Data/Books/default.txt
 * 
 * Input: Text file must have the first
 *      line be the title, the second line
 *      be the author, and the rest be the
 *      body of the book. Quotes in the 
 *      text should be written like this:
 *          He said, \"I will not go!\"
 *      Blank lines are ignored. Too many
 *      special characters in the title
 *      might cause the script to fail.
 * 
 * Output: New scripts are saved as the
 *      title of the book, without spaces
 *      or special characters. Filenames
 *      are the name of the class plus
 *      the .cs extension. Files are
 *      saved to the Data/Books/ folder.
 *
 *******************************************/

/***************************************************************************
 *
 *   This program 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 2 of the License, or
 *   (at your option) any later version.
 *
 ***************************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Collections;
using Server.Items;
using Server.Misc;
using Server.Commands;
using Server.Network;

namespace Server.Custom
{
    public enum ReadStatus
    {
        None, Closed, Open, BadFile, IO_Error, EOF, Finished
    }

    public class ReadBookFromTxt
    {
        public static void Initialize()
        {
            CommandSystem.Register("ReadBookFrom", AccessLevel.Administrator, new CommandEventHandler(ReadBookFrom_OnCommand));
        }

        private const string m_DefaultFile = "default.txt";

        [Usage("ReadBookFrom {filename}")]
        [Description("Reads the specified book.")]
        public static void ReadBookFrom_OnCommand(CommandEventArgs e)
        {
            Console.WriteLine("ReadBookFrom Command given."); 

            m_Lines = new List<string>();
            string filename = e.GetString(0);

            if (string.IsNullOrEmpty(filename))
            {
                Console.WriteLine("No text file specified, so will use '{0}'.", m_DefaultFile);
                filename = m_DefaultFile;
            }
            ReadStatus newReader = ReadBook(filename);

            m_BookStream.Close();
            char[] badchars = new char[] { '.', ';', '{', '}', '=', '+', '-', '(', ')', '?', '/',
                    '!', '@', '#', '$', '%', '^', '&', '*', ':', '<', '>' };

            switch (newReader)
            {
                case ReadStatus.BadFile: 
                    Console.WriteLine("Bad filename specified."); 
                    break;

                case ReadStatus.Finished:
                    string[] words = m_Title.Split(' ');
                    for (int x = 0; x < words.Length;x++)
                    {
                        if (words[x].IndexOfAny(badchars) >= 0)
                            words[x] = words[x].Remove(words[x].IndexOfAny(badchars), 1);
                    }
                    string fname = string.Concat(words);
                    Console.WriteLine("Read Successful. {0} lines were read.", m_Lines.Count);
                    if (WriteBook(fname))
                        Console.WriteLine("Write Successful.");
                    else
                        Console.WriteLine("Write Failed.");
                    break;

                case ReadStatus.IO_Error:
                    for (int x = 0; x < m_Lines.Count; x++)
                        CommandLogging.WriteLine(e.Mobile, m_Lines[x]);
                    Console.WriteLine("IO Error detected. {0} lines written to Command Log.", m_Lines.Count);
                    break;

                case ReadStatus.Open:
                    for (int x = 0; x < m_Lines.Count; x++)
                        CommandLogging.WriteLine(e.Mobile, m_Lines[x]);
                    Console.WriteLine("Read Interrupted. {0} lines written to Command Log.", m_Lines.Count);
                    break;

                default:
                    Console.WriteLine("Unknown error occurred.");
                    break;
            }
        }

        private static StreamReader m_BookStream;
        private static string[] m_PageText;
        private static List<string> m_Lines;
        private static string m_Title;
        private static string m_Author;

        public static ReadStatus ReadBook(string filename)
        {
            ReadStatus read = ReadStatus.None;
            string book = "Data/Books/" + filename;
            List<string> nextLines = new List<string>();

            if (File.Exists(book))
            {
                try
                {
                    m_BookStream = new StreamReader(book, Encoding.Default, false);
                    read = ReadStatus.Open;
                }
                catch { read = ReadStatus.IO_Error; }
                finally
                {
                    m_Title = m_BookStream.ReadLine();
                    m_Author = m_BookStream.ReadLine();

                    while (read == ReadStatus.Open)
                    {
                        try
                        {
                            nextLines = ReadLines();
                        }
                        catch { read = ReadStatus.IO_Error; }
                        finally
                        {
                            for (int x = 0; x < nextLines.Count; x++)
                            {
                                m_Lines.Add(nextLines[x]);
                            }
                        }
                        if (m_BookStream.EndOfStream) read = ReadStatus.EOF;
                    }
                    if (read == ReadStatus.EOF) read = ReadStatus.Finished;
                }
            }
            else
            {
                read = ReadStatus.BadFile;
            }

            return read;
        }

        public static List<string> ReadLines()
        {
            List<string> lines = new List<string>();
            string line = m_BookStream.ReadLine();
            line.TrimEnd(' ');

            string[] words = line.Split(' ');
            string templine = words[0];
            bool linefull = true;

            for (int x = 1; x < words.Length; x++)
            {
                linefull = false;
                if (templine == TryAddWord(templine, words[x]))
                {
                    lines.Add(templine);
                    templine = words[x];
                    if (x == words.Length - 1 && words[x] != "")
                        linefull = false;
                    else
                        linefull = true;
                }
                else
                {
                    templine = TryAddWord(templine, words[x]);
                    linefull = false;
                }
            }
            if (!linefull) lines.Add(templine);
            return lines;
        }

        public static bool WriteBook(string fname)
        {
            string filename = "Data/Books/" + fname + ".cs";
            string line = "";
            string output = "";
            bool write = true;

            FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write);
            StreamWriter sw = new StreamWriter(fs);
            StringBuilder sb = new StringBuilder("");

            int pages = m_Lines.Count / 8;
            int left = m_Lines.Count % 8;
            int count = 0;

            try
            {
                for (int x = 0; x < pages; x++)
                {
                    line = string.Format(NewBookPageTemplate, m_Lines[count++],
                        m_Lines[count++], m_Lines[count++], m_Lines[count++], m_Lines[count++],
                        m_Lines[count++], m_Lines[count++], m_Lines[count++]);
                    sb.Append(line);
                    if (x < pages - 1 || left > 0) sb.Append(",");
                }
                switch (left)
                {
                    case 7: line = string.Format(NewBookPageTemplate, m_Lines[count++],
                        m_Lines[count++], m_Lines[count++], m_Lines[count++], m_Lines[count++],
                        m_Lines[count++], m_Lines[count++], "");
                        sb.Append(line);
                        break;
                    case 6: line = string.Format(NewBookPageTemplate, m_Lines[count++],
                        m_Lines[count++], m_Lines[count++], m_Lines[count++], m_Lines[count++],
                        m_Lines[count++], "", "");
                        sb.Append(line);
                        break;
                    case 5: line = string.Format(NewBookPageTemplate, m_Lines[count++],
                        m_Lines[count++], m_Lines[count++], m_Lines[count++], m_Lines[count++],
                        "", "", "");
                        sb.Append(line);
                        break;
                    case 4: line = string.Format(NewBookPageTemplate, m_Lines[count++],
                        m_Lines[count++], m_Lines[count++], m_Lines[count++], 
                        "\"\"", "\"\"", "\"\"", "\"\"");
                        sb.Append(line);
                        break;
                    case 3: line = string.Format(NewBookPageTemplate, m_Lines[count++],
                        m_Lines[count++], m_Lines[count++], "", "", "", "", "");
                        sb.Append(line);
                        break;
                    case 2: line = string.Format(NewBookPageTemplate, m_Lines[count++],
                        m_Lines[count++], "", "", "", "", "", "");
                        sb.Append(line);
                        break;
                    case 1: line = string.Format(NewBookPageTemplate, m_Lines[count++],
                        "", "", "", "", "", "", "");
                        sb.Append(line);
                        break;
                    default: break;
                }

                output = BookTemplate.Replace("{name}", fname);
                output = output.Replace("{title}", m_Title);
                output = output.Replace("{author}", m_Author);
                output = output.Replace("{pages}", sb.ToString());
            }
            catch(Exception e) { Console.Write(e.ToString()); write = false; }
            finally
            {
                try
                {
                    sw.Write(output);
                }
                catch (Exception e) { Console.Write(e.ToString()); write = false; }
            }
            sw.Close();
            fs.Close();
            return write;
        }

        public static string TryAddWord(string line, string word)
        {
            string newline = line;
            if (line.Length + word.Length <= 22)
                newline += " " + word;
            return newline;
        }
        
        public const string BookTemplate = @"//////////////////////////////////////////////
//
// {title} by {author}
//
// Created using Lokai's ReadBookFromTxt.cs
//
//////////////////////////////////////////////
using System;
using Server;

namespace Server.Items
{
	public class {name} : BaseBook
	{
		public static readonly BookContent Content = new BookContent
			(
				""{title}"", ""{author}"", {pages}
			);

		public override BookContent DefaultContent{ get{ return Content; } }

		[Constructable]
		public {name}() : base( Utility.Random( 0xFEF, 2 ), false )
		{
		}

		public {name}( Serial serial ) : base( serial )
		{
		}

		public override void Serialize( GenericWriter writer )
		{
			base.Serialize( writer );

			writer.WriteEncodedInt( (int) 0 ); // version
		}

		public override void Deserialize( GenericReader reader )
		{
			base.Deserialize( reader );

			int version = reader.ReadEncodedInt();
		}
	}
}";
        public const string NewBookPageTemplate = @"
				new BookPageInfo
				(
					""{0}"",
					""{1}"",
					""{2}"",
					""{3}"",
					""{4}"",
					""{5}"",
					""{6}"",
					""{7}""
				)";
    }
}
 

Lokai

Knight
Yes. I checked the file again, and it's fine. I don't understand how you got a crash, when it has a check for correct values and try/catch blocks.
 

datguy

Sorceror
This is with command only
Code:
Server Crash Report
===================

RunUO Version 2.0, Build 2702.22364
Operating System: Microsoft Windows NT 5.1.2600 Service Pack 2
.NET Framework: 2.0.50727.1433
Time: 5/3/2008 5:01:26 PM
Mobiles: 11411
Items: 327990
Exception:
System.NullReferenceException: Object reference not set to an instance of an object.
   at Server.Custom.ReadBookFromTxt.ReadBookFrom_OnCommand(CommandEventArgs e) in e:\OasisSVN\Scripts\Custom\ReadBookFromTxt\ReadBookFromTxt.cs:line 86
   at Server.Commands.CommandSystem.Handle(Mobile from, String text, MessageType type)
   at Server.Mobile.DoSpeech(String text, Int32[] keywords, MessageType type, Int32 hue)
   at Server.Mobiles.PlayerMobile.DoSpeech(String text, Int32[] keywords, MessageType type, Int32 hue) in e:\OasisSVN\Scripts\Mobiles\PlayerMobile.cs:line 2313
   at Server.Engines.PartySystem.Chat3Guild.UnicodeSpeechChat3(NetState state, PacketReader pvSrc) in e:\OasisSVN\Scripts\Custom\Knives Chat\Knives Chat 3.0 Beta 9\General\Chat3Guild.cs:line 122
   at Server.Network.MessagePump.HandleReceive(NetState ns)
   at Server.Network.MessagePump.Slice()
   at Server.Core.Main(String[] args)

Clients:
- Count: 1
 

Lokai

Knight
datguy;754480 said:
This is with command only
Code:
Server Crash Report
===================
 
RunUO Version 2.0, Build 2702.22364
Operating System: Microsoft Windows NT 5.1.2600 Service Pack 2
.NET Framework: 2.0.50727.1433
Time: 5/3/2008 5:01:26 PM
Mobiles: 11411
Items: 327990
Exception:
System.NullReferenceException: Object reference not set to an instance of an object.
   at Server.Custom.ReadBookFromTxt.ReadBookFrom_OnCommand(CommandEventArgs e) in e:\OasisSVN\Scripts\Custom\ReadBookFromTxt\ReadBookFromTxt.cs:line 86
   at Server.Commands.CommandSystem.Handle(Mobile from, String text, MessageType type)
   at Server.Mobile.DoSpeech(String text, Int32[] keywords, MessageType type, Int32 hue)
   at Server.Mobiles.PlayerMobile.DoSpeech(String text, Int32[] keywords, MessageType type, Int32 hue) in e:\OasisSVN\Scripts\Mobiles\PlayerMobile.cs:line 2313
   at Server.Engines.PartySystem.Chat3Guild.UnicodeSpeechChat3(NetState state, PacketReader pvSrc) in e:\OasisSVN\Scripts\Custom\Knives Chat\Knives Chat 3.0 Beta 9\General\Chat3Guild.cs:line 122
   at Server.Network.MessagePump.HandleReceive(NetState ns)
   at Server.Network.MessagePump.Slice()
   at Server.Core.Main(String[] args)
 
Clients:
- Count: 1

Thank you for running in debug mode, you told me exactly what line was causing the error. It is now fixed. Please download the latest version above.
 

datguy

Sorceror
Ok, that worked nicely.
If I didn't do it correctly I got console message 'Bad Filename Specified'

Would it be possible to get that ingame, even though Admins could make the book script at home & upload the finished script so not a big deal really.


Great Job
 
to have the message in game would be just a minoe change

where the "consol write line is in there - just change it to
from.SendMessage("message words");
and change the "from" to how ever it is in there for the person calling the command is being called
and how ever the mesage area is in the script replace ("message words"); with that

(i have not downloaded the script, but that is hoiw it would be done)
 

datguy

Sorceror
Ah yes, now that I look at it I realize the minority of it:D

was in 15 other scripts & tested this one onthefly:p
 

nadious

Sorceror
This is PERFECT. This is EXACTLY what I need for my upcoming quest / event. I've tried making books other ways and had trouble with it... this is JUST WHAT I NEED.

Talk about timing!

Thanks!
 
I know this is an old thread, but for those using this who dont want to have to go through and escape all the quotation marks, find a unicode version of the book, the opening and closing unicode quotes dont have to be escaped. Anyways, this is very useful, been looking for something like this for quite some time.
 

duponthigh

Sorceror
Was wondering if there was a way i can do this without haven to restart the server to get the book to show ingame?Also How would u go about being able to right in the book and it save your changes can this be done? Awsome Script Love your work.You do put the Script in the custom folder right also.I had to make a folder in Data Folder called Books Hope this is correct?
 

Lokai

Knight
The purpose of this is to convert plain text files to c-sharp scripts that can be used in game. As far as I know, you will need to restart for it to load those c-sharp scripts into the game. It does not matter what folder you put the c-sharp files, but yes, the text files you are reading should be in the Books folder. The other thing is that once you have converted it to a script, that script can be shared with anyone's server, and of course they do NOT need the original text file, as the script file is completely independent.
 
Top