Repository navigation
IT UO Topic http
Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
Home · C# · IDE · UO API · A–Z · Esempi · Lingue
HTTP-query e lettura della risposta. Il codice di stato, l'intestazione e il corpo della risposta sono dati separati.
| Argomento | Comandi e spiegazioni |
|---|---|
| HTTP_Get | UO.HTTP_Get |
| HTTP_Post | UO.HTTP_Post |
| HTTP_Header | UO.HTTP_Header |
| HTTP_Body | UO.HTTP_Body |
| Messaggi esterni | UO.Messenger - Telegram, Discord e Viber |
UO.HTTP_Get · UO.HTTP_Post · UO.HTTP_Header · UO.HTTP_Body
Ogni carta comando ha diversi scenari indipendenti: codice diretto, funzioni e classi. Di seguito sono selezionati brevi scenari; restrizioni e un'analisi completa sono nelle carte.
Parametri, risultato e tutti gli scenari
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;Parametri, risultato e tutti gli scenari
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();Legge il testo dell'ultima risposta HTTP di questo script. Ad esempio, dopo HTTP_Get puoi analizzare JSON con le impostazioni o confrontare la risposta del tuo servizio con la stringa prevista. La lettura stessa non va in rete.
Non ci sono parametri.
string: testo salvato. Prima della prima richiesta in questo runtime, dopo GET nello stream e dopo l'errore di rete: una riga vuota. Una risposta normale ha anche un corpo vuoto, ad esempio HTTP 204. Non confrontare il risultato con true/false come indicazione di consegna.
- L'ultima risposta viene archiviata solo nel runtime corrente dello script. Il successivo GET/POST di questo runtime lo sostituisce; altri script eseguiti contemporaneamente non lo modificano. La risposta non viene salvata nel profilo. Se ne hai bisogno dopo la richiesta successiva, copia in anticipo il corpo e le intestazioni nelle variabili.
- GET/POST attende una risposta nel thread dello script in esecuzione. Il tempo totale per la richiesta e la lettura del corpo è di 20 secondi. L'arresto dello script annulla l'attesa; HTTP_Body/HTTP_Header non aspettarti nulla. L'intero corpo viene caricato in memoria anche quando viene trasferito FileStream; Non si tratta di un download in streaming di file di grandi dimensioni.
- Il testo viene decodificato in base al set di caratteri della risposta, in assenza/codifica sconosciuta - UTF-8. Vengono lette anche le risposte HTTP 4xx/5xx. Quando si verifica un errore di rete o un timeout, il client scrive un errore, il corpo e le intestazioni diventano vuoti; Try/Catch non sostituisce il controllo della risposta prevista. La cancellazione dello script si estende ulteriormente. Un errore di scrittura del file locale o di argomento non valido può essere rilevato da Try/Catch.
- HTTP_Body legge solo l'ultimo buffer: non ripete la richiesta, non cancella la risposta e non restituisce dati da un altro script. Dopo il binario GET, usa MemoryStream.ToArray() o un file memorizzato, non questo buffer di testo.
Ogni esempio può essere salvato come file separato .csx ed eseguito in IDE. Le funzioni oggetto UO e attesa forniscono l'host della sessione di gioco corrente. Sostituisci i nomi, le coordinate e gli indirizzi demo serial con i tuoi.
Esegui questo codice in un file .csx separato. Gli argomenti sono visibili nella chiamata; sostituisci nomi, serial e indirizzi di esempio con i tuoi.
Il risultato di una sola chiamata viene mostrato nel diario. Un numero non viene convertito in bool; per un array viene mostrato il numero di elementi.
UO.HTTP_Get("https://example.com/");
object? result = UO.HTTP_Body();
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parametri e flusso di esecuzione:
- Il servizio deve restituire l'autorizzazione. Un'altra risposta, inclusa una vuota, dà false. L'esempio calcola semplicemente la risoluzione; non innesca movimento o combattimento.
- Gli indirizzi example.com sono illustrativi e non forniscono tale servizio. Sostituiscili con i tuoi; l'esecuzione dell'esempio crea una vera query HTTP. L'esempio non esegue azioni di gioco.
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();Parametri e flusso di esecuzione:
- Innanzitutto viene memorizzato il nome del percorso, quindi viene richiesta una descrizione. Senza routeName, la seconda GET sostituirebbe la prima risposta.
- Gli indirizzi example.com sono illustrativi e non forniscono tale servizio. Sostituiscili con i tuoi; l'esecuzione dell'esempio crea una vera query HTTP. L'esempio non esegue azioni di gioco.
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;
}Parametri e flusso di esecuzione:
- Dopo GET con System.IO.MemoryStream i byte sono nello stream e HTTP_Body è vuoto. Questa regola vale anche per una risposta binaria corretta; il testo vuoto non significa nessun byte.
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# distingue maiuscole e minuscole. Usare il nome UO esatto. Confrontare i flag numerici con 0; usare bool solo se la firma restituisce bool.
Parametri: Nessun parametro.
Risultato: dynamic / Any.
Durante la chiamata:
Codice interno di implementazione; non è uno script autonomo.
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);Carica i dati su HTTP/HTTPS. Adatto per leggere le impostazioni del tuo servizio o ricevere un file; non gestisce la connessione del gioco né esegue il codice scaricato.
-
url- Obbligatorio string: indirizzo completo http:// oppure https://. Sostituisci example.com con l'indirizzo del tuo servizio. Per questa richiesta non sono necessari il gioco e il server di gioco; Viene utilizzata la normale connessione di rete del processo e non il profilo proxy del gioco. -
lStreamè uno standard opzionale .NET System.IO.Stream, scrivibile: ad esempio new System.IO.MemoryStream() o System.IO.File.Create(percorso). Without it or with 0/null the text reads HTTP_Body(). Il thread riceve i byte originali. For a seekable stream, the previous content is reset to zero, and the position before and after the write becomes 0; The non-seekable thread receives a write to the current position. Creating FileStream via File.Create nullifies the file immediately; la directory padre deve esistere. An inappropriate argument or read-only stream is rejected before the request.
void - nessun valore restituito. Chiama su una linea separata; il risultato non può essere utilizzato come bool, ID o numero di byte. Il testo dopo una normale richiesta viene letto da HTTP_Body(), i dati binari vengono letti dal flusso trasmesso.
- L'ultima risposta viene archiviata solo nel runtime corrente dello script. Il successivo GET/POST di questo runtime lo sostituisce; altri script eseguiti contemporaneamente non lo modificano. La risposta non viene salvata nel profilo. Se ne hai bisogno dopo la richiesta successiva, copia in anticipo il corpo e le intestazioni nelle variabili.
- GET/POST attende una risposta nel thread dello script in esecuzione. Il tempo totale per la richiesta e la lettura del corpo è di 20 secondi. L'arresto dello script annulla l'attesa; HTTP_Body/HTTP_Header non aspettarti nulla. L'intero corpo viene caricato in memoria anche quando viene trasferito FileStream; Non si tratta di un download in streaming di file di grandi dimensioni.
- Il testo viene decodificato in base al set di caratteri della risposta, in assenza/codifica sconosciuta - UTF-8. Vengono lette anche le risposte HTTP 4xx/5xx. Quando si verifica un errore di rete o un timeout, il client scrive un errore, il corpo e le intestazioni diventano vuoti; Try/Catch non sostituisce il controllo della risposta prevista. La cancellazione dello script si estende ulteriormente. Un errore di scrittura del file locale o di argomento non valido può essere rilevato da Try/Catch.
- GET senza thread aggiorna testo e intestazioni. GET con stream scrive byte, cancella HTTP_Body e salva le intestazioni. Anche una risposta vuota/errore di rete sostituisce il contenuto dello stream con dati vuoti: per salvare il vecchio file, scaricalo prima su MemoryStream e controlla i dati.
Ogni esempio può essere salvato come file separato .csx ed eseguito in IDE. Le funzioni oggetto UO e attesa forniscono l'host della sessione di gioco corrente. Sostituisci i nomi, le coordinate e gli indirizzi demo serial con i tuoi.
Esegui questo codice in un file .csx separato. Gli argomenti sono visibili nella chiamata; sostituisci nomi, serial e indirizzi di esempio con i tuoi.
Il comando è un’istruzione separata. Il messaggio precedente indica l’inizio della chiamata e non conferma un’azione del server.
UO.Print("Calling UO.HTTP_Get");
UO.HTTP_Get("https://example.com/");Parametri e flusso di esecuzione:
- example.com - indirizzo demo; sostituiscilo con il tuo. System.Text.Json legge il corpo della risposta e accetta solo il numero intero minMana da 0 a 100. Un JSON vuoto/non valido fornisce il valore predefinito 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;Parametri e flusso di esecuzione:
- Viene trasmesso il System.IO.MemoryStream standard. Riceve i byte originali della risposta; HTTP_Body diventa vuoto. Il download.bin esistente viene sostituito solo dopo aver ricevuto dati non vuoti. Il controllo della lunghezza non dimostra che il contenuto sia corretto.
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;
}Parametri e flusso di esecuzione:
- System.IO.File.Create crea o annulla immediatamente un file; GET scrive i byte originali. Se la risposta è vuota, il file rimarrà vuoto. Per salvare la versione precedente, utilizzare prima MemoryStream come nello script precedente. utilizzando chiude il flusso.
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# distingue maiuscole e minuscole. Usare il nome UO esatto. Confrontare i flag numerici con 0; usare bool solo se la firma restituisce bool.
Parametri: url (Any)
Risultato: void / Unit.
Durante la chiamata:
-
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).
Codice interno di implementazione; non è uno script autonomo.
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;
}Parametri: url (Any), lStream (Any)
Risultato: void / Unit.
Durante la chiamata:
-
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).
Codice interno di implementazione; non è uno script autonomo.
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);Codice interno di implementazione; non è uno script autonomo.
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();Legge le intestazioni dell'ultima risposta HTTP di questo script: ad esempio Content-Type, per scoprire il formato dati dichiarato. Questo non è il corpo della risposta, le intestazioni della richiesta o il codice numerico HTTP.
Non ci sono parametri.
string — stringhe nella forma Nome: valore, separate da CRLF. Prima della prima richiesta e dopo l'errore di rete: una riga vuota. Le linee HTTP/1.1 200 OK non sono qui; Il codice di stato non è rappresentato da un comando separato. L'ordine e le maiuscole dei nomi non sono garantiti.
- L'ultima risposta viene archiviata solo nel runtime corrente dello script. Il successivo GET/POST di questo runtime lo sostituisce; altri script eseguiti contemporaneamente non lo modificano. La risposta non viene salvata nel profilo. Se ne hai bisogno dopo la richiesta successiva, copia in anticipo il corpo e le intestazioni nelle variabili.
- GET/POST attende una risposta nel thread dello script in esecuzione. Il tempo totale per la richiesta e la lettura del corpo è di 20 secondi. L'arresto dello script annulla l'attesa; HTTP_Body/HTTP_Header non aspettarti nulla. L'intero corpo viene caricato in memoria anche quando viene trasferito FileStream; Non si tratta di un download in streaming di file di grandi dimensioni.
- Il testo viene decodificato in base al set di caratteri della risposta, in assenza/codifica sconosciuta - UTF-8. Vengono lette anche le risposte HTTP 4xx/5xx. Quando si verifica un errore di rete o un timeout, il client scrive un errore, il corpo e le intestazioni diventano vuoti; Try/Catch non sostituisce il controllo della risposta prevista. La cancellazione dello script si estende ulteriormente. Un errore di scrittura del file locale o di argomento non valido può essere rilevato da Try/Catch.
- HTTP_Header combina le intestazioni della risposta e il suo contenuto. Sono disponibili anche dopo il binario GET. Il nome deve essere controllato senza distinzione tra maiuscole e minuscole. Content-Type è un'istruzione del server, non un controllo del contenuto; non eseguire il testo scaricato come codice.
Ogni esempio può essere salvato come file separato .csx ed eseguito in IDE. Le funzioni oggetto UO e attesa forniscono l'host della sessione di gioco corrente. Sostituisci i nomi, le coordinate e gli indirizzi demo serial con i tuoi.
Esegui questo codice in un file .csx separato. Gli argomenti sono visibili nella chiamata; sostituisci nomi, serial e indirizzi di esempio con i tuoi.
Il risultato di una sola chiamata viene mostrato nel diario. Un numero non viene convertito in bool; per un array viene mostrato il numero di elementi.
UO.HTTP_Get("https://example.com/");
object? result = UO.HTTP_Header();
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parametri e flusso di esecuzione:
- I titoli vengono analizzati riga per riga. Il nome del tipo di contenuto viene confrontato senza distinzione tra maiuscole e minuscole; se non è presente alcuna stringa, viene restituita una stringa vuota.
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 "";
}Parametri e flusso di esecuzione:
- Viene controllato il testo dell'intestazione salvata localmente. Il Content-Type stesso non garantisce la correttezza di JSON; controllare il contenuto separatamente 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;
}Parametri e flusso di esecuzione:
- GET inoltra i byte di origine a System.IO.MemoryStream. Le ultime intestazioni di risposta leggono ancora HTTP_Header; il testo HTTP_Body per questo modulo è vuoto. Solo le intestazioni vengono salvate nel file.
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# distingue maiuscole e minuscole. Usare il nome UO esatto. Confrontare i flag numerici con 0; usare bool solo se la firma restituisce bool.
Parametri: Nessun parametro.
Risultato: dynamic / Any.
Durante la chiamata:
Codice interno di implementazione; non è uno script autonomo.
case "http_header": return new InjectionValue(httpHeader);Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어
dynamic UO.HTTP_Post(object? url, object? postData);Invia un testo al suo servizio HTTP utilizzando il metodo POST e restituisce il testo di risposta. Ad esempio, uno script può segnalare una fermata del percorso. Questo non è un comando Telegram/Discord già pronto: il loro protocollo, l'autorizzazione e il formato della richiesta richiedono un supporto separato.
-
url- Obbligatorio string: indirizzo completo http:// oppure https://. Sostituisci example.com con l'indirizzo del tuo servizio. Per questa richiesta non sono necessari il gioco e il server di gioco; Viene utilizzata la normale connessione di rete del processo e non il profilo proxy del gioco. -
postData— Obbligatorio string con corpo della richiesta. Inviato da UTF-8 con tipo di contenuto: text/plain; set di caratteri=utf-8. Non è prevista la codifica automatica dei moduli e il passaggio ad application/json. System.Text.Json.JsonSerializer.Serialize genera solo testo: il server di esempio dovrebbe accettare JSON esattamente come text/plain. Non è possibile configurare intestazioni personalizzate utilizzando questi comandi.
string — testo della risposta; è accessibile anche tramite HTTP_Body(). Questo non è bool e non è il codice HTTP. Una stringa vuota non indica un errore, ma una stringa non vuota non indica il successo dell'operazione sul server.
- L'ultima risposta viene archiviata solo nel runtime corrente dello script. Il successivo GET/POST di questo runtime lo sostituisce; altri script eseguiti contemporaneamente non lo modificano. La risposta non viene salvata nel profilo. Se ne hai bisogno dopo la richiesta successiva, copia in anticipo il corpo e le intestazioni nelle variabili.
- GET/POST attende una risposta nel thread dello script in esecuzione. Il tempo totale per la richiesta e la lettura del corpo è di 20 secondi. L'arresto dello script annulla l'attesa; HTTP_Body/HTTP_Header non aspettarti nulla. L'intero corpo viene caricato in memoria anche quando viene trasferito FileStream; Non si tratta di un download in streaming di file di grandi dimensioni.
- Il testo viene decodificato in base al set di caratteri della risposta, in assenza/codifica sconosciuta - UTF-8. Vengono lette anche le risposte HTTP 4xx/5xx. Quando si verifica un errore di rete o un timeout, il client scrive un errore, il corpo e le intestazioni diventano vuoti; Try/Catch non sostituisce il controllo della risposta prevista. La cancellazione dello script si estende ulteriormente. Un errore di scrittura del file locale o di argomento non valido può essere rilevato da Try/Catch.
- POST aggiorna il corpo e le intestazioni e restituisce lo stesso corpo come stringa. Non ripetere POST automaticamente solo perché la risposta è vuota: il server potrebbe aver già eseguito l'azione. Il controllo accettato/stato negli esempi è un accordo con il tuo servizio, non un segno incorporato di HTTP-successo.
Ogni esempio può essere salvato come file separato .csx ed eseguito in IDE. Le funzioni oggetto UO e attesa forniscono l'host della sessione di gioco corrente. Sostituisci i nomi, le coordinate e gli indirizzi demo serial con i tuoi.
Esegui questo codice in un file .csx separato. Gli argomenti sono visibili nella chiamata; sostituisci nomi, serial e indirizzi di esempio con i tuoi.
Il risultato di una sola chiamata viene mostrato nel diario. Un numero non viene convertito in bool; per un array viene mostrato il numero di elementi.
object? result = UO.HTTP_Post("https://example.com/", "Hello from C#");
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));Parametri e flusso di esecuzione:
- Il servizio accetta il testo Itinerario interrotto e, previo accordo, risponde con accettato. Main restituisce true solo con questo testo; Questo è un controllo del protocollo del tuo servizio, non un controllo del codice HTTP.
- Gli indirizzi example.com sono illustrativi e non forniscono tale servizio. Sostituiscili con i tuoi; l'esecuzione dell'esempio crea una vera query HTTP. L'esempio non esegue azioni di gioco.
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();Parametri e flusso di esecuzione:
- System.Text.Json.JsonSerializer evita le stringhe del dizionario. Il valore dello stato viene letto dopo aver controllato JSON; Sostituisci l'indirizzo demo con il tuo.
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;
}Parametri e flusso di esecuzione:
- firstReply e firstHeaders memorizzano la risposta POST. Il successivo GET sostituisce i buffer interni, ma le variabili locali contengono ancora la prima risposta.
- Gli indirizzi example.com sono illustrativi e non forniscono tale servizio. Sostituiscili con i tuoi; l'esecuzione dell'esempio crea una vera query HTTP. L'esempio non esegue azioni di gioco.
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# distingue maiuscole e minuscole. Usare il nome UO esatto. Confrontare i flag numerici con 0; usare bool solo se la firma restituisce bool.
Parametri: url (Any), postData (Any)
Risultato: dynamic / Any.
Durante la chiamata:
-
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility. -
ClassicUO.Game.Managers.ClassicUOInjectionApiBridge.HttpRequest:bridge.HttpRequest("POST", Text(0), Text(1)). -
InjectionScript.Runtime.InjectionApiUO.ExecuteClientApiCompatibility::Text:Text(0).
Codice interno di implementazione; non è uno script autonomo.
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);Crea un oggetto per le notifiche di testo e la ricezione di messaggi Telegram, Discord o Viber. Ad esempio, lo script potrebbe segnalare la fine della raccolta delle risorse o verificare una richiesta di interruzione da parte di un utente prespecificato. La creazione di un oggetto non connette ancora il bot e non invia nulla.
-
provider- string: "telegramma", "discord" o "viber"; il caso non è importante Altri valori causano un errore.
Oggetto Messenger. Questo non è bool e non ID. ID messaggi, mittenti e chat in questo oggetto sono sempre string: confrontali con stringhe, non convertire tramite Convert.ToInt32/Convert.ToDouble.
-
Provider() → string;Connected() → 1/0(true/false): Venditore ed esito dell'ultimo controllo autorizzativo. Connected non garantisce la disponibilità di Internet in questo momento. -
Connect(token) → null: controlla il token del bot;ConnectFromFile(path) → null: legge il token UTF-8 dal file fino a 1024 byte. Il percorso relativo viene calcolato dalla cartella dello script corrente. La riconnessione richiede Disconnect. Gli errori possono essere rilevati da Try/Catch. -
Disconnect() → null: interrompe la ricezione locale, cancella token e cursori; l'oggetto può essere nuovamente collegato.Dispose() → null: chiude completamente l'oggetto. -
SendMessage(text, recipient) → string: ID messaggio ricevuto. Parametri: chat di testo e stringhe ID Telegram, canale ID Discord o abbonato ID Viber. Limiti di lunghezza: 4096/2000/7000 rispettivamente; anche Viber JSON ≤30000 byte. Il testo vuoto è vietato. Discord non crea menzioni di tutti/ruoli. -
WatchChannel(channelId) → null: Discord, ricorda l'ultimo messaggio corrente e legge solo quelli successivi.WatchChannel(channelId, afterMessageId) → null: inizia dopo la stringa data ID; "0" include la cronologia. Fino a 32 canali per oggetto. -
Receive(timeoutSeconds) → Array;Receive(): 0 timeout. Intervallo 0..20 secondi; un array vuoto significa che non ci sono messaggi di testo disponibili. Telegram utilizza il polling long, Discord interroga i canali selezionati, Viber legge la coda del webhook. La richiesta di rete può richiedere fino a 30 secondi. - Ciascuno MessengerMessage:
Id(),SenderId(),SenderName(),ChatId(),Text()→ string. Un post di Telegram da un canale potrebbe non avere SenderId. Gli allegati, gli eventi non testuali e i messaggi Discord dei bot non verranno restituiti. -
RetryAfter() → int: quanti secondi attendere dopo aver limitato il servizio. Prima della scadenza di questo periodo, le nuove richieste HTTP non vengono eseguite. L'invio dopo un errore non viene ripetuto automaticamente: il server potrebbe aver già ricevuto il messaggio. -
StartReceiver(localPort, publicHttpsUrl) → int: solo Viber; port 1..65535, restituisce la porta locale occupata. L'indirizzo pubblico HTTPS deve terminare con /viber/ e inoltrare POST a 127.0.0.1:port/viber/ con il corpo originale e l'intestazione della firma in anticipo. Il metodo registra un webhook con Viber. - Hai bisogno di un token bot, non di una password per un account personale. Telegram con un webhook esistente viene rifiutato senza rimuoverlo. Discord richiede permessi di lettura/invio del canale e MESSAGE_CONTENT per il testo accessibile; Viber invia agli utenti iscritti.
- Receive salva il cursore solo dopo aver analizzato l'intero stack. Telegram/Discord restituisce fino a 100 voci per richiesta; richiamare nuovamente la ricezione per i pacchetti successivi. Discord senza il secondo argomento WatchChannel salta la vecchia storia.
- Viber controlla HMAC-SHA256 del corpo di origine. Coda - I messaggi 100, ripetuti ID vengono memorizzati per le ultime consegne 2048; l'overflow dà HTTP 503 per riprovare da parte del servizio. Hai bisogno di un proxy HTTPS con Content-Length; le richieste in blocchi sull'input locale vengono rifiutate.
- Il token non viene registrato nel profilo Connect, nel testo dell'errore o nella cronologia degli argomenti. Utilizzare ConnectFromFile per evitare di memorizzarlo in variabili di script visibili al debugger. Non pubblicare file token.
- Creare un oggetto all'interno di una procedura. Non più di 32 contemporaneamente; Using/Dispose lo libera prima. Quando uno script viene completato, fallisce o si interrompe, tutti i suoi oggetti messenger vengono chiusi. La chiusura del ricevitore Viber non elimina il webhook dal servizio.
- Questa è un'interfaccia testuale: non esegue il testo ricevuto come codice e non collega account di gioco. Le condizioni per fidarsi del mittente sono impostate dallo script stesso.
Ogni esempio può essere salvato come file separato .csx ed eseguito in IDE. Le funzioni oggetto UO e attesa forniscono l'host della sessione di gioco corrente. Sostituisci i nomi, le coordinate e gli indirizzi demo serial con i tuoi.
Esegui questo codice in un file .csx separato. Gli argomenti sono visibili nella chiamata; sostituisci nomi, serial e indirizzi di esempio con i tuoi.
dynamic messenger = UO.Messenger("telegram");
UO.Print(messenger.Provider());
messenger.Dispose();Parametri e flusso di esecuzione:
- Posiziona telegram-token.txt accanto allo script, sostituisci 12345678 con la tua chat ID. L'esempio invia una notifica e restituisce la stringa ID; la ricezione di una risposta dal server non conferma la lettura umana.
- Hai bisogno delle tue impostazioni del bot. Gli esempi vengono testati con risposte ai test locali; non sono stati inviati a utenti reali.
var bot = UO.Messenger("telegram");
using (var resource = bot)
{
bot.ConnectFromFile("telegram-token.txt");
var messageId = bot.SendMessage("Harvest finished", "12345678");
return messageId;
}Parametri e flusso di esecuzione:
- Inserisci il tuo canale e ID mittente consentito. true significa che questo controllo ha ricevuto da lui il testo stop; l'esempio in sé non ferma il movimento. Questo risultato può essere utilizzato nella propria condizione di ciclo di lavoro.
- Hai bisogno delle tue impostazioni del bot. Gli esempi vengono testati con risposte ai test locali; non sono stati inviati a utenti reali.
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();Parametri e flusso di esecuzione:
- System.Text.Json legge la porta locale/publicUrl. Il token viene archiviato in un file locale separato; gli invii effettivi non vengono eseguiti da questo esempio. È selezionato Trusted SenderId, non testo in entrata arbitrario.
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# distingue maiuscole e minuscole. Usare il nome UO esatto. Confrontare i flag numerici con 0; usare bool solo se la firma restituisce bool.
Parametri: provider (String)
Risultato: dynamic / Object.
Durante la chiamata:
Codice interno di implementazione; non è uno script autonomo.
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