From 963d579da61dcb76a3c4d68e584c59735a12b0bc Mon Sep 17 00:00:00 2001 From: DeReve Date: Wed, 4 Oct 2023 00:15:30 +0200 Subject: [PATCH] Adding webhook functionality for interactions with toys. --- Game/MainScene.gd | 7 ++ Game/MainScene.tscn | 2 + Game/Options/GlobalOptions.gd | 52 ++++++++++++ Game/PlayerPanel.gd | 13 +++ Game/PlayerPanel.tscn | 2 + Misc/Webhook.md | 14 ++++ Misc/xtoys_script.txt | 152 ++++++++++++++++++++++++++++++++++ 7 files changed, 242 insertions(+) create mode 100644 Misc/Webhook.md create mode 100644 Misc/xtoys_script.txt diff --git a/Game/MainScene.gd b/Game/MainScene.gd index f03a51070..048e9d651 100644 --- a/Game/MainScene.gd +++ b/Game/MainScene.gd @@ -1033,6 +1033,13 @@ func _on_Player_holePinafullyStretched(bodypart, _who): addMessage("OW! Your pussy [b]hurts[/b]..") if(bodypart == BodypartSlot.Anus): addMessage("OW! Your anus [b]hurts[/b]..") + callPainWebhook(bodypart) + +func callPainWebhook(bodypart): + var jsonStr = "" + if(OPTIONS.getWebhookPainEnabled()): + jsonStr= '{"action": "painstretch","bodypart": "' + str(bodypart) + '"}' + $HTTPRequest.request(OPTIONS.getWebhookURL(), ["Content-Type: application/json"], true, HTTPClient.METHOD_POST , jsonStr) func _on_Player_gotWoundedBy(_who): addMessage("OW! That [b]really[/b] hurt..") diff --git a/Game/MainScene.tscn b/Game/MainScene.tscn index b8ca714d2..7edbe8470 100644 --- a/Game/MainScene.tscn +++ b/Game/MainScene.tscn @@ -28,6 +28,8 @@ script = ExtResource( 2 ) [node name="DynamicCharacters" type="Node" parent="."] +[node name="HTTPRequest" type="HTTPRequest" parent="."] + [connection signal="onDevComButton" from="GameUI" to="." method="_on_GameUI_onDevComButton"] [connection signal="on_option_button" from="GameUI" to="." method="_on_GameUI_on_option_button"] [connection signal="on_rollback_button" from="GameUI" to="." method="_on_GameUI_on_rollback_button"] diff --git a/Game/Options/GlobalOptions.gd b/Game/Options/GlobalOptions.gd index f06319c84..72b402c08 100644 --- a/Game/Options/GlobalOptions.gd +++ b/Game/Options/GlobalOptions.gd @@ -76,6 +76,9 @@ var visibleWritings:bool = true var autosaveEnabled = true var genderNamesOverrides = {} +var webhookURL = "https://webhook.xtoys.app/abcrandomidentifier" +var webhookStatsEnabled = false +var webhookPainEnabled = false func resetToDefaults(): fetchNewRelease = true @@ -312,6 +315,14 @@ func getInventoryIconSize(): if(inventoryIconsSize == "big"): return 64 return 32 +func getWebhookStatsEnabled(): + return webhookStatsEnabled + +func getWebhookPainEnabled(): + return webhookPainEnabled + +func getWebhookURL(): + return webhookURL func getChangeableOptions(): var settings = [ @@ -879,6 +890,33 @@ func getChangeableOptions(): }, ] }, + { + "name": "Webhook", + "id": "webhook", + "options": [ + { + "name": "Webhook base URL", + "description": "The base URL of the webhook", + "id": "webhookURL", + "type": "string", + "value": webhookURL, + }, + { + "name": "Stats enabled", + "description": "Sends POST requests with basic player character stats", + "id": "webhookStatsEnabled", + "type": "checkbox", + "value": webhookStatsEnabled, + }, + { + "name": "Painful insertions enabled", + "description": "Sends POST requests with painful insertion information", + "id": "webhookPainEnabled", + "type": "checkbox", + "value": webhookPainEnabled, + }, + ] + }, { "name": "Debug", "id": "debug", @@ -1068,6 +1106,14 @@ func applyOption(categoryID, optionID, value): if(optionID == "visibleWritings"): visibleWritings = value + if(categoryID == "webhook"): + if(optionID == "webhookStatsEnabled"): + webhookStatsEnabled = value + if(optionID == "webhookPainEnabled"): + webhookPainEnabled = value + if(optionID == "webhookURL"): + webhookURL = value + if(categoryID == "debug"): if(optionID == "debugPanel"): debugPanel = value @@ -1160,6 +1206,9 @@ func saveData(): "blockCatcherPanelHeight": blockCatcherPanelHeight, "webTextInputFallback": webTextInputFallback, "fullscreen": fullscreen, + "webhookStatsEnabled": webhookStatsEnabled, + "webhookPainEnabled": webhookStatsEnabled, + "webhookURL": webhookURL, } return data @@ -1220,6 +1269,9 @@ func loadData(data): blockCatcherPanelHeight = loadVar(data, "blockCatcherPanelHeight", 16) webTextInputFallback = loadVar(data, "webTextInputFallback", false) fullscreen = loadVar(data, "fullscreen", false) + webhookStatsEnabled = loadVar(data, "webhookStatsEnabled", false) + webhookPainEnabled = loadVar(data, "webhookPainEnabled", false) + webhookURL = loadVar(data, "webhookURL", "https://webhook.xtoys.app/abcrandomid") func saveToFile(): var saveData = saveData() diff --git a/Game/PlayerPanel.gd b/Game/PlayerPanel.gd index 667a2324c..de2915ccb 100644 --- a/Game/PlayerPanel.gd +++ b/Game/PlayerPanel.gd @@ -36,6 +36,19 @@ func loadingSavefileFinished(): func on_player_statchange(): updateUI() + callStatsWebhook() + +func callStatsWebhook(): + var jsonStr = "" + if(OPTIONS.getWebhookStatsEnabled()): + #$HTTPRequest.request(OPTIONS.getWebhookURL) + jsonStr= '{"action": "stats","p": ' + str(GM.pc.getPain()) + ',"pt": ' + str(GM.pc.painThreshold()) + jsonStr= jsonStr + ',"l": ' + str(GM.pc.getLust()) + ' ,"lt": ' + str(GM.pc.lustThreshold()) + jsonStr= jsonStr + ',"s": ' + str(GM.pc.getStamina()) + ' ,"ms": ' + str(GM.pc.getMaxStamina()) + jsonStr= jsonStr + ',"lp": ' + str(int(GM.pc.getSkillsHolder().getLevelProgress()*100)) + ' ,"lvl": ' + str(GM.pc.getSkillsHolder().getLevel()) + jsonStr= jsonStr + ',"ar": ' + str(int(GM.pc.getArousal()*100)) + ' ,"ll": ' + str(int(GM.pc.getLustLevel()*100)) + '}' + $HTTPRequest.request(OPTIONS.getWebhookURL(), ["Content-Type: application/json"], true, HTTPClient.METHOD_POST , jsonStr) + func updateUI(): nameLabel.text = GM.pc.getName() + ", " + GM.pc.getSpeciesFullName() diff --git a/Game/PlayerPanel.tscn b/Game/PlayerPanel.tscn index 6990a6d0b..83eba1dff 100644 --- a/Game/PlayerPanel.tscn +++ b/Game/PlayerPanel.tscn @@ -177,6 +177,8 @@ margin_top = -128.289 margin_right = 280.291 margin_bottom = -96.289 +[node name="HTTPRequest" type="HTTPRequest" parent="."] + [connection signal="gui_input" from="ViewportWrapper" to="." method="_on_ViewportWrapper_gui_input"] [connection signal="mouse_entered" from="ViewportWrapper/CustomViewportControl" to="." method="_on_ViewportContainer_mouse_entered"] [connection signal="mouse_exited" from="ViewportWrapper/CustomViewportControl" to="." method="_on_ViewportContainer_mouse_exited"] diff --git a/Misc/Webhook.md b/Misc/Webhook.md new file mode 100644 index 000000000..31dc8e067 --- /dev/null +++ b/Misc/Webhook.md @@ -0,0 +1,14 @@ +# Webhook +The webhook settings added in the Options can send the basic statistics to xtoys.app (or any other platform accepting JSON POST) for sex toy automation. + +## Usage + +1. Open https://xtoys.app and connect to your toys. +2. Add the "BDCC Simple Webhook" script from Public Scripts (or import the Json in webhook_script.txt in the Misc folder) +3. Generate a random id by clicking the dice (might require an xtoys.app account), and copy the random value +4. Open BDCC, go to Options in the Webhook section set the URL to "https://webhook.xtoys.app/RANDOMVALUEHERE" remember to replace RANDOMVALUEHERE with the value from the previous step. +5. Tick the boxes to send either the stats (Pain, Lust, Stamina etc.) or the painful insertion triggers, or both. +6. Connect the script to devices in xtoys.app by clicking the D in the header. +7. Press play on the script in the xtoys.app dashboard. + +Stat changes might have an update delay until the in-game scene progresses. \ No newline at end of file diff --git a/Misc/xtoys_script.txt b/Misc/xtoys_script.txt new file mode 100644 index 000000000..b36aef51a --- /dev/null +++ b/Misc/xtoys_script.txt @@ -0,0 +1,152 @@ +{ + "initialActions": [ + { + "job": "Main", + "type": "updateJob", + "action": "start" + } + ], + "finalActions": [], + "globalTriggers": [ + { + "type": "componentState", + "action": "stats", + "actions": [ + { + "type": "updateComponent", + "action": "setVolume", + "channel": "generic-1-a", + "rampTime": "1", + "percentVolume": "{trigger-p}*100/{trigger-pt}", + "parsedRampTime": 1 + }, + { + "type": "updateComponent", + "action": "setVolume", + "channel": "generic-1-b", + "rampTime": "1", + "percentVolume": "{trigger-l} * 100 / {trigger-lt}" + }, + { + "type": "updateComponent", + "action": "setVolume", + "channel": "generic-1-c", + "rampTime": "1", + "percentVolume": "{trigger-s} * 100 / {trigger-sm}" + } + ], + "channel": "webhook-a", + "parsedAction": "stats" + }, + { + "type": "componentState", + "action": "painstretch", + "actions": [ + { + "type": "updateComponent", + "action": "setVolume", + "channel": "part-grip-expander-a", + "rampTime": "5", + "percentVolume": "100" + }, + { + "type": "updateComponent", + "action": "setVolume", + "channel": "part-grip-expander-a", + "rampTime": "1", + "percentVolume": "0" + } + ], + "channel": "webhook-a", + "parsedAction": "painstretch", + "requiredExpression": "{trigger-bodypart} == \"vagina\"" + }, + { + "type": "componentState", + "action": "painstretch", + "actions": [ + { + "type": "updateComponent", + "action": "setVolume", + "channel": "generic-1-a", + "rampTime": "5", + "percentVolume": "100" + }, + { + "type": "updateComponent", + "action": "setVolume", + "channel": "generic-1-a", + "rampTime": "1", + "percentVolume": "0" + } + ], + "channel": "webhook-a", + "parsedAction": "painstretch", + "requiredExpression": "{trigger-bodypart}==\"anus\"" + } + ], + "jobs": { + "Main": { + "steps": { + "START": { + "actions": [], + "triggers": [] + } + } + }, + "Reset Inf": { + "steps": { + "Reset": { + "actions": [], + "triggers": [] + }, + "START": { + "actions": [], + "triggers": [] + } + } + } + }, + "queues": [], + "channels": { + "webhook-a": { + "name": "WH", + "type": "webhook", + "outbound": false, + "hideWebhookInfo": false + }, + "generic-1-a": { + "name": "Pain %", + "type": "generic-1" + }, + "generic-1-b": { + "name": "Lust %", + "type": "generic-1" + }, + "generic-1-c": { + "name": "Stamina %", + "type": "generic-1" + }, + "part-grip-expander-a": { + "name": "Inflate Vagina", + "type": "part-grip-expander" + }, + "part-grip-expander-b": { + "name": "Inflate Anus", + "type": "part-grip-expander" + } + }, + "controls": [ + { + "id": "p", + "type": "textarea" + } + ], + "controlPresets": [], + "media": { + "patterns": {}, + "audio": {}, + "voices": {} + }, + "customFunctions": "" +} \ No newline at end of file