| … | … | @@ -27,7 +27,7 @@ A Godot plugin and example project for loading assets from the [hypercore-protoc |
| 27 | 27 | - [ ] Basic Multiplayer demo using extension messages |
| 28 | 28 | - [x] Refactor chat system to be more general purpose (not just texts) |
| 29 | 29 | - [x] Basic demo moving blobs around on a map |
| 30 | - [ ] Place usernames in a hyperdrive's json file along with an image for your blob | |
| 30 | - [x] Place usernames in a hyperdrive's json file along with an image for your blob | |
| 31 | 31 | - [ ] Create custom maps from an image and a JSON file |
| 32 | 32 | - [ ] Auto-discover which maps are active |
| 33 | 33 | - [ ] Enable code to work in Godot Web in Agregore |
| … | … | @@ -74,7 +74,7 @@ Display=8 |
| 74 | 74 | [application] |
| 75 | 75 | |
| 76 | 76 | config/name="HyperGodot" |
| 77 | run/main_scene="res://src/HyperLoad/HyperLoad.tscn" | |
| 77 | run/main_scene="res://src/MultiplayerDemo/MultiplayerDemo.tscn" | |
| 78 | 78 | config/icon="res://icon.png" |
| 79 | 79 | |
| 80 | 80 | [display] |
| … | … | @@ -5,6 +5,8 @@ var RemoteBullet = preload("res://src/MultiplayerDemo/RemoteBullet.tscn") |
| 5 | 5 | |
| 6 | 6 | #export var url: String = "hyper://blog.mauve.moe/" |
| 7 | 7 | export var url: String = "hyper://70338a94d7415990ab4a3160cf98a5d940243d7fa24dd297352e66b52d3ff841/" |
| 8 | export var profile : String = "" | |
| 9 | export var spawn_gateway = true | |
| 8 | 10 | |
| 9 | 11 | onready var gossip = $HyperGossip |
| 10 | 12 | onready var player = $Player |
| … | … | @@ -16,7 +18,8 @@ const SHOOT = 'shoot' |
| 16 | 18 | const knownPlayers = {} |
| 17 | 19 | |
| 18 | 20 | func _ready(): |
| 19 | gateway.start() | |
| 21 | if spawn_gateway: gateway.start() | |
| 22 | elif profile.length() != 0: player.load_profile(profile) | |
| 20 | 23 | |
| 21 | 24 | func get_player_object(id): |
| 22 | 25 | if knownPlayers.has(id): return knownPlayers[id] |
| … | … | @@ -34,6 +37,7 @@ func _broadcast_player(): |
| 34 | 37 | var rotation = player.rotation_degrees |
| 35 | 38 | var velocity = player.velocity |
| 36 | 39 | var data = { |
| 40 | "profile": profile, | |
| 37 | 41 | "position": { |
| 38 | 42 | "x": position.x, |
| 39 | 43 | "y": position.y |
| … | … | @@ -49,6 +53,7 @@ func _broadcast_player(): |
| 49 | 53 | |
| 50 | 54 | func _broadcast_shoot(direction,location): |
| 51 | 55 | var data = { |
| 56 | "profile": profile, | |
| 52 | 57 | "direction": direction, |
| 53 | 58 | "position": { |
| 54 | 59 | "x": location.x, |
| … | … | @@ -61,6 +66,10 @@ func _broadcast_shoot(direction,location): |
| 61 | 66 | func _on_remote_player_moved(positionData, id): |
| 62 | 67 | # print('Moving player', id, " ", positionData) |
| 63 | 68 | var remotePlayer = get_player_object(id) |
| 69 | ||
| 70 | if positionData.has('profile') and positionData.profile.length() != 0: | |
| 71 | if !remotePlayer.has_profile: remotePlayer.load_profile(positionData.profile) | |
| 72 | ||
| 64 | 73 | var rotation_degrees = positionData.rotation |
| 65 | 74 | var raw_position = positionData.position |
| 66 | 75 | var raw_velocity = positionData.velocity |
| … | … | @@ -95,6 +104,8 @@ func _on_Player_shoot(Bullet, direction, location): |
| 95 | 104 | _broadcast_shoot(direction, location) |
| 96 | 105 | |
| 97 | 106 | func _on_HyperGateway_started_gateway(_pid): |
| 107 | if profile.length() != 0: player.load_profile(profile) | |
| 108 | ||
| 98 | 109 | gossip.url = url |
| 99 | 110 | gossip.start_listening() |
| 100 | 111 |
| … | … | @@ -1,19 +1,20 @@ |
| 1 | 1 | extends "res://src/ResizeRoot.gd" |
| 2 | 2 | |
| 3 | signal profile_ready(url) | |
| 3 | # TODO: Better error dialogs | |
| 4 | # TODO: Better UX for updating the username | |
| 4 | 5 | |
| 5 | export var profile_URL: String = 'hyper://flyballs-profile/' | |
| 6 | export var profile_file: String = 'profile.json' | |
| 7 | export var cache_folder: String = 'user://hyper-file-cache/' | |
| 6 | signal profile_ready(url) | |
| 8 | 7 | |
| 9 | var picture_name = "" | |
| 10 | var picture_path = "" | |
| 8 | export var profile_url = 'hyper://flyballs-profile/' | |
| 9 | export var spawn_gateway = true | |
| 11 | 10 | |
| 12 | 11 | func _ready(): |
| 13 | var dir = Directory.new() | |
| 14 | var err = dir.make_dir_recursive(cache_folder) | |
| 15 | if err != OK: | |
| 16 | printerr("Unable to create cache directory ", err) | |
| 12 | if spawn_gateway: $HyperGateway.start() | |
| 13 | ||
| 14 | func load_profile(): | |
| 15 | print("Initial profile load") | |
| 16 | $PlayerProfile.url = profile_url | |
| 17 | $PlayerProfile.load_profile() | |
| 17 | 18 | |
| 18 | 19 | func hide_loader(): |
| 19 | 20 | $Loader.hide() |
| … | … | @@ -23,142 +24,65 @@ func show_loader(): |
| 23 | 24 | $Loader.show() |
| 24 | 25 | $Form.hide() |
| 25 | 26 | |
| 26 | func load_url(): | |
| 27 | var url_record = profile_URL + '.well-known/hyper' | |
| 28 | $LoadURLRequest.request(url_record) | |
| 29 | ||
| 30 | func update_profile(data): | |
| 31 | var json = JSON.print(data) | |
| 32 | var info_url = profile_URL + profile_file | |
| 33 | ||
| 34 | $UpdateProfileRequest.request(info_url, [], true, HTTPClient.METHOD_PUT, json) | |
| 35 | ||
| 36 | 27 | func get_username(): |
| 37 | 28 | return $Form/UsernameInput.text |
| 38 | 29 | |
| 39 | func load_profile(): | |
| 40 | var info_url = profile_URL + profile_file | |
| 41 | $ListInfoRequest.request(info_url) | |
| 42 | ||
| 43 | 30 | func load_image(image: String): |
| 44 | 31 | print('Loading image') |
| 45 | 32 | show_loader() |
| 46 | var file_name = image.get_file() | |
| 47 | picture_path = cache_folder + file_name | |
| 48 | # TODO: Save file_path somewhere? | |
| 49 | $LoadImageRequest.download_file = picture_path | |
| 50 | $LoadImageRequest.request(image) | |
| 33 | $PlayerProfile.download_image(image) | |
| 51 | 34 | |
| 52 | 35 | func _on_ImageChooser_pressed(): |
| 36 | print('Choosing image') | |
| 53 | 37 | $FileDialog.popup() |
| 54 | 38 | |
| 55 | 39 | func _on_FileDialog_file_selected(path: String): |
| 40 | print('Selected image, uploading:', path) | |
| 56 | 41 | show_loader() |
| 57 | ||
| 58 | picture_name = path.get_file() | |
| 59 | var picture_url = profile_URL + picture_name | |
| 60 | ||
| 61 | $HyperUploader.upload_file(picture_url, path) | |
| 42 | $PlayerProfile.upload_image(path) | |
| 62 | 43 | |
| 63 | 44 | func _on_HyperGateway_started_gateway(_pid): |
| 64 | 45 | load_profile() |
| 65 | 46 | |
| 66 | func _on_ListInfoRequest_request_completed(_result, response_code, _headers, body): | |
| 67 | if response_code != 200: | |
| 68 | printerr('Cannot load existing profile info: ', response_code) | |
| 69 | hide_loader() | |
| 70 | return | |
| 71 | ||
| 72 | var parsed = JSON.parse(body.get_string_from_utf8()) | |
| 73 | if parsed.error != OK: | |
| 74 | printerr(parsed.error_string) | |
| 75 | hide_loader() | |
| 76 | return | |
| 77 | ||
| 78 | $Form/StartButton.disabled = false | |
| 79 | ||
| 80 | $Form/UsernameInput.text = parsed.result.username | |
| 47 | func _on_StartButton_pressed(): | |
| 48 | print("Starting next step") | |
| 49 | show_loader() | |
| 50 | $PlayerProfile.resolve_url() | |
| 81 | 51 | |
| 82 | var image = parsed.result.image | |
| 83 | if image != null: | |
| 84 | load_image(image) | |
| 85 | else: hide_loader() | |
| 52 | func _on_PlayerProfile_error(err): | |
| 53 | # TODO: Show an error dialog? | |
| 54 | print("Error interacting with profile:", err) | |
| 86 | 55 | |
| 87 | func _on_HyperUploader_uploaded(url, response_code): | |
| 88 | if response_code != 200: | |
| 89 | printerr('Unable to upload file ') | |
| 90 | hide_loader() | |
| 91 | return | |
| 92 | ||
| 93 | if !url || (url.length() == 0): | |
| 94 | printerr("Unable to load Link header for image.") | |
| 95 | hide_loader() | |
| 96 | return | |
| 97 | ||
| 98 | update_profile({ | |
| 99 | "username": get_username(), | |
| 100 | "image": url | |
| 101 | }) | |
| 102 | ||
| 103 | load_image(url) | |
| 104 | ||
| 105 | func _on_UploadFileRequest_request_completed(_result, response_code, headers, body): | |
| 106 | print('Uploaded picture') | |
| 107 | if response_code != 200: | |
| 108 | printerr('Unable to upload: ', body.get_string_from_utf8()) | |
| 109 | return | |
| 110 | ||
| 111 | var regex = RegEx.new() | |
| 112 | regex.compile("link: <(.+)>") | |
| 113 | var final_url = '' | |
| 114 | ||
| 115 | for header in headers: | |
| 116 | var result = regex.search(header) | |
| 117 | final_url = result.get_string(1) | |
| 118 | ||
| 119 | if !final_url || (final_url.size() == 0): | |
| 120 | printerr("Unable to load Link header for image. ", headers) | |
| 121 | hide_loader() | |
| 122 | return | |
| 123 | ||
| 124 | update_profile({ | |
| 125 | "username": get_username(), | |
| 126 | "image": final_url | |
| 127 | }) | |
| 128 | ||
| 129 | func _on_LoadImageRequest_request_completed(result, response_code, _headers, body): | |
| 56 | func _on_PlayerProfile_image(path): | |
| 57 | print("Image loaded, setting texture") | |
| 130 | 58 | hide_loader() |
| 131 | if result != OK or response_code != 200: | |
| 132 | printerr('Unable to load image: ', result, ": ", body.get_string_from_utf8()) | |
| 133 | return | |
| 134 | ||
| 135 | print(result, ' Image got downloaded: ', picture_path) | |
| 136 | ||
| 137 | 59 | var texture = ImageTexture.new() |
| 138 | 60 | var image = Image.new() |
| 139 | image.load(picture_path) | |
| 61 | image.load(path) | |
| 140 | 62 | texture.create_from_image(image) |
| 141 | 63 | texture.set_size_override(Vector2(64, 64)) |
| 142 | 64 | |
| 143 | 65 | $Form/ImageChooser.icon = texture |
| 144 | 66 | |
| 145 | func _on_UpdateProfileRequest_request_completed(_result, _response_code, _headers, _body): | |
| 146 | hide_loader() | |
| 67 | func _on_PlayerProfile_info(username: String, image: String): | |
| 68 | print("Loaded player profile:", {"username": username, "image": image}) | |
| 147 | 69 | $Form/StartButton.disabled = false |
| 70 | $Form/UsernameInput.text = username | |
| 148 | 71 | |
| 149 | func _on_StartButton_pressed(): | |
| 150 | show_loader() | |
| 151 | load_url() | |
| 72 | if image != null && image.length() != 0: | |
| 73 | load_image(image) | |
| 74 | else: hide_loader() | |
| 152 | 75 | |
| 153 | func _on_LoadURLRequest_request_completed(result, response_code, _headers, body: PoolByteArray): | |
| 154 | if result != OK or response_code != 200: | |
| 155 | printerr('Unable to load final profile URL') | |
| 156 | return | |
| 76 | func _on_PlayerProfile_updated(): | |
| 77 | print('Updated player profile"') | |
| 78 | hide_loader() | |
| 79 | $Form/StartButton.disabled = false | |
| 157 | 80 | |
| 158 | var lines = body.get_string_from_utf8() | |
| 159 | var url = lines.split('\n')[0] | |
| 160 | if !url.ends_with('/'): | |
| 161 | url += '/' | |
| 81 | func _on_PlayerProfile_resolved(url): | |
| 162 | 82 | print('Profile ready') |
| 163 | 83 | print(url) |
| 164 | 84 | emit_signal('profile_ready', url) |
| 85 | ||
| 86 | func _on_PlayerProfile_no_info(): | |
| 87 | print('No existing profile info') | |
| 88 | hide_loader() |
| … | … | @@ -1,9 +1,8 @@ |
| 1 | [gd_scene load_steps=5 format=2] | |
| 1 | [gd_scene load_steps=4 format=2] | |
| 2 | 2 | |
| 3 | 3 | [ext_resource path="res://src/MultiplayerDemo/LoadProfile.gd" type="Script" id=1] |
| 4 | 4 | [ext_resource path="res://src/HyperGateway/HyperGateway.gd" type="Script" id=2] |
| 5 | [ext_resource path="res://src/HyperRequest/HyperRequest.gd" type="Script" id=3] | |
| 6 | [ext_resource path="res://src/HyperRequest/HyperUploader.gd" type="Script" id=4] | |
| 5 | [ext_resource path="res://src/MultiplayerDemo/PlayerProfile.tscn" type="PackedScene" id=3] | |
| 7 | 6 | |
| 8 | 7 | [node name="LoadProfile" type="VBoxContainer"] |
| 9 | 8 | anchor_right = 1.0 |
| … | … | @@ -15,18 +14,19 @@ __meta__ = { |
| 15 | 14 | |
| 16 | 15 | [node name="Loader" type="CenterContainer" parent="."] |
| 17 | 16 | margin_right = 666.0 |
| 18 | margin_bottom = 331.0 | |
| 17 | margin_bottom = 666.0 | |
| 19 | 18 | size_flags_horizontal = 3 |
| 20 | 19 | size_flags_vertical = 3 |
| 21 | 20 | |
| 22 | 21 | [node name="Label" type="Label" parent="Loader"] |
| 23 | 22 | margin_left = 308.0 |
| 24 | margin_top = 158.0 | |
| 23 | margin_top = 326.0 | |
| 25 | 24 | margin_right = 357.0 |
| 26 | margin_bottom = 172.0 | |
| 25 | margin_bottom = 340.0 | |
| 27 | 26 | text = "Loading" |
| 28 | 27 | |
| 29 | 28 | [node name="Form" type="VBoxContainer" parent="."] |
| 29 | visible = false | |
| 30 | 30 | margin_top = 335.0 |
| 31 | 31 | margin_right = 666.0 |
| 32 | 32 | margin_bottom = 666.0 |
| … | … | @@ -64,24 +64,9 @@ text = "Start" |
| 64 | 64 | |
| 65 | 65 | [node name="HyperGateway" type="Node" parent="."] |
| 66 | 66 | script = ExtResource( 2 ) |
| 67 | autoStart = false | |
| 67 | 68 | |
| 68 | [node name="UploadFileRequest" type="HTTPRequest" parent="."] | |
| 69 | script = ExtResource( 3 ) | |
| 70 | ||
| 71 | [node name="ListInfoRequest" type="HTTPRequest" parent="."] | |
| 72 | script = ExtResource( 3 ) | |
| 73 | ||
| 74 | [node name="LoadImageRequest" type="HTTPRequest" parent="."] | |
| 75 | script = ExtResource( 3 ) | |
| 76 | ||
| 77 | [node name="LoadURLRequest" type="HTTPRequest" parent="."] | |
| 78 | script = ExtResource( 3 ) | |
| 79 | ||
| 80 | [node name="UpdateProfileRequest" type="HTTPRequest" parent="."] | |
| 81 | script = ExtResource( 3 ) | |
| 82 | ||
| 83 | [node name="HyperUploader" type="Node" parent="."] | |
| 84 | script = ExtResource( 4 ) | |
| 69 | [node name="PlayerProfile" parent="." instance=ExtResource( 3 )] | |
| 85 | 70 | |
| 86 | 71 | [node name="FileDialog" type="FileDialog" parent="."] |
| 87 | 72 | margin_top = 536.0 |
| … | … | @@ -99,10 +84,10 @@ current_path = "/home/mauve/programming/godot/hypergodot/" |
| 99 | 84 | [connection signal="pressed" from="Form/ImageChooser" to="." method="_on_ImageChooser_pressed"] |
| 100 | 85 | [connection signal="pressed" from="Form/StartButton" to="." method="_on_StartButton_pressed"] |
| 101 | 86 | [connection signal="started_gateway" from="HyperGateway" to="." method="_on_HyperGateway_started_gateway"] |
| 102 | [connection signal="request_completed" from="UploadFileRequest" to="." method="_on_UploadFileRequest_request_completed"] | |
| 103 | [connection signal="request_completed" from="ListInfoRequest" to="." method="_on_ListInfoRequest_request_completed"] | |
| 104 | [connection signal="request_completed" from="LoadImageRequest" to="." method="_on_LoadImageRequest_request_completed"] | |
| 105 | [connection signal="request_completed" from="LoadURLRequest" to="." method="_on_LoadURLRequest_request_completed"] | |
| 106 | [connection signal="request_completed" from="UpdateProfileRequest" to="." method="_on_UpdateProfileRequest_request_completed"] | |
| 107 | [connection signal="uploaded" from="HyperUploader" to="." method="_on_HyperUploader_uploaded"] | |
| 87 | [connection signal="error" from="PlayerProfile" to="." method="_on_PlayerProfile_error"] | |
| 88 | [connection signal="image" from="PlayerProfile" to="." method="_on_PlayerProfile_image"] | |
| 89 | [connection signal="info" from="PlayerProfile" to="." method="_on_PlayerProfile_info"] | |
| 90 | [connection signal="no_info" from="PlayerProfile" to="." method="_on_PlayerProfile_no_info"] | |
| 91 | [connection signal="resolved" from="PlayerProfile" to="." method="_on_PlayerProfile_resolved"] | |
| 92 | [connection signal="updated" from="PlayerProfile" to="." method="_on_PlayerProfile_updated"] | |
| 108 | 93 | [connection signal="file_selected" from="FileDialog" to="." method="_on_FileDialog_file_selected"] |
| … | … | @@ -0,0 +1,14 @@ |
| 1 | extends "res://src/ResizeRoot.gd" | |
| 2 | ||
| 3 | var FlyBalls = preload("res://src/MultiplayerDemo/FlyBalls.tscn") | |
| 4 | ||
| 5 | func _on_LoadProfile_profile_ready(url): | |
| 6 | remove_child($LoadProfile) | |
| 7 | ||
| 8 | var game = FlyBalls.instance() | |
| 9 | game.profile = url | |
| 10 | game.spawn_gateway = false | |
| 11 | add_child(game) | |
| 12 | ||
| 13 | func _on_HyperGateway_started_gateway(pid): | |
| 14 | $LoadProfile.load_profile() |
| … | … | @@ -0,0 +1,32 @@ |
| 1 | [gd_scene load_steps=4 format=2] | |
| 2 | ||
| 3 | [ext_resource path="res://src/MultiplayerDemo/MultiplayerDemo.gd" type="Script" id=1] | |
| 4 | [ext_resource path="res://src/MultiplayerDemo/LoadProfile.tscn" type="PackedScene" id=2] | |
| 5 | [ext_resource path="res://src/HyperGateway/HyperGateway.gd" type="Script" id=3] | |
| 6 | ||
| 7 | [node name="MultiplayerDemo" type="VBoxContainer"] | |
| 8 | anchor_right = 1.0 | |
| 9 | anchor_bottom = 1.0 | |
| 10 | margin_right = -617.0 | |
| 11 | margin_bottom = -652.0 | |
| 12 | size_flags_horizontal = 3 | |
| 13 | size_flags_vertical = 3 | |
| 14 | script = ExtResource( 1 ) | |
| 15 | __meta__ = { | |
| 16 | "_edit_use_anchors_": false | |
| 17 | } | |
| 18 | ||
| 19 | [node name="LoadProfile" parent="." instance=ExtResource( 2 )] | |
| 20 | anchor_right = 0.0 | |
| 21 | anchor_bottom = 0.0 | |
| 22 | margin_right = 49.0 | |
| 23 | margin_bottom = 14.0 | |
| 24 | size_flags_horizontal = 3 | |
| 25 | size_flags_vertical = 3 | |
| 26 | spawn_gateway = false | |
| 27 | ||
| 28 | [node name="HyperGateway" type="Node" parent="."] | |
| 29 | script = ExtResource( 3 ) | |
| 30 | ||
| 31 | [connection signal="profile_ready" from="LoadProfile" to="." method="_on_LoadProfile_profile_ready"] | |
| 32 | [connection signal="started_gateway" from="HyperGateway" to="." method="_on_HyperGateway_started_gateway"] |
| … | … | @@ -0,0 +1,144 @@ |
| 1 | extends Node | |
| 2 | ||
| 3 | var URLParser = preload("res://src/utils/URLParser.gd") | |
| 4 | var parser = URLParser.new() | |
| 5 | ||
| 6 | signal info(username, image) | |
| 7 | signal no_info() | |
| 8 | signal image(path) | |
| 9 | signal updated() | |
| 10 | signal resolved(url) | |
| 11 | signal error(err) | |
| 12 | ||
| 13 | export var url = 'hyper://blog.mauve.moe/' | |
| 14 | export var cache_folder: String = 'user://hyper-file-cache/' | |
| 15 | export var profile_file: String = 'profile.json' | |
| 16 | ||
| 17 | export var autoload = false | |
| 18 | export var autoload_image = false | |
| 19 | ||
| 20 | const DEFAULT_USERNAME = 'Anonymous' | |
| 21 | ||
| 22 | var info_cache = null | |
| 23 | var has_loaded = false | |
| 24 | var picture_path = '' | |
| 25 | ||
| 26 | func _ready(): | |
| 27 | var dir = Directory.new() | |
| 28 | var err = dir.make_dir_recursive(cache_folder) | |
| 29 | if err != OK: | |
| 30 | printerr("Unable to create cache directory ", err) | |
| 31 | ||
| 32 | print("Profile setup") | |
| 33 | if autoload: | |
| 34 | load_profile() | |
| 35 | ||
| 36 | func get_username(): | |
| 37 | if info_cache == null: return DEFAULT_USERNAME | |
| 38 | if !info_cache.has('username'): return DEFAULT_USERNAME | |
| 39 | return info_cache.username | |
| 40 | ||
| 41 | func set_username(username): | |
| 42 | update_info({ | |
| 43 | "username": username | |
| 44 | }) | |
| 45 | ||
| 46 | func update_info(updates): | |
| 47 | var data = {} | |
| 48 | ||
| 49 | if info_cache != null: | |
| 50 | for key in info_cache.keys(): | |
| 51 | data[key] = info_cache[key] | |
| 52 | ||
| 53 | for key in updates.keys(): | |
| 54 | data[key] = info_cache[key] | |
| 55 | ||
| 56 | var json = JSON.print(data) | |
| 57 | var info_url = url + profile_file | |
| 58 | ||
| 59 | $updateInfoRequest.request(info_url, [], true, HTTPClient.METHOD_PUT, json) | |
| 60 | ||
| 61 | func load_profile(): | |
| 62 | var info_url = url + profile_file | |
| 63 | $loadInfoRequest.request(info_url) | |
| 64 | ||
| 65 | func resolve_url(): | |
| 66 | var url_record = url + '.well-known/hyper' | |
| 67 | $resolveURLRequest.request(url_record) | |
| 68 | ||
| 69 | func download_image(url: String): | |
| 70 | print('Loading image: ', url) | |
| 71 | var file_name = url.get_file() | |
| 72 | var key = parser.parse(url).host | |
| 73 | # Save the picture with the profile key prefixed to it | |
| 74 | picture_path = cache_folder + key + '-' + file_name | |
| 75 | $loadImageRequest.download_file = picture_path | |
| 76 | $loadImageRequest.request(url) | |
| 77 | ||
| 78 | func upload_image(path: String): | |
| 79 | var picture_name = path.get_file() | |
| 80 | var picture_url = url + picture_name | |
| 81 | ||
| 82 | $uploader.upload_file(picture_url, path) | |
| 83 | ||
| 84 | func _on_loadInfoRequest_request_completed(_result, response_code, _headers, body): | |
| 85 | print("Loaded info", _result, " ", response_code) | |
| 86 | if response_code != 200: | |
| 87 | printerr('Cannot load existing profile info: ', response_code) | |
| 88 | emit_signal("no_info") | |
| 89 | return | |
| 90 | ||
| 91 | var parsed = JSON.parse(body.get_string_from_utf8()) | |
| 92 | if parsed.error != OK: | |
| 93 | printerr(parsed.error_string) | |
| 94 | emit_signal("no_info") | |
| 95 | return | |
| 96 | ||
| 97 | info_cache = parsed.result | |
| 98 | ||
| 99 | var username = info_cache.username | |
| 100 | var image = info_cache.image | |
| 101 | ||
| 102 | emit_signal("info", username, image) | |
| 103 | ||
| 104 | if image != null and autoload_image: | |
| 105 | download_image(image) | |
| 106 | ||
| 107 | func _on_uploader_uploaded(resolved_url, response_code): | |
| 108 | if response_code != 200: | |
| 109 | printerr('Unable to upload file ') | |
| 110 | return | |
| 111 | ||
| 112 | if !url || (url.length() == 0): | |
| 113 | printerr("Unable to load Link header for image.") | |
| 114 | return | |
| 115 | ||
| 116 | update_info({ | |
| 117 | "username": get_username(), | |
| 118 | "image": resolved_url | |
| 119 | }) | |
| 120 | ||
| 121 | download_image(resolved_url) | |
| 122 | ||
| 123 | func _on_loadImageRequest_request_completed(result, response_code, _headers, body): | |
| 124 | if result != OK or response_code != 200: | |
| 125 | printerr('Unable to load image: ', result, ": ", body.get_string_from_utf8()) | |
| 126 | return | |
| 127 | ||
| 128 | print(result, ' Image got downloaded: ', picture_path) | |
| 129 | ||
| 130 | emit_signal('image', picture_path) | |
| 131 | ||
| 132 | func _on_updateInfoRequest_request_completed(_result, _response_code, _headers, _body): | |
| 133 | emit_signal("updated") | |
| 134 | ||
| 135 | func _on_resolveURLRequest_request_completed(result, response_code, _headers, body: PoolByteArray): | |
| 136 | if result != OK or response_code != 200: | |
| 137 | printerr('Unable to load final profile URL') | |
| 138 | return | |
| 139 | ||
| 140 | var lines = body.get_string_from_utf8() | |
| 141 | var url = lines.split('\n')[0] | |
| 142 | if !url.ends_with('/'): | |
| 143 | url += '/' | |
| 144 | emit_signal('resolved', url) |
| … | … | @@ -0,0 +1,29 @@ |
| 1 | [gd_scene load_steps=4 format=2] | |
| 2 | ||
| 3 | [ext_resource path="res://src/MultiplayerDemo/PlayerProfile.gd" type="Script" id=1] | |
| 4 | [ext_resource path="res://src/HyperRequest/HyperRequest.gd" type="Script" id=2] | |
| 5 | [ext_resource path="res://src/HyperRequest/HyperUploader.gd" type="Script" id=3] | |
| 6 | ||
| 7 | [node name="PlayerProfile" type="Node"] | |
| 8 | script = ExtResource( 1 ) | |
| 9 | ||
| 10 | [node name="loadInfoRequest" type="HTTPRequest" parent="."] | |
| 11 | script = ExtResource( 2 ) | |
| 12 | ||
| 13 | [node name="loadImageRequest" type="HTTPRequest" parent="."] | |
| 14 | script = ExtResource( 2 ) | |
| 15 | ||
| 16 | [node name="updateInfoRequest" type="HTTPRequest" parent="."] | |
| 17 | script = ExtResource( 2 ) | |
| 18 | ||
| 19 | [node name="resolveURLRequest" type="HTTPRequest" parent="."] | |
| 20 | script = ExtResource( 2 ) | |
| 21 | ||
| 22 | [node name="uploader" type="Node" parent="."] | |
| 23 | script = ExtResource( 3 ) | |
| 24 | ||
| 25 | [connection signal="request_completed" from="loadInfoRequest" to="." method="_on_loadInfoRequest_request_completed"] | |
| 26 | [connection signal="request_completed" from="loadImageRequest" to="." method="_on_loadImageRequest_request_completed"] | |
| 27 | [connection signal="request_completed" from="updateInfoRequest" to="." method="_on_updateInfoRequest_request_completed"] | |
| 28 | [connection signal="request_completed" from="resolveURLRequest" to="." method="_on_resolveURLRequest_request_completed"] | |
| 29 | [connection signal="uploaded" from="uploader" to="." method="_on_uploader_uploaded"] |
| … | … | @@ -1,6 +1,12 @@ |
| 1 | 1 | extends KinematicBody2D |
| 2 | 2 | |
| 3 | 3 | export var radius: float = 30 setget set_radius |
| 4 | export var has_profile = false | |
| 5 | ||
| 6 | func load_profile(profile_url): | |
| 7 | has_profile = true | |
| 8 | $PlayerProfile.url = profile_url | |
| 9 | $PlayerProfile.load_profile() | |
| 4 | 10 | |
| 5 | 11 | func set_texture(texture): |
| 6 | 12 | $Sprite.texture = texture |
| … | … | @@ -35,3 +41,10 @@ func _set_colission_radius(radius): |
| 35 | 41 | func _set_visibility_radius(radius): |
| 36 | 42 | var rect = Rect2(-radius, -radius, radius*2, radius*2) |
| 37 | 43 | $VisibilityNotifier2D.rect = rect |
| 44 | ||
| 45 | func _on_PlayerProfile_image(path): | |
| 46 | var texture = ImageTexture.new() | |
| 47 | var image = Image.new() | |
| 48 | image.load(path) | |
| 49 | texture.create_from_image(image) | |
| 50 | set_texture(texture) |
| … | … | @@ -1,7 +1,8 @@ |
| 1 | [gd_scene load_steps=5 format=2] | |
| 1 | [gd_scene load_steps=6 format=2] | |
| 2 | 2 | |
| 3 | 3 | [ext_resource path="res://src/MultiplayerDemo/icon.png" type="Texture" id=1] |
| 4 | 4 | [ext_resource path="res://src/MultiplayerDemo/PlayerSprite.gd" type="Script" id=2] |
| 5 | [ext_resource path="res://src/MultiplayerDemo/PlayerProfile.tscn" type="PackedScene" id=3] | |
| 5 | 6 | |
| 6 | 7 | [sub_resource type="ParticlesMaterial" id=1] |
| 7 | 8 | flag_disable_z = true |
| … | … | @@ -39,4 +40,8 @@ shape = SubResource( 2 ) |
| 39 | 40 | [node name="VisibilityNotifier2D" type="VisibilityNotifier2D" parent="."] |
| 40 | 41 | rect = Rect2( -40, -40, 80, 80 ) |
| 41 | 42 | |
| 43 | [node name="PlayerProfile" parent="." instance=ExtResource( 3 )] | |
| 44 | autoload_image = true | |
| 45 | ||
| 42 | 46 | [connection signal="screen_exited" from="VisibilityNotifier2D" to="." method="_on_VisibilityNotifier2D_screen_exited"] |
| 47 | [connection signal="image" from="PlayerProfile" to="." method="_on_PlayerProfile_image"] |