Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add scene coordinator #9

Merged
merged 3 commits into from
Jun 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 0 additions & 6 deletions godot/.godot/global_script_class_cache.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,6 @@ list=Array[Dictionary]([{
"path": "res://src/logic/camera.gd"
}, {
"base": &"Node",
"class": &"HTTPManyRequester",
"icon": "",
"language": &"GDScript",
"path": "res://src/logic/http_many_requester.gd"
}, {
"base": &"Node",
"class": &"ParcelManager",
"icon": "",
"language": &"GDScript",
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
6 changes: 4 additions & 2 deletions godot/src/logic/content_manager.gd
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ func process_loading_gltf(content: Dictionary, finished_downloads: Array[Request
var local_gltf_path = "user://content/" + file_hash

var stage = content.get("stage", 0)

# TODO: this is temp
var it = content.get("it", 0)
if it > 100000:
printerr("timeout ", file_path, " stage ", stage)
Expand Down Expand Up @@ -137,7 +139,7 @@ func process_loading_gltf(content: Dictionary, finished_downloads: Array[Request
var gltf := GLTFDocument.new()
var pre_gltf_state := GLTFState.new()
pre_gltf_state.set_additional_data("placeholder_image", true)
var err = gltf.append_from_file(local_gltf_path, pre_gltf_state, 0, "user://")
var err = gltf.append_from_file(local_gltf_path, pre_gltf_state, 0, OS.get_user_data_dir())
if err != OK:
printerr("GLTF " + file_path + " couldn't be loaded succesfully: ", err)
return false
Expand Down Expand Up @@ -182,7 +184,7 @@ func process_loading_gltf(content: Dictionary, finished_downloads: Array[Request

new_gltf_state.set_additional_data("base_path", base_path)
new_gltf_state.set_additional_data("mappings", content["gltf_mappings"])
var err = new_gltf.append_from_file(local_gltf_path, new_gltf_state, 0, "user://")
var err = new_gltf.append_from_file(local_gltf_path, new_gltf_state, 0, OS.get_user_data_dir())

var node = new_gltf.generate_scene(new_gltf_state)
if node != null:
Expand Down
6 changes: 3 additions & 3 deletions godot/src/logic/custom_gltf_importer.gd
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ func _import_preflight(state: GLTFState, _extensions: PackedStringArray) -> Erro
var dependencies: Array[String] = []
for image in state.json.get("images", []):
var uri = image.get("uri", "")
if not uri.is_empty():
if not uri.is_empty() and not uri.begins_with("data:"):
dependencies.push_back(String(uri))
image["uri"] = "decentraland_logo.png"
state.set_additional_data("dependencies", dependencies)
Expand All @@ -16,6 +16,6 @@ func _import_preflight(state: GLTFState, _extensions: PackedStringArray) -> Erro
var mappings = state.get_additional_data("mappings")
for image in state.json.get("images", []):
var uri = image.get("uri", "")
if not uri.is_empty():
image["uri"]= mappings.get(uri, "decentraland_logo.png")
if not uri.is_empty() and not uri.begins_with("data:"):
image["uri"]= mappings.get(uri, uri)
return OK
69 changes: 0 additions & 69 deletions godot/src/logic/http_many_requester.gd

This file was deleted.

191 changes: 61 additions & 130 deletions godot/src/logic/parcel_manager.gd
Original file line number Diff line number Diff line change
Expand Up @@ -2,98 +2,73 @@ extends Node

class_name ParcelManager

const MAIN_FILE_REQUEST = 100

var scene_runner: SceneManager = null
var realm: Realm = null
var last_parcel: Vector2i = Vector2i(-1000,-1000)
var loaded_scenes: Dictionary = {}

const SCENE_RADIUS = 3

var desired_scene = []
var http_requester: RustHttpRequesterWrapper = RustHttpRequesterWrapper.new()

const ACTIVE_ENTITIES_REQUEST = 1
const ENTITY_METADATA_REQUEST = 2
const MAIN_FILE_REQUEST = 3

var pointers: Array[String] = []
var current_position: Vector2i = Vector2i(-1000,-1000)
var loaded_scenes: Dictionary = {}
var scene_entity_coordinator: SceneEntityCoordinator = SceneEntityCoordinator.new()
var last_version_updated: int = -1

func _ready():
scene_runner = get_tree().root.get_node("scene_runner")
realm = get_tree().root.get_node("realm")

realm.realm_changed.connect(self._on_realm_changed)

http_requester.request_completed.connect(self._on_requested_completed)

func _process(_dt):
http_requester.poll()
scene_entity_coordinator.update()
if scene_entity_coordinator.get_version() != last_version_updated:
_on_desired_parsel_manager_update()
last_version_updated = scene_entity_coordinator.get_version()

func _on_desired_parsel_manager_update():
var d = scene_entity_coordinator.get_desired_scenes()
var loadable_scenes = d.get("loadable_scenes", [])
for scene_id in loadable_scenes:
if not loaded_scenes.has(scene_id):
var dict = scene_entity_coordinator.get_scene_dict(scene_id)
if dict.size() > 0:
dict["metadata"] = JSON.parse_string(dict.metadata)
load_scene(scene_id, dict)
else:
printerr("shoud load scene_id ", scene_id, " but data is empty")

func _on_realm_changed():
var should_load_city_pointers = true
var content_base_url = realm.content_base_url

if not realm.realm_city_loader_content_base_url.is_empty():
content_base_url = realm.realm_city_loader_content_base_url

if realm.realm_scene_urns.size() > 0 and realm.realm_city_loader_content_base_url.is_empty():
should_load_city_pointers = false

print(content_base_url , " & ", should_load_city_pointers)
scene_entity_coordinator.config(content_base_url + "entities/active", content_base_url, should_load_city_pointers)
scene_entity_coordinator.set_current_position(current_position.x, current_position.y)
var scenes_urns: Array = realm.realm_about.get("configurations", {}).get("scenesUrn", [])
scene_entity_coordinator.set_fixed_desired_entities_urns(scenes_urns)

for scene in loaded_scenes.values():
var scene_number_id: int = scene.get("scene_number_id", -1)
if scene_number_id != -1:
scene_runner.kill_scene(scene_number_id)

loaded_scenes = {}

func _on_requested_completed(response: RequestResponse):
match response.reference_id():
ACTIVE_ENTITIES_REQUEST:
_on_active_entities_requested_completed(response)
ENTITY_METADATA_REQUEST:
_on_entity_metadata_requested_completed(response)
MAIN_FILE_REQUEST:
_on_main_file_requested_completed(response)
_:
pass

func _on_active_entities_requested_completed(response: RequestResponse):
var status_code = response.status_code()
if response.is_error() or status_code < 200 or status_code > 299:
return null

var json = response.get_string_response_as_json()
if json == null:
printerr("do_request_json failed because json_string is not a valid json")
return

for entity in json:
if not entity.has("baseUrl"):
entity["baseUrl"] = realm.content_base_url + "contents/"
if not entity.has("entityId"):
entity["entityId"] = entity.get("id", "no-id")

load_scene(entity)

for scene_id in loaded_scenes.keys():
var scene = loaded_scenes[scene_id]
var should_unload = true
var scene_pointers = scene.get("scene_json", {}).get("metadata", {}).get("scene", {}).get("parcels", [])
for pointer in pointers:
for parcel in scene_pointers:
if parcel == pointer:
should_unload = false
break
if not should_unload:
break

if should_unload:
var scene_number_id: int = scene.get("scene_number_id", -1)
if scene_number_id != -1:
scene_runner.kill_scene(scene_number_id)

loaded_scenes[scene_id] = {}

for scene_id in loaded_scenes.keys():
if loaded_scenes[scene_id].keys().is_empty():
loaded_scenes.erase(scene_id)

func _on_entity_metadata_requested_completed(response: RequestResponse):
var status_code = response.status_code()
if response.is_error() or status_code < 200 or status_code > 299:
return null

var json = response.get_string_response_as_json()
if json == null:
printerr("do_request_json failed because json_string is not a valid json")
return

var request_id = response.id()
for scene in loaded_scenes:
if scene.get("entity_metadata_request_id", "") == request_id:
_on_load_scene_entity(json)

func _on_main_file_requested_completed(response: RequestResponse):
var status_code = response.status_code()
Expand All @@ -104,93 +79,49 @@ func _on_main_file_requested_completed(response: RequestResponse):
for scene in loaded_scenes.values():
if scene.get("main_file_request_id", "") == request_id:
_on_try_spawn_scene(scene)

func request_active_entities(pointers: Array):
if realm.realm_about == null:
return

var body_json = JSON.stringify({"pointers": pointers})
http_requester._requester.request_json(ACTIVE_ENTITIES_REQUEST, realm.content_base_url + "entities/active", HTTPClient.METHOD_POST, body_json, ["Content-type: application/json"])

func update_position(new_position: Vector2i) -> void:
if last_parcel == new_position or realm.content_base_url.is_empty():
if current_position == new_position:
return

last_parcel = new_position

# TODO: when there are desired scene, should it load also parcels from pointers?
if realm.realm_desired_running_scenes.size() > 0:
return

pointers.clear()
for x in range(new_position.x - SCENE_RADIUS, new_position.x + SCENE_RADIUS + 1):
for z in range(new_position.y - SCENE_RADIUS, new_position.y + SCENE_RADIUS + 1):
pointers.push_back(str(x) + "," + str(z))
request_active_entities(pointers)
current_position = new_position
scene_entity_coordinator.set_current_position(current_position.x, current_position.y)

func _on_realm_changed():
print("realm changed ")

for realm_scene in realm.realm_desired_running_scenes:
load_scene(realm_scene)

func load_scene(entity: Dictionary):
var scene_entity_id: String = entity.get("entityId", "")

if loaded_scenes.has(scene_entity_id):
return true

func load_scene(scene_entity_id: String, entity: Dictionary):
loaded_scenes[scene_entity_id] = {
"entity": entity,
"scene_number_id": -1
}

if entity.get("metadata") == null:
var scene_entity_url: String = entity.get("baseUrl", "") + entity.get("entityId", "")
var entity_metadata_request_id = http_requester._requester.request_json(ENTITY_METADATA_REQUEST, scene_entity_url, HTTPClient.METHOD_GET, "", [])
loaded_scenes[scene_entity_id]["entity_metadata_request_id"] = entity_metadata_request_id
else:
_on_load_scene_entity(entity)

func _on_load_scene_entity(scene_json: Dictionary):
var scene_entity_id: String = scene_json.get("entityId", "")

if scene_json == null:
printerr("Scene ", scene_entity_id, " fail getting the entity.")
return false
var main_crdt_file_hash = entity.get("content", {}).get("main.crdt", null)
if main_crdt_file_hash != null:
pass
# TODO: load main.crdt

var file_content: Dictionary = {}
for file_hash in scene_json.get("content", []):
file_content[file_hash.get("file", "null")] = file_hash.get("hash", "no_hash")

var main_js_file_hash = file_content.get(scene_json.get("metadata", {}).get("main", ""), null)
var main_js_file_hash = entity.get("content", {}).get(entity.get("metadata", {}).get("main", ""), null)
if main_js_file_hash == null or main_js_file_hash == "no_hash":
printerr("Scene ", scene_entity_id, " fail getting the main js file hash.")
return false

var local_main_js_path = "user://content/" + main_js_file_hash
var main_js_file_url: String = scene_json.get("baseUrl", "") + main_js_file_hash
var main_js_file_url: String = entity.baseUrl + main_js_file_hash
var request_id = http_requester._requester.request_file(MAIN_FILE_REQUEST, main_js_file_url, local_main_js_path.replace("user:/", OS.get_user_data_dir()))
loaded_scenes[scene_entity_id]["main_file_request_id"] = request_id
loaded_scenes[scene_entity_id]["local_main_js_path"] = local_main_js_path
loaded_scenes[scene_entity_id]["scene_json"] = scene_json
loaded_scenes[scene_entity_id]["file_content"] = file_content


func _on_try_spawn_scene(scene):
var scene_json = scene["scene_json"]
var local_main_js_path = scene["local_main_js_path"]

if not FileAccess.file_exists(local_main_js_path):
return false

var base_parcel = scene_json.get("metadata", {}).get("scene", {}).get("base", "0,0").split_floats(",")
var base_parcel = scene.entity.get("metadata", {}).get("scene", {}).get("base", "0,0").split_floats(",")
var offset: Vector3 = 16 * Vector3(base_parcel[0], 0, -base_parcel[1])
var base_url = scene_json.get("baseUrl", "")
var base_url = scene.entity.get("baseUrl", "")
var content_mapping = ContentMapping.new()
content_mapping.set_content_mapping(scene["file_content"])
content_mapping.set_base_url(base_url)
content_mapping.set_content_mapping(scene.entity["content"])
content_mapping.set_base_url(scene.entity.baseUrl)
var scene_number_id: int = scene_runner.start_scene(local_main_js_path, offset, content_mapping)
scene.scene_number_id = scene_number_id

return true
Loading