Skip to content

LuaMenu: load LuaSocket socket.lua from the base VFS#3078

Open
tomjn wants to merge 3 commits into
beyond-all-reason:masterfrom
tomjn:luamenu/luasocket-base-vfs
Open

LuaMenu: load LuaSocket socket.lua from the base VFS#3078
tomjn wants to merge 3 commits into
beyond-all-reason:masterfrom
tomjn:luamenu/luasocket-base-vfs

Conversation

@tomjn

@tomjn tomjn commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

What

CLuaMenu::InitLuaSocket loaded a bare "socket.lua" from the default VFS
(SPRING_VFS_RAW_FIRST). That path never resolves: the file actually ships in
springcontent.sdz at LuaSocket/socket.lua. So the menu/lobby's LuaSocket
layer never initialised, logged Error loading socket.lua, and Chobby could
not connect to multiplayer servers.

It now loads LuaSocket/socket.lua from SPRING_VFS_BASE with a FileExists
guard, exactly matching the already-correct CLuaUI::InitLuaSocket.

Why this is cross-platform

This is a general VFS-path bug, not platform-specific. The lookup fails on every
platform because the requested path/mode never matched the file's actual
location in the base content; it merely surfaced first during macOS lobby
testing. The fix brings the menu's socket init in line with the in-game UI's,
which has always used the correct path and mode.

Verification

engine-headless builds on macOS with the change (LuaMenu.cpp recompiled,
spring-headless linked). Building alone does not exercise the runtime path;
functional verification (lobby connecting to a multiplayer server via Chobby)
is recommended. The mechanism is straightforward: socket.lua now resolves
from the base VFS, so luaopen_socket_core plus the Lua wrapper initialise.

Provenance

Ported from e9ca2151b5 in ExaDev/RecoilEngine.

AI disclosure

Diagnosis and patch prepared with AI assistance (Claude). The change is a small,
verbatim alignment with existing CLuaUI::InitLuaSocket; reviewed and built
locally by a human.

CLuaMenu::InitLuaSocket looked for a bare 'socket.lua' in the default VFS
(SPRING_VFS_RAW_FIRST), which never resolved: the file actually ships in
springcontent.sdz at LuaSocket/socket.lua. As a result the menu/lobby's
LuaSocket layer failed to initialise and logged 'Error loading socket.lua',
so Chobby could not connect to multiplayer servers.

Load it from SPRING_VFS_BASE using the correct LuaSocket/socket.lua path,
with a FileExists guard, exactly matching the working CLuaUI::InitLuaSocket.
This is a general VFS-path bug, not platform-specific.

Ported from ExaDev/RecoilEngine e9ca215.

@sprunk sprunk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function seems to be the same in LuaUI and LuaMenu now so should probably be extracted into /rts/Lua/LuaLibs.cpp as something like LuaLibs::OpenLuaSocket.

@tomjn

tomjn commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

@sprunk The shared body ends with LoadCode which is protected in CLuaHandle, so a LuaLibs::OpenLuaSocket can't call it directly without either taking the load step as a callback or replicating LoadCode's traceback/fenv handling.

As both CLuaUI and CLuaMenu derive from CLuaHandle, maybe we should put it in a CLuaHandle::InitLuaSocket so they both inherit instead?

Something like this:

// rts/Lua/LuaHandle.h  (in the protected: section, near LoadCode at line 331)
      bool InitLuaSocket(lua_State* L);

// rts/Lua/LuaHandle.cpp
bool CLuaHandle::InitLuaSocket(lua_State* L)
{
      RECOIL_DETAILED_TRACY_ZONE;
      // socket.lua ships in springcontent.sdz under LuaSocket/; load it from the
      // base VFS. A bare "socket.lua" in the default VFS never resolves, so the
      // menu/lobby's LuaSocket support failed to initialise, breaking multiplayer
      // connections from Chobby.
      const std::string filename = "LuaSocket/socket.lua";
      CFileHandler f(filename, SPRING_VFS_BASE);

      if (!f.FileExists()) {
              LOG_L(L_ERROR, "Error loading %s (file does not exist)", filename.c_str());
              return false;
      }

      LUA_OPEN_LIB(L, luaopen_socket_core);

      std::string code;
      if (!f.LoadStringData(code)) {
              LOG_L(L_ERROR, "Error loading %s", filename.c_str());
              return false;
      }

      return LoadCode(L, std::move(code), filename);
}

@sprunk

sprunk commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

Sounds okay. Being in LuaLibs would be ideal because that's where all the other "open lib" functions are, but if that is hard (idk, make LoadCode public and OpenLuaSocket a template?) then commonizing it elsewhere is also fine.

tomjn and others added 2 commits June 30, 2026 13:53
CLuaUI and CLuaMenu had identical InitLuaSocket bodies after beyond-all-reason#3078.
Commonise as a protected CLuaHandle::InitLuaSocket so both inherit a
single source of truth, per sprunk's review on beyond-all-reason#3078.

A free LuaLibs::OpenLuaSocket would require making the privileged
CLuaHandle::LoadCode public (templating a free function does not grant
access to a protected member), so the protected-member form sprunk
also OK'd is used instead.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants