From 67e3de5726df7a0e8e1540038720f31ae2974531 Mon Sep 17 00:00:00 2001 From: Dolly132 <109222243+Dolly132@users.noreply.github.com> Date: Sun, 1 Mar 2026 20:32:21 +0200 Subject: [PATCH 1/8] feat(api): Add CreateMenu API function --- addons/sourcemod/scripting/SMJSONAPI.sp | 9 +++ addons/sourcemod/scripting/include/API.inc | 68 ++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/addons/sourcemod/scripting/SMJSONAPI.sp b/addons/sourcemod/scripting/SMJSONAPI.sp index d365313..c9e162c 100644 --- a/addons/sourcemod/scripting/SMJSONAPI.sp +++ b/addons/sourcemod/scripting/SMJSONAPI.sp @@ -267,6 +267,11 @@ stock JSONArray HandleRequestFunctionArgs(Request request, Response response) jArgsArray.GetString(i, asValues[sValues], sizeof(asValues[])); Call_PushStringEx(asValues[sValues++], sizeof(asValues[]), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); } + else if(jType == JSON_OBJECT) + { + aiValues[iValues] = view_as(jArgsArray.Get(i)); + Call_PushCell(aiValues[iValues++]); + } else { Call_Cancel(); @@ -356,6 +361,10 @@ stock JSONArray HandleRequestFunctionArgs(Request request, Response response) { jArgsResponse.PushString(asValues[sValues++]); } + else if(jType == JSON_OBJECT) + { + jArgsResponse.Push(view_as(aiValues[iValues++])); + } } return jArgsResponse; } diff --git a/addons/sourcemod/scripting/include/API.inc b/addons/sourcemod/scripting/include/API.inc index b9b1745..c8836e3 100644 --- a/addons/sourcemod/scripting/include/API.inc +++ b/addons/sourcemod/scripting/include/API.inc @@ -94,3 +94,71 @@ public int API_GetUserFlagBits(int client) return GetUserFlagBits(client); } + +public void API_CreateMenu(int client, int data) +{ + if (!IsClientInGame(client)) + return; + + Menu menu = new Menu(API_MenuCallback); + + JSONObject dataObj = view_as(data); + + char title[128]; + dataObj.GetString("title", title, sizeof(title)); + menu.SetTitle(title); + + JSONArray options = view_as(dataObj.Get("options")); + if (options == null) + return; + + for (int i = 0; i < options.Length; i++) + { + JSONArray thisArr = view_as(options.Get(i)); + if (thisArr == null) + continue; + + char option_data[255], option_display[255]; + thisArr.GetString(0, option_data, sizeof(option_data)); + thisArr.GetString(1, option_display, sizeof(option_display)); + + menu.AddItem(option_data, option_display); + } + + menu.ExitButton = true; + menu.Display(client, MENU_TIME_FOREVER); +} + +public int API_MenuCallback(Menu menu, MenuAction action, int param1, int param2) +{ + switch (action) + { + case MenuAction_End: + delete menu; + + case MenuAction_Select: + { + char[] sEventName = "OnMenuSelect"; + + JSONObject jEvent = new JSONObject(); + jEvent.SetString("name", sEventName); + + JSONObject jEventData = new JSONObject(); + jEventData.SetString("type", "trigger"); + jEventData.SetInt("client", param1); + + char option[255]; + menu.GetItem(param2, option, sizeof(option)); + + jEventData.SetString("option", option); + + jEvent.Set("data", jEventData); + + Subscribe_Forwards_Publish(sEventName, jEvent); + + delete jEventData; + } + } + + return 0; +} From 1187b2b331b9465177d27e6e5a238060b7b23f81 Mon Sep 17 00:00:00 2001 From: Dolly132 <109222243+Dolly132@users.noreply.github.com> Date: Sun, 1 Mar 2026 20:33:01 +0200 Subject: [PATCH 2/8] bump version --- addons/sourcemod/scripting/SMJSONAPI.sp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/SMJSONAPI.sp b/addons/sourcemod/scripting/SMJSONAPI.sp index c9e162c..53bf408 100644 --- a/addons/sourcemod/scripting/SMJSONAPI.sp +++ b/addons/sourcemod/scripting/SMJSONAPI.sp @@ -28,7 +28,7 @@ public Plugin myinfo = name = "SM JSON API", author = "BotoX, maxime1907", description = "SourceMod TCP JSON API", - version = "1.0.7", + version = "1.0.8", url = "" } From bc3cca416a7eb75a8a2844cf0e07af27f8fa36af Mon Sep 17 00:00:00 2001 From: Dolly132 <109222243+Dolly132@users.noreply.github.com> Date: Mon, 2 Mar 2026 21:04:00 +0200 Subject: [PATCH 3/8] Bump version from 1.0.8 to 1.1.0 --- addons/sourcemod/scripting/SMJSONAPI.sp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/SMJSONAPI.sp b/addons/sourcemod/scripting/SMJSONAPI.sp index 53bf408..f8d63b1 100644 --- a/addons/sourcemod/scripting/SMJSONAPI.sp +++ b/addons/sourcemod/scripting/SMJSONAPI.sp @@ -28,7 +28,7 @@ public Plugin myinfo = name = "SM JSON API", author = "BotoX, maxime1907", description = "SourceMod TCP JSON API", - version = "1.0.8", + version = "1.1.0", url = "" } From fc42bf1dda56ef929233b8c2caaf311e818aca51 Mon Sep 17 00:00:00 2001 From: Dolly132 <109222243+Dolly132@users.noreply.github.com> Date: Mon, 2 Mar 2026 21:54:30 +0200 Subject: [PATCH 4/8] Add client validity checks --- addons/sourcemod/scripting/include/API.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/include/API.inc b/addons/sourcemod/scripting/include/API.inc index c8836e3..e1bff41 100644 --- a/addons/sourcemod/scripting/include/API.inc +++ b/addons/sourcemod/scripting/include/API.inc @@ -97,7 +97,7 @@ public int API_GetUserFlagBits(int client) public void API_CreateMenu(int client, int data) { - if (!IsClientInGame(client)) + if (!(1 <= client <= MaxClients) || !IsClientInGame(client)) return; Menu menu = new Menu(API_MenuCallback); From 4726b98bf6ddd011db3e84597f33dbb7a2e69aaa Mon Sep 17 00:00:00 2001 From: Dolly132 <109222243+Dolly132@users.noreply.github.com> Date: Mon, 2 Mar 2026 23:19:14 +0200 Subject: [PATCH 5/8] Update addons/sourcemod/scripting/include/API.inc Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- addons/sourcemod/scripting/include/API.inc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/sourcemod/scripting/include/API.inc b/addons/sourcemod/scripting/include/API.inc index e1bff41..2a28858 100644 --- a/addons/sourcemod/scripting/include/API.inc +++ b/addons/sourcemod/scripting/include/API.inc @@ -110,7 +110,10 @@ public void API_CreateMenu(int client, int data) JSONArray options = view_as(dataObj.Get("options")); if (options == null) + { + delete menu; return; + } for (int i = 0; i < options.Length; i++) { From f38efcb695f6a4d11e9999fe3dabd373c881d6dd Mon Sep 17 00:00:00 2001 From: Dolly132 <109222243+Dolly132@users.noreply.github.com> Date: Mon, 2 Mar 2026 23:35:25 +0200 Subject: [PATCH 6/8] fix memory leaks --- addons/sourcemod/scripting/include/API.inc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/addons/sourcemod/scripting/include/API.inc b/addons/sourcemod/scripting/include/API.inc index 2a28858..2145f56 100644 --- a/addons/sourcemod/scripting/include/API.inc +++ b/addons/sourcemod/scripting/include/API.inc @@ -125,13 +125,25 @@ public void API_CreateMenu(int client, int data) thisArr.GetString(0, option_data, sizeof(option_data)); thisArr.GetString(1, option_display, sizeof(option_display)); + delete thisArr; + menu.AddItem(option_data, option_display); } + delete options; + + RequestFrame(API_FreeHandle, data) + menu.ExitButton = true; menu.Display(client, MENU_TIME_FOREVER); } +void API_FreeHandle(int data) +{ + JSONObject obj = view_as(data); + delete obj; +} + public int API_MenuCallback(Menu menu, MenuAction action, int param1, int param2) { switch (action) From 2d10a7f205c91bbc9b8e58fb045cd0cf3ccba6c9 Mon Sep 17 00:00:00 2001 From: Dolly132 <109222243+Dolly132@users.noreply.github.com> Date: Mon, 2 Mar 2026 23:40:57 +0200 Subject: [PATCH 7/8] more fixes --- addons/sourcemod/scripting/include/API.inc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/addons/sourcemod/scripting/include/API.inc b/addons/sourcemod/scripting/include/API.inc index 2145f56..4442358 100644 --- a/addons/sourcemod/scripting/include/API.inc +++ b/addons/sourcemod/scripting/include/API.inc @@ -103,9 +103,15 @@ public void API_CreateMenu(int client, int data) Menu menu = new Menu(API_MenuCallback); JSONObject dataObj = view_as(data); - + RequestFrame(API_FreeHandle, data); + char title[128]; - dataObj.GetString("title", title, sizeof(title)); + if (!dataObj.GetString("title", title, sizeof(title))) + { + delete menu; + return; + } + menu.SetTitle(title); JSONArray options = view_as(dataObj.Get("options")); @@ -132,8 +138,6 @@ public void API_CreateMenu(int client, int data) delete options; - RequestFrame(API_FreeHandle, data) - menu.ExitButton = true; menu.Display(client, MENU_TIME_FOREVER); } From 79d694825d29c20165d908368d3a7341a4bc0bcb Mon Sep 17 00:00:00 2001 From: Rushaway Date: Tue, 3 Mar 2026 10:25:57 +0100 Subject: [PATCH 8/8] Prevent leak if early return --- addons/sourcemod/scripting/include/API.inc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/include/API.inc b/addons/sourcemod/scripting/include/API.inc index 4442358..9e7dfd8 100644 --- a/addons/sourcemod/scripting/include/API.inc +++ b/addons/sourcemod/scripting/include/API.inc @@ -97,13 +97,14 @@ public int API_GetUserFlagBits(int client) public void API_CreateMenu(int client, int data) { + RequestFrame(API_FreeHandle, data); + if (!(1 <= client <= MaxClients) || !IsClientInGame(client)) return; Menu menu = new Menu(API_MenuCallback); JSONObject dataObj = view_as(data); - RequestFrame(API_FreeHandle, data); char title[128]; if (!dataObj.GetString("title", title, sizeof(title)))