Skip to content

IT UO Topic http

Codex edited this page Oct 12, 2026 · 4 revisions

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

HTTP

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.

Sezioni

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

Tutti i comandi del tema

HTTP Richieste

UO.HTTP_Get · UO.HTTP_Post · UO.HTTP_Header · UO.HTTP_Body

Esempi sull'argomento

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.

UO.HTTP_Get

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;

UO.HTTP_Body

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();

Riferimento completo dei comandi


UO.HTTP_Body

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

Firme C#

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.

Parametri

Non ci sono parametri.

Valore restituito

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.

Comportamento

  • 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.

Script C# autonomi

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.

Esempio semplice

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));

1. Consenti azione solo con il testo previsto: script diretto

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();

2. Raccogli una descrizione da due risposte: funzione script

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;
}

3. Separa il flusso binario dal buffer di testo: classe di script

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;
    }
}

Implementazione del comando

C# distingue maiuscole e minuscole. Usare il nome UO esatto. Confrontare i flag numerici con 0; usare bool solo se la firma restituisce bool.

UO.HTTP_Body() — UO.HTTP_Body()

Parametri: Nessun parametro.

Risultato: dynamic / Any.

Durante la chiamata:

Codice interno di implementazione; non è uno script autonomo.

case "http_body": return new InjectionValue(httpBody);

UO.HTTP_Get

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

Firme C#

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.

Parametri

  • 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.

Valore restituito

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.

Comportamento

  • 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.

Script C# autonomi

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.

Esempio semplice

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/");

1. Leggi la configurazione JSON con controllo dell'intervallo - script diretto

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;

2. Controlla i byte binari prima di salvare il file - funzione script

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;
}

3. Scarica la risposta binaria direttamente nella classe FileStream dello script

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;
    }
}

Implementazione del comando

C# distingue maiuscole e minuscole. Usare il nome UO esatto. Confrontare i flag numerici con 0; usare bool solo se la firma restituisce bool.

UO.HTTP_Get(url) — UO.HTTP_Get(Any)

Parametri: url (Any)

Risultato: void / Unit.

Durante la chiamata:

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;

                }

UO.HTTP_Get(url, lStream) — UO.HTTP_Get(Any,Any)

Parametri: url (Any), lStream (Any)

Risultato: void / Unit.

Durante la chiamata:

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;

                }

UO.HTTP_Header

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

Firme C#

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.

Parametri

Non ci sono parametri.

Valore restituito

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.

Comportamento

  • 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.

Script C# autonomi

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.

Esempio semplice

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));

1. Leggi l'intestazione della risposta senza distinzione tra maiuscole e minuscole: script diretto

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 "";
}

2. Controlla dichiarato JSON Content-Type - funzione script

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;
}

3. Salva intestazioni di risposta binaria - Classe di script

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;
    }
}

Implementazione del comando

C# distingue maiuscole e minuscole. Usare il nome UO esatto. Confrontare i flag numerici con 0; usare bool solo se la firma restituisce bool.

UO.HTTP_Header() — UO.HTTP_Header()

Parametri: Nessun parametro.

Risultato: dynamic / Any.

Durante la chiamata:

Codice interno di implementazione; non è uno script autonomo.

case "http_header": return new InjectionValue(httpHeader);

UO.HTTP_Post

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

Firme C#

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.

Parametri

  • 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.

Valore restituito

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.

Comportamento

  • 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.

Script C# autonomi

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.

Esempio semplice

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));

1. Controlla la risposta concordata del servizio - script diretto

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();

2. Invia risposta JSON serializzata e analizza la risposta JSON - funzione script

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;
}

3. Salva la risposta fino alla richiesta successiva: classe di script

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;
    }
}

Implementazione del comando

C# distingue maiuscole e minuscole. Usare il nome UO esatto. Confrontare i flag numerici con 0; usare bool solo se la firma restituisce bool.

UO.HTTP_Post(url, postData) — UO.HTTP_Post(Any,Any)

Parametri: url (Any), postData (Any)

Risultato: dynamic / Any.

Durante la chiamata:

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);

                }

UO.Messenger

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

Firme C#

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.

Parametri

  • provider - string: "telegramma", "discord" o "viber"; il caso non è importante Altri valori causano un errore.

Valore restituito

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.

Comportamento

  • 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.

Script C# autonomi

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.

Esempio semplice

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();

1. Telegram: notifica al termine dei lavori - script diretto

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;
}

2. Discord: richiesta di interruzione da parte dell'utente selezionato - Funzione script

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();

3. Carica le impostazioni del ricevitore dal file JSON - classe script

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;
}

Implementazione del comando

C# distingue maiuscole e minuscole. Usare il nome UO esatto. Confrontare i flag numerici con 0; usare bool solo se la firma restituisce bool.

UO.Messenger(provider) — UO.Messenger(String)

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;
        }

Clone this wiki locally