Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
be14434
Merge pull request #1 from TaloDev/develop
tudddorrr May 4, 2024
cb6c56e
Merge pull request #2 from TaloDev/develop
tudddorrr May 7, 2024
778b832
Merge pull request #3 from TaloDev/develop
tudddorrr May 7, 2024
8e64536
Merge pull request #4 from TaloDev/develop
tudddorrr May 9, 2024
ee4515a
Merge pull request #7 from TaloDev/develop
tudddorrr Jun 13, 2024
203e92b
Merge pull request #9 from TaloDev/develop
tudddorrr Jul 11, 2024
c35f092
Merge pull request #11 from TaloDev/develop
tudddorrr Jul 25, 2024
ea2ddf5
Merge pull request #13 from TaloDev/develop
tudddorrr Aug 1, 2024
b8a016b
Merge pull request #15 from TaloDev/develop
tudddorrr Aug 8, 2024
25395aa
Merge pull request #18 from TaloDev/develop
tudddorrr Aug 30, 2024
5e407ac
Merge pull request #20 from TaloDev/develop
tudddorrr Sep 8, 2024
58bde26
Merge pull request #21 from TaloDev/develop
tudddorrr Sep 14, 2024
923b972
Merge pull request #23 from TaloDev/develop
tudddorrr Sep 21, 2024
643e168
Merge pull request #27 from TaloDev/develop
tudddorrr Sep 26, 2024
5de74c4
Merge branch 'develop'
tudddorrr Sep 26, 2024
879cc4d
Merge pull request #30 from TaloDev/develop
tudddorrr Oct 3, 2024
1a61ae6
Merge pull request #32 from TaloDev/develop
tudddorrr Oct 8, 2024
effad38
Merge pull request #35 from TaloDev/develop
tudddorrr Oct 20, 2024
b42ba80
Merge pull request #38 from TaloDev/develop
tudddorrr Oct 28, 2024
8faf833
Merge pull request #44 from TaloDev/develop
tudddorrr Nov 14, 2024
3de6d86
Merge pull request #46 from TaloDev/develop
tudddorrr Nov 27, 2024
1c5edff
Merge branch 'develop'
tudddorrr Nov 27, 2024
64ee25e
Merge pull request #51 from TaloDev/develop
tudddorrr Dec 9, 2024
9d92c68
Merge pull request #54 from TaloDev/develop
tudddorrr Dec 15, 2024
41aa029
Merge pull request #56 from TaloDev/develop
tudddorrr Jan 3, 2025
bd12ee0
Merge pull request #61 from TaloDev/develop
tudddorrr Jan 9, 2025
aae5f0c
Merge pull request #64 from TaloDev/develop
tudddorrr Jan 28, 2025
494ca10
Merge pull request #66 from TaloDev/develop
tudddorrr Feb 14, 2025
9cdff0c
Merge pull request #68 from TaloDev/develop
tudddorrr Feb 19, 2025
43bbe6d
Use `RefCounted` instead of `Node` to avoid unnecessary memory manage.
Daylily-Zeleen Feb 21, 2025
dbff565
Optimize leaderboard api.
Daylily-Zeleen Feb 21, 2025
db8745e
Optimize channels api.
Daylily-Zeleen Feb 23, 2025
e102a74
Let GameConfigAPI.get_live_config() return the TaloLiveConfig( useful…
Daylily-Zeleen Feb 23, 2025
62fa464
Let PlayerAuthAPI.login() return `LoginResult` instead of an Array.
Daylily-Zeleen Feb 23, 2025
67f3d67
Let some apis in PlayerAPI return `TaloPlayer` directly( for async pr…
Daylily-Zeleen Feb 23, 2025
06c70bb
1. Some tiny fix.
Daylily-Zeleen Feb 23, 2025
fca7f04
Disallow SavesManager to emit SavesAPI's signals.
Daylily-Zeleen Feb 23, 2025
49fb607
Try to create default settings file when plugin enabling instead of a…
Daylily-Zeleen Feb 23, 2025
6296cce
Rename "is_last_page" to "last_page".
Daylily-Zeleen Feb 24, 2025
1af9d39
Update samples to adapt to changes of SDK.
Daylily-Zeleen Feb 24, 2025
6d7e781
Rename "TimeUtils" to "TaloTimeUtils".
Daylily-Zeleen Feb 24, 2025
d831939
Add missing channel events/signals.
Daylily-Zeleen Feb 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion addons/talo/apis/api.gd
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ class_name TaloAPI extends Node

var client: TaloClient

func _init(base_path: String):
func _init(base_path: String) -> void:
name = "Talo%s" % base_path
client = TaloClient.new(base_path)
add_child(client)
77 changes: 54 additions & 23 deletions addons/talo/apis/channels_api.gd
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
class_name ChannelsAPI extends TaloAPI
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will use this file as a base for most of my comments:

  1. I'd like to keep using the class_name xAPI extends TaloAPI format - unless there's any reason not to. I like the declarative nature of showing exactly what the class name is.
  2. For consistency I'd prefer if we didn't use the p_ prefixes on variable names. I understand the idea behind it but I don't think the values are being shadowed in the same way they would be in other languages.
  3. Really love that you added these signals - would be great if the changes in this file could be pulled out into their own PR
  4. Similarly love the idea of the ChannelPage struct - if this could be part of the same PR as the above that would be great!

Copy link
Contributor Author

@Daylily-Zeleen Daylily-Zeleen Feb 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I think a plugin should avoid expose unnecessary class name, class_name is global scope, it will contaminate user's namespace. Any class_name in plugin should be thought twice.
    If you definitely want to keep them has an explicit class name, we can consider to user an independence script with a class_name and declare other scripts as a constant value like in "talo_manager.gd" in this pre.
    For example:
# talo.gd
class_name TaloScope # Maybe "TaloScope" is not an appropriate name of Talo namespace.

const ChannelsAPI = preload("apis/channels_api.gd")
...




# talo_manager.gd
...

var channels : TaloScope.ChannelsAPI
...

  1. This is mainly to improve maintainability, for example:
var name: String = "abc"

# The argument "name" is shadowing the property "name".
func foo(name: String) -> void:
    var a := name

    ...... # A very long piece of code.

    print(name) # Will print the value of argument "name". (Correct)

If we consider to change the argument "name" and fix relate logic partially, it will be like this:

var name: String = "abc"

# Change "name" to be an int value "id". 
func foo(id: int) -> void:
    var a := id

    ...... # A very long piece of code.

    # Because "name" is a property in this script, it will not be an error and easy to be ignored.
    print(name) # Will print "abc". (Wrong)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fully see your point and agree in principle but I think the main problem with polluting namespaces is naming collisions. I'm hopeful that one day gdscript will add namespaces but until then I think 99.9% of Godot projects won't have any naming collisions with any of the Talo APIs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can’t assume the user's naming preferences. For example, TimeUtils, it is entirely possible for the user to create type with the same name.
At least we need to add the prefix "Talo" to all Talo types like the C language library.

We can consider it from another perspective, reduce expose unnecessary types to users can reduce the number of related types in the completion list when users type "Talo" in code editor, so user can ignore them. This reduces unnecessary complexity and keep the simplicity of the API.
Especially for some types in the "utilis" folder, they are completely inaccessible to users but have a global class name, this is completely inappropriate.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah I think adding Talo as a prefix to the APIs is a good middle ground, especially because that won't lead to a breaking change

## ChannelsAPI
extends TaloAPI
## An interface for communicating with the Talo Channels API.
##
## This API is used to send messages between players who are subscribed to channels.
Expand All @@ -7,18 +8,36 @@ class_name ChannelsAPI extends TaloAPI

## Emitted when a message is received from a channel.
signal message_received(channel: TaloChannel, player_alias: TaloPlayerAlias, message: String)
## Emitted when a player is joined to a channel.
signal player_joined(channel: TaloChannel, player_alias: TaloPlayerAlias)
## Emitted when a player is left from a channel.
signal player_left(channel: TaloChannel, player_alias: TaloPlayerAlias)
## Emitted when a channel's ownership transferred.
signal channel_ownership_transferred(channel: TaloChannel, new_owner_player_alias: TaloPlayerAlias)
## Emitted when a channel is deleted.
signal channel_deleted(channel: TaloChannel)

func _ready():

func _ready() -> void:
await Talo.init_completed
Talo.socket.message_received.connect(_on_message_received)

func _on_message_received(res: String, data: Dictionary) -> void:
if res == "v1.channels.message":
message_received.emit(TaloChannel.new(data.channel), TaloPlayerAlias.new(data.playerAlias), data.message)
match res:
"v1.channels.message":
message_received.emit(TaloChannel.new(data.channel), TaloPlayerAlias.new(data.playerAlias), data.message)
"v1.channels.player-joined":
player_joined.emit(TaloChannel.new(data.channel), TaloPlayerAlias.new(data.playerAlias))
"v1.channels.player-left":
player_left.emit(TaloChannel.new(data.channel), TaloPlayerAlias.new(data.playerAlias))
"v1.channels.ownership-transferred":
player_left.emit(TaloChannel.new(data.channel), TaloPlayerAlias.new(data.playerAlias))
"v1.channels.deleted":
channel_deleted.emit(TaloChannel.new(data.channel))

## Get a channel by its ID.
func find(channel_id: int) -> TaloChannel:
var res = await client.make_request(HTTPClient.METHOD_GET, "/%s" % channel_id)
var res := await client.make_request(HTTPClient.METHOD_GET, "/%s" % channel_id)

match (res.status):
200:
Expand All @@ -27,41 +46,41 @@ func find(channel_id: int) -> TaloChannel:
return null

## Get a list of channels that players can join.
func get_channels(page: int) -> Array:
var res = await client.make_request(HTTPClient.METHOD_GET, "?page=%s" % page)
func get_channels(page: int) -> ChannelPage:
var res := await client.make_request(HTTPClient.METHOD_GET, "?page=%s" % page)

match (res.status):
200:
var channels: Array[TaloChannel] = []
channels.assign(res.body.channels.map(func (channel: Dictionary): return TaloChannel.new(channel)))
return [channels, res.body.count, res.body.isLastPage]
channels.assign(res.body.channels.map(func (channel: Dictionary) -> TaloChannel: return TaloChannel.new(channel)))
return ChannelPage.new(channels, res.body.count, res.body.isLastPage)
_:
return []
return null

## Get a list of channels that the current player is subscribed to.
func get_subscribed_channels() -> Array[TaloChannel]:
if Talo.identity_check() != OK:
return []

var res = await client.make_request(HTTPClient.METHOD_GET, "/subscriptions")
var res := await client.make_request(HTTPClient.METHOD_GET, "/subscriptions")

match (res.status):
200:
var channels: Array[TaloChannel] = []
channels.assign(res.body.channels.map(func (channel: Dictionary): return TaloChannel.new(channel)))
channels.assign(res.body.channels.map(func (channel: Dictionary) -> TaloChannel: return TaloChannel.new(channel)))
return channels
_:
return []

## Create a new channel. The player who creates this channel will automatically become the owner. If auto cleanup is enabled, the channel will be deleted when the owner or the last member leaves.
func create(name: String, auto_cleanup: bool = false, props: Dictionary = {}) -> TaloChannel:
func create(p_name: String, auto_cleanup: bool = false, props: Dictionary = {}) -> TaloChannel:
if Talo.identity_check() != OK:
return

var props_to_send = props.keys().map(func (key: String): return { key = key, value = str(props[key]) })
var props_to_send := props.keys().map(func (key: String) -> Dictionary: return { key = key, value = str(props[key]) })

var res = await client.make_request(HTTPClient.METHOD_POST, "", {
name = name,
var res := await client.make_request(HTTPClient.METHOD_POST, "", {
name = p_name,
autoCleanup = auto_cleanup,
props = props_to_send
})
Expand All @@ -77,7 +96,7 @@ func join(channel_id: int) -> TaloChannel:
if Talo.identity_check() != OK:
return

var res = await client.make_request(HTTPClient.METHOD_POST, "/%s/join" % channel_id)
var res := await client.make_request(HTTPClient.METHOD_POST, "/%s/join" % channel_id)

match (res.status):
200:
Expand All @@ -93,19 +112,19 @@ func leave(channel_id: int) -> void:
await client.make_request(HTTPClient.METHOD_POST, "/%s/leave" % channel_id)

## Update a channel. This will only work if the current player is the owner of the channel.
func update(channel_id: int, name: String = "", new_owner_alias_id: int = -1, props: Dictionary = {}) -> TaloChannel:
func update(channel_id: int, p_name: String = "", new_owner_alias_id: int = -1, props: Dictionary = {}) -> TaloChannel:
if Talo.identity_check() != OK:
return

var data = {}
if not name.is_empty():
data.name = name
var data := {}
if not p_name.is_empty():
data.name = p_name
if new_owner_alias_id != -1:
data.ownerAliasId = new_owner_alias_id
if props.size() > 0:
data.props = props

var res = await client.make_request(HTTPClient.METHOD_PUT, "/%s" % channel_id, data)
var res := await client.make_request(HTTPClient.METHOD_PUT, "/%s" % channel_id, data)

match (res.status):
200:
Expand All @@ -121,7 +140,7 @@ func delete(channel_id: int) -> void:
if Talo.identity_check() != OK:
return

var res = await client.make_request(HTTPClient.METHOD_DELETE, "/%s" % channel_id)
var res := await client.make_request(HTTPClient.METHOD_DELETE, "/%s" % channel_id)

match (res.status):
403:
Expand All @@ -138,3 +157,15 @@ func send_message(channel_id: int, message: String) -> void:
},
message = message
})


# Structs
class ChannelPage:
var channels: Array[TaloChannel]
var count: int
var last_page: bool

func _init(p_channels: Array[TaloChannel], p_count: int, p_last_page: bool) -> void:
channels = p_channels
count = p_count
last_page = p_last_page
23 changes: 12 additions & 11 deletions addons/talo/apis/events_api.gd
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
class_name EventsAPI extends TaloAPI
## EventsAPI
extends TaloAPI
## An interface for communicating with the Talo Events API.
##
## This API is used to track events in your game. Events are used to measure user interactions such as button clicks, level completions and other kinds of game interactions.
##
## @tutorial: https://docs.trytalo.com/docs/godot/events

var _queue = []
var _min_queue_size = 10
var _queue := []
var _min_queue_size := 10

func _get_window_mode() -> String:
match DisplayServer.window_get_mode():
Expand All @@ -29,24 +30,24 @@ func _build_meta_props() -> Array[TaloProp]:
]

func _has_errors(errors: Array) -> bool:
return errors.any((func (err: Array): return err.size() > 0))
return errors.any((func (err: Array) -> bool: return err.size() > 0))

## Track an event with optional props (key-value pairs) and add it to the queue of events ready to be sent to the backend. If the queue reaches the minimum size, it will be flushed.
func track(name: String, props: Dictionary = {}) -> void:
func track(p_name: String, props: Dictionary = {}) -> void:
if Talo.identity_check() != OK:
return

var final_props = _build_meta_props()
var final_props := _build_meta_props()
final_props.append_array(
props
.keys()
.map(func (key: String): return TaloProp.new(key, str(props[key])))
.map(func (key: String) -> TaloProp: return TaloProp.new(key, str(props[key])))
)

_queue.push_back({
name = name,
props = final_props.map(func (prop: TaloProp): return prop.to_dictionary()),
timestamp = TimeUtils.get_timestamp_msec()
name = p_name,
props = final_props.map(func (prop: TaloProp) -> Dictionary: return prop.to_dictionary()),
timestamp = TaloTimeUtils.get_timestamp_msec()
})

if _queue.size() >= _min_queue_size:
Expand All @@ -57,7 +58,7 @@ func flush() -> void:
if _queue.size() == 0:
return

var res = await client.make_request(HTTPClient.METHOD_POST, "/", { events = _queue })
var res := await client.make_request(HTTPClient.METHOD_POST, "/", { events = _queue })
_queue.clear()

match (res.status):
Expand Down
7 changes: 4 additions & 3 deletions addons/talo/apis/feedback_api.gd
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
class_name FeedbackAPI extends TaloAPI
## FeedbackAPI
extends TaloAPI
## An interface for communicating with the Talo Feedback API.
##
## This API is used to submit feedback across different categories from your players.
Expand All @@ -7,12 +8,12 @@ class_name FeedbackAPI extends TaloAPI

## Get a list of feedback categories that are available for players to submit feedback.
func get_categories() -> Array[TaloFeedbackCategory]:
var res = await client.make_request(HTTPClient.METHOD_GET, "/categories")
var res := await client.make_request(HTTPClient.METHOD_GET, "/categories")

match (res.status):
200:
var categories: Array[TaloFeedbackCategory] = []
categories.assign(res.body.feedbackCategories.map(func (category: Dictionary): return TaloFeedbackCategory.new(category)))
categories.assign(res.body.feedbackCategories.map(func (category: Dictionary) -> TaloFeedbackCategory: return TaloFeedbackCategory.new(category)))
return categories
_:
return []
Expand Down
10 changes: 7 additions & 3 deletions addons/talo/apis/game_config_api.gd
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
class_name GameConfigAPI extends TaloAPI
## GameConfigAPI
extends TaloAPI
## An interface for communicating with the Talo Live Config API.
##
## This API is used to fetch the live config for your game. The live config is a set of key-value pairs that can be updated in the Talo dashboard.
Expand All @@ -20,9 +21,12 @@ func _on_message_received(res: String, data: Dictionary) -> void:
live_config_updated.emit(TaloLiveConfig.new(data.config))

## Get the live config for your game.
func get_live_config() -> void:
var res = await client.make_request(HTTPClient.METHOD_GET, "/")
func get_live_config() -> TaloLiveConfig:
var res := await client.make_request(HTTPClient.METHOD_GET, "/")
match (res.status):
200:
Talo.live_config = TaloLiveConfig.new(res.body.config)
live_config_loaded.emit(Talo.live_config)
return Talo.live_config
_:
return null
5 changes: 3 additions & 2 deletions addons/talo/apis/health_check_api.gd
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
class_name HealthCheckAPI extends TaloAPI
## HealthCheckAPI
extends TaloAPI
## An interface for communicating with the Talo Health Check API.
##
## This API is used to check if Talo can be reached by Continuity. You shouldn't need to use this API directly in your game.
Expand All @@ -7,5 +8,5 @@ class_name HealthCheckAPI extends TaloAPI

## Ping the Talo Health Check API to check if Talo can be reached.
func ping() -> bool:
var res = await client.make_request(HTTPClient.METHOD_GET, "")
var res := await client.make_request(HTTPClient.METHOD_GET, "")
return res.status == 204
Loading