Repository navigation
DE UO Topic http
Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
Home · C# · IDE · UO API · A–Z · Beispiele · Sprachen
HTTP-Abfragen und Lesen der Antwort. Der Statuscode, der Header und der Antworttext sind separate Daten.
| Thema | Befehle und Erklärungen |
|---|---|
| HTTP_Get | UO.HTTP_Get |
| HTTP_Post | UO.HTTP_Post |
| HTTP_Header | UO.HTTP_Header |
| HTTP_Body | UO.HTTP_Body |
| Externe Nachrichten | UO.Messenger – Telegram, Discord und Viber |
UO.HTTP_Get · UO.HTTP_Post · UO.HTTP_Header · UO.HTTP_Body
Jede Befehlskarte verfügt über mehrere unabhängige Szenarien: Direktcode, Funktionen und Klassen. Nachfolgend finden Sie ausgewählte kurze Szenarien; Einschränkungen und eine vollständige Analyse sind geplant.
Parameter, Ergebnis und alle Szenarien
UO.HTTP_Get("https://example.com/csharp-config.json");
try
{
string body = Convert.ToString(UO.HTTP_Body()) ?? "";
using (var document = System.Text.Json.JsonDocument.Parse(body))
{
if (document.RootElement.TryGetProperty("minMana", out var value) &&
value.TryGetInt32(out int threshold) && threshold is >= 0 and <= 100)
return threshold;
}
}
catch (System.Text.Json.JsonException)
{
UO.Print("Response is not a valid configuration; using the default.");
}
return 30;Parameter, Ergebnis und alle Szenarien
UO.HTTP_Get("https://example.com/C#-permission");
var permission = TrimText(UO.HTTP_Body());
return Truth(permission == "allow");
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
string TrimText(object? value) => (Convert.ToString(value) ?? "").Trim();Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.HTTP_Body();Liest den Text der letzten HTTP-Antwort dieses Skripts. Nach HTTP_Get können Sie beispielsweise JSON mit Einstellungen analysieren oder die Antwort Ihres Dienstes mit der erwarteten Zeichenfolge vergleichen. Die Lesung selbst geht nicht ins Netzwerk.
Es gibt keine Parameter.
string – gespeicherter Text. Vor der ersten Anfrage in dieser Laufzeit, nach GET im Stream und nach dem Netzwerkfehler – eine Leerzeile. Eine normale Antwort hat auch einen leeren Textkörper, zum Beispiel HTTP 204. Vergleichen Sie das Ergebnis nicht mit true/false als Hinweis auf die Lieferung.
- Die letzte Antwort wird nur in der aktuellen Laufzeit des Skripts gespeichert. Das nächste GET/POST dieser Laufzeit ersetzt es; Andere gleichzeitig laufende Skripte ändern daran nichts. Die Antwort wird nicht im Profil gespeichert. Wenn Sie es nach der nächsten Anfrage benötigen, kopieren Sie den Text und die Header vorab in Variablen.
- GET/POST Warten Sie auf eine Antwort im laufenden Skript-Thread. Die Gesamtzeit für das Anfordern und Lesen des Körpers beträgt 20 Sekunden. Durch Stoppen des Skripts wird die Wartezeit abgebrochen. HTTP_Body/HTTP_Header erwarte nichts. Der gesamte Körper wird in den Speicher geladen, auch wenn FileStream übertragen wird; Dies ist kein Streaming-Download großer Dateien.
- Der Text wird entsprechend dem Zeichensatz der Antwort dekodiert, bei fehlender/unbekannter Kodierung - UTF-8. Antworten HTTP 4xx/5xx werden ebenfalls gelesen. Wenn ein Netzwerkfehler oder eine Zeitüberschreitung auftritt, schreibt der Client einen Fehler, der Textkörper und die Header werden leer; Try/Catch ersetzt nicht die Prüfung auf die erwartete Antwort. Die Skriptstornierung erstreckt sich noch weiter. Ein Fehler beim Schreiben einer lokalen Datei oder aufgrund eines ungültigen Arguments kann mit Try/Catch abgefangen werden.
- HTTP_Body liest nur den letzten Puffer: Es wiederholt die Anfrage nicht, löscht die Antwort nicht und gibt keine Daten von einem anderen Skript zurück. Verwenden Sie nach dem binären GET MemoryStream.ToArray() oder eine gespeicherte Datei, nicht diesen Textpuffer.
Jedes Beispiel kann als separate Datei .csx gespeichert und in IDE ausgeführt werden. Die UO-Objekt- und Wartefunktionen stellen den Host der aktuellen Spielsitzung bereit. Ersetzen Sie Demo-serial-Namen, Koordinaten und Adressen durch Ihre eigenen.
Führe diesen Code als eigene .csx-Datei aus. Die Argumente stehen direkt im Aufruf; ersetze Beispielnamen, Serials und Adressen durch eigene Werte.
Das Ergebnis eines Aufrufs wird im Journal ausgegeben. Zahlen werden nicht in bool umgewandelt; bei Arrays wird die Anzahl der Elemente angezeigt.
UO.HTTP_Get("https://example.com/");
object? result = UO.HTTP_Body();
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameter und Ablauf:
- Der Dienst muss die Rückgabe zulassen. Eine andere Antwort, auch eine leere, ergibt false. Das Beispiel berechnet lediglich die Auflösung; löst weder Bewegung noch Kampf aus.
- Die example.com-Adressen dienen der Veranschaulichung und bieten keinen solchen Dienst. Ersetzen Sie sie durch Ihre eigenen; Das Ausführen des Beispiels führt zu einer echten HTTP-Abfrage. Das Beispiel führt keine Spielaktionen aus.
UO.HTTP_Get("https://example.com/C#-permission");
var permission = TrimText(UO.HTTP_Body());
return Truth(permission == "allow");
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
string TrimText(object? value) => (Convert.ToString(value) ?? "").Trim();Parameter und Ablauf:
- Zunächst wird der Routenname gespeichert, anschließend wird eine Beschreibung abgefragt. Ohne routeName würde das zweite GET die erste Antwort ersetzen.
- Die example.com-Adressen dienen der Veranschaulichung und bieten keinen solchen Dienst. Ersetzen Sie sie durch Ihre eigenen; Das Ausführen des Beispiels führt zu einer echten HTTP-Abfrage. Das Beispiel führt keine Spielaktionen aus.
return RunScenario();
object? RunScenario()
{
UO.HTTP_Get("https://example.com/route-name");
var routeName = UO.HTTP_Body();
UO.HTTP_Get("https://example.com/route-description");
return routeName + ": " + UO.HTTP_Body();
return null;
}Parameter und Ablauf:
- Nach GET mit System.IO.MemoryStream sind die Bytes im Stream und HTTP_Body ist leer. Diese Regel gilt auch für eine korrekte binäre Antwort; leerer Text bedeutet nicht, dass es keine Bytes gibt.
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()
{
using (var data = new System.IO.MemoryStream())
{
UO.HTTP_Get("https://example.com/route-data.bin", data);
string body = Convert.ToString(UO.HTTP_Body()) ?? "";
UO.Print($"Binary bytes: {data.Length}; text-body characters: {body.Length}");
return body;
}
return null;
}
}C# unterscheidet Groß- und Kleinschreibung. Verwenden Sie den genauen UO-Namen. Numerische Flags mit 0 vergleichen; bool nur bei Rückgabetyp bool verwenden.
Parameter: Keine Parameter.
Ergebnis: dynamic / Any.
Beim Aufruf:
Interner Implementierungscode; kein eigenständiges Skript.
case "http_body": return new InjectionValue(httpBody);Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
void UO.HTTP_Get(object? url);
void UO.HTTP_Get(object? url, object? lStream);Lädt Daten auf HTTP/HTTPS. Geeignet zum Lesen von Einstellungen aus Ihrem Dienst oder zum Empfangen einer Datei; verwaltet die Spielverbindung nicht und führt den heruntergeladenen Code nicht aus.
-
url– Erforderlich string: vollständige Adresse http:// oder https://. Ersetzen Sie example.com durch die Adresse Ihres Dienstes. Das Spiel und der Spieleserver werden für diese Anfrage nicht benötigt; Es wird die normale Netzwerkverbindung des Prozesses verwendet und nicht das Spiel-Proxy-Profil. -
lStreamist ein optionaler Standard .NET System.IO.Stream, beschreibbar: zum Beispiel neues System.IO.MemoryStream() oder System.IO.File.Create(path). Ohne oder mit 0/null lautet der Text HTTP_Body(). Der Thread erhält die ursprünglichen Bytes. Bei einem durchsuchbaren Stream wird der vorherige Inhalt auf Null zurückgesetzt und die Position vor und nach dem Schreibvorgang wird zu 0; Der nicht suchbare Thread erhält einen Schreibvorgang an der aktuellen Position. Durch das Erstellen von FileStream über File.Create wird die Datei sofort ungültig. Das übergeordnete Verzeichnis muss vorhanden sein. Ein ungeeignetes Argument oder ein schreibgeschützter Stream wird vor der Anfrage abgelehnt.
void – kein Rückgabewert. Rufen Sie eine separate Leitung an; Das Ergebnis kann nicht als bool, ID oder Anzahl der Bytes verwendet werden. Der Text nach einer normalen Anfrage wird von HTTP_Body() gelesen, die Binärdaten werden aus dem übertragenen Stream gelesen.
- Die letzte Antwort wird nur in der aktuellen Laufzeit des Skripts gespeichert. Das nächste GET/POST dieser Laufzeit ersetzt es; Andere gleichzeitig laufende Skripte ändern daran nichts. Die Antwort wird nicht im Profil gespeichert. Wenn Sie es nach der nächsten Anfrage benötigen, kopieren Sie den Text und die Header vorab in Variablen.
- GET/POST Warten Sie auf eine Antwort im laufenden Skript-Thread. Die Gesamtzeit für das Anfordern und Lesen des Körpers beträgt 20 Sekunden. Durch Stoppen des Skripts wird die Wartezeit abgebrochen. HTTP_Body/HTTP_Header erwarte nichts. Der gesamte Körper wird in den Speicher geladen, auch wenn FileStream übertragen wird; Dies ist kein Streaming-Download großer Dateien.
- Der Text wird entsprechend dem Zeichensatz der Antwort dekodiert, bei fehlender/unbekannter Kodierung - UTF-8. Antworten HTTP 4xx/5xx werden ebenfalls gelesen. Wenn ein Netzwerkfehler oder eine Zeitüberschreitung auftritt, schreibt der Client einen Fehler, der Textkörper und die Header werden leer; Try/Catch ersetzt nicht die Prüfung auf die erwartete Antwort. Die Skriptstornierung erstreckt sich noch weiter. Ein Fehler beim Schreiben einer lokalen Datei oder aufgrund eines ungültigen Arguments kann mit Try/Catch abgefangen werden.
- GET ohne Thread-Updates, Text und Überschriften. GET mit Stream schreibt Bytes, löscht HTTP_Body und speichert Header. Selbst eine leere Antwort/ein Netzwerkfehler ersetzt den Inhalt des Streams durch leere Daten: Um die alte Datei zu speichern, laden Sie sie zunächst auf MemoryStream herunter und überprüfen Sie die Daten.
Jedes Beispiel kann als separate Datei .csx gespeichert und in IDE ausgeführt werden. Die UO-Objekt- und Wartefunktionen stellen den Host der aktuellen Spielsitzung bereit. Ersetzen Sie Demo-serial-Namen, Koordinaten und Adressen durch Ihre eigenen.
Führe diesen Code als eigene .csx-Datei aus. Die Argumente stehen direkt im Aufruf; ersetze Beispielnamen, Serials und Adressen durch eigene Werte.
Der Befehl steht in einer eigenen Anweisung. Die Meldung davor zeigt den Beginn des Aufrufs und bestätigt keine Serveraktion.
UO.Print("Calling UO.HTTP_Get");
UO.HTTP_Get("https://example.com/");Parameter und Ablauf:
- example.com – Demoadresse; Ersetze es durch deins. System.Text.Json liest den Antworttext und akzeptiert nur die Ganzzahl minMana von 0 bis 100. Ein leeres/ungültiges JSON ergibt den Standardwert 30.
UO.HTTP_Get("https://example.com/csharp-config.json");
try
{
string body = Convert.ToString(UO.HTTP_Body()) ?? "";
using (var document = System.Text.Json.JsonDocument.Parse(body))
{
if (document.RootElement.TryGetProperty("minMana", out var value) &&
value.TryGetInt32(out int threshold) && threshold is >= 0 and <= 100)
return threshold;
}
}
catch (System.Text.Json.JsonException)
{
UO.Print("Response is not a valid configuration; using the default.");
}
return 30;Parameter und Ablauf:
- Es wird der Standard System.IO.MemoryStream übertragen. Es empfängt die Originalbytes der Antwort; HTTP_Body wird leer. Die vorhandene download.bin wird erst ersetzt, nachdem nicht leere Daten empfangen wurden. Die Überprüfung der Länge beweist nicht, dass der Inhalt korrekt ist.
return RunScenario();
object? RunScenario()
{
using (var data = new System.IO.MemoryStream())
{
UO.HTTP_Get("https://example.com/route-data.bin", data);
if (data.Length == 0)
{
UO.Print("The response is empty; no file was written.");
return false;
}
System.IO.File.WriteAllBytes("download.bin", data.ToArray());
return true;
}
return null;
}Parameter und Ablauf:
- System.IO.File.Create erstellt eine Datei oder setzt sie sofort auf Null; GET schreibt die Originalbytes. Wenn die Antwort leer ist, bleibt die Datei leer. Um die vorherige Version zu speichern, verwenden Sie zunächst MemoryStream wie im vorherigen Skript. using schließt den Stream.
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()
{
using (var output = System.IO.File.Create("http-download.bin"))
{
UO.HTTP_Get("https://example.com/route-data.bin", output);
}
return UO.HTTP_Header();
return null;
}
}C# unterscheidet Groß- und Kleinschreibung. Verwenden Sie den genauen UO-Namen. Numerische Flags mit 0 vergleichen; bool nur bei Rückgabetyp bool verwenden.
Parameter: url (Any)
Ergebnis: void / Unit.
Beim Aufruf:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.HttpRequest:bridge.HttpRequest("GET", Text(0), string.Empty). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Text:Text(0). -
InjectionScript.Runtime.ObjectTypes.MemoryStreamObject.ReplaceBytes:memoryStream.ReplaceBytes(raw).
Interner Implementierungscode; kein eigenständiges Skript.
case "http_get":
{
bool hasStream = arguments.Length > 1
&& !(arguments[1].Kind == InjectionValueKind.Integer && arguments[1].Integer == 0)
&& arguments[1].Kind != InjectionValueKind.Unit;
// Validate before network side effects and before changing the last response.
if (hasStream && !(arguments[1].Object is MemoryStreamObject))
throw new NativeSubrutineException("UO.HTTP_Get: LStream must be a writable System.IO.Stream, 0, or omitted.");
string[] response = bridge.HttpRequest("GET", Text(0), string.Empty);
httpHeader = response.Length > 1 ? response[1] : string.Empty;
httpBody = hasStream ? string.Empty : response.Length > 0 ? response[0] : string.Empty;
if (!hasStream)
{
return InjectionValue.Unit;
}
byte[] raw = response.Length > 3 && !string.IsNullOrEmpty(response[3])
? Convert.FromBase64String(response[3])
: Array.Empty<byte>();
if (arguments[1].Object is MemoryStreamObject memoryStream)
memoryStream.ReplaceBytes(raw);
else
throw new NativeSubrutineException("UO.HTTP_Get: LStream must be a writable System.IO.Stream.");
// Stream overloads keep the response as bytes, not cached text.
return InjectionValue.Unit;
}Parameter: url (Any), lStream (Any)
Ergebnis: void / Unit.
Beim Aufruf:
-
ClassicUO.CSharp.CSharpScriptGlobals.CSharpScriptGlobals. -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.HttpRequest:bridge.HttpRequest("GET", Text(0), string.Empty). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Text:Text(0). -
InjectionScript.Runtime.ObjectTypes.MemoryStreamObject.ReplaceBytes:memoryStream.ReplaceBytes(raw).
Interner Implementierungscode; kein eigenständiges Skript.
if (name == "HTTP_Get" && arguments.Length == 2 && arguments[1] is Stream stream)
{
if (!stream.CanWrite) throw new ArgumentException("HTTP_Get requires a writable .NET stream.");
// Adapt the existing binary response path without fetching the
// response twice or converting its bytes through text encoding.
var type = typeof(InjectionValue).Assembly.GetType("InjectionScript.Runtime.ObjectTypes.MemoryStreamObject", throwOnError: true)!;
using var native = (IDisposable)Activator.CreateInstance(type, nonPublic: true)!;
value = Invoke(name, [arguments[0], native]);
var bytes = (InjectionValue)type.GetMethod("ToArray")!.Invoke(native, null)!;
byte[] payload = bytes.Array.Select(item => checked((byte)item.Integer)).ToArray();
if (stream.CanSeek) { stream.SetLength(0); stream.Position = 0; }
stream.Write(payload);
if (stream.CanSeek) stream.Position = 0;
}
else value = Invoke(name, arguments);Interner Implementierungscode; kein eigenständiges Skript.
case "http_get":
{
bool hasStream = arguments.Length > 1
&& !(arguments[1].Kind == InjectionValueKind.Integer && arguments[1].Integer == 0)
&& arguments[1].Kind != InjectionValueKind.Unit;
// Validate before network side effects and before changing the last response.
if (hasStream && !(arguments[1].Object is MemoryStreamObject))
throw new NativeSubrutineException("UO.HTTP_Get: LStream must be a writable System.IO.Stream, 0, or omitted.");
string[] response = bridge.HttpRequest("GET", Text(0), string.Empty);
httpHeader = response.Length > 1 ? response[1] : string.Empty;
httpBody = hasStream ? string.Empty : response.Length > 0 ? response[0] : string.Empty;
if (!hasStream)
{
return InjectionValue.Unit;
}
byte[] raw = response.Length > 3 && !string.IsNullOrEmpty(response[3])
? Convert.FromBase64String(response[3])
: Array.Empty<byte>();
if (arguments[1].Object is MemoryStreamObject memoryStream)
memoryStream.ReplaceBytes(raw);
else
throw new NativeSubrutineException("UO.HTTP_Get: LStream must be a writable System.IO.Stream.");
// Stream overloads keep the response as bytes, not cached text.
return InjectionValue.Unit;
}Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.HTTP_Header();Liest die Header der letzten HTTP-Antwort dieses Skripts: zum Beispiel Content-Type, um das deklarierte Datenformat herauszufinden. Dabei handelt es sich nicht um den Antworttext, die Anforderungsheader oder den numerischen Code HTTP.
Es gibt keine Parameter.
string – Zeichenfolgen der Form Name: Wert, getrennt durch CRLF. Vor der ersten Anfrage und nach dem Netzwerkfehler - eine Leerzeile. Die Zeilen HTTP/1.1 200 OK sind nicht hier; Der Statuscode wird nicht durch einen separaten Befehl dargestellt. Die Reihenfolge und Groß-/Kleinschreibung der Namen kann nicht garantiert werden.
- Die letzte Antwort wird nur in der aktuellen Laufzeit des Skripts gespeichert. Das nächste GET/POST dieser Laufzeit ersetzt es; Andere gleichzeitig laufende Skripte ändern daran nichts. Die Antwort wird nicht im Profil gespeichert. Wenn Sie es nach der nächsten Anfrage benötigen, kopieren Sie den Text und die Header vorab in Variablen.
- GET/POST Warten Sie auf eine Antwort im laufenden Skript-Thread. Die Gesamtzeit für das Anfordern und Lesen des Körpers beträgt 20 Sekunden. Durch Stoppen des Skripts wird die Wartezeit abgebrochen. HTTP_Body/HTTP_Header erwarte nichts. Der gesamte Körper wird in den Speicher geladen, auch wenn FileStream übertragen wird; Dies ist kein Streaming-Download großer Dateien.
- Der Text wird entsprechend dem Zeichensatz der Antwort dekodiert, bei fehlender/unbekannter Kodierung - UTF-8. Antworten HTTP 4xx/5xx werden ebenfalls gelesen. Wenn ein Netzwerkfehler oder eine Zeitüberschreitung auftritt, schreibt der Client einen Fehler, der Textkörper und die Header werden leer; Try/Catch ersetzt nicht die Prüfung auf die erwartete Antwort. Die Skriptstornierung erstreckt sich noch weiter. Ein Fehler beim Schreiben einer lokalen Datei oder aufgrund eines ungültigen Arguments kann mit Try/Catch abgefangen werden.
- HTTP_Header kombiniert die Header der Antwort und deren Inhalt. Nach dem binären GET stehen sie ebenfalls zur Verfügung. Der Name sollte ohne Berücksichtigung der Groß-/Kleinschreibung geprüft werden. Content-Type ist eine Serveranweisung, keine Inhaltsprüfung; Führen Sie den heruntergeladenen Text nicht als Code aus.
Jedes Beispiel kann als separate Datei .csx gespeichert und in IDE ausgeführt werden. Die UO-Objekt- und Wartefunktionen stellen den Host der aktuellen Spielsitzung bereit. Ersetzen Sie Demo-serial-Namen, Koordinaten und Adressen durch Ihre eigenen.
Führe diesen Code als eigene .csx-Datei aus. Die Argumente stehen direkt im Aufruf; ersetze Beispielnamen, Serials und Adressen durch eigene Werte.
Das Ergebnis eines Aufrufs wird im Journal ausgegeben. Zahlen werden nicht in bool umgewandelt; bei Arrays wird die Anzahl der Elemente angezeigt.
UO.HTTP_Get("https://example.com/");
object? result = UO.HTTP_Header();
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameter und Ablauf:
- Überschriften werden Zeile für Zeile analysiert. Beim Vergleich des Namens des Inhaltstyps wird die Groß-/Kleinschreibung nicht beachtet. Wenn keine Zeichenfolge vorhanden ist, wird eine leere Zeichenfolge zurückgegeben.
UO.HTTP_Get("https://example.com/csharp-status");
return ReadHeader(Convert.ToString(UO.HTTP_Header()) ?? "", "Content-Type");
string ReadHeader(string headers, string name)
{
foreach (string line in headers.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries))
{
int separator = line.IndexOf(':');
if (separator > 0 && line[..separator].Trim().Equals(name, StringComparison.OrdinalIgnoreCase))
return line[(separator + 1)..].Trim();
}
return "";
}Parameter und Ablauf:
- Der lokal gespeicherte Headertext wird überprüft. Content-Type selbst garantiert nicht die Richtigkeit von JSON; Überprüfen Sie den Inhalt separat in System.Text.Json.
return RunScenario();
object? RunScenario()
{
UO.HTTP_Get("https://example.com/csharp-status");
string headers = Convert.ToString(UO.HTTP_Header()) ?? "";
return headers.Contains("application/json", StringComparison.OrdinalIgnoreCase);
return null;
}Parameter und Ablauf:
- GET leitet die Quellbytes an System.IO.MemoryStream weiter. Die letzten Antwortheader lauten immer noch HTTP_Header; Text HTTP_Body für dieses Formular ist leer. Nur die Header werden in der Datei gespeichert.
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()
{
using (var data = new System.IO.MemoryStream())
{
UO.HTTP_Get("https://example.com/route-data.bin", data);
string headers = Convert.ToString(UO.HTTP_Header()) ?? "";
System.IO.File.WriteAllText("http-response-headers.txt", headers);
UO.Print($"Saved response headers; downloaded {data.Length} binary bytes.");
return headers;
}
return null;
}
}C# unterscheidet Groß- und Kleinschreibung. Verwenden Sie den genauen UO-Namen. Numerische Flags mit 0 vergleichen; bool nur bei Rückgabetyp bool verwenden.
Parameter: Keine Parameter.
Ergebnis: dynamic / Any.
Beim Aufruf:
Interner Implementierungscode; kein eigenständiges Skript.
case "http_header": return new InjectionValue(httpHeader);Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.HTTP_Post(object? url, object? postData);Sendet mit der Methode POST einen Text an seinen HTTP-Dienst und gibt den Antworttext zurück. Beispielsweise kann ein Skript einen Routenstopp melden. Dies ist kein vorgefertigter Telegram-/Discord-Befehl: Ihr Protokoll, ihre Autorisierung und ihr Anfrageformat erfordern separate Unterstützung.
-
url– Erforderlich string: vollständige Adresse http:// oder https://. Ersetzen Sie example.com durch die Adresse Ihres Dienstes. Das Spiel und der Spieleserver werden für diese Anfrage nicht benötigt; Es wird die normale Netzwerkverbindung des Prozesses verwendet und nicht das Spiel-Proxy-Profil. -
postData– Obligatorisch string mit Anforderungstext. Gesendet von UTF-8 mit Content-Type: text/plain; charset=utf-8. Es gibt keine automatische Formularkodierung und Umstellung auf application/json. System.Text.Json.JsonSerializer.Serialize generiert nur Text: Der Beispielserver sollte JSON genau als Text/Plain akzeptieren. Mit diesen Befehlen können Sie keine benutzerdefinierten Header konfigurieren.
string – Antworttext; es ist auch über HTTP_Body() zugänglich. Dies ist nicht bool und nicht der Code HTTP. Eine leere Zeichenfolge weist nicht auf einen Fehler hin, eine nicht leere Zeichenfolge weist jedoch nicht auf den Erfolg des Vorgangs auf dem Server hin.
- Die letzte Antwort wird nur in der aktuellen Laufzeit des Skripts gespeichert. Das nächste GET/POST dieser Laufzeit ersetzt es; Andere gleichzeitig laufende Skripte ändern daran nichts. Die Antwort wird nicht im Profil gespeichert. Wenn Sie es nach der nächsten Anfrage benötigen, kopieren Sie den Text und die Header vorab in Variablen.
- GET/POST Warten Sie auf eine Antwort im laufenden Skript-Thread. Die Gesamtzeit für das Anfordern und Lesen des Körpers beträgt 20 Sekunden. Durch Stoppen des Skripts wird die Wartezeit abgebrochen. HTTP_Body/HTTP_Header erwarte nichts. Der gesamte Körper wird in den Speicher geladen, auch wenn FileStream übertragen wird; Dies ist kein Streaming-Download großer Dateien.
- Der Text wird entsprechend dem Zeichensatz der Antwort dekodiert, bei fehlender/unbekannter Kodierung - UTF-8. Antworten HTTP 4xx/5xx werden ebenfalls gelesen. Wenn ein Netzwerkfehler oder eine Zeitüberschreitung auftritt, schreibt der Client einen Fehler, der Textkörper und die Header werden leer; Try/Catch ersetzt nicht die Prüfung auf die erwartete Antwort. Die Skriptstornierung erstreckt sich noch weiter. Ein Fehler beim Schreiben einer lokalen Datei oder aufgrund eines ungültigen Arguments kann mit Try/Catch abgefangen werden.
- POST aktualisiert den Text und die Header und gibt denselben Text als Zeichenfolge zurück. Wiederholen Sie POST nicht automatisch, nur weil die Antwort leer ist: Der Server hat die Aktion möglicherweise bereits ausgeführt. Die Akzeptanz-/Statusprüfung in den Beispielen ist eine Vereinbarung mit Ihrem Dienst und kein eingebautes Zeichen für den HTTP-Erfolg.
Jedes Beispiel kann als separate Datei .csx gespeichert und in IDE ausgeführt werden. Die UO-Objekt- und Wartefunktionen stellen den Host der aktuellen Spielsitzung bereit. Ersetzen Sie Demo-serial-Namen, Koordinaten und Adressen durch Ihre eigenen.
Führe diesen Code als eigene .csx-Datei aus. Die Argumente stehen direkt im Aufruf; ersetze Beispielnamen, Serials und Adressen durch eigene Werte.
Das Ergebnis eines Aufrufs wird im Journal ausgegeben. Zahlen werden nicht in bool umgewandelt; bei Arrays wird die Anzahl der Elemente angezeigt.
object? result = UO.HTTP_Post("https://example.com/", "Hello from C#");
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parameter und Ablauf:
- Der Dienst akzeptiert den Text „Route gestoppt“ und antwortet nach Vereinbarung mit „Akzeptiert“. Main gibt true nur mit diesem Text zurück; Dies ist eine Überprüfung des Protokolls Ihres Dienstes, keine Überprüfung des HTTP-Codes.
- Die example.com-Adressen dienen der Veranschaulichung und bieten keinen solchen Dienst. Ersetzen Sie sie durch Ihre eigenen; Das Ausführen des Beispiels führt zu einer echten HTTP-Abfrage. Das Beispiel führt keine Spielaktionen aus.
var reply = UO.HTTP_Post("https://example.com/C#-event", "Route stopped");
return Truth(TrimText(reply) == "accepted");
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
string TrimText(object? value) => (Convert.ToString(value) ?? "").Trim();Parameter und Ablauf:
- System.Text.Json.JsonSerializer maskiert Wörterbuchzeichenfolgen. Der Statuswert wird nach Prüfung von JSON gelesen; Ersetzen Sie die Demo-Adresse durch Ihre.
return RunScenario();
object? RunScenario()
{
var report = new Dictionary<string, string>
{
["event"] = "route-stopped",
["text"] = "line one\nline two"
};
string payload = System.Text.Json.JsonSerializer.Serialize(report);
string reply = Convert.ToString(UO.HTTP_Post("https://example.com/csharp-report", payload)) ?? "";
try
{
using (var document = System.Text.Json.JsonDocument.Parse(reply))
{
return document.RootElement.TryGetProperty("status", out var value) ? value.GetString() : "unknown";
}
}
catch (System.Text.Json.JsonException)
{
return "invalid response";
}
return null;
}Parameter und Ablauf:
- firstReply und firstHeaders speichern die Antwort POST. Das anschließende GET ersetzt die internen Puffer, die lokalen Variablen enthalten jedoch weiterhin die erste Antwort.
- Die example.com-Adressen dienen der Veranschaulichung und bieten keinen solchen Dienst. Ersetzen Sie sie durch Ihre eigenen; Das Ausführen des Beispiels führt zu einer echten HTTP-Abfrage. Das Beispiel führt keine Spielaktionen aus.
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 firstReply = UO.HTTP_Post("https://example.com/C#-event", "Route stopped");
var firstHeaders = UO.HTTP_Header();
UO.HTTP_Get("https://example.com/C#-status");
return firstReply + "|" + firstHeaders;
return null;
}
}C# unterscheidet Groß- und Kleinschreibung. Verwenden Sie den genauen UO-Namen. Numerische Flags mit 0 vergleichen; bool nur bei Rückgabetyp bool verwenden.
Parameter: url (Any), postData (Any)
Ergebnis: dynamic / Any.
Beim Aufruf:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.HttpRequest:bridge.HttpRequest("POST", Text(0), Text(1)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Text:Text(0).
Interner Implementierungscode; kein eigenständiges Skript.
case "http_post":
{
string[] response = bridge.HttpRequest("POST", Text(0), Text(1));
httpBody = response.Length > 0 ? response[0] : string.Empty;
httpHeader = response.Length > 1 ? response[1] : string.Empty;
return new InjectionValue(httpBody);
}Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.Messenger(object? provider);Erstellt ein Objekt für Textbenachrichtigungen und den Empfang von Telegram-, Discord- oder Viber-Nachrichten. Beispielsweise könnte das Skript das Ende der Ressourcensammlung signalisieren oder nach einer Stoppanforderung eines vorab festgelegten Benutzers suchen. Durch das Erstellen eines Objekts wird der Bot noch nicht verbunden und es wird nichts gesendet.
-
provider- string: „Telegram“, „Discord“ oder „Viber“; Der Fall ist nicht wichtig. Andere Werte verursachen einen Fehler.
Objekt Messenger. Dies ist nicht bool und nicht ID. ID Nachrichten, Absender und Chats in diesem Objekt sind immer string: mit Strings vergleichen, nicht über Convert.ToInt32/Convert.ToDouble konvertieren.
-
Provider() → string;Connected() → 1/0(true/false): Anbieter und Ergebnis der letzten Autorisierungsprüfung. Connected garantiert derzeit keine Internetverfügbarkeit. -
Connect(token) → null: prüft den Bot-Token;ConnectFromFile(path) → null: Liest UTF-8-Token aus der Datei bis zu 1024 Bytes. Der relative Pfad wird aus dem aktuellen Skriptordner berechnet. Für die erneute Verbindung ist Disconnect erforderlich. Fehler können mit Try/Catch abgefangen werden. -
Disconnect() → null: stoppt den lokalen Empfang, löscht Token und Cursor; Das Objekt kann wieder verbunden werden.Dispose() → null: Schließt das Objekt vollständig. -
SendMessage(text, recipient) → string: ID Nachricht empfangen. Parameter - Text- und String-Chat ID Telegram, Kanal ID Discord oder ID Viber-Abonnent. Längenbegrenzungen: jeweils 4096/2000/7000; auch Viber JSON ≤30000 Bytes. Leertext ist verboten. Discord erstellt keine Erwähnungen aller Personen/Rollen. -
WatchChannel(channelId) → null: Discord, merkt sich die aktuell letzte Nachricht und liest nur die nachfolgenden.WatchChannel(channelId, afterMessageId) → null: beginnt nach der angegebenen Zeichenfolge ID; „0“ beinhaltet den Verlauf. Bis zu 32 Kanäle pro Objekt. -
Receive(timeoutSeconds) → Array;Receive(): 0 Zeitüberschreitung. Bereich 0..20 Sekunden; Ein leeres Array bedeutet, dass keine Textnachrichten verfügbar sind. Telegram verwendet long-Polling, Discord fragt ausgewählte Kanäle ab, Viber liest die Webhook-Warteschlange. Die Netzwerkanfrage kann bis zu 30 Sekunden dauern. - Jeweils MessengerMessage:
Id(),SenderId(),SenderName(),ChatId(),Text()→ string. Ein Telegram-Beitrag von einem Kanal darf nicht SenderId haben. Anhänge, Nicht-Text-Ereignisse und Discord-Nachrichten von Bots werden nicht zurückgegeben. -
RetryAfter() → int: wie viele Sekunden nach der Einschränkung des Dienstes gewartet werden soll. Vor Ablauf dieser Frist werden neue HTTP-Anfragen nicht ausgeführt. Das Senden nach einem Fehler wird nicht automatisch wiederholt: Möglicherweise hat der Server die Nachricht bereits empfangen. -
StartReceiver(localPort, publicHttpsUrl) → int: Nur Viber; Port 1..65535, gibt den belegten lokalen Port zurück. Die öffentliche HTTPS-Adresse muss mit /viber/ enden und POST an 127.0.0.1:port/viber/ mit dem Originaltext und dem Signaturheader im Voraus weiterleiten. Die Methode registriert einen Webhook bei Viber. - Sie benötigen ein Bot-Token, kein persönliches Kontopasswort. Telegramm mit einem vorhandenen Webhook wird abgelehnt, ohne ihn zu entfernen. Discord erfordert Lese-/Sendeberechtigungen für den Kanal und MESSAGE_CONTENT für barrierefreien Text; Viber sendet an abonnierte Benutzer.
- Empfangen speichert den Cursor erst, nachdem der gesamte Stapel analysiert wurde. Telegram/Discord gibt bis zu 100 Einträge pro Anfrage zurück; Rufen Sie „Receive“ für nachfolgende Pakete erneut auf. Discord ohne das zweite Argument WatchChannel überspringt die alte Geschichte.
- Viber prüft den HMAC-SHA256 des Quellkörpers. Warteschlange – 100-Nachrichten, wiederholt ID werden für die letzten 2048-Zustellungen gespeichert; Überlauf ergibt HTTP 503 für einen erneuten Versuch durch den Dienst. Sie benötigen einen HTTPS-Proxy mit Content-Length; Chunked-Anfragen bei lokaler Eingabe werden abgelehnt.
- Das Token wird nicht im Connect-Profil, im Fehlertext oder im Argumentverlauf aufgezeichnet. Verwenden Sie ConnectFromFile, um zu vermeiden, dass es in Skriptvariablen gespeichert wird, die für den Debugger sichtbar sind. Veröffentlichen Sie keine Tokendateien.
- Erstellen Sie ein Objekt innerhalb einer Prozedur. Nicht mehr als 32 gleichzeitig; Mit/Entsorgen wird es früher freigegeben. Wenn ein Skript abgeschlossen wird, fehlschlägt oder stoppt, werden alle seine Messenger-Objekte geschlossen. Durch das Schließen des Viber-Receivers wird der Webhook nicht aus dem Dienst gelöscht.
- Dies ist eine Textschnittstelle: Sie führt den empfangenen Text nicht als Code aus und verbindet keine Spielkonten. Die Bedingungen für das Vertrauen des Absenders werden vom Skript selbst festgelegt.
Jedes Beispiel kann als separate Datei .csx gespeichert und in IDE ausgeführt werden. Die UO-Objekt- und Wartefunktionen stellen den Host der aktuellen Spielsitzung bereit. Ersetzen Sie Demo-serial-Namen, Koordinaten und Adressen durch Ihre eigenen.
Führe diesen Code als eigene .csx-Datei aus. Die Argumente stehen direkt im Aufruf; ersetze Beispielnamen, Serials und Adressen durch eigene Werte.
dynamic messenger = UO.Messenger("telegram");
UO.Print(messenger.Provider());
messenger.Dispose();Parameter und Ablauf:
- Platzieren Sie telegram-token.txt neben dem Skript und ersetzen Sie 12345678 durch Ihren Chat ID. Das Beispiel sendet eine Benachrichtigung und gibt die Zeichenfolge ID zurück; Der Empfang einer Serverantwort bestätigt nicht das menschliche Lesen.
- Sie benötigen Ihre eigenen Bot-Einstellungen. Beispiele werden mit lokalen Testantworten getestet; Sie wurden nicht an echte Benutzer gesendet.
var bot = UO.Messenger("telegram");
using (var resource = bot)
{
bot.ConnectFromFile("telegram-token.txt");
var messageId = bot.SendMessage("Harvest finished", "12345678");
return messageId;
}Parameter und Ablauf:
- Geben Sie Ihren Kanal und den zulässigen Absender ID ein. true bedeutet, dass dieser Scheck den Textstopp von ihm erhalten hat; Das Beispiel selbst stoppt die Bewegung nicht. Dieses Ergebnis kann in Ihrer eigenen Arbeitszyklusbedingung verwendet werden.
- Sie benötigen Ihre eigenen Bot-Einstellungen. Beispiele werden mit lokalen Testantworten getestet; Sie wurden nicht an echte Benutzer gesendet.
return RunScenario();
object? RunScenario()
{
var bot = UO.Messenger("discord");
using (var resource = bot)
{
bot.ConnectFromFile("discord-token.txt");
bot.WatchChannel("123456789012345678");
var messages = bot.Receive(5);
foreach (var message in messages)
{
if (Truth(message.SenderId() == "987654321098765432") && Truth(Convert.ToString(TrimText(message.Text())) == "stop"))
{
return true;
}
}
return false;
}
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
string TrimText(object? value) => (Convert.ToString(value) ?? "").Trim();Parameter und Ablauf:
- System.Text.Json liest den lokalen Port/publicUrl. Das Token wird in einer separaten lokalen Datei gespeichert; Tatsächliche Versendungen werden in diesem Beispiel nicht durchgeführt. Es wird auf vertrauenswürdiges SenderId geprüft, nicht auf beliebigen eingehenden Text.
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 settingsDocument = System.Text.Json.JsonDocument.Parse(System.IO.File.ReadAllText("viber-settings.json"));
using (settingsDocument)
{
var settings = settingsDocument.RootElement;
var bot = UO.Messenger("viber");
using (var resource = bot)
{
bot.ConnectFromFile("viber-token.txt");
bot.StartReceiver(settings.GetProperty("port").GetInt32(), settings.GetProperty("publicUrl").GetString());
var messages = bot.Receive(5);
foreach (var message in messages)
{
if (Truth(message.SenderId() == "trusted-subscriber-id"))
{
return message.Text();
}
}
return "";
}
}
return null;
}
bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}C# unterscheidet Groß- und Kleinschreibung. Verwenden Sie den genauen UO-Namen. Numerische Flags mit 0 vergleichen; bool nur bei Rückgabetyp bool verwenden.
Parameter: provider (String)
Ergebnis: dynamic / Object.
Beim Aufruf:
Interner Implementierungscode; kein eigenständiges Skript.
private InjectionObject CreateMessenger(string provider)
{
var owner=NativeScriptResourceScope.Current??throw new StatementFailedException("Create messenger objects inside an active C# script execution.");owner.Checkpoint();
var client=MessengerFactory!=null?MessengerFactory(provider,()=>owner.Cancellation,owner.Checkpoint):new Messaging.MessengerClient(provider,()=>owner.Cancellation,owner.Checkpoint);
var resource=new MessengerObject(client,owner.Forget,file=>Path.GetFullPath(Path.Combine(paths.ScriptPath??string.Empty,file)));owner.Track(resource);return resource;
}ClassicUO — Bad Newbie & C# Scripts IDE