openvibers/source.openvibe.games Commits

Continuing phase...

CO Copilot committed 29 Jun 2026 · 21cc04e0cb · 11 files, +1377 −9


Changes

ddiff --git a/.tmp/quickjs-smoke/smoke-quickjs b/.tmp/quickjs-smoke/smoke-quickjs
iindex 472d2b0..e5fdd1a 100755
BBinary files a/.tmp/quickjs-smoke/smoke-quickjs and b/.tmp/quickjs-smoke/smoke-quickjs differ
ddiff --git a/sdk/openvibe/third_party/quickjs/quickjs.c b/sdk/openvibe/third_party/quickjs/quickjs.c
iindex e3716a4..6fd00ad 100644
---- a/sdk/openvibe/third_party/quickjs/quickjs.c
++++ b/sdk/openvibe/third_party/quickjs/quickjs.c
@@@ -1,3 +1,20 @@
++#ifndef OPENVIBE_QUICKJS_STRICT_C_SHIM
++#define OPENVIBE_QUICKJS_STRICT_C_SHIM
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE
++#endif
++
++#ifndef CONFIG_VERSION
++#define CONFIG_VERSION "openvibe"
++#endif
++
++#if defined(__GNUC__) && !defined(__cplusplus) && defined(__STRICT_ANSI__) && !defined(asm)
++#define asm __asm__
++#endif
++
++#endif
++
/*
* QuickJS Javascript Engine
*
ddiff --git a/tools/apply-openvibe-sdk.sh b/tools/apply-openvibe-sdk.sh
iindex d5007d6..cbe2219 100755
---- a/tools/apply-openvibe-sdk.sh
++++ b/tools/apply-openvibe-sdk.sh
@@@ -53,6 +53,8 @@ copy_file "$ROOT/sdk/openvibe/server/hl2mp/openvibe_js_server.cpp" \
copy_tree "$ROOT/sdk/openvibe/third_party/quickjs" \
"$SDK/src/game/shared/openvibe/third_party/quickjs"
++"$ROOT/tools/build-quickjs-lib.sh"
++
QJS_C="$SDK/src/game/shared/openvibe/third_party/quickjs/quickjs.c"
if [[ -f "$QJS_C" ]] && ! grep -q 'OPENVIBE_QUICKJS_CONFIG' "$QJS_C"; then
tmp="$(mktemp)"
@@@ -88,13 +90,7 @@ perl -0pi -e '
s/^.*openvibe\\ov_js_runtime\.cpp.*\n//mg;
s/^.*openvibe\\ov_js_bindings\.cpp.*\n//mg;
s/^.*openvibe\\ov_js_player\.cpp.*\n//mg;
-- s/^.*openvibe\\third_party\\quickjs\\quickjs\.c.*\n//mg;
-- s/^.*openvibe\\third_party\\quickjs\\libregexp\.c.*\n//mg;
-- s/^.*openvibe\\third_party\\quickjs\\libunicode\.c.*\n//mg;
-- s/^.*openvibe\\third_party\\quickjs\\cutils\.c.*\n//mg;
-- s/^.*openvibe\\third_party\\quickjs\\dtoa\.c.*\n//mg;
-- s/^.*openvibe\\third_party\\quickjs\\libbf\.c.*\n//mg;
-- s/(\$File\s+"hl2mp\\hl2mp_player\.h"\n)/$1\t\t\t\$File\t"hl2mp\\openvibe_server.cpp"\n\t\t\t\$File\t"hl2mp\\openvibe_js_server.cpp"\n\t\t\t\$File\t"..\\shared\\openvibe\\ov_js_runtime.cpp"\n\t\t\t\$File\t"..\\shared\\openvibe\\ov_js_bindings.cpp"\n\t\t\t\$File\t"..\\shared\\openvibe\\ov_js_player.cpp"\n\t\t\t\$File\t"..\\shared\\openvibe\\third_party\\quickjs\\quickjs.c"\n\t\t\t\$File\t"..\\shared\\openvibe\\third_party\\quickjs\\libregexp.c"\n\t\t\t\$File\t"..\\shared\\openvibe\\third_party\\quickjs\\libunicode.c"\n\t\t\t\$File\t"..\\shared\\openvibe\\third_party\\quickjs\\cutils.c"\n\t\t\t\$File\t"..\\shared\\openvibe\\third_party\\quickjs\\dtoa.c"\n/s;
++ s/(\$File\s+"hl2mp\\hl2mp_player\.h"\n)/$1\t\t\t\$File\t"hl2mp\\openvibe_server.cpp"\n\t\t\t\$File\t"hl2mp\\openvibe_js_server.cpp"\n\t\t\t\$File\t"..\\shared\\openvibe\\ov_js_runtime.cpp"\n\t\t\t\$File\t"..\\shared\\openvibe\\ov_js_bindings.cpp"\n\t\t\t\$File\t"..\\shared\\openvibe\\ov_js_player.cpp"\n/s;
' "$SERVER_VPC"
echo "[openvibe-sdk] patched server_hl2mp.vpc"
@@@ -170,4 +166,69 @@ p.write_text(s)
PY
fi
++
++# OPENVIBE_CONTINUE_QUICKJS_POSTPATCH
++patch_openvibe_quickjs_after_apply() {
++ local qjs_dir="$SDK/src/game/shared/openvibe/third_party/quickjs"
++ local qjs_c="$qjs_dir/quickjs.c"
++
++ if [[ -f "$qjs_c" ]] && ! grep -q 'OPENVIBE_QUICKJS_STRICT_C_SHIM' "$qjs_c"; then
++ local tmp
++ tmp="$(mktemp)"
++ cat > "$tmp" <<'QJS_SHIM'
++#ifndef OPENVIBE_QUICKJS_STRICT_C_SHIM
++#define OPENVIBE_QUICKJS_STRICT_C_SHIM
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE
++#endif
++
++#ifndef CONFIG_VERSION
++#define CONFIG_VERSION "openvibe"
++#endif
++
++#if defined(__GNUC__) && !defined(__cplusplus) && defined(__STRICT_ANSI__) && !defined(asm)
++#define asm __asm__
++#endif
++
++#endif
++
++QJS_SHIM
++ cat "$qjs_c" >> "$tmp"
++ mv "$tmp" "$qjs_c"
++ echo "[openvibe-sdk] patched QuickJS strict-C shim"
++ fi
++
++ if [[ ! -f "$qjs_dir/libbf.c" ]]; then
++ perl -0pi -e 's/^.*openvibe\\\\third_party\\\\quickjs\\\\libbf\.c.*\n//mg; s/^.*openvibe\\third_party\\quickjs\\libbf\.c.*\n//mg' "$SERVER_VPC" || true
++ echo "[openvibe-sdk] libbf.c missing; removed libbf.c from server_hl2mp.vpc"
++ fi
++}
++
++patch_openvibe_quickjs_after_apply
++
echo "[openvibe-sdk] Source SDK OpenVibe patch applied"
++
++
++# Link prebuilt QuickJS C static library. QuickJS must be compiled as C, not C++.
++if ! grep -q 'libquickjs_openvibe.a' "$SERVER_VPC"; then
++ perl -0pi -e 's/(\$File\s+"hl2mp\\openvibe_js_server\.cpp"\n)/$1\t\t\t\$Lib\t"..\\shared\\openvibe\\third_party\\quickjs\\build\\libquickjs_openvibe.a"\n/s' "$SERVER_VPC"
++ echo "[openvibe-sdk] linked QuickJS static library"
++fi
++
++
++# OPENVIBE_REMOVE_DIRECT_QUICKJS_C
++if [[ -f "$SERVER_VPC" ]]; then
++ perl -0pi -e '
++ s/^.*quickjs\\quickjs\.c.*\n//mg;
++ s/^.*quickjs\\libregexp\.c.*\n//mg;
++ s/^.*quickjs\\libunicode\.c.*\n//mg;
++ s/^.*quickjs\\cutils\.c.*\n//mg;
++ s/^.*quickjs\\dtoa\.c.*\n//mg;
++ s/^.*quickjs\\libbf\.c.*\n//mg;
++ ' "$SERVER_VPC"
++
++ if ! grep -q 'libquickjs_openvibe.a' "$SERVER_VPC"; then
++ perl -0pi -e 's/(\$File\s+"hl2mp\\openvibe_js_server\.cpp"\n)/$1\t\t\t\$Lib\t"..\\shared\\openvibe\\third_party\\quickjs\\build\\libquickjs_openvibe.a"\n/s' "$SERVER_VPC"
++ fi
++fi
ddiff --git a/tools/apply-openvibe-sdk.sh.bak.20260628-202430 b/tools/apply-openvibe-sdk.sh.bak.20260628-202430
nnew file mode 100755
iindex 0000000..d5007d6
---- /dev/null
++++ b/tools/apply-openvibe-sdk.sh.bak.20260628-202430
@@@ -0,0 +1,173 @@
++#!/usr/bin/env bash
++set -euo pipefail
++
++ROOT="${OPENVIBE_ROOT:-$HOME/src/openvibe-source}"
++SDK="${OPENVIBE_SDK:-$ROOT/engine/source-sdk-2013}"
++
++if [[ ! -d "$SDK/src/game/client/hl2mp" || ! -d "$SDK/src/game/server/hl2mp" ]]; then
++ echo "Source SDK 2013 checkout not found at $SDK" >&2
++ echo "Set OPENVIBE_SDK=/path/to/source-sdk-2013 if it lives elsewhere." >&2
++ exit 1
++fi
++
++copy_file() {
++ local src="$1"
++ local dst="$2"
++ install -D -m 0644 "$src" "$dst"
++ echo "[openvibe-sdk] copied ${dst#$SDK/}"
++}
++
++copy_tree() {
++ local src="$1"
++ local dst="$2"
++ mkdir -p "$dst"
++ rsync -a --delete "$src/" "$dst/"
++ echo "[openvibe-sdk] copied tree ${dst#$SDK/}"
++}
++
++copy_file "$ROOT/sdk/openvibe/client/hl2mp/openvibe_client.cpp" \
++ "$SDK/src/game/client/hl2mp/openvibe_client.cpp"
++copy_file "$ROOT/sdk/openvibe/client/hl2mp/vgui_openvibe_menu.cpp" \
++ "$SDK/src/game/client/hl2mp/vgui_openvibe_menu.cpp"
++copy_file "$ROOT/sdk/openvibe/server/hl2mp/openvibe_server.cpp" \
++ "$SDK/src/game/server/hl2mp/openvibe_server.cpp"
++
++copy_file "$ROOT/sdk/openvibe/shared/ov_js_runtime.h" \
++ "$SDK/src/game/shared/openvibe/ov_js_runtime.h"
++copy_file "$ROOT/sdk/openvibe/shared/ov_js_runtime.cpp" \
++ "$SDK/src/game/shared/openvibe/ov_js_runtime.cpp"
++copy_file "$ROOT/sdk/openvibe/shared/ov_js_bindings.h" \
++ "$SDK/src/game/shared/openvibe/ov_js_bindings.h"
++copy_file "$ROOT/sdk/openvibe/shared/ov_js_bindings.cpp" \
++ "$SDK/src/game/shared/openvibe/ov_js_bindings.cpp"
++copy_file "$ROOT/sdk/openvibe/shared/ov_js_player.h" \
++ "$SDK/src/game/shared/openvibe/ov_js_player.h"
++copy_file "$ROOT/sdk/openvibe/shared/ov_js_player.cpp" \
++ "$SDK/src/game/shared/openvibe/ov_js_player.cpp"
++
++copy_file "$ROOT/sdk/openvibe/server/hl2mp/openvibe_js_server.h" \
++ "$SDK/src/game/server/hl2mp/openvibe_js_server.h"
++copy_file "$ROOT/sdk/openvibe/server/hl2mp/openvibe_js_server.cpp" \
++ "$SDK/src/game/server/hl2mp/openvibe_js_server.cpp"
++
++copy_tree "$ROOT/sdk/openvibe/third_party/quickjs" \
++ "$SDK/src/game/shared/openvibe/third_party/quickjs"
++
++QJS_C="$SDK/src/game/shared/openvibe/third_party/quickjs/quickjs.c"
++if [[ -f "$QJS_C" ]] && ! grep -q 'OPENVIBE_QUICKJS_CONFIG' "$QJS_C"; then
++ tmp="$(mktemp)"
++ cat > "$tmp" <<'QCFG'
++#ifndef OPENVIBE_QUICKJS_CONFIG
++#define OPENVIBE_QUICKJS_CONFIG
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE
++#endif
++#ifndef CONFIG_VERSION
++#define CONFIG_VERSION "openvibe"
++#endif
++#endif
++
++QCFG
++ cat "$QJS_C" >> "$tmp"
++ mv "$tmp" "$QJS_C"
++fi
++
++CLIENT_VPC="$SDK/src/game/client/client_hl2mp.vpc"
++SERVER_VPC="$SDK/src/game/server/server_hl2mp.vpc"
++HL2MP_CLIENT="$SDK/src/game/server/hl2mp/hl2mp_client.cpp"
++HL2MP_CLIENTMODE="$SDK/src/game/client/hl2mp/clientmode_hl2mpnormal.cpp"
++GAMEINTERFACE="$SDK/src/game/server/gameinterface.cpp"
++HL2MP_PLAYER="$SDK/src/game/server/hl2mp/hl2mp_player.cpp"
++
++perl -0pi -e 's/^.*hl2mp\\openvibe_client\.cpp.*\n//mg; s/^.*hl2mp\\vgui_openvibe_menu\.cpp.*\n//mg; s/(\$File\s+"hl2mp\\clientmode_hl2mpnormal\.h"\n)/$1\t\t\t\$File\t"hl2mp\\openvibe_client.cpp"\n\t\t\t\$File\t"hl2mp\\vgui_openvibe_menu.cpp"\n/s' "$CLIENT_VPC"
++echo "[openvibe-sdk] patched client_hl2mp.vpc"
++
++perl -0pi -e '
++ s/^.*hl2mp\\openvibe_server\.cpp.*\n//mg;
++ s/^.*hl2mp\\openvibe_js_server\.cpp.*\n//mg;
++ s/^.*openvibe\\ov_js_runtime\.cpp.*\n//mg;
++ s/^.*openvibe\\ov_js_bindings\.cpp.*\n//mg;
++ s/^.*openvibe\\ov_js_player\.cpp.*\n//mg;
++ s/^.*openvibe\\third_party\\quickjs\\quickjs\.c.*\n//mg;
++ s/^.*openvibe\\third_party\\quickjs\\libregexp\.c.*\n//mg;
++ s/^.*openvibe\\third_party\\quickjs\\libunicode\.c.*\n//mg;
++ s/^.*openvibe\\third_party\\quickjs\\cutils\.c.*\n//mg;
++ s/^.*openvibe\\third_party\\quickjs\\dtoa\.c.*\n//mg;
++ s/^.*openvibe\\third_party\\quickjs\\libbf\.c.*\n//mg;
++ s/(\$File\s+"hl2mp\\hl2mp_player\.h"\n)/$1\t\t\t\$File\t"hl2mp\\openvibe_server.cpp"\n\t\t\t\$File\t"hl2mp\\openvibe_js_server.cpp"\n\t\t\t\$File\t"..\\shared\\openvibe\\ov_js_runtime.cpp"\n\t\t\t\$File\t"..\\shared\\openvibe\\ov_js_bindings.cpp"\n\t\t\t\$File\t"..\\shared\\openvibe\\ov_js_player.cpp"\n\t\t\t\$File\t"..\\shared\\openvibe\\third_party\\quickjs\\quickjs.c"\n\t\t\t\$File\t"..\\shared\\openvibe\\third_party\\quickjs\\libregexp.c"\n\t\t\t\$File\t"..\\shared\\openvibe\\third_party\\quickjs\\libunicode.c"\n\t\t\t\$File\t"..\\shared\\openvibe\\third_party\\quickjs\\cutils.c"\n\t\t\t\$File\t"..\\shared\\openvibe\\third_party\\quickjs\\dtoa.c"\n/s;
++' "$SERVER_VPC"
++echo "[openvibe-sdk] patched server_hl2mp.vpc"
++
++if ! grep -q 'OpenVibe_OnClientActive' "$HL2MP_CLIENT"; then
++ sed -i '/void Host_Say/a void OpenVibe_OnClientActive( CHL2MP_Player *pPlayer );' "$HL2MP_CLIENT"
++ sed -i '/FinishClientPutInServer( pPlayer );/a \ OpenVibe_OnClientActive( pPlayer );' "$HL2MP_CLIENT"
++ echo "[openvibe-sdk] patched hl2mp_client.cpp arrival hook"
++fi
++
++perl -0pi -e 's/[^\S\r\n]*\x0boid OpenVibe_OnClientActive/void OpenVibe_OnClientActive/g; s/\\tOpenVibe_OnClientActive/\tOpenVibe_OnClientActive/g; s/^[ \t]*void OpenVibe_OnClientActive/void OpenVibe_OnClientActive/m' "$HL2MP_CLIENT"
++
++if ! grep -q 'OpenVibe_OnClientModeInit' "$HL2MP_CLIENTMODE"; then
++ sed -i '/#include "ienginevgui.h"/a void OpenVibe_OnClientModeInit();' "$HL2MP_CLIENTMODE"
++ sed -i '/BaseClass::Init();/a \ OpenVibe_OnClientModeInit();' "$HL2MP_CLIENTMODE"
++ echo "[openvibe-sdk] patched clientmode_hl2mpnormal.cpp OpenVibe menu hook"
++fi
++
++perl -0pi -e 's/^[ \t]*tOpenVibe_OnClientModeInit\(\);/ OpenVibe_OnClientModeInit();/m' "$HL2MP_CLIENTMODE"
++
++if [[ -f "$GAMEINTERFACE" ]]; then
++ if ! grep -q 'OpenVibe_OnFrame' "$GAMEINTERFACE"; then
++ sed -i '/CServerGameDLL::GameFrame/i #ifdef HL2MP\nvoid OpenVibe_OnFrame();\n#endif' "$GAMEINTERFACE"
++ sed -i '/VPROF( "CServerGameDLL::GameFrame" );/a #ifdef HL2MP\n\tOpenVibe_OnFrame();\n#endif' "$GAMEINTERFACE"
++ echo "[openvibe-sdk] patched gameinterface.cpp frame hook"
++ fi
++
++ if ! grep -q 'OpenVibe_OnClientDisconnect' "$GAMEINTERFACE"; then
++ perl -pi -e 's/void CServerGameClients::ClientDisconnect/#ifdef HL2MP\nvoid OpenVibe_OnClientDisconnect( CBasePlayer *pPlayer );\n#endif\nvoid CServerGameClients::ClientDisconnect/' "$GAMEINTERFACE"
++ perl -0777 -pi -e 's/(void CServerGameClients::ClientDisconnect\( edict_t \*pEdict \)\s*\{\s*extern bool\s+g_fGameOver;\s*CBasePlayer \*player = \( CBasePlayer \* \)CBaseEntity::Instance\( pEdict \);)/$1\n#ifdef HL2MP\n\tif ( player ) { OpenVibe_OnClientDisconnect( player ); }\n#endif/g' "$GAMEINTERFACE"
++ echo "[openvibe-sdk] patched gameinterface.cpp disconnect hook"
++ fi
++fi
++
++if [[ -f "$HL2MP_PLAYER" ]]; then
++ if ! grep -q 'OpenVibe_OnPlayerDeath' "$HL2MP_PLAYER"; then
++ sed -i '/CHL2MP_Player::Event_Killed/i void OpenVibe_OnPlayerDeath( CHL2MP_Player *pPlayer, CBaseEntity *pKiller );' "$HL2MP_PLAYER"
++ sed -i '/CTakeDamageInfo subinfo = info;/i \ OpenVibe_OnPlayerDeath( this, info.GetAttacker() );' "$HL2MP_PLAYER"
++ echo "[openvibe-sdk] patched hl2mp_player.cpp death hook"
++ fi
++
++ if ! grep -q 'OpenVibeJS_Server_PlayerSpawn' "$HL2MP_PLAYER"; then
++ sed -i '/CHL2MP_Player::Spawn/i void OpenVibeJS_Server_PlayerSpawn( CHL2MP_Player *pPlayer );' "$HL2MP_PLAYER"
++ sed -i '0,/BaseClass::Spawn();/s//BaseClass::Spawn();\n\tOpenVibeJS_Server_PlayerSpawn( this );/' "$HL2MP_PLAYER"
++ echo "[openvibe-sdk] patched hl2mp_player.cpp spawn hook"
++ fi
++fi
++
++if [[ -f "$HL2MP_CLIENT" ]] && ! grep -q 'OpenVibeJS_Server_PlayerSay' "$HL2MP_CLIENT"; then
++ sed -i '/void Host_Say/a bool OpenVibeJS_Server_PlayerSay( CHL2MP_Player *pPlayer, const char *pszText );' "$HL2MP_CLIENT"
++ python3 - "$HL2MP_CLIENT" <<'PY'
++from pathlib import Path
++import re, sys
++
++p = Path(sys.argv[1])
++s = p.read_text()
++
++# Best-effort patch for common Source SDK 2013 HL2MP Host_Say shape:
++# CHL2MP_Player *client = ...
++# const char *p = args.ArgS();
++if "OpenVibeJS_Server_PlayerSay( client," not in s:
++ s2 = re.sub(
++ r'(const char \*p\s*=\s*args\.ArgS\(\);\s*)',
++ r'\1\n\tif ( client && OpenVibeJS_Server_PlayerSay( client, p ) )\n\t\treturn;\n',
++ s,
++ count=1,
++ )
++ if s2 != s:
++ s = s2
++ print("[openvibe-sdk] patched hl2mp_client.cpp PlayerSay hook")
++ else:
++ print("[openvibe-sdk] WARNING: could not auto-patch Host_Say PlayerSay body")
++p.write_text(s)
++PY
++fi
++
++echo "[openvibe-sdk] Source SDK OpenVibe patch applied"
ddiff --git a/tools/apply-openvibe-sdk.sh.bak.20260628-202702 b/tools/apply-openvibe-sdk.sh.bak.20260628-202702
nnew file mode 100755
iindex 0000000..cff52fc
---- /dev/null
++++ b/tools/apply-openvibe-sdk.sh.bak.20260628-202702
@@@ -0,0 +1,214 @@
++#!/usr/bin/env bash
++set -euo pipefail
++
++ROOT="${OPENVIBE_ROOT:-$HOME/src/openvibe-source}"
++SDK="${OPENVIBE_SDK:-$ROOT/engine/source-sdk-2013}"
++
++if [[ ! -d "$SDK/src/game/client/hl2mp" || ! -d "$SDK/src/game/server/hl2mp" ]]; then
++ echo "Source SDK 2013 checkout not found at $SDK" >&2
++ echo "Set OPENVIBE_SDK=/path/to/source-sdk-2013 if it lives elsewhere." >&2
++ exit 1
++fi
++
++copy_file() {
++ local src="$1"
++ local dst="$2"
++ install -D -m 0644 "$src" "$dst"
++ echo "[openvibe-sdk] copied ${dst#$SDK/}"
++}
++
++copy_tree() {
++ local src="$1"
++ local dst="$2"
++ mkdir -p "$dst"
++ rsync -a --delete "$src/" "$dst/"
++ echo "[openvibe-sdk] copied tree ${dst#$SDK/}"
++}
++
++copy_file "$ROOT/sdk/openvibe/client/hl2mp/openvibe_client.cpp" \
++ "$SDK/src/game/client/hl2mp/openvibe_client.cpp"
++copy_file "$ROOT/sdk/openvibe/client/hl2mp/vgui_openvibe_menu.cpp" \
++ "$SDK/src/game/client/hl2mp/vgui_openvibe_menu.cpp"
++copy_file "$ROOT/sdk/openvibe/server/hl2mp/openvibe_server.cpp" \
++ "$SDK/src/game/server/hl2mp/openvibe_server.cpp"
++
++copy_file "$ROOT/sdk/openvibe/shared/ov_js_runtime.h" \
++ "$SDK/src/game/shared/openvibe/ov_js_runtime.h"
++copy_file "$ROOT/sdk/openvibe/shared/ov_js_runtime.cpp" \
++ "$SDK/src/game/shared/openvibe/ov_js_runtime.cpp"
++copy_file "$ROOT/sdk/openvibe/shared/ov_js_bindings.h" \
++ "$SDK/src/game/shared/openvibe/ov_js_bindings.h"
++copy_file "$ROOT/sdk/openvibe/shared/ov_js_bindings.cpp" \
++ "$SDK/src/game/shared/openvibe/ov_js_bindings.cpp"
++copy_file "$ROOT/sdk/openvibe/shared/ov_js_player.h" \
++ "$SDK/src/game/shared/openvibe/ov_js_player.h"
++copy_file "$ROOT/sdk/openvibe/shared/ov_js_player.cpp" \
++ "$SDK/src/game/shared/openvibe/ov_js_player.cpp"
++
++copy_file "$ROOT/sdk/openvibe/server/hl2mp/openvibe_js_server.h" \
++ "$SDK/src/game/server/hl2mp/openvibe_js_server.h"
++copy_file "$ROOT/sdk/openvibe/server/hl2mp/openvibe_js_server.cpp" \
++ "$SDK/src/game/server/hl2mp/openvibe_js_server.cpp"
++
++copy_tree "$ROOT/sdk/openvibe/third_party/quickjs" \
++ "$SDK/src/game/shared/openvibe/third_party/quickjs"
++
++QJS_C="$SDK/src/game/shared/openvibe/third_party/quickjs/quickjs.c"
++if [[ -f "$QJS_C" ]] && ! grep -q 'OPENVIBE_QUICKJS_CONFIG' "$QJS_C"; then
++ tmp="$(mktemp)"
++ cat > "$tmp" <<'QCFG'
++#ifndef OPENVIBE_QUICKJS_CONFIG
++#define OPENVIBE_QUICKJS_CONFIG
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE
++#endif
++#ifndef CONFIG_VERSION
++#define CONFIG_VERSION "openvibe"
++#endif
++#endif
++
++QCFG
++ cat "$QJS_C" >> "$tmp"
++ mv "$tmp" "$QJS_C"
++fi
++
++CLIENT_VPC="$SDK/src/game/client/client_hl2mp.vpc"
++SERVER_VPC="$SDK/src/game/server/server_hl2mp.vpc"
++HL2MP_CLIENT="$SDK/src/game/server/hl2mp/hl2mp_client.cpp"
++HL2MP_CLIENTMODE="$SDK/src/game/client/hl2mp/clientmode_hl2mpnormal.cpp"
++GAMEINTERFACE="$SDK/src/game/server/gameinterface.cpp"
++HL2MP_PLAYER="$SDK/src/game/server/hl2mp/hl2mp_player.cpp"
++
++perl -0pi -e 's/^.*hl2mp\\openvibe_client\.cpp.*\n//mg; s/^.*hl2mp\\vgui_openvibe_menu\.cpp.*\n//mg; s/(\$File\s+"hl2mp\\clientmode_hl2mpnormal\.h"\n)/$1\t\t\t\$File\t"hl2mp\\openvibe_client.cpp"\n\t\t\t\$File\t"hl2mp\\vgui_openvibe_menu.cpp"\n/s' "$CLIENT_VPC"
++echo "[openvibe-sdk] patched client_hl2mp.vpc"
++
++perl -0pi -e '
++ s/^.*hl2mp\\openvibe_server\.cpp.*\n//mg;
++ s/^.*hl2mp\\openvibe_js_server\.cpp.*\n//mg;
++ s/^.*openvibe\\ov_js_runtime\.cpp.*\n//mg;
++ s/^.*openvibe\\ov_js_bindings\.cpp.*\n//mg;
++ s/^.*openvibe\\ov_js_player\.cpp.*\n//mg;
++ s/^.*openvibe\\third_party\\quickjs\\quickjs\.c.*\n//mg;
++ s/^.*openvibe\\third_party\\quickjs\\libregexp\.c.*\n//mg;
++ s/^.*openvibe\\third_party\\quickjs\\libunicode\.c.*\n//mg;
++ s/^.*openvibe\\third_party\\quickjs\\cutils\.c.*\n//mg;
++ s/^.*openvibe\\third_party\\quickjs\\dtoa\.c.*\n//mg;
++ s/^.*openvibe\\third_party\\quickjs\\libbf\.c.*\n//mg;
++ s/(\$File\s+"hl2mp\\hl2mp_player\.h"\n)/$1\t\t\t\$File\t"hl2mp\\openvibe_server.cpp"\n\t\t\t\$File\t"hl2mp\\openvibe_js_server.cpp"\n\t\t\t\$File\t"..\\shared\\openvibe\\ov_js_runtime.cpp"\n\t\t\t\$File\t"..\\shared\\openvibe\\ov_js_bindings.cpp"\n\t\t\t\$File\t"..\\shared\\openvibe\\ov_js_player.cpp"\n\t\t\t\$File\t"..\\shared\\openvibe\\third_party\\quickjs\\quickjs.c"\n\t\t\t\$File\t"..\\shared\\openvibe\\third_party\\quickjs\\libregexp.c"\n\t\t\t\$File\t"..\\shared\\openvibe\\third_party\\quickjs\\libunicode.c"\n\t\t\t\$File\t"..\\shared\\openvibe\\third_party\\quickjs\\cutils.c"\n\t\t\t\$File\t"..\\shared\\openvibe\\third_party\\quickjs\\dtoa.c"\n/s;
++' "$SERVER_VPC"
++echo "[openvibe-sdk] patched server_hl2mp.vpc"
++
++if ! grep -q 'OpenVibe_OnClientActive' "$HL2MP_CLIENT"; then
++ sed -i '/void Host_Say/a void OpenVibe_OnClientActive( CHL2MP_Player *pPlayer );' "$HL2MP_CLIENT"
++ sed -i '/FinishClientPutInServer( pPlayer );/a \ OpenVibe_OnClientActive( pPlayer );' "$HL2MP_CLIENT"
++ echo "[openvibe-sdk] patched hl2mp_client.cpp arrival hook"
++fi
++
++perl -0pi -e 's/[^\S\r\n]*\x0boid OpenVibe_OnClientActive/void OpenVibe_OnClientActive/g; s/\\tOpenVibe_OnClientActive/\tOpenVibe_OnClientActive/g; s/^[ \t]*void OpenVibe_OnClientActive/void OpenVibe_OnClientActive/m' "$HL2MP_CLIENT"
++
++if ! grep -q 'OpenVibe_OnClientModeInit' "$HL2MP_CLIENTMODE"; then
++ sed -i '/#include "ienginevgui.h"/a void OpenVibe_OnClientModeInit();' "$HL2MP_CLIENTMODE"
++ sed -i '/BaseClass::Init();/a \ OpenVibe_OnClientModeInit();' "$HL2MP_CLIENTMODE"
++ echo "[openvibe-sdk] patched clientmode_hl2mpnormal.cpp OpenVibe menu hook"
++fi
++
++perl -0pi -e 's/^[ \t]*tOpenVibe_OnClientModeInit\(\);/ OpenVibe_OnClientModeInit();/m' "$HL2MP_CLIENTMODE"
++
++if [[ -f "$GAMEINTERFACE" ]]; then
++ if ! grep -q 'OpenVibe_OnFrame' "$GAMEINTERFACE"; then
++ sed -i '/CServerGameDLL::GameFrame/i #ifdef HL2MP\nvoid OpenVibe_OnFrame();\n#endif' "$GAMEINTERFACE"
++ sed -i '/VPROF( "CServerGameDLL::GameFrame" );/a #ifdef HL2MP\n\tOpenVibe_OnFrame();\n#endif' "$GAMEINTERFACE"
++ echo "[openvibe-sdk] patched gameinterface.cpp frame hook"
++ fi
++
++ if ! grep -q 'OpenVibe_OnClientDisconnect' "$GAMEINTERFACE"; then
++ perl -pi -e 's/void CServerGameClients::ClientDisconnect/#ifdef HL2MP\nvoid OpenVibe_OnClientDisconnect( CBasePlayer *pPlayer );\n#endif\nvoid CServerGameClients::ClientDisconnect/' "$GAMEINTERFACE"
++ perl -0777 -pi -e 's/(void CServerGameClients::ClientDisconnect\( edict_t \*pEdict \)\s*\{\s*extern bool\s+g_fGameOver;\s*CBasePlayer \*player = \( CBasePlayer \* \)CBaseEntity::Instance\( pEdict \);)/$1\n#ifdef HL2MP\n\tif ( player ) { OpenVibe_OnClientDisconnect( player ); }\n#endif/g' "$GAMEINTERFACE"
++ echo "[openvibe-sdk] patched gameinterface.cpp disconnect hook"
++ fi
++fi
++
++if [[ -f "$HL2MP_PLAYER" ]]; then
++ if ! grep -q 'OpenVibe_OnPlayerDeath' "$HL2MP_PLAYER"; then
++ sed -i '/CHL2MP_Player::Event_Killed/i void OpenVibe_OnPlayerDeath( CHL2MP_Player *pPlayer, CBaseEntity *pKiller );' "$HL2MP_PLAYER"
++ sed -i '/CTakeDamageInfo subinfo = info;/i \ OpenVibe_OnPlayerDeath( this, info.GetAttacker() );' "$HL2MP_PLAYER"
++ echo "[openvibe-sdk] patched hl2mp_player.cpp death hook"
++ fi
++
++ if ! grep -q 'OpenVibeJS_Server_PlayerSpawn' "$HL2MP_PLAYER"; then
++ sed -i '/CHL2MP_Player::Spawn/i void OpenVibeJS_Server_PlayerSpawn( CHL2MP_Player *pPlayer );' "$HL2MP_PLAYER"
++ sed -i '0,/BaseClass::Spawn();/s//BaseClass::Spawn();\n\tOpenVibeJS_Server_PlayerSpawn( this );/' "$HL2MP_PLAYER"
++ echo "[openvibe-sdk] patched hl2mp_player.cpp spawn hook"
++ fi
++fi
++
++if [[ -f "$HL2MP_CLIENT" ]] && ! grep -q 'OpenVibeJS_Server_PlayerSay' "$HL2MP_CLIENT"; then
++ sed -i '/void Host_Say/a bool OpenVibeJS_Server_PlayerSay( CHL2MP_Player *pPlayer, const char *pszText );' "$HL2MP_CLIENT"
++ python3 - "$HL2MP_CLIENT" <<'PY'
++from pathlib import Path
++import re, sys
++
++p = Path(sys.argv[1])
++s = p.read_text()
++
++# Best-effort patch for common Source SDK 2013 HL2MP Host_Say shape:
++# CHL2MP_Player *client = ...
++# const char *p = args.ArgS();
++if "OpenVibeJS_Server_PlayerSay( client," not in s:
++ s2 = re.sub(
++ r'(const char \*p\s*=\s*args\.ArgS\(\);\s*)',
++ r'\1\n\tif ( client && OpenVibeJS_Server_PlayerSay( client, p ) )\n\t\treturn;\n',
++ s,
++ count=1,
++ )
++ if s2 != s:
++ s = s2
++ print("[openvibe-sdk] patched hl2mp_client.cpp PlayerSay hook")
++ else:
++ print("[openvibe-sdk] WARNING: could not auto-patch Host_Say PlayerSay body")
++p.write_text(s)
++PY
++fi
++
++
++# OPENVIBE_CONTINUE_QUICKJS_POSTPATCH
++patch_openvibe_quickjs_after_apply() {
++ local qjs_dir="$SDK/src/game/shared/openvibe/third_party/quickjs"
++ local qjs_c="$qjs_dir/quickjs.c"
++
++ if [[ -f "$qjs_c" ]] && ! grep -q 'OPENVIBE_QUICKJS_STRICT_C_SHIM' "$qjs_c"; then
++ local tmp
++ tmp="$(mktemp)"
++ cat > "$tmp" <<'QJS_SHIM'
++#ifndef OPENVIBE_QUICKJS_STRICT_C_SHIM
++#define OPENVIBE_QUICKJS_STRICT_C_SHIM
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE
++#endif
++
++#ifndef CONFIG_VERSION
++#define CONFIG_VERSION "openvibe"
++#endif
++
++#if defined(__GNUC__) && !defined(__cplusplus) && defined(__STRICT_ANSI__) && !defined(asm)
++#define asm __asm__
++#endif
++
++#endif
++
++QJS_SHIM
++ cat "$qjs_c" >> "$tmp"
++ mv "$tmp" "$qjs_c"
++ echo "[openvibe-sdk] patched QuickJS strict-C shim"
++ fi
++
++ if [[ ! -f "$qjs_dir/libbf.c" ]]; then
++ perl -0pi -e 's/^.*openvibe\\\\third_party\\\\quickjs\\\\libbf\.c.*\n//mg; s/^.*openvibe\\third_party\\quickjs\\libbf\.c.*\n//mg' "$SERVER_VPC" || true
++ echo "[openvibe-sdk] libbf.c missing; removed libbf.c from server_hl2mp.vpc"
++ fi
++}
++
++patch_openvibe_quickjs_after_apply
++
++echo "[openvibe-sdk] Source SDK OpenVibe patch applied"
ddiff --git a/tools/apply-openvibe-sdk.sh.bak.20260628-202731 b/tools/apply-openvibe-sdk.sh.bak.20260628-202731
nnew file mode 100755
iindex 0000000..9e835bf
---- /dev/null
++++ b/tools/apply-openvibe-sdk.sh.bak.20260628-202731
@@@ -0,0 +1,217 @@
++#!/usr/bin/env bash
++set -euo pipefail
++
++ROOT="${OPENVIBE_ROOT:-$HOME/src/openvibe-source}"
++SDK="${OPENVIBE_SDK:-$ROOT/engine/source-sdk-2013}"
++
++if [[ ! -d "$SDK/src/game/client/hl2mp" || ! -d "$SDK/src/game/server/hl2mp" ]]; then
++ echo "Source SDK 2013 checkout not found at $SDK" >&2
++ echo "Set OPENVIBE_SDK=/path/to/source-sdk-2013 if it lives elsewhere." >&2
++ exit 1
++fi
++
++copy_file() {
++ local src="$1"
++ local dst="$2"
++ install -D -m 0644 "$src" "$dst"
++ echo "[openvibe-sdk] copied ${dst#$SDK/}"
++}
++
++copy_tree() {
++ local src="$1"
++ local dst="$2"
++ mkdir -p "$dst"
++ rsync -a --delete "$src/" "$dst/"
++ echo "[openvibe-sdk] copied tree ${dst#$SDK/}"
++}
++
++copy_file "$ROOT/sdk/openvibe/client/hl2mp/openvibe_client.cpp" \
++ "$SDK/src/game/client/hl2mp/openvibe_client.cpp"
++copy_file "$ROOT/sdk/openvibe/client/hl2mp/vgui_openvibe_menu.cpp" \
++ "$SDK/src/game/client/hl2mp/vgui_openvibe_menu.cpp"
++copy_file "$ROOT/sdk/openvibe/server/hl2mp/openvibe_server.cpp" \
++ "$SDK/src/game/server/hl2mp/openvibe_server.cpp"
++
++copy_file "$ROOT/sdk/openvibe/shared/ov_js_runtime.h" \
++ "$SDK/src/game/shared/openvibe/ov_js_runtime.h"
++copy_file "$ROOT/sdk/openvibe/shared/ov_js_runtime.cpp" \
++ "$SDK/src/game/shared/openvibe/ov_js_runtime.cpp"
++copy_file "$ROOT/sdk/openvibe/shared/ov_js_bindings.h" \
++ "$SDK/src/game/shared/openvibe/ov_js_bindings.h"
++copy_file "$ROOT/sdk/openvibe/shared/ov_js_bindings.cpp" \
++ "$SDK/src/game/shared/openvibe/ov_js_bindings.cpp"
++copy_file "$ROOT/sdk/openvibe/shared/ov_js_player.h" \
++ "$SDK/src/game/shared/openvibe/ov_js_player.h"
++copy_file "$ROOT/sdk/openvibe/shared/ov_js_player.cpp" \
++ "$SDK/src/game/shared/openvibe/ov_js_player.cpp"
++
++copy_file "$ROOT/sdk/openvibe/server/hl2mp/openvibe_js_server.h" \
++ "$SDK/src/game/server/hl2mp/openvibe_js_server.h"
++copy_file "$ROOT/sdk/openvibe/server/hl2mp/openvibe_js_server.cpp" \
++ "$SDK/src/game/server/hl2mp/openvibe_js_server.cpp"
++
++copy_tree "$ROOT/sdk/openvibe/third_party/quickjs" \
++ "$SDK/src/game/shared/openvibe/third_party/quickjs"
++
++"$ROOT/tools/build-quickjs-lib.sh"
++
++QJS_C="$SDK/src/game/shared/openvibe/third_party/quickjs/quickjs.c"
++if [[ -f "$QJS_C" ]] && ! grep -q 'OPENVIBE_QUICKJS_CONFIG' "$QJS_C"; then
++ tmp="$(mktemp)"
++ cat > "$tmp" <<'QCFG'
++#ifndef OPENVIBE_QUICKJS_CONFIG
++#define OPENVIBE_QUICKJS_CONFIG
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE
++#endif
++#ifndef CONFIG_VERSION
++#define CONFIG_VERSION "openvibe"
++#endif
++#endif
++
++QCFG
++ cat "$QJS_C" >> "$tmp"
++ mv "$tmp" "$QJS_C"
++fi
++
++CLIENT_VPC="$SDK/src/game/client/client_hl2mp.vpc"
++SERVER_VPC="$SDK/src/game/server/server_hl2mp.vpc"
++HL2MP_CLIENT="$SDK/src/game/server/hl2mp/hl2mp_client.cpp"
++HL2MP_CLIENTMODE="$SDK/src/game/client/hl2mp/clientmode_hl2mpnormal.cpp"
++GAMEINTERFACE="$SDK/src/game/server/gameinterface.cpp"
++HL2MP_PLAYER="$SDK/src/game/server/hl2mp/hl2mp_player.cpp"
++
++perl -0pi -e 's/^.*hl2mp\\openvibe_client\.cpp.*\n//mg; s/^.*hl2mp\\vgui_openvibe_menu\.cpp.*\n//mg; s/(\$File\s+"hl2mp\\clientmode_hl2mpnormal\.h"\n)/$1\t\t\t\$File\t"hl2mp\\openvibe_client.cpp"\n\t\t\t\$File\t"hl2mp\\vgui_openvibe_menu.cpp"\n/s' "$CLIENT_VPC"
++echo "[openvibe-sdk] patched client_hl2mp.vpc"
++
++perl -0pi -e '
++ s/^.*hl2mp\\openvibe_server\.cpp.*\n//mg;
++ s/^.*hl2mp\\openvibe_js_server\.cpp.*\n//mg;
++ s/^.*openvibe\\ov_js_runtime\.cpp.*\n//mg;
++ s/^.*openvibe\\ov_js_bindings\.cpp.*\n//mg;
++ s/^.*openvibe\\ov_js_player\.cpp.*\n//mg;
++ s/(\$File\s+"hl2mp\\hl2mp_player\.h"\n)/$1\t\t\t\$File\t"hl2mp\\openvibe_server.cpp"\n\t\t\t\$File\t"hl2mp\\openvibe_js_server.cpp"\n\t\t\t\$File\t"..\\shared\\openvibe\\ov_js_runtime.cpp"\n\t\t\t\$File\t"..\\shared\\openvibe\\ov_js_bindings.cpp"\n\t\t\t\$File\t"..\\shared\\openvibe\\ov_js_player.cpp"\n/s;
++' "$SERVER_VPC"
++echo "[openvibe-sdk] patched server_hl2mp.vpc"
++
++if ! grep -q 'OpenVibe_OnClientActive' "$HL2MP_CLIENT"; then
++ sed -i '/void Host_Say/a void OpenVibe_OnClientActive( CHL2MP_Player *pPlayer );' "$HL2MP_CLIENT"
++ sed -i '/FinishClientPutInServer( pPlayer );/a \ OpenVibe_OnClientActive( pPlayer );' "$HL2MP_CLIENT"
++ echo "[openvibe-sdk] patched hl2mp_client.cpp arrival hook"
++fi
++
++perl -0pi -e 's/[^\S\r\n]*\x0boid OpenVibe_OnClientActive/void OpenVibe_OnClientActive/g; s/\\tOpenVibe_OnClientActive/\tOpenVibe_OnClientActive/g; s/^[ \t]*void OpenVibe_OnClientActive/void OpenVibe_OnClientActive/m' "$HL2MP_CLIENT"
++
++if ! grep -q 'OpenVibe_OnClientModeInit' "$HL2MP_CLIENTMODE"; then
++ sed -i '/#include "ienginevgui.h"/a void OpenVibe_OnClientModeInit();' "$HL2MP_CLIENTMODE"
++ sed -i '/BaseClass::Init();/a \ OpenVibe_OnClientModeInit();' "$HL2MP_CLIENTMODE"
++ echo "[openvibe-sdk] patched clientmode_hl2mpnormal.cpp OpenVibe menu hook"
++fi
++
++perl -0pi -e 's/^[ \t]*tOpenVibe_OnClientModeInit\(\);/ OpenVibe_OnClientModeInit();/m' "$HL2MP_CLIENTMODE"
++
++if [[ -f "$GAMEINTERFACE" ]]; then
++ if ! grep -q 'OpenVibe_OnFrame' "$GAMEINTERFACE"; then
++ sed -i '/CServerGameDLL::GameFrame/i #ifdef HL2MP\nvoid OpenVibe_OnFrame();\n#endif' "$GAMEINTERFACE"
++ sed -i '/VPROF( "CServerGameDLL::GameFrame" );/a #ifdef HL2MP\n\tOpenVibe_OnFrame();\n#endif' "$GAMEINTERFACE"
++ echo "[openvibe-sdk] patched gameinterface.cpp frame hook"
++ fi
++
++ if ! grep -q 'OpenVibe_OnClientDisconnect' "$GAMEINTERFACE"; then
++ perl -pi -e 's/void CServerGameClients::ClientDisconnect/#ifdef HL2MP\nvoid OpenVibe_OnClientDisconnect( CBasePlayer *pPlayer );\n#endif\nvoid CServerGameClients::ClientDisconnect/' "$GAMEINTERFACE"
++ perl -0777 -pi -e 's/(void CServerGameClients::ClientDisconnect\( edict_t \*pEdict \)\s*\{\s*extern bool\s+g_fGameOver;\s*CBasePlayer \*player = \( CBasePlayer \* \)CBaseEntity::Instance\( pEdict \);)/$1\n#ifdef HL2MP\n\tif ( player ) { OpenVibe_OnClientDisconnect( player ); }\n#endif/g' "$GAMEINTERFACE"
++ echo "[openvibe-sdk] patched gameinterface.cpp disconnect hook"
++ fi
++fi
++
++if [[ -f "$HL2MP_PLAYER" ]]; then
++ if ! grep -q 'OpenVibe_OnPlayerDeath' "$HL2MP_PLAYER"; then
++ sed -i '/CHL2MP_Player::Event_Killed/i void OpenVibe_OnPlayerDeath( CHL2MP_Player *pPlayer, CBaseEntity *pKiller );' "$HL2MP_PLAYER"
++ sed -i '/CTakeDamageInfo subinfo = info;/i \ OpenVibe_OnPlayerDeath( this, info.GetAttacker() );' "$HL2MP_PLAYER"
++ echo "[openvibe-sdk] patched hl2mp_player.cpp death hook"
++ fi
++
++ if ! grep -q 'OpenVibeJS_Server_PlayerSpawn' "$HL2MP_PLAYER"; then
++ sed -i '/CHL2MP_Player::Spawn/i void OpenVibeJS_Server_PlayerSpawn( CHL2MP_Player *pPlayer );' "$HL2MP_PLAYER"
++ sed -i '0,/BaseClass::Spawn();/s//BaseClass::Spawn();\n\tOpenVibeJS_Server_PlayerSpawn( this );/' "$HL2MP_PLAYER"
++ echo "[openvibe-sdk] patched hl2mp_player.cpp spawn hook"
++ fi
++fi
++
++if [[ -f "$HL2MP_CLIENT" ]] && ! grep -q 'OpenVibeJS_Server_PlayerSay' "$HL2MP_CLIENT"; then
++ sed -i '/void Host_Say/a bool OpenVibeJS_Server_PlayerSay( CHL2MP_Player *pPlayer, const char *pszText );' "$HL2MP_CLIENT"
++ python3 - "$HL2MP_CLIENT" <<'PY'
++from pathlib import Path
++import re, sys
++
++p = Path(sys.argv[1])
++s = p.read_text()
++
++# Best-effort patch for common Source SDK 2013 HL2MP Host_Say shape:
++# CHL2MP_Player *client = ...
++# const char *p = args.ArgS();
++if "OpenVibeJS_Server_PlayerSay( client," not in s:
++ s2 = re.sub(
++ r'(const char \*p\s*=\s*args\.ArgS\(\);\s*)',
++ r'\1\n\tif ( client && OpenVibeJS_Server_PlayerSay( client, p ) )\n\t\treturn;\n',
++ s,
++ count=1,
++ )
++ if s2 != s:
++ s = s2
++ print("[openvibe-sdk] patched hl2mp_client.cpp PlayerSay hook")
++ else:
++ print("[openvibe-sdk] WARNING: could not auto-patch Host_Say PlayerSay body")
++p.write_text(s)
++PY
++fi
++
++
++# OPENVIBE_CONTINUE_QUICKJS_POSTPATCH
++patch_openvibe_quickjs_after_apply() {
++ local qjs_dir="$SDK/src/game/shared/openvibe/third_party/quickjs"
++ local qjs_c="$qjs_dir/quickjs.c"
++
++ if [[ -f "$qjs_c" ]] && ! grep -q 'OPENVIBE_QUICKJS_STRICT_C_SHIM' "$qjs_c"; then
++ local tmp
++ tmp="$(mktemp)"
++ cat > "$tmp" <<'QJS_SHIM'
++#ifndef OPENVIBE_QUICKJS_STRICT_C_SHIM
++#define OPENVIBE_QUICKJS_STRICT_C_SHIM
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE
++#endif
++
++#ifndef CONFIG_VERSION
++#define CONFIG_VERSION "openvibe"
++#endif
++
++#if defined(__GNUC__) && !defined(__cplusplus) && defined(__STRICT_ANSI__) && !defined(asm)
++#define asm __asm__
++#endif
++
++#endif
++
++QJS_SHIM
++ cat "$qjs_c" >> "$tmp"
++ mv "$tmp" "$qjs_c"
++ echo "[openvibe-sdk] patched QuickJS strict-C shim"
++ fi
++
++ if [[ ! -f "$qjs_dir/libbf.c" ]]; then
++ perl -0pi -e 's/^.*openvibe\\\\third_party\\\\quickjs\\\\libbf\.c.*\n//mg; s/^.*openvibe\\third_party\\quickjs\\libbf\.c.*\n//mg' "$SERVER_VPC" || true
++ echo "[openvibe-sdk] libbf.c missing; removed libbf.c from server_hl2mp.vpc"
++ fi
++}
++
++patch_openvibe_quickjs_after_apply
++
++echo "[openvibe-sdk] Source SDK OpenVibe patch applied"
++
++
++# Link prebuilt QuickJS C static library. QuickJS must be compiled as C, not C++.
++if ! grep -q 'libquickjs_openvibe.a' "$SERVER_VPC"; then
++ perl -0pi -e 's/(\$File\s+"hl2mp\\openvibe_js_server\.cpp"\n)/$1\t\t\t\$Lib\t"..\\shared\\openvibe\\third_party\\quickjs\\build\\libquickjs_openvibe.a"\n/s' "$SERVER_VPC"
++ echo "[openvibe-sdk] linked QuickJS static library"
++fi
ddiff --git a/tools/build-quickjs-lib.sh b/tools/build-quickjs-lib.sh
nnew file mode 100755
iindex 0000000..b7bb918
---- /dev/null
++++ b/tools/build-quickjs-lib.sh
@@@ -0,0 +1,54 @@
++#!/usr/bin/env bash
++set -euo pipefail
++
++ROOT="${OPENVIBE_ROOT:-$HOME/src/openvibe-source}"
++SDK="${OPENVIBE_SDK:-$ROOT/engine/source-sdk-2013}"
++
++SRC_QJS="$ROOT/sdk/openvibe/third_party/quickjs"
++SDK_QJS="$SDK/src/game/shared/openvibe/third_party/quickjs"
++OUT="$SDK_QJS/build"
++
++if [[ ! -f "$SRC_QJS/quickjs.c" ]]; then
++ echo "Missing $SRC_QJS/quickjs.c" >&2
++ echo "Run: tools/vendor-quickjs.sh" >&2
++ exit 1
++fi
++
++mkdir -p "$SDK_QJS"
++
++# Important: exclude build/ so rsync does not delete our object output dir.
++rsync -a --delete --exclude='build/' "$SRC_QJS/" "$SDK_QJS/"
++
++mkdir -p "$OUT"
++
++sources=(
++ quickjs.c
++ libregexp.c
++ libunicode.c
++ cutils.c
++)
++
++[[ -f "$SDK_QJS/dtoa.c" ]] && sources+=(dtoa.c)
++[[ -f "$SDK_QJS/libbf.c" ]] && sources+=(libbf.c)
++
++rm -f "$OUT"/*.o "$OUT"/libquickjs_openvibe.a
++
++for src in "${sources[@]}"; do
++ obj="$OUT/${src%.c}.o"
++ echo "[openvibe-qjs] cc $src -> $obj"
++
++ cc \
++ -std=gnu11 \
++ -O2 \
++ -fPIC \
++ -D_GNU_SOURCE \
++ -DCONFIG_VERSION=\"openvibe\" \
++ -I"$SDK_QJS" \
++ -c "$SDK_QJS/$src" \
++ -o "$obj"
++done
++
++ar rcs "$OUT/libquickjs_openvibe.a" "$OUT"/*.o
++
++echo "[openvibe-qjs] built $OUT/libquickjs_openvibe.a"
++ls -lh "$OUT/libquickjs_openvibe.a"
ddiff --git a/tools/continue-embedded-js.sh b/tools/continue-embedded-js.sh
nnew file mode 100755
iindex 0000000..26f438c
---- /dev/null
++++ b/tools/continue-embedded-js.sh
@@@ -0,0 +1,313 @@
++#!/usr/bin/env bash
++set -euo pipefail
++
++ROOT="${OPENVIBE_ROOT:-$HOME/src/openvibe-source}"
++SDK="${OPENVIBE_SDK:-$ROOT/engine/source-sdk-2013}"
++QJS="$ROOT/sdk/openvibe/third_party/quickjs"
++STAMP="$(date +%Y%m%d-%H%M%S)"
++
++cd "$ROOT"
++
++backup_file() {
++ local file="$1"
++ [[ -f "$file" ]] && cp "$file" "$file.bak.$STAMP"
++}
++
++patch_quickjs_tree() {
++ local qjs_dir="$1"
++ local qjs_c="$qjs_dir/quickjs.c"
++
++ [[ -f "$qjs_c" ]] || return 0
++
++ if ! grep -q 'OPENVIBE_QUICKJS_STRICT_C_SHIM' "$qjs_c"; then
++ local tmp
++ tmp="$(mktemp)"
++
++ cat > "$tmp" <<'QJS_SHIM'
++#ifndef OPENVIBE_QUICKJS_STRICT_C_SHIM
++#define OPENVIBE_QUICKJS_STRICT_C_SHIM
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE
++#endif
++
++#ifndef CONFIG_VERSION
++#define CONFIG_VERSION "openvibe"
++#endif
++
++#if defined(__GNUC__) && !defined(__cplusplus) && defined(__STRICT_ANSI__) && !defined(asm)
++#define asm __asm__
++#endif
++
++#endif
++
++QJS_SHIM
++
++ cat "$qjs_c" >> "$tmp"
++ mv "$tmp" "$qjs_c"
++ echo "[openvibe] patched QuickJS strict-C shim: $qjs_c"
++ fi
++}
++
++echo "[openvibe] refreshing remote branch metadata, without resetting your local files"
++git fetch origin codex/openvibe-next-steps || true
++
++echo "[openvibe] checking embedded JS files from previous step"
++
++missing=0
++for f in \
++ tools/apply-openvibe-sdk.sh \
++ sdk/openvibe/server/hl2mp/openvibe_server.cpp \
++ sdk/openvibe/shared/ov_js_runtime.cpp \
++ sdk/openvibe/shared/ov_js_bindings.cpp \
++ sdk/openvibe/shared/ov_js_player.cpp \
++ sdk/openvibe/server/hl2mp/openvibe_js_server.cpp \
++ game/openvibe.games/js/core/hook.js \
++ game/openvibe.games/js/core/gamemode.js \
++ game/openvibe.games/js/bridge.js \
++ game/openvibe.games/js/gamemodes/hub/server.js
++do
++ if [[ ! -f "$f" ]]; then
++ echo "[openvibe] MISSING: $f"
++ missing=1
++ fi
++done
++
++if [[ "$missing" = "1" ]]; then
++ echo
++ echo "[openvibe] Some embedded JS files are missing."
++ echo "[openvibe] Re-run tools/implement-embedded-js.sh first, then run this continue script again."
++ exit 1
++fi
++
++echo "[openvibe] rewriting robust QuickJS vendor script"
++
++cat > tools/vendor-quickjs.sh <<'VENDOR'
++#!/usr/bin/env bash
++set -euo pipefail
++
++ROOT="${OPENVIBE_ROOT:-$HOME/src/openvibe-source}"
++DEST="$ROOT/sdk/openvibe/third_party/quickjs"
++TMP="${TMPDIR:-/tmp}/openvibe-quickjs-vendor"
++
++rm -rf "$TMP"
++
++git clone --depth 1 https://github.com/bellard/quickjs.git "$TMP"
++
++rm -rf "$DEST"
++mkdir -p "$DEST"
++
++rsync -av \
++ --include='quickjs.c' \
++ --include='quickjs.h' \
++ --include='quickjs-atom.h' \
++ --include='quickjs-opcode.h' \
++ --include='libregexp.c' \
++ --include='libregexp.h' \
++ --include='libregexp-opcode.h' \
++ --include='libunicode.c' \
++ --include='libunicode.h' \
++ --include='libunicode-table.h' \
++ --include='cutils.c' \
++ --include='cutils.h' \
++ --include='dtoa.c' \
++ --include='dtoa.h' \
++ --include='libbf.c' \
++ --include='libbf.h' \
++ --include='list.h' \
++ --include='LICENSE' \
++ --include='VERSION' \
++ --exclude='*' \
++ "$TMP/" \
++ "$DEST/"
++
++git -C "$TMP" rev-parse HEAD > "$DEST/UPSTREAM_COMMIT"
++
++cat > "$DEST/README.openvibe.md" <<'DOC'
++# QuickJS vendored for OpenVibe: Source
++
++Vendored QuickJS core files for OpenVibe's embedded JavaScript runtime.
++
++Excluded intentionally:
++- qjs.c
++- qjsc.c
++- quickjs-libc.c
++- quickjs-libc.h
++
++Reason:
++OpenVibe embeds QuickJS as a sandboxed script VM. Community scripts should not
++receive raw std/os/filesystem/process APIs.
++DOC
++
++echo "[openvibe] vendored QuickJS into $DEST"
++echo "[openvibe] upstream commit: $(cat "$DEST/UPSTREAM_COMMIT")"
++VENDOR
++
++chmod +x tools/vendor-quickjs.sh
++
++if [[ "${FORCE_REVENDOR:-0}" = "1" || ! -f "$QJS/quickjs.c" ]]; then
++ echo "[openvibe] vendoring QuickJS"
++ tools/vendor-quickjs.sh
++else
++ echo "[openvibe] using existing QuickJS folder"
++fi
++
++patch_quickjs_tree "$QJS"
++
++echo "[openvibe] writing robust smoke test"
++
++cat > tools/smoke-quickjs.sh <<'SMOKE'
++#!/usr/bin/env bash
++set -euo pipefail
++
++ROOT="${OPENVIBE_ROOT:-$HOME/src/openvibe-source}"
++QJS="$ROOT/sdk/openvibe/third_party/quickjs"
++BUILD="$ROOT/.tmp/quickjs-smoke"
++
++rm -rf "$BUILD"
++mkdir -p "$BUILD"
++
++cat > "$BUILD/smoke.c" <<'C'
++#include <stdio.h>
++#include "quickjs.h"
++
++int main(void) {
++ JSRuntime *rt = JS_NewRuntime();
++ JSContext *ctx = JS_NewContext(rt);
++
++ JSValue value = JS_Eval(ctx, "1 + 2 + 3", 9, "<smoke>", JS_EVAL_TYPE_GLOBAL);
++ int32_t out = 0;
++ JS_ToInt32(ctx, &out, value);
++
++ JS_FreeValue(ctx, value);
++ JS_FreeContext(ctx);
++ JS_FreeRuntime(rt);
++
++ printf("quickjs result=%d\n", out);
++ return out == 6 ? 0 : 1;
++}
++C
++
++sources=(
++ "$QJS/quickjs.c"
++ "$QJS/libregexp.c"
++ "$QJS/libunicode.c"
++ "$QJS/cutils.c"
++)
++
++[[ -f "$QJS/dtoa.c" ]] && sources+=("$QJS/dtoa.c")
++[[ -f "$QJS/libbf.c" ]] && sources+=("$QJS/libbf.c")
++
++cc \
++ -std=gnu11 \
++ -D_GNU_SOURCE \
++ -DCONFIG_VERSION=\"openvibe\" \
++ -I"$QJS" \
++ "$BUILD/smoke.c" \
++ "${sources[@]}" \
++ -lm \
++ -ldl \
++ -lpthread \
++ -o "$BUILD/smoke-quickjs"
++
++"$BUILD/smoke-quickjs"
++SMOKE
++
++chmod +x tools/smoke-quickjs.sh
++
++echo "[openvibe] patching apply-openvibe-sdk.sh post-apply QuickJS cleanup"
++
++backup_file tools/apply-openvibe-sdk.sh
++
++python3 <<'PY'
++from pathlib import Path
++
++p = Path("tools/apply-openvibe-sdk.sh")
++s = p.read_text()
++
++marker = "OPENVIBE_CONTINUE_QUICKJS_POSTPATCH"
++
++block = r'''
++# OPENVIBE_CONTINUE_QUICKJS_POSTPATCH
++patch_openvibe_quickjs_after_apply() {
++ local qjs_dir="$SDK/src/game/shared/openvibe/third_party/quickjs"
++ local qjs_c="$qjs_dir/quickjs.c"
++
++ if [[ -f "$qjs_c" ]] && ! grep -q 'OPENVIBE_QUICKJS_STRICT_C_SHIM' "$qjs_c"; then
++ local tmp
++ tmp="$(mktemp)"
++ cat > "$tmp" <<'QJS_SHIM'
++#ifndef OPENVIBE_QUICKJS_STRICT_C_SHIM
++#define OPENVIBE_QUICKJS_STRICT_C_SHIM
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE
++#endif
++
++#ifndef CONFIG_VERSION
++#define CONFIG_VERSION "openvibe"
++#endif
++
++#if defined(__GNUC__) && !defined(__cplusplus) && defined(__STRICT_ANSI__) && !defined(asm)
++#define asm __asm__
++#endif
++
++#endif
++
++QJS_SHIM
++ cat "$qjs_c" >> "$tmp"
++ mv "$tmp" "$qjs_c"
++ echo "[openvibe-sdk] patched QuickJS strict-C shim"
++ fi
++
++ if [[ ! -f "$qjs_dir/libbf.c" ]]; then
++ perl -0pi -e 's/^.*openvibe\\\\third_party\\\\quickjs\\\\libbf\.c.*\n//mg; s/^.*openvibe\\third_party\\quickjs\\libbf\.c.*\n//mg' "$SERVER_VPC" || true
++ echo "[openvibe-sdk] libbf.c missing; removed libbf.c from server_hl2mp.vpc"
++ fi
++}
++
++patch_openvibe_quickjs_after_apply
++'''
++
++if marker not in s:
++ final_echo = 'echo "[openvibe-sdk] Source SDK OpenVibe patch applied"'
++ if final_echo in s:
++ s = s.replace(final_echo, block + "\n" + final_echo)
++ else:
++ s += "\n" + block + "\n"
++
++p.write_text(s)
++PY
++
++echo "[openvibe] QuickJS files:"
++find "$QJS" -maxdepth 1 -type f -printf " - %f\n" | sort
++
++echo "[openvibe] running QuickJS smoke test"
++tools/smoke-quickjs.sh
++
++echo "[openvibe] applying SDK patch"
++tools/apply-openvibe-sdk.sh
++
++SDK_QJS="$SDK/src/game/shared/openvibe/third_party/quickjs"
++patch_quickjs_tree "$SDK_QJS"
++
++if [[ ! -f "$SDK_QJS/libbf.c" ]]; then
++ SERVER_VPC="$SDK/src/game/server/server_hl2mp.vpc"
++ perl -0pi -e 's/^.*openvibe\\\\third_party\\\\quickjs\\\\libbf\.c.*\n//mg; s/^.*openvibe\\third_party\\quickjs\\libbf\.c.*\n//mg' "$SERVER_VPC" || true
++fi
++
++echo
++echo "[openvibe] continue step complete."
++echo
++echo "Next build command:"
++echo " tools/build-sdk-linux.sh 2>&1 | tee ~/ov-build.log"
++echo
++echo "If you want this script to attempt the build now:"
++echo " RUN_BUILD=1 tools/continue-embedded-js.sh"
++echo
++
++if [[ "${RUN_BUILD:-0}" = "1" ]]; then
++ echo "[openvibe] running SDK build"
++ tools/build-sdk-linux.sh 2>&1 | tee "$HOME/ov-build.log"
++ echo "[openvibe] build finished"
++fi
ddiff --git a/tools/fix-quickjs-build-dir.sh b/tools/fix-quickjs-build-dir.sh
nnew file mode 100755
iindex 0000000..2ecd08c
---- /dev/null
++++ b/tools/fix-quickjs-build-dir.sh
@@@ -0,0 +1,146 @@
++#!/usr/bin/env bash
++set -euo pipefail
++
++ROOT="${OPENVIBE_ROOT:-$HOME/src/openvibe-source}"
++SDK="${OPENVIBE_SDK:-$ROOT/engine/source-sdk-2013}"
++
++cd "$ROOT"
++
++echo "[openvibe] replacing tools/build-quickjs-lib.sh"
++
++cat > tools/build-quickjs-lib.sh <<'BUILDQJS'
++#!/usr/bin/env bash
++set -euo pipefail
++
++ROOT="${OPENVIBE_ROOT:-$HOME/src/openvibe-source}"
++SDK="${OPENVIBE_SDK:-$ROOT/engine/source-sdk-2013}"
++
++SRC_QJS="$ROOT/sdk/openvibe/third_party/quickjs"
++SDK_QJS="$SDK/src/game/shared/openvibe/third_party/quickjs"
++OUT="$SDK_QJS/build"
++
++if [[ ! -f "$SRC_QJS/quickjs.c" ]]; then
++ echo "Missing $SRC_QJS/quickjs.c" >&2
++ echo "Run: tools/vendor-quickjs.sh" >&2
++ exit 1
++fi
++
++mkdir -p "$SDK_QJS"
++
++# Important: exclude build/ so rsync does not delete our object output dir.
++rsync -a --delete --exclude='build/' "$SRC_QJS/" "$SDK_QJS/"
++
++mkdir -p "$OUT"
++
++sources=(
++ quickjs.c
++ libregexp.c
++ libunicode.c
++ cutils.c
++)
++
++[[ -f "$SDK_QJS/dtoa.c" ]] && sources+=(dtoa.c)
++[[ -f "$SDK_QJS/libbf.c" ]] && sources+=(libbf.c)
++
++rm -f "$OUT"/*.o "$OUT"/libquickjs_openvibe.a
++
++for src in "${sources[@]}"; do
++ obj="$OUT/${src%.c}.o"
++ echo "[openvibe-qjs] cc $src -> $obj"
++
++ cc \
++ -std=gnu11 \
++ -O2 \
++ -fPIC \
++ -D_GNU_SOURCE \
++ -DCONFIG_VERSION=\"openvibe\" \
++ -I"$SDK_QJS" \
++ -c "$SDK_QJS/$src" \
++ -o "$obj"
++done
++
++ar rcs "$OUT/libquickjs_openvibe.a" "$OUT"/*.o
++
++echo "[openvibe-qjs] built $OUT/libquickjs_openvibe.a"
++ls -lh "$OUT/libquickjs_openvibe.a"
++BUILDQJS
++
++chmod +x tools/build-quickjs-lib.sh
++
++echo "[openvibe] removing direct QuickJS .c files from server_hl2mp.vpc"
++
++SERVER_VPC="$SDK/src/game/server/server_hl2mp.vpc"
++
++if [[ -f "$SERVER_VPC" ]]; then
++ cp "$SERVER_VPC" "$SERVER_VPC.bak.$(date +%Y%m%d-%H%M%S)"
++
++ perl -0pi -e '
++ s/^.*quickjs\\quickjs\.c.*\n//mg;
++ s/^.*quickjs\\libregexp\.c.*\n//mg;
++ s/^.*quickjs\\libunicode\.c.*\n//mg;
++ s/^.*quickjs\\cutils\.c.*\n//mg;
++ s/^.*quickjs\\dtoa\.c.*\n//mg;
++ s/^.*quickjs\\libbf\.c.*\n//mg;
++ ' "$SERVER_VPC"
++
++ if ! grep -q 'libquickjs_openvibe.a' "$SERVER_VPC"; then
++ perl -0pi -e 's/(\$File\s+"hl2mp\\openvibe_js_server\.cpp"\n)/$1\t\t\t\$Lib\t"..\\shared\\openvibe\\third_party\\quickjs\\build\\libquickjs_openvibe.a"\n/s' "$SERVER_VPC"
++ fi
++fi
++
++echo "[openvibe] patching apply-openvibe-sdk.sh so future applies keep this fix"
++
++python3 <<'PY'
++from pathlib import Path
++import re
++
++p = Path("tools/apply-openvibe-sdk.sh")
++s = p.read_text()
++
++# Make sure apply script calls static library builder after copying QuickJS.
++if '"$ROOT/tools/build-quickjs-lib.sh"' not in s:
++ needle = 'copy_tree "$ROOT/sdk/openvibe/third_party/quickjs" \\\n "$SDK/src/game/shared/openvibe/third_party/quickjs"'
++ if needle in s:
++ s = s.replace(needle, needle + '\n\n"$ROOT/tools/build-quickjs-lib.sh"')
++ else:
++ s += '\n\n"$ROOT/tools/build-quickjs-lib.sh"\n'
++
++# Add a strong cleanup block near the end.
++marker = "OPENVIBE_REMOVE_DIRECT_QUICKJS_C"
++if marker not in s:
++ s += r'''
++
++# OPENVIBE_REMOVE_DIRECT_QUICKJS_C
++if [[ -f "$SERVER_VPC" ]]; then
++ perl -0pi -e '
++ s/^.*quickjs\\quickjs\.c.*\n//mg;
++ s/^.*quickjs\\libregexp\.c.*\n//mg;
++ s/^.*quickjs\\libunicode\.c.*\n//mg;
++ s/^.*quickjs\\cutils\.c.*\n//mg;
++ s/^.*quickjs\\dtoa\.c.*\n//mg;
++ s/^.*quickjs\\libbf\.c.*\n//mg;
++ ' "$SERVER_VPC"
++
++ if ! grep -q 'libquickjs_openvibe.a' "$SERVER_VPC"; then
++ perl -0pi -e 's/(\$File\s+"hl2mp\\openvibe_js_server\.cpp"\n)/$1\t\t\t\$Lib\t"..\\shared\\openvibe\\third_party\\quickjs\\build\\libquickjs_openvibe.a"\n/s' "$SERVER_VPC"
++ fi
++fi
++'''
++
++p.write_text(s)
++PY
++
++echo "[openvibe] building QuickJS static lib"
++tools/build-quickjs-lib.sh
++
++echo
++echo "[openvibe] checking VPC for bad direct QuickJS C entries"
++if [[ -f "$SERVER_VPC" ]]; then
++ grep -nE 'quickjs\\(quickjs|libregexp|libunicode|cutils|dtoa|libbf)\.c' "$SERVER_VPC" || true
++ grep -n 'libquickjs_openvibe.a' "$SERVER_VPC" || true
++fi
++
++echo
++echo "[openvibe] fixed. Now run:"
++echo " tools/apply-openvibe-sdk.sh"
++echo " tools/build-sdk-linux.sh 2>&1 | tee ~/ov-build.log"
ddiff --git a/tools/fix-quickjs-c-link.sh b/tools/fix-quickjs-c-link.sh
nnew file mode 100755
iindex 0000000..a5d4608
---- /dev/null
++++ b/tools/fix-quickjs-c-link.sh
@@@ -0,0 +1,174 @@
++#!/usr/bin/env bash
++set -euo pipefail
++
++ROOT="${OPENVIBE_ROOT:-$HOME/src/openvibe-source}"
++SDK="${OPENVIBE_SDK:-$ROOT/engine/source-sdk-2013}"
++STAMP="$(date +%Y%m%d-%H%M%S)"
++
++cd "$ROOT"
++
++backup_file() {
++ local file="$1"
++ [[ -f "$file" ]] && cp "$file" "$file.bak.$STAMP"
++}
++
++echo "[openvibe] writing QuickJS static library builder"
++
++cat > tools/build-quickjs-lib.sh <<'BUILDQJS'
++#!/usr/bin/env bash
++set -euo pipefail
++
++ROOT="${OPENVIBE_ROOT:-$HOME/src/openvibe-source}"
++SDK="${OPENVIBE_SDK:-$ROOT/engine/source-sdk-2013}"
++
++SRC_QJS="$ROOT/sdk/openvibe/third_party/quickjs"
++SDK_QJS="$SDK/src/game/shared/openvibe/third_party/quickjs"
++OUT="$SDK_QJS/build"
++
++mkdir -p "$OUT"
++
++if [[ ! -f "$SRC_QJS/quickjs.c" ]]; then
++ echo "Missing $SRC_QJS/quickjs.c" >&2
++ echo "Run: tools/vendor-quickjs.sh" >&2
++ exit 1
++fi
++
++# Make sure SDK copy exists. apply-openvibe-sdk.sh also does this,
++# but this makes the script usable directly.
++mkdir -p "$SDK_QJS"
++rsync -a --delete "$SRC_QJS/" "$SDK_QJS/"
++
++sources=(
++ quickjs.c
++ libregexp.c
++ libunicode.c
++ cutils.c
++)
++
++[[ -f "$SDK_QJS/dtoa.c" ]] && sources+=(dtoa.c)
++[[ -f "$SDK_QJS/libbf.c" ]] && sources+=(libbf.c)
++
++rm -f "$OUT"/*.o "$OUT"/libquickjs_openvibe.a
++
++for src in "${sources[@]}"; do
++ obj="$OUT/${src%.c}.o"
++ echo "[openvibe-qjs] cc $src"
++ cc \
++ -std=gnu11 \
++ -O2 \
++ -fPIC \
++ -D_GNU_SOURCE \
++ -DCONFIG_VERSION=\"openvibe\" \
++ -I"$SDK_QJS" \
++ -c "$SDK_QJS/$src" \
++ -o "$obj"
++done
++
++ar rcs "$OUT/libquickjs_openvibe.a" "$OUT"/*.o
++
++echo "[openvibe-qjs] built $OUT/libquickjs_openvibe.a"
++ls -lh "$OUT/libquickjs_openvibe.a"
++BUILDQJS
++
++chmod +x tools/build-quickjs-lib.sh
++
++echo "[openvibe] patching apply-openvibe-sdk.sh to link libquickjs_openvibe.a instead of compiling QuickJS C files"
++
++backup_file tools/apply-openvibe-sdk.sh
++
++python3 <<'PY'
++from pathlib import Path
++import re
++
++p = Path("tools/apply-openvibe-sdk.sh")
++s = p.read_text()
++
++# Remove QuickJS .c cleanup patterns from perl patch block if they exist.
++for name in ["quickjs", "libregexp", "libunicode", "cutils", "dtoa", "libbf"]:
++ s = re.sub(
++ rf'\s*s/\^\.\*openvibe\\\\third_party\\\\quickjs\\\\{name}\\\.c\.\*\\n//mg;\n?',
++ '\n',
++ s,
++ )
++ s = re.sub(
++ rf'\s*s/\^\.\*openvibe\\\\\\\\third_party\\\\\\\\quickjs\\\\\\\\{name}\\\\\.c\.\*\\n//mg;\n?',
++ '\n',
++ s,
++ )
++
++# Remove inserted QuickJS .c $File entries from replacement text.
++for name in ["quickjs", "libregexp", "libunicode", "cutils", "dtoa", "libbf"]:
++ s = s.replace(
++ f'\\n\\t\\t\\t\\$File\\t"..\\\\shared\\\\openvibe\\\\third_party\\\\quickjs\\\\{name}.c"',
++ ''
++ )
++ s = s.replace(
++ f'\n\t\t\t\\$File\t"..\\\\shared\\\\openvibe\\\\third_party\\\\quickjs\\\\{name}.c"',
++ ''
++ )
++ s = s.replace(
++ f'\n\t\t\t$File\t"..\\\\shared\\\\openvibe\\\\third_party\\\\quickjs\\\\{name}.c"',
++ ''
++ )
++
++# Remove any actual already-written lines from the script text.
++s = re.sub(r'^.*quickjs\\\\(quickjs|libregexp|libunicode|cutils|dtoa|libbf)\.c.*\n', '', s, flags=re.M)
++s = re.sub(r'^.*quickjs\\(quickjs|libregexp|libunicode|cutils|dtoa|libbf)\.c.*\n', '', s, flags=re.M)
++
++# Ensure build-quickjs-lib is called after copy_tree.
++if "tools/build-quickjs-lib.sh" not in s:
++ needle = 'copy_tree "$ROOT/sdk/openvibe/third_party/quickjs" \\\n "$SDK/src/game/shared/openvibe/third_party/quickjs"'
++ replacement = needle + '\n\n"$ROOT/tools/build-quickjs-lib.sh"'
++ if needle in s:
++ s = s.replace(needle, replacement)
++ else:
++ s += '\n\n"$ROOT/tools/build-quickjs-lib.sh"\n'
++
++# Add static lib to server_hl2mp.vpc patch.
++# Try to insert a $Lib line near the openvibe source files, only once.
++lib_line = '\t\t\t$Lib\t"..\\\\shared\\\\openvibe\\\\third_party\\\\quickjs\\\\build\\\\libquickjs_openvibe.a"'
++if 'libquickjs_openvibe.a' not in s:
++ # Add after openvibe_js_server.cpp if present in replacement text.
++ s = s.replace(
++ '\t\t\t\\$File\t"hl2mp\\\\openvibe_js_server.cpp"',
++ '\t\t\t\\$File\t"hl2mp\\\\openvibe_js_server.cpp"\\n' + lib_line.replace('$', '\\$')
++ )
++ # If that escaped replacement did not hit, add a direct post-patch insertion block.
++ if 'libquickjs_openvibe.a' not in s:
++ s += r'''
++
++# Link prebuilt QuickJS C static library. QuickJS must be compiled as C, not C++.
++if ! grep -q 'libquickjs_openvibe.a' "$SERVER_VPC"; then
++ perl -0pi -e 's/(\$File\s+"hl2mp\\openvibe_js_server\.cpp"\n)/$1\t\t\t\$Lib\t"..\\shared\\openvibe\\third_party\\quickjs\\build\\libquickjs_openvibe.a"\n/s' "$SERVER_VPC"
++ echo "[openvibe-sdk] linked QuickJS static library"
++fi
++'''
++
++p.write_text(s)
++PY
++
++echo "[openvibe] also patching already-applied SDK VPC now, if it exists"
++
++SERVER_VPC="$SDK/src/game/server/server_hl2mp.vpc"
++
++if [[ -f "$SERVER_VPC" ]]; then
++ backup_file "$SERVER_VPC"
++
++ # Remove direct QuickJS C files from VPC.
++ perl -0pi -e 's/^.*openvibe\\\\third_party\\\\quickjs\\\\(quickjs|libregexp|libunicode|cutils|dtoa|libbf)\.c.*\n//mg; s/^.*openvibe\\third_party\\quickjs\\(quickjs|libregexp|libunicode|cutils|dtoa|libbf)\.c.*\n//mg' "$SERVER_VPC"
++
++ if ! grep -q 'libquickjs_openvibe.a' "$SERVER_VPC"; then
++ perl -0pi -e 's/(\$File\s+"hl2mp\\openvibe_js_server\.cpp"\n)/$1\t\t\t\$Lib\t"..\\shared\\openvibe\\third_party\\quickjs\\build\\libquickjs_openvibe.a"\n/s' "$SERVER_VPC"
++ fi
++fi
++
++echo "[openvibe] building QuickJS C static library"
++tools/build-quickjs-lib.sh
++
++echo
++echo "[openvibe] fixed QuickJS C/C++ build split."
++echo
++echo "Now run:"
++echo " tools/apply-openvibe-sdk.sh"
++echo " tools/build-sdk-linux.sh 2>&1 | tee ~/ov-build.log"
++echo " tail -160 ~/ov-build.log"
ddiff --git a/tools/vendor-quickjs.sh b/tools/vendor-quickjs.sh
iindex b014f98..bd68310 100755
---- a/tools/vendor-quickjs.sh
++++ b/tools/vendor-quickjs.sh
@@@ -7,8 +7,7 @@ TMP="${TMPDIR:-/tmp}/openvibe-quickjs-vendor"
rm -rf "$TMP"
--git clone --depth 1 https://github.com/bellard/quickjs.git "$TMP" || \
--git clone --depth 1 https://github.com/quickjs-ng/quickjs.git "$TMP"
++git clone --depth 1 https://github.com/bellard/quickjs.git "$TMP"
rm -rf "$DEST"
mkdir -p "$DEST"