Add collaborative surface drawing
This commit is contained in:
parent
6b7ef4c11b
commit
b92c55562d
28 changed files with 3504 additions and 2 deletions
|
|
@ -11,6 +11,7 @@ var _known: KnownPlayerStore
|
|||
var _spawn: PlayerSpawnService
|
||||
var _chat: NetworkChatService
|
||||
var _mail: NetworkMailService
|
||||
var _surface_drawing: NetworkSurfaceDrawingService
|
||||
var _revision := 0
|
||||
var _host_block_pairs: Dictionary[String, bool] = {}
|
||||
var _peer_fingerprints: Dictionary[int, String] = {}
|
||||
|
|
@ -96,6 +97,42 @@ func get_bans() -> Array[Dictionary]:
|
|||
return _bans.get_bans(_session.get_host_identity_fingerprint()) if _session.is_host() else []
|
||||
|
||||
|
||||
func set_surface_drawing_service(
|
||||
service: NetworkSurfaceDrawingService,
|
||||
) -> void:
|
||||
_surface_drawing = service
|
||||
if (
|
||||
_surface_drawing != null
|
||||
and not _surface_drawing.session_artwork_changed.is_connected(
|
||||
_on_session_artwork_changed
|
||||
)
|
||||
):
|
||||
_surface_drawing.session_artwork_changed.connect(
|
||||
_on_session_artwork_changed
|
||||
)
|
||||
_changed()
|
||||
|
||||
|
||||
func get_session_artwork_counts() -> Vector2i:
|
||||
if _surface_drawing == null:
|
||||
return Vector2i.ZERO
|
||||
return Vector2i(
|
||||
_surface_drawing.get_canvas_count(),
|
||||
_surface_drawing.get_painted_cell_count(),
|
||||
)
|
||||
|
||||
|
||||
func reset_session_artwork() -> bool:
|
||||
if not _session.is_host() or _surface_drawing == null:
|
||||
return false
|
||||
var ok: bool = _surface_drawing.clear_session_artwork()
|
||||
moderation_finished.emit(
|
||||
ok,
|
||||
"Session artwork cleared." if ok else "Session artwork could not be cleared.",
|
||||
)
|
||||
return ok
|
||||
|
||||
|
||||
func set_muted(fingerprint: String, display_name: String, value: bool) -> bool:
|
||||
if fingerprint == _session.get_local_identity_fingerprint():
|
||||
return false
|
||||
|
|
@ -269,3 +306,10 @@ func _entry_before(a: PlayerListEntry, b: PlayerListEntry) -> bool:
|
|||
func _changed() -> void:
|
||||
_revision += 1
|
||||
entries_changed.emit()
|
||||
|
||||
|
||||
func _on_session_artwork_changed(
|
||||
_canvas_count: int,
|
||||
_painted_cell_count: int,
|
||||
) -> void:
|
||||
_changed()
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const MAX_PUBLIC_KEY_LENGTH: int = 8192
|
|||
const MAX_SIGNATURE_LENGTH: int = 2048
|
||||
# ENet channels: 0 reliable lifecycle, 1 movement input, 2 movement
|
||||
# snapshots, 3 fishing input, 4 fishing snapshots, 5 reliable sales,
|
||||
# 6 reliable shop transactions, 7 reliable item/equipment/showcase lifecycle,
|
||||
# 6 reliable shop transactions, 7 reliable item/equipment/showcase/drawing,
|
||||
# 8 reliable ordered session chat, 9 reliable private session mail.
|
||||
const SALE_RELIABLE_CHANNEL: int = 5
|
||||
const SHOP_RELIABLE_CHANNEL: int = 6
|
||||
|
|
@ -18,6 +18,7 @@ const ITEM_RELIABLE_CHANNEL: int = 7
|
|||
const CHAT_RELIABLE_CHANNEL: int = 8
|
||||
const MAIL_RELIABLE_CHANNEL: int = 9
|
||||
const ENET_CHANNEL_COUNT: int = 10
|
||||
const SURFACE_DRAWING_CAPABILITY: String = "surface_drawing_v1"
|
||||
|
||||
enum RejectionCode {
|
||||
NONE,
|
||||
|
|
@ -83,7 +84,9 @@ static func make_client_hello(
|
|||
"local_profile_id": profile_id,
|
||||
"display_name": display_name,
|
||||
"client_nonce": client_nonce,
|
||||
"capability_flags": PackedStringArray(),
|
||||
"capability_flags": PackedStringArray([
|
||||
SURFACE_DRAWING_CAPABILITY,
|
||||
]),
|
||||
"cosmetic_snapshot": cosmetic_snapshot,
|
||||
"identity_fingerprint": identity_fingerprint,
|
||||
"identity_signature": identity_signature,
|
||||
|
|
@ -122,6 +125,16 @@ static func validate_client_hello(data: Variant) -> String:
|
|||
TYPE_ARRAY,
|
||||
]:
|
||||
return "Capabilities are invalid."
|
||||
var capabilities: Variant = payload["capability_flags"]
|
||||
if capabilities.size() > 32:
|
||||
return "Capabilities are invalid."
|
||||
for capability: Variant in capabilities:
|
||||
if (
|
||||
typeof(capability) not in [TYPE_STRING, TYPE_STRING_NAME]
|
||||
or str(capability).is_empty()
|
||||
or str(capability).length() > 64
|
||||
):
|
||||
return "Capabilities are invalid."
|
||||
if typeof(payload["cosmetic_snapshot"]) != TYPE_DICTIONARY:
|
||||
return "Cosmetic snapshot is invalid."
|
||||
if (
|
||||
|
|
@ -188,6 +201,7 @@ static func make_server_hello(
|
|||
"item_use_v1",
|
||||
"equipment_v1",
|
||||
"fish_showcase_v1",
|
||||
SURFACE_DRAWING_CAPABILITY,
|
||||
"chat_v1",
|
||||
"mail_v1",
|
||||
"profile_v1",
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ func start_private_host(port: int = DEFAULT_PORT) -> bool:
|
|||
NetworkProtocol.PROTOCOL_VERSION,
|
||||
_player_identity.fingerprint,
|
||||
_player_identity.public_pem,
|
||||
PackedStringArray([NetworkProtocol.SURFACE_DRAWING_CAPABILITY]),
|
||||
)
|
||||
_registry.update_appearance(1, _local_appearance_snapshot)
|
||||
var host_profile_hello := NetworkProtocol.make_client_hello(
|
||||
|
|
@ -361,6 +362,7 @@ func supports_server_capability(capability: StringName) -> bool:
|
|||
return str(capability) in PackedStringArray([
|
||||
"movement_v1", "fishing_v1", "sale_v1", "shop_v1",
|
||||
"item_use_v1", "equipment_v1", "fish_showcase_v1",
|
||||
NetworkProtocol.SURFACE_DRAWING_CAPABILITY,
|
||||
"chat_v1",
|
||||
"mail_v1",
|
||||
"profile_v1",
|
||||
|
|
@ -373,6 +375,14 @@ func get_peer_record(peer_id: int) -> PeerRegistry.PeerRecord:
|
|||
return _registry.get_peer(peer_id)
|
||||
|
||||
|
||||
func peer_supports_capability(
|
||||
peer_id: int,
|
||||
capability: StringName,
|
||||
) -> bool:
|
||||
var record: PeerRegistry.PeerRecord = _registry.get_peer(peer_id)
|
||||
return record != null and str(capability) in record.capability_flags
|
||||
|
||||
|
||||
func get_authenticated_peer_ids() -> Array[int]:
|
||||
return _registry.get_peer_ids()
|
||||
|
||||
|
|
@ -931,6 +941,7 @@ func submit_client_hello(data: Dictionary) -> void:
|
|||
NetworkProtocol.PROTOCOL_VERSION,
|
||||
identity["fingerprint"],
|
||||
identity["public_key"],
|
||||
_sanitized_capabilities(data.get("capability_flags", [])),
|
||||
):
|
||||
_reject_peer(
|
||||
sender_id,
|
||||
|
|
@ -1062,6 +1073,7 @@ func receive_server_hello(data: Dictionary) -> void:
|
|||
NetworkProtocol.PROTOCOL_VERSION,
|
||||
_player_identity.fingerprint,
|
||||
_player_identity.public_pem,
|
||||
PackedStringArray([NetworkProtocol.SURFACE_DRAWING_CAPABILITY]),
|
||||
)
|
||||
_registry.update_appearance(local_peer_id, _local_appearance_snapshot)
|
||||
var local_record := _registry.get_peer(local_peer_id)
|
||||
|
|
@ -1143,6 +1155,7 @@ func _apply_spawn_entry(entry: Dictionary) -> void:
|
|||
NetworkProtocol.PROTOCOL_VERSION,
|
||||
str(entry.get("identity_fingerprint", "")),
|
||||
str(entry.get("identity_public_key", "")),
|
||||
_sanitized_capabilities(entry.get("capability_flags", [])),
|
||||
)
|
||||
var added_record := _registry.get_peer(peer_id)
|
||||
if added_record != null and added_record.identity_authenticated:
|
||||
|
|
@ -1218,9 +1231,28 @@ func _make_spawn_entry(
|
|||
record.profile_authorization.duplicate(true)
|
||||
if record != null else {}
|
||||
),
|
||||
"capability_flags": (
|
||||
record.capability_flags.duplicate()
|
||||
if record != null else PackedStringArray()
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
func _sanitized_capabilities(value: Variant) -> PackedStringArray:
|
||||
var result := PackedStringArray()
|
||||
if typeof(value) not in [TYPE_ARRAY, TYPE_PACKED_STRING_ARRAY]:
|
||||
return result
|
||||
for capability: Variant in value:
|
||||
if (
|
||||
typeof(capability) in [TYPE_STRING, TYPE_STRING_NAME]
|
||||
and not str(capability).is_empty()
|
||||
and str(capability).length() <= 64
|
||||
and str(capability) not in result
|
||||
):
|
||||
result.append(str(capability))
|
||||
return result
|
||||
|
||||
|
||||
func _verify_spawn_identity(entry: Dictionary) -> bool:
|
||||
var fingerprint := str(entry.get("identity_fingerprint", ""))
|
||||
var public_pem := NetworkIdentityCrypto.normalize_public_pem(
|
||||
|
|
|
|||
1731
network/network_surface_drawing_service.gd
Normal file
1731
network/network_surface_drawing_service.gd
Normal file
File diff suppressed because it is too large
Load diff
1
network/network_surface_drawing_service.gd.uid
Normal file
1
network/network_surface_drawing_service.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://bkiepgu8j5r6t
|
||||
|
|
@ -16,6 +16,7 @@ class PeerRecord:
|
|||
var identity_public_key: String = ""
|
||||
var identity_authenticated: bool = false
|
||||
var profile_authorization: Dictionary = {}
|
||||
var capability_flags: PackedStringArray = PackedStringArray()
|
||||
|
||||
|
||||
var _records: Dictionary[int, PeerRecord] = {}
|
||||
|
|
@ -28,6 +29,7 @@ func add_peer(
|
|||
protocol_version: int,
|
||||
identity_fingerprint: String = "",
|
||||
identity_public_key: String = "",
|
||||
capability_flags: PackedStringArray = PackedStringArray(),
|
||||
) -> bool:
|
||||
if (
|
||||
peer_id <= 0
|
||||
|
|
@ -49,6 +51,7 @@ func add_peer(
|
|||
record.identity_authenticated = NetworkIdentityCrypto.valid_fingerprint(
|
||||
identity_fingerprint
|
||||
)
|
||||
record.capability_flags = capability_flags.duplicate()
|
||||
_records[peer_id] = record
|
||||
return true
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue