added firebase and rudimentary leaderboard support

This commit is contained in:
derek
2025-04-09 11:19:02 -05:00
parent ce08df66e6
commit 25eb9e725a
121 changed files with 4987 additions and 4 deletions

View File

@@ -0,0 +1,129 @@
@tool
extends Node
signal new_sse_event(headers, event, data)
signal connected
signal connection_error(error)
const event_tag = "event:"
const data_tag = "data:"
const continue_internal = "continue_internal"
var httpclient = HTTPClient.new()
var is_connected = false
var domain
var url_after_domain
var port
var trusted_chain
var common_name_override
var told_to_connect = false
var connection_in_progress = false
var is_requested = false
var response_body = PackedByteArray()
func connect_to_host(domain : String, url_after_domain : String, port : int = -1, trusted_chain : X509Certificate = null, common_name_override : String = ""):
process_mode = Node.PROCESS_MODE_INHERIT
self.domain = domain
self.url_after_domain = url_after_domain
self.port = port
self.trusted_chain = trusted_chain
self.common_name_override = common_name_override
told_to_connect = true
func attempt_to_connect():
var tls_options = TLSOptions.client(trusted_chain, common_name_override)
var err = httpclient.connect_to_host(domain, port, tls_options)
if err == OK:
connected.emit()
is_connected = true
else:
connection_error.emit(str(err))
func attempt_to_request(httpclient_status):
if httpclient_status == HTTPClient.STATUS_CONNECTING or httpclient_status == HTTPClient.STATUS_RESOLVING:
return
if httpclient_status == HTTPClient.STATUS_CONNECTED:
var err = httpclient.request(HTTPClient.METHOD_POST, url_after_domain, ["Accept: text/event-stream"])
if err == OK:
is_requested = true
func _parse_response_body(headers):
var body = response_body.get_string_from_utf8()
if body:
var event_data = get_event_data(body)
if event_data.event != "keep-alive" and event_data.event != continue_internal:
var result = Utilities.get_json_data(event_data.data)
if result != null:
var parsed_text = result
if response_body.size() > 0: # stop here if the value doesn't parse
response_body.resize(0)
new_sse_event.emit(headers, event_data.event, result)
else:
if event_data.event != continue_internal:
response_body.resize(0)
func _process(delta):
if !told_to_connect:
return
if !is_connected:
if !connection_in_progress:
attempt_to_connect()
connection_in_progress = true
return
httpclient.poll()
var httpclient_status = httpclient.get_status()
if !is_requested:
attempt_to_request(httpclient_status)
return
if httpclient.has_response() or httpclient_status == HTTPClient.STATUS_BODY:
var headers = httpclient.get_response_headers_as_dictionary()
if httpclient_status == HTTPClient.STATUS_BODY:
httpclient.poll()
var chunk = httpclient.read_response_body_chunk()
if(chunk.size() == 0):
return
else:
response_body = response_body + chunk
_parse_response_body(headers)
elif Firebase.emulating and Firebase._config.workarounds.database_connection_closed_issue:
# Emulation does not send the close connection header currently, so we need to manually read the response body
# see issue https://github.com/firebase/firebase-tools/issues/3329 in firebase-tools
# also comment https://github.com/GodotNuts/GodotFirebase/issues/154#issuecomment-831377763 which explains the issue
while httpclient.connection.get_available_bytes():
var data = httpclient.connection.get_partial_data(1)
if data[0] == OK:
response_body.append_array(data[1])
if response_body.size() > 0:
_parse_response_body(headers)
func get_event_data(body : String):
var result = {}
var event_idx = body.find(event_tag)
if event_idx == -1:
result["event"] = continue_internal
return result
assert(event_idx != -1)
var data_idx = body.find(data_tag, event_idx + event_tag.length())
assert(data_idx != -1)
var event = body.substr(event_idx, data_idx)
var event_value = event.replace(event_tag, "").strip_edges()
assert(event_value)
assert(event_value.length() > 0)
result["event"] = event_value
var data = body.right(body.length() - (data_idx + data_tag.length())).strip_edges()
assert(data)
assert(data.length() > 0)
result["data"] = data
return result
func _exit_tree():
if httpclient:
httpclient.close()

View File

@@ -0,0 +1 @@
uid://cdxp41ctxh5eb

View File

@@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/http-sse-client/HTTPSSEClient.gd" type="Script" id=1]
[node name="HTTPSSEClient" type="Node"]
script = ExtResource( 1 )

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Kyle Szklenski
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,16 @@
# HTTPSSEClient
This is an implementation of the server-sent events/event-source protocol (https://www.w3.org/TR/eventsource/) in GDScript for the Godot game engine.
To use this, simply download this project and place it into the `res://addons/HTTPSSEClient/` folder in your project; then you can just turn it on.
I've included Demo.tscn and Demo.gd to show the usage of this plugin, and here's a summary:
1) Download and place into the proper folder as the above suggests
2) Switch the new plugin, found in Project Settings -> Plugins, to active
3) Instantiate a new HTTPSSEClient node in your scene tree somewhere
4) Click on the script icon for the newly-created node
5) Enter in any connection information necessary to connect to your SSE-supported server; for demonstration purposes, I use Firebase, and in the config dictionary, I just add the entire config I get back from adding a new Android app to any Firebase project (it'll give you back the google-services.json file, copy/paste it into config and change the url in the script to firebase_url and you're set for this)
6) If you're using Firebase, you need a sub_url value that is something like "/your_demo_list.json?auth=" and then the value of either your Firebase ID token, or your database secret. It's not clear how long database secrets will remain functional as they're already deprecated, but it is supported for the time being due to backward compatibility issues.
When using my GDFirebase plugin, all of the above is handled for you automatically, so you will only need to use the information provided by that plugin.

View File

@@ -0,0 +1,8 @@
@tool
extends EditorPlugin
func _enter_tree():
add_custom_type("HTTPSSEClient", "Node", preload("HTTPSSEClient.gd"), preload("icon.png"))
func _exit_tree():
remove_custom_type("HTTPSSEClient")

View File

@@ -0,0 +1 @@
uid://l8ynb8chj2cg

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 B

View File

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cr4uf04actcj5"
path="res://.godot/imported/icon.png-fd61c0c5f1d1b4df37e0abe3d8f80985.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/http-sse-client/icon.png"
dest_files=["res://.godot/imported/icon.png-fd61c0c5f1d1b4df37e0abe3d8f80985.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@@ -0,0 +1,7 @@
[plugin]
name="HTTPSSEClient"
description="An HTTPClient-based implementation that supports server-sent events, effectively enabling push notifications in Godot, using GDScript."
author="Kyle Szklenski"
version="1.0"
script="httpsseclient_plugin.gd"