added firebase and rudimentary leaderboard support
This commit is contained in:
129
addons/http-sse-client/HTTPSSEClient.gd
Normal file
129
addons/http-sse-client/HTTPSSEClient.gd
Normal 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()
|
||||
1
addons/http-sse-client/HTTPSSEClient.gd.uid
Normal file
1
addons/http-sse-client/HTTPSSEClient.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cdxp41ctxh5eb
|
||||
6
addons/http-sse-client/HTTPSSEClient.tscn
Normal file
6
addons/http-sse-client/HTTPSSEClient.tscn
Normal 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 )
|
||||
21
addons/http-sse-client/LICENSE
Normal file
21
addons/http-sse-client/LICENSE
Normal 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.
|
||||
16
addons/http-sse-client/README.md
Normal file
16
addons/http-sse-client/README.md
Normal 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.
|
||||
8
addons/http-sse-client/httpsseclient_plugin.gd
Normal file
8
addons/http-sse-client/httpsseclient_plugin.gd
Normal 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")
|
||||
1
addons/http-sse-client/httpsseclient_plugin.gd.uid
Normal file
1
addons/http-sse-client/httpsseclient_plugin.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://l8ynb8chj2cg
|
||||
BIN
addons/http-sse-client/icon.png
Normal file
BIN
addons/http-sse-client/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 137 B |
34
addons/http-sse-client/icon.png.import
Normal file
34
addons/http-sse-client/icon.png.import
Normal 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
|
||||
7
addons/http-sse-client/plugin.cfg
Normal file
7
addons/http-sse-client/plugin.cfg
Normal 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"
|
||||
Reference in New Issue
Block a user