EN UO Topic books - LIHACHTETAN/ClassicUO-Bad-Newbie-CSharp-Scripts-IDE GitHub Wiki
Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
Home · C# · IDE · UO API · A–Z · Examples · Languages
Reading and editing game books: title, pages and text. See the card for valid page numbers and recording effect.
| Topic | Commands and explanations |
|---|---|
| Read Page | UO.BookGetPageText |
| Set Page | UO.BookSetPageText |
| Set Header | UO.BookSetHeader |
| Set Text | UO.BookSetText |
| Clear Text | UO.BookClearText |
UO.BookGetPageText · UO.BookSetPageText · UO.BookSetHeader · UO.BookSetText · UO.BookClearText
Each command card has several independent scenarios: direct code, functions and classes. Below are selected short scenarios; restrictions and full analysis are in the cards.
Parameters, result and all scenarios
var text = UO.BookGetPageText(1);
if (Truth(text != ""))
{
UO.Print(text);
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters, result and all scenarios
UO.BookSetPageText(2, "Camp A");Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
void UO.BookClearText();Removes text from all pages of an open editable book, preserving the title and author.
There are no parameters.
void - no value. This is a write request, not true/false or a server confirmation. The server may prohibit editing.
- First, open the desired book using a game action. The commands use the last opened book: ID book is not accepted. If you have multiple books, make sure you select the right one. Get reads already loaded pages and does not itself request the missing page.
- In the manager, the contents of the book are stored in the session and are available without graphics. Closing the game window saves the book and draft, opening it again restores them. Closing a workbook itself removes it from open workbooks; breaking the connection resets the server books.
- Changes are only available for the book you are editing. Invalid page or text that is too long is rejected. BookSetText checks all pages before first submission: an erroneous late page does not cause a partial write.
- BookClearText sends empty text for each page. This destroys the previous text of the book; use on your edited copy. The title and author remain the same.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The command is a separate statement. The message before it marks the start of the call; it does not confirm a server action.
UO.Print("Calling UO.BookClearText");
UO.BookClearText();Parameters and execution flow:
- All examples assume that the required book is already open, the required pages have been received, and the book is being edited for recording. The numbers 1, 2 and 3 are page numbers; make sure they exist. Text/names are for demonstration purposes.
UO.BookClearText();Parameters and execution flow:
- All examples assume that the required book is already open, the required pages have been received, and the book is being edited for recording. The numbers 1, 2 and 3 are page numbers; make sure they exist. Text/names are for demonstration purposes.
return RunScenario();
object? RunScenario()
{
UO.BookClearText();
UO.BookSetHeader("New expedition", "Alice");
UO.BookSetPageText(1, "Bring bandages");
return null;
}Parameters and execution flow:
- All examples assume that the required book is already open, the required pages have been received, and the book is being edited for recording. The numbers 1, 2 and 3 are page numbers; make sure they exist. Text/names are for demonstration purposes.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
ResetNotebook("Supply list", "Alice", "Bandages" + Chr(10) + "Food");
return null;
}
void ResetNotebook(dynamic title, dynamic author, dynamic firstPage)
{
UO.BookClearText();
UO.BookSetHeader(title, author);
UO.BookSetPageText(1, firstPage);
}
string Chr(object? value) => ((char)Convert.ToInt32(value)).ToString();
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: No parameters.
Result: void / Unit.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.BookClearText:bridge.BookClearText().
Internal implementation code; this is not a standalone script.
case "bookcleartext":
state.BookPages.Clear();
bridge.BookClearText();
return InjectionValue.Unit;Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.BookGetPageText(object? page);Reads the text of one page of the last opened book.
-
page— Page number from 1, not a serial book. The upper limit is the number of pages reported by the server.
string — page lines separated by a newline character, without empty lines at the end. An empty string is also returned if the workbook is not open, the page has not yet been received, or the number is incorrect. This is not an indication that the page exists or is writable.
- First, open the desired book using a game action. The commands use the last opened book: ID book is not accepted. If you have multiple books, make sure you select the right one. Get reads already loaded pages and does not itself request the missing page.
- In the manager, the contents of the book are stored in the session and are available without graphics. Closing the game window saves the book and draft, opening it again restores them. Closing a workbook itself removes it from open workbooks; breaking the connection resets the server books.
- Changes are only available for the book you are editing. Invalid page or text that is too long is rejected. BookSetText checks all pages before first submission: an erroneous late page does not cause a partial write.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The result of one call is printed in the journal. A number is not converted to bool; an array is displayed as its element count.
object? result = UO.BookGetPageText(1);
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameters and execution flow:
- All examples assume that the required book is already open, the required pages have been received, and the book is being edited for recording. The numbers 1, 2 and 3 are page numbers; make sure they exist. Text/names are for demonstration purposes.
var text = UO.BookGetPageText(1);
if (Truth(text != ""))
{
UO.Print(text);
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- All examples assume that the required book is already open, the required pages have been received, and the book is being edited for recording. The numbers 1, 2 and 3 are page numbers; make sure they exist. Text/names are for demonstration purposes.
return RunScenario();
object? RunScenario()
{
var firstPage = UO.BookGetPageText(1);
if (Truth(firstPage != ""))
{
UO.BookSetPageText(3, firstPage);
}
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;Parameters and execution flow:
- All examples assume that the required book is already open, the required pages have been received, and the book is being edited for recording. The numbers 1, 2 and 3 are page numbers; make sure they exist. Text/names are for demonstration purposes.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
ReplaceCampNote(2);
return null;
}
void ReplaceCampNote(dynamic page)
{
var text = UO.BookGetPageText(page);
if (Truth(text == "Camp A"))
{
UO.BookSetPageText(page, "Camp B");
}
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: page (Any)
Result: dynamic / Any.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.BookGetPageText:bridge.BookGetPageText(pageNumber).
Internal implementation code; this is not a standalone script.
case "bookgetpagetext":
{
int pageNumber = Math.Max(1, Arg(0));
string liveText = bridge.BookGetPageText(pageNumber);
if (!string.IsNullOrEmpty(liveText))
return new InjectionValue(liveText);
int page = pageNumber - 1;
return new InjectionValue(page < state.BookPages.Count ? state.BookPages[page] : string.Empty);
}Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
void UO.BookSetHeader(object? title, object? author);Specifies the title and author of the open editable book.
-
title— Title; The graphic editor and command save the first 47 characters. -
author— Author; The first 29 characters are saved.
void - no value. This is a write request, not true/false or a server confirmation. The server may prohibit editing.
- First, open the desired book using a game action. The commands use the last opened book: ID book is not accepted. If you have multiple books, make sure you select the right one. Get reads already loaded pages and does not itself request the missing page.
- In the manager, the contents of the book are stored in the session and are available without graphics. Closing the game window saves the book and draft, opening it again restores them. Closing a workbook itself removes it from open workbooks; breaking the connection resets the server books.
- Changes are only available for the book you are editing. Invalid page or text that is too long is rejected. BookSetText checks all pages before first submission: an erroneous late page does not cause a partial write.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The command is a separate statement. The message before it marks the start of the call; it does not confirm a server action.
UO.Print("Calling UO.BookSetHeader");
UO.BookSetHeader("Mining route", "Alice");Parameters and execution flow:
- All examples assume that the required book is already open, the required pages have been received, and the book is being edited for recording. The numbers 1, 2 and 3 are page numbers; make sure they exist. Text/names are for demonstration purposes.
UO.BookSetHeader("Mining route", "Alice");Parameters and execution flow:
- All examples assume that the required book is already open, the required pages have been received, and the book is being edited for recording. The numbers 1, 2 and 3 are page numbers; make sure they exist. Text/names are for demonstration purposes.
return RunScenario();
object? RunScenario()
{
var route = "Northern mine";
var author = "Alice";
UO.BookSetHeader("Route: " + route, author);
return null;
}Parameters and execution flow:
- All examples assume that the required book is already open, the required pages have been received, and the book is being edited for recording. The numbers 1, 2 and 3 are page numbers; make sure they exist. Text/names are for demonstration purposes.
- The auxiliary function is shown in its entirety. Its true means only performing a local check and call; it does not return confirmation of the recording by the server.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var requested = SetNotebookHeader("Supply list", "Alice");
return null;
}
dynamic SetNotebookHeader(dynamic title, dynamic author)
{
if (Truth(Len(title) > 47) || Truth(Len(author) > 29))
{
return false;
}
UO.BookSetHeader(title, author);
return true;
}
int Len(object? value) => Convert.ToString(value)?.Length ?? 0;
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: title (Any), author (Any)
Result: void / Unit.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Text:Text(0). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.BookSetHeader:bridge.BookSetHeader(state.BookTitle, state.BookAuthor).
Internal implementation code; this is not a standalone script.
case "booksetheader":
state.BookTitle = Text(0);
state.BookAuthor = Text(1);
bridge.BookSetHeader(state.BookTitle, state.BookAuthor);
return InjectionValue.Unit;Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
void UO.BookSetPageText(object? page, object? text);Replaces the text of one page of an open editable book.
-
page— Page number from 1, not a serial book. The upper limit is the number of pages reported by the server. -
text— Text. The lines are separated by Chr(10); Chr(13) is removed. Up to 10 lines per page and 53 characters per line. The null character is prohibited.
void - no value. This is a write request, not true/false or a server confirmation. The server may prohibit editing.
- First, open the desired book using a game action. The commands use the last opened book: ID book is not accepted. If you have multiple books, make sure you select the right one. Get reads already loaded pages and does not itself request the missing page.
- In the manager, the contents of the book are stored in the session and are available without graphics. Closing the game window saves the book and draft, opening it again restores them. Closing a workbook itself removes it from open workbooks; breaking the connection resets the server books.
- Changes are only available for the book you are editing. Invalid page or text that is too long is rejected. BookSetText checks all pages before first submission: an erroneous late page does not cause a partial write.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The command is a separate statement. The message before it marks the start of the call; it does not confirm a server action.
UO.Print("Calling UO.BookSetPageText");
UO.BookSetPageText(2, "Camp A");Parameters and execution flow:
- All examples assume that the required book is already open, the required pages have been received, and the book is being edited for recording. The numbers 1, 2 and 3 are page numbers; make sure they exist. Text/names are for demonstration purposes.
UO.BookSetPageText(2, "Camp A");Parameters and execution flow:
- All examples assume that the required book is already open, the required pages have been received, and the book is being edited for recording. The numbers 1, 2 and 3 are page numbers; make sure they exist. Text/names are for demonstration purposes.
return RunScenario();
object? RunScenario()
{
UO.BookSetPageText(1, "Supplies" + Chr(10) + "Bandages" + Chr(10) + "Food");
return null;
}
string Chr(object? value) => ((char)Convert.ToInt32(value)).ToString();Parameters and execution flow:
- All examples assume that the required book is already open, the required pages have been received, and the book is being edited for recording. The numbers 1, 2 and 3 are page numbers; make sure they exist. Text/names are for demonstration purposes.
- The auxiliary function is shown in its entirety. Its true means only performing a local check and call; it does not return confirmation of the recording by the server.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
var requested = AppendNote(1, "Return before night");
return null;
}
dynamic AppendNote(dynamic page, dynamic line)
{
if (Truth(Len(line) > 53))
{
return false;
}
var previous = UO.BookGetPageText(page);
if (Truth(previous == ""))
{
UO.BookSetPageText(page, line);
return true;
}
var lineCount = 1;
for (int index = (int)(1); index <= Len(previous); index += (int)(1))
{
if (Truth(Mid(previous, index, 1) == Chr(10)))
{
lineCount = lineCount + 1;
}
}
if (Truth(lineCount >= 10))
{
return false;
}
UO.BookSetPageText(page, previous + Chr(10) + line);
return true;
}
string Chr(object? value) => ((char)Convert.ToInt32(value)).ToString();
int Len(object? value) => Convert.ToString(value)?.Length ?? 0;
string Mid(object? value, int start, int length = int.MaxValue)
{
string text = Convert.ToString(value) ?? "";
int offset = Math.Clamp(start - 1, 0, text.Length);
return text.Substring(offset, Math.Min(Math.Max(0, length), text.Length - offset));
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: page (Any), text (Any)
Result: void / Unit.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Arg:Arg(0). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Text:Text(1). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.BookSetPageText:bridge.BookSetPageText(page + 1, state.BookPages[page]).
Internal implementation code; this is not a standalone script.
case "booksetpagetext":
{
int page = Math.Max(0, Arg(0) - 1);
while (state.BookPages.Count <= page) state.BookPages.Add(string.Empty);
state.BookPages[page] = Text(1);
bridge.BookSetPageText(page + 1, state.BookPages[page]);
return InjectionValue.Unit;
}Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
void UO.BookSetText(object? text);Writes text from the first page of an open editable book.
-
text— Text. The lines are separated by Chr(10); Chr(13) is removed. Up to 10 lines per page and 53 characters per line. The null character is prohibited.
void - no value. This is a write request, not true/false or a server confirmation. The server may prohibit editing.
- First, open the desired book using a game action. The commands use the last opened book: ID book is not accepted. If you have multiple books, make sure you select the right one. Get reads already loaded pages and does not itself request the missing page.
- In the manager, the contents of the book are stored in the session and are available without graphics. Closing the game window saves the book and draft, opening it again restores them. Closing a workbook itself removes it from open workbooks; breaking the connection resets the server books.
- Changes are only available for the book you are editing. Invalid page or text that is too long is rejected. BookSetText checks all pages before first submission: an erroneous late page does not cause a partial write.
- BookSetText: Chr(12) explicitly separates pages. If Chr(12) is not present, every 10 lines form a page. The remaining old pages are not cleared: to completely replace them, first call BookClearText separately. Blank text replaces only the first page.
Each example can be saved as a separate file .csx and run in IDE. The UO object and wait functions provide the host of the current game session. Replace demo serial names, coordinates and addresses with your own.
Run this code as a separate .csx file. Arguments appear directly in the call; replace demonstration names, serials and addresses with your own.
The command is a separate statement. The message before it marks the start of the call; it does not confirm a server action.
UO.Print("Calling UO.BookSetText");
UO.BookSetText("Camp A\nReturn home");Parameters and execution flow:
- All examples assume that the required book is already open, the required pages have been received, and the book is being edited for recording. The numbers 1, 2 and 3 are page numbers; make sure they exist. Text/names are for demonstration purposes.
UO.BookSetText("Mining route" + Chr(10) + "Start at camp");
string Chr(object? value) => ((char)Convert.ToInt32(value)).ToString();Parameters and execution flow:
- All examples assume that the required book is already open, the required pages have been received, and the book is being edited for recording. The numbers 1, 2 and 3 are page numbers; make sure they exist. Text/names are for demonstration purposes.
return RunScenario();
object? RunScenario()
{
UO.BookSetText("Camp A" + Chr(12) + "Camp B" + Chr(12) + "Return home");
return null;
}
string Chr(object? value) => ((char)Convert.ToInt32(value)).ToString();Parameters and execution flow:
- All examples assume that the required book is already open, the required pages have been received, and the book is being edited for recording. The numbers 1, 2 and 3 are page numbers; make sure they exist. Text/names are for demonstration purposes.
return new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
class ScriptScenario
{
private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
private readonly Func<int, Task> WaitAsync;
private readonly string[] Args;
private readonly CancellationToken Cancellation;
private readonly Action Checkpoint;
public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
{
UO = api;
WaitAsync = wait;
Args = args;
Cancellation = cancellation;
Checkpoint = checkpoint;
}
public object? RunScenario()
{
WriteRoute("Northern mine", "Bring bandages");
return null;
}
void WriteRoute(dynamic destination, dynamic supplies)
{
var firstPage = "Destination" + Chr(10) + destination;
var secondPage = "Supplies" + Chr(10) + supplies;
UO.BookSetText(firstPage + Chr(12) + secondPage);
}
string Chr(object? value) => ((char)Convert.ToInt32(value)).ToString();
}C# is case sensitive. Use the exact UO name. Compare numeric flags with 0; use bool only where the signature returns bool.
Parameters: text (Any)
Result: void / Unit.
During a call:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Text:Text(0). -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.BookSetText:bridge.BookSetText(bookText).
Internal implementation code; this is not a standalone script.
case "booksettext":
{
string bookText = Text(0) ?? string.Empty;
state.BookPages.Clear();
state.BookPages.AddRange(bookText.Split(new[] { '\f' }, StringSplitOptions.None));
bridge.BookSetText(bookText);
return InjectionValue.Unit;
}