Skip to content

Going online

Tom_XV edited this page Sep 23, 2026 · 3 revisions

English | 日本語

Experimental. This came in with core 1.2.0, and mods network with Tool window 1.1.0 (framework 1.2.0, 2026-09-17).

A mod runs with the same rights as the game, so it can send anything anywhere. Players can't see that happen, and most never read a mod's source. So the framework has a simple rule: a mod that connects to the internet says so, and players can see it on the Mods screen before anything surprises them.

Why

Talking to the internet is also where malware would hide. A mod can send a player's files away, or fetch and run code, and look like any other mod while it does. The framework can't stop a mod that's written to deceive (see What it is not). What it can do is make going online something every mod has to say openly. That way:

  • players can see, before and while they play, which mods talk to which hosts and why
  • a mod that connects somewhere it never mentioned stands out, on the Mods screen and in the log, where players, reviewers and other mod makers will notice it
  • honest mod makers have a plain, standard way to say what they do.

There are three parts to it: a rule for mod makers (GUIDE rule 11), a declaration in ModInfo.Network that the Mods screen shows, and a watch that notes which mods actually connected and marks the ones that didn't say so.

For mod authors: the rule

A mod that connects to the internet lists every host in ModInfo.Network, with what it's for, what it sends and how to turn it off. Anything about the player (their name, their save, what they typed, an ID that follows them) is sent only after they turn it on. A check that sends nothing about the player may be on by default, like the framework's own update check.

For mod authors: the declaration

ModFramework.Register(new ModInfo
{
    Guid = MyMod.Guid,
    DisplayName = "My Mod",
    Network = new[]
    {
        new NetworkUse
        {
            Host = "api.example.com",          // or "*.example.com"
            Purpose = "Downloads the latest word list once a day.",
            Sends = "The language you chose. Nothing that identifies you.",
            TurnOff = "Mods → My Mod → Settings → Online word list",
        },
    },
});
  • A host has to match exactly, or you can write *.example.com to cover example.com and everything under it. If your mod connects to a bare address, it declares that address.
  • UpdateRepository needs nothing extra. The framework makes that request (to api.github.com) on the mod's behalf and declares it for the mod, the same way it declares its own update check. When the player turns update checks off, those entries go away.
  • Write TurnOff as the path a player follows on the Mods screen.

For players: what you see

On the Mods screen (Options → Mods):

  • The list shows an Online tag on every mod that declares a host or was seen connecting.
  • The details show Uses the internet: with the hosts.
  • The mod's Internet tab lists each host with What for, What is sent and How to turn it off, then what the mod was seen connecting to this session. It's a tab next to About and Settings (1.5.0). Before that, it was a page you opened with a button above Settings.
  • Warning colour means the mod connected to a host it didn't declare. The details then say Went online without saying so: with a button to the Internet tab, the tab gets a warning dot, and the tab marks that host not declared by the mod. The mod also shows up under the Needs attention filter (1.5.0). The log has a warning too.

mods network in the Console prints the same thing for every loaded plugin.

The watch

NetworkWatch (Mods → Drag'n Wash ModFramework → Settings → Watch connections, [Network] Watch connections, on by default) notes which mod connected where. It watches these calls:

API Watched
UnityWebRequest SendWebRequest()
WebRequest (and so WebClient) Create, CreateDefault, CreateHttp
HttpClient SendAsync(request, option, token), which every Get/Post/Send ends up in. Watched once System.Net.Http loads
Socket Connect(EndPoint), Connect(host, port), BeginConnect(EndPoint, ...), BeginConnect(host, port, ...), ConnectAsync(SocketAsyncEventArgs), SendTo(..., EndPoint)
TcpClient Connect(host, port)

For each call, it finds the first plugin on the calling stack and records the mod, the host and the API. The first time a mod reaches a host, the log gets an info line if that host was declared. If it wasn't, the log gets a warning and the mod gets the marks on the Mods screen described above.

  • Only the outermost call counts. CreateHttp calls Create, and Connect("host") calls Connect(address), but only one entry is kept, the one with the host name. A socket opened inside HttpWebRequest, HttpClient or TLS is left to the call that started it.
  • file:, jar: and other non-network URLs aren't counted, and neither are localhost and loopback addresses. Name lookups (Dns) aren't watched, because a lookup on its own only sends a name to the resolver.
  • Credit goes to the first plugin on the stack. Work a library does for a mod counts as the library's. Code that runs later on another thread with no mod on its stack (an async continuation) isn't credited to anyone and isn't recorded, since the call that started it already was.
  • The cost is a stack walk per watched call. Connections are rare, so it doesn't matter.

What it is not

It only watches. Nothing is blocked, delayed or changed, and a failure inside the watch is swallowed so the mod's request still runs.

It's not a security boundary. Native code, a mod's own socket library, Harmony tricks that remove the watch, or code that hides its calling stack all get past it. It makes honest use visible and makes mistakes stand out, but it can't prove a mod is safe. The Internet tab says so in one line.

Switching things off

  • To stop a mod's own connections, follow what its Internet tab says under How to turn it off, or switch the mod off on the Mods screen.
  • Update checks (the framework's and every mod's with UpdateRepository) are switched off at Mods → Drag'n Wash ModFramework → Settings → Check for updates.
  • The watch itself is switched off at Mods → Drag'n Wash ModFramework → Settings → Watch connections. With it off, nothing is recorded and the Internet tab says watching is off. Declarations are still shown.

API

API Member
NetworkUse Host, Purpose, Sends, TurnOff
ModInfo.Network NetworkUse[]
NetworkWatch.Enabled The player's setting
NetworkWatch.DeclaredBy(guid) What a mod declares, plus the framework's update check for it
NetworkWatch.SeenBy(guid) / All() Connections this session: Guid, Host, Via, Count, Declared, FirstSeenUtc
NetworkWatch.HasUndeclared(guid) True when the mod reached a host it did not declare

Clone this wiki locally