summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/gdscript/gdscript_vm.cpp4
-rw-r--r--modules/gltf/extensions/gltf_light.cpp1
-rw-r--r--modules/gltf/gltf_document.cpp2
-rw-r--r--modules/gltf/structures/gltf_camera.cpp1
-rw-r--r--modules/gridmap/doc_classes/GridMap.xml29
-rw-r--r--modules/gridmap/editor/grid_map_editor_plugin.cpp10
-rw-r--r--modules/gridmap/grid_map.cpp52
-rw-r--r--modules/gridmap/grid_map.h8
-rw-r--r--modules/mbedtls/crypto_mbedtls.h6
-rw-r--r--modules/mbedtls/dtls_server_mbedtls.h2
-rw-r--r--modules/mbedtls/packet_peer_mbed_dtls.cpp44
-rw-r--r--modules/mbedtls/packet_peer_mbed_dtls.h4
-rw-r--r--modules/mbedtls/register_types.cpp4
-rw-r--r--modules/mbedtls/stream_peer_mbedtls.cpp40
-rw-r--r--modules/mbedtls/stream_peer_mbedtls.h14
-rw-r--r--modules/mbedtls/tls_context_mbedtls.cpp (renamed from modules/mbedtls/ssl_context_mbedtls.cpp)32
-rw-r--r--modules/mbedtls/tls_context_mbedtls.h (renamed from modules/mbedtls/ssl_context_mbedtls.h)20
-rw-r--r--modules/mono/README.md10
-rwxr-xr-xmodules/mono/build_scripts/build_assemblies.py14
-rw-r--r--modules/mono/build_scripts/mono_configure.py290
-rw-r--r--modules/mono/config.py20
-rw-r--r--modules/mono/csharp_script.cpp64
-rw-r--r--modules/mono/csharp_script.h3
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.targets4
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MustBeVariantAnalyzer.cs5
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs18
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs16
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs12
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs16
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs2
-rw-r--r--modules/mono/editor/bindings_generator.cpp2
-rw-r--r--modules/mono/editor/hostfxr_resolver.cpp335
-rw-r--r--modules/mono/editor/hostfxr_resolver.h45
-rw-r--r--modules/mono/editor/semver.cpp149
-rw-r--r--modules/mono/editor/semver.h106
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs70
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs3
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs10
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs10
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs57
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj1
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj1
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp101
-rw-r--r--modules/mono/signal_awaiter_utils.cpp2
-rw-r--r--modules/mono/thirdparty/coreclr_delegates.h47
-rw-r--r--modules/mono/thirdparty/hostfxr.h323
-rw-r--r--modules/multiplayer/multiplayer_spawner.cpp4
-rw-r--r--modules/multiplayer/scene_replication_state.cpp2
-rw-r--r--modules/navigation/editor/navigation_mesh_editor_plugin.cpp2
-rw-r--r--modules/navigation/navigation_mesh_generator.cpp6
-rw-r--r--modules/openxr/editor/openxr_action_map_editor.cpp4
-rw-r--r--modules/openxr/editor/openxr_select_action_dialog.cpp2
-rw-r--r--modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp2
-rw-r--r--modules/websocket/doc_classes/WebSocketClient.xml14
-rw-r--r--modules/websocket/doc_classes/WebSocketServer.xml8
-rw-r--r--modules/websocket/emws_client.cpp6
-rw-r--r--modules/websocket/emws_client.h2
-rw-r--r--modules/websocket/websocket_client.cpp36
-rw-r--r--modules/websocket/websocket_client.h14
-rw-r--r--modules/websocket/websocket_server.cpp14
-rw-r--r--modules/websocket/websocket_server.h6
-rw-r--r--modules/websocket/wsl_client.cpp32
-rw-r--r--modules/websocket/wsl_client.h6
-rw-r--r--modules/websocket/wsl_server.cpp28
-rw-r--r--modules/websocket/wsl_server.h4
68 files changed, 1518 insertions, 689 deletions
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp
index 61e2c61abc..afebe3c149 100644
--- a/modules/gdscript/gdscript_vm.cpp
+++ b/modules/gdscript/gdscript_vm.cpp
@@ -2163,7 +2163,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_AWAIT) {
CHECK_SPACE(2);
- // Do the oneshot connect.
+ // Do the one-shot connect.
GET_INSTRUCTION_ARG(argobj, 0);
Signal sig;
@@ -2234,7 +2234,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
retvalue = gdfs;
- Error err = sig.connect(Callable(gdfs.ptr(), "_signal_callback").bind(retvalue), Object::CONNECT_ONESHOT);
+ Error err = sig.connect(Callable(gdfs.ptr(), "_signal_callback").bind(retvalue), Object::CONNECT_ONE_SHOT);
if (err != OK) {
err_text = "Error connecting to signal: " + sig.get_name() + " during await.";
OPCODE_BREAK;
diff --git a/modules/gltf/extensions/gltf_light.cpp b/modules/gltf/extensions/gltf_light.cpp
index ab5a15c671..6923c765cb 100644
--- a/modules/gltf/extensions/gltf_light.cpp
+++ b/modules/gltf/extensions/gltf_light.cpp
@@ -109,6 +109,7 @@ void GLTFLight::set_outer_cone_angle(float p_outer_cone_angle) {
Ref<GLTFLight> GLTFLight::from_node(const Light3D *p_light) {
Ref<GLTFLight> l;
l.instantiate();
+ ERR_FAIL_COND_V_MSG(!p_light, l, "Tried to create a GLTFLight from a Light3D node, but the given node was null.");
l->color = p_light->get_color();
if (cast_to<DirectionalLight3D>(p_light)) {
l->light_type = "directional";
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index 61af58bda7..6cb398b5f8 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -5271,7 +5271,7 @@ void GLTFDocument::_convert_grid_map_to_gltf(GridMap *p_grid_map, GLTFNodeIndex
cell_xform.basis.scale(Vector3(p_grid_map->get_cell_scale(),
p_grid_map->get_cell_scale(),
p_grid_map->get_cell_scale()));
- cell_xform.set_origin(p_grid_map->map_to_world(
+ cell_xform.set_origin(p_grid_map->map_to_local(
Vector3(cell_location.x, cell_location.y, cell_location.z)));
Ref<GLTFMesh> gltf_mesh;
gltf_mesh.instantiate();
diff --git a/modules/gltf/structures/gltf_camera.cpp b/modules/gltf/structures/gltf_camera.cpp
index 5069f39c4b..212b9b80c8 100644
--- a/modules/gltf/structures/gltf_camera.cpp
+++ b/modules/gltf/structures/gltf_camera.cpp
@@ -58,6 +58,7 @@ void GLTFCamera::_bind_methods() {
Ref<GLTFCamera> GLTFCamera::from_node(const Camera3D *p_camera) {
Ref<GLTFCamera> c;
c.instantiate();
+ ERR_FAIL_COND_V_MSG(!p_camera, c, "Tried to create a GLTFCamera from a Camera3D node, but the given node was null.");
c->set_perspective(p_camera->get_projection() == Camera3D::ProjectionType::PROJECTION_PERSPECTIVE);
// GLTF spec (yfov) is in radians, Godot's camera (fov) is in degrees.
c->set_fov(Math::deg_to_rad(p_camera->get_fov()));
diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml
index 6717f23057..ed6cb8656a 100644
--- a/modules/gridmap/doc_classes/GridMap.xml
+++ b/modules/gridmap/doc_classes/GridMap.xml
@@ -84,7 +84,7 @@
<method name="get_meshes" qualifiers="const">
<return type="Array" />
<description>
- Returns an array of [Transform3D] and [Mesh] references corresponding to the non-empty cells in the grid. The transforms are specified in world space.
+ Returns an array of [Transform3D] and [Mesh] references corresponding to the non-empty cells in the grid. The transforms are specified in local space.
</description>
</method>
<method name="get_navigation_layer_value" qualifiers="const">
@@ -94,6 +94,13 @@
Returns whether or not the specified layer of the [member navigation_layers] bitmask is enabled, given a [code]layer_number[/code] between 1 and 32.
</description>
</method>
+ <method name="get_navigation_map" qualifiers="const">
+ <return type="RID" />
+ <description>
+ Returns the [RID] of the navigation map this GridMap node uses for its cell baked navigation meshes.
+ This function returns always the map set on the GridMap node and not the map on the NavigationServer. If the map is changed directly with the NavigationServer API the GridMap node will not be aware of the map change.
+ </description>
+ </method>
<method name="get_orthogonal_index_from_basis" qualifiers="const">
<return type="int" />
<param index="0" name="basis" type="Basis" />
@@ -114,6 +121,13 @@
Returns an array of all cells with the given item index specified in [code]item[/code].
</description>
</method>
+ <method name="local_to_map" qualifiers="const">
+ <return type="Vector3i" />
+ <param index="0" name="local_position" type="Vector3" />
+ <description>
+ Returns the map coordinates of the cell containing the given [param local_position]. If [param local_position] is in global coordinates, consider using [method Node3D.to_local] before passing it to this method. See also [method map_to_local].
+ </description>
+ </method>
<method name="make_baked_meshes">
<return type="void" />
<param index="0" name="gen_lightmap_uv" type="bool" default="false" />
@@ -121,11 +135,11 @@
<description>
</description>
</method>
- <method name="map_to_world" qualifiers="const">
+ <method name="map_to_local" qualifiers="const">
<return type="Vector3" />
<param index="0" name="map_position" type="Vector3i" />
<description>
- Returns the position of a grid cell in the GridMap's local coordinate space.
+ Returns the position of a grid cell in the GridMap's local coordinate space. To convert the returned value into global coordinates, use [method Node3D.to_global]. See also [method map_to_local].
</description>
</method>
<method name="resource_changed">
@@ -169,12 +183,11 @@
Based on [code]value[/code], enables or disables the specified layer in the [member navigation_layers] bitmask, given a [code]layer_number[/code] between 1 and 32.
</description>
</method>
- <method name="world_to_map" qualifiers="const">
- <return type="Vector3i" />
- <param index="0" name="world_position" type="Vector3" />
+ <method name="set_navigation_map">
+ <return type="void" />
+ <param index="0" name="navigation_map" type="RID" />
<description>
- Returns the coordinates of the grid cell containing the given point.
- [code]pos[/code] should be in the GridMap's local coordinate space.
+ Sets the [RID] of the navigation map this GridMap node should use for its cell baked navigation meshes.
</description>
</method>
</methods>
diff --git a/modules/gridmap/editor/grid_map_editor_plugin.cpp b/modules/gridmap/editor/grid_map_editor_plugin.cpp
index 17f9832096..b5afd8507d 100644
--- a/modules/gridmap/editor/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/editor/grid_map_editor_plugin.cpp
@@ -603,13 +603,13 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
- if (mb->get_button_index() == MouseButton::WHEEL_UP && (mb->is_command_pressed() || mb->is_shift_pressed())) {
+ if (mb->get_button_index() == MouseButton::WHEEL_UP && (mb->is_command_or_control_pressed() || mb->is_shift_pressed())) {
if (mb->is_pressed()) {
floor->set_value(floor->get_value() + mb->get_factor());
}
return EditorPlugin::AFTER_GUI_INPUT_STOP; // Eaten.
- } else if (mb->get_button_index() == MouseButton::WHEEL_DOWN && (mb->is_command_pressed() || mb->is_shift_pressed())) {
+ } else if (mb->get_button_index() == MouseButton::WHEEL_DOWN && (mb->is_command_or_control_pressed() || mb->is_shift_pressed())) {
if (mb->is_pressed()) {
floor->set_value(floor->get_value() - mb->get_factor());
}
@@ -629,7 +629,7 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D
} else if (mb->is_shift_pressed() && can_edit) {
input_action = INPUT_SELECT;
last_selection = selection;
- } else if (mb->is_command_pressed() && can_edit) {
+ } else if (mb->is_command_or_control_pressed() && can_edit) {
input_action = INPUT_PICK;
} else {
input_action = INPUT_PAINT;
@@ -746,7 +746,7 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D
Ref<InputEventPanGesture> pan_gesture = p_event;
if (pan_gesture.is_valid()) {
- if (pan_gesture->is_alt_pressed() && (pan_gesture->is_command_pressed() || pan_gesture->is_shift_pressed())) {
+ if (pan_gesture->is_alt_pressed() && (pan_gesture->is_command_or_control_pressed() || pan_gesture->is_shift_pressed())) {
const real_t delta = pan_gesture->get_delta().y * 0.5;
accumulated_floor_delta += delta;
int step = 0;
@@ -807,7 +807,7 @@ void GridMapEditor::_mesh_library_palette_input(const Ref<InputEvent> &p_ie) {
const Ref<InputEventMouseButton> mb = p_ie;
// Zoom in/out using Ctrl + mouse wheel
- if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed()) {
+ if (mb.is_valid() && mb->is_pressed() && mb->is_command_or_control_pressed()) {
if (mb->is_pressed() && mb->get_button_index() == MouseButton::WHEEL_UP) {
size_slider->set_value(size_slider->get_value() + 0.2);
}
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index 8486e2c58b..466a2efd21 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -226,6 +226,27 @@ bool GridMap::is_baking_navigation() {
return bake_navigation;
}
+void GridMap::set_navigation_map(RID p_navigation_map) {
+ map_override = p_navigation_map;
+ for (const KeyValue<OctantKey, Octant *> &E : octant_map) {
+ Octant &g = *octant_map[E.key];
+ for (KeyValue<IndexKey, Octant::NavMesh> &F : g.navmesh_ids) {
+ if (F.value.region.is_valid()) {
+ NavigationServer3D::get_singleton()->region_set_map(F.value.region, map_override);
+ }
+ }
+ }
+}
+
+RID GridMap::get_navigation_map() const {
+ if (map_override.is_valid()) {
+ return map_override;
+ } else if (is_inside_tree()) {
+ return get_world_3d()->get_navigation_map();
+ }
+ return RID();
+}
+
void GridMap::set_navigation_layers(uint32_t p_navigation_layers) {
navigation_layers = p_navigation_layers;
_recreate_octant_data();
@@ -497,18 +518,18 @@ int GridMap::get_orthogonal_index_from_basis(const Basis &p_basis) const {
return 0;
}
-Vector3i GridMap::world_to_map(const Vector3 &p_world_position) const {
+Vector3i GridMap::local_to_map(const Vector3 &p_world_position) const {
Vector3 map_position = (p_world_position / cell_size).floor();
return Vector3i(map_position);
}
-Vector3 GridMap::map_to_world(const Vector3i &p_map_position) const {
+Vector3 GridMap::map_to_local(const Vector3i &p_map_position) const {
Vector3 offset = _get_offset();
- Vector3 world_pos(
+ Vector3 local_position(
p_map_position.x * cell_size.x + offset.x,
p_map_position.y * cell_size.y + offset.y,
p_map_position.z * cell_size.z + offset.z);
- return world_pos;
+ return local_position;
}
void GridMap::_octant_transform(const OctantKey &p_key) {
@@ -639,10 +660,15 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
NavigationServer3D::get_singleton()->region_set_navmesh(region, navmesh);
NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform() * nm.xform);
if (is_inside_tree()) {
- NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
+ if (map_override.is_valid()) {
+ NavigationServer3D::get_singleton()->region_set_map(region, map_override);
+ } else {
+ NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
+ }
}
nm.region = region;
+#ifdef DEBUG_ENABLED
// add navigation debugmesh visual instances if debug is enabled
SceneTree *st = SceneTree::get_singleton();
if (st && st->is_debugging_navigation_hint()) {
@@ -650,15 +676,14 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
RID navmesh_debug_rid = navmesh->get_debug_mesh()->get_rid();
nm.navmesh_debug_instance = RS::get_singleton()->instance_create();
RS::get_singleton()->instance_set_base(nm.navmesh_debug_instance, navmesh_debug_rid);
- RS::get_singleton()->mesh_surface_set_material(navmesh_debug_rid, 0, st->get_debug_navigation_material()->get_rid());
}
if (is_inside_tree()) {
RS::get_singleton()->instance_set_scenario(nm.navmesh_debug_instance, get_world_3d()->get_scenario());
RS::get_singleton()->instance_set_transform(nm.navmesh_debug_instance, get_global_transform() * nm.xform);
}
}
+#endif // DEBUG_ENABLED
}
-
g.navmesh_ids[E] = nm;
}
}
@@ -757,7 +782,11 @@ void GridMap::_octant_enter_world(const OctantKey &p_key) {
NavigationServer3D::get_singleton()->region_set_navigation_layers(region, navigation_layers);
NavigationServer3D::get_singleton()->region_set_navmesh(region, nm);
NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform() * F.value.xform);
- NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
+ if (map_override.is_valid()) {
+ NavigationServer3D::get_singleton()->region_set_map(region, map_override);
+ } else {
+ NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
+ }
F.value.region = region;
}
@@ -1022,6 +1051,9 @@ void GridMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bake_navigation", "bake_navigation"), &GridMap::set_bake_navigation);
ClassDB::bind_method(D_METHOD("is_baking_navigation"), &GridMap::is_baking_navigation);
+ ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &GridMap::set_navigation_map);
+ ClassDB::bind_method(D_METHOD("get_navigation_map"), &GridMap::get_navigation_map);
+
ClassDB::bind_method(D_METHOD("set_navigation_layers", "layers"), &GridMap::set_navigation_layers);
ClassDB::bind_method(D_METHOD("get_navigation_layers"), &GridMap::get_navigation_layers);
@@ -1047,8 +1079,8 @@ void GridMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_basis_with_orthogonal_index", "index"), &GridMap::get_basis_with_orthogonal_index);
ClassDB::bind_method(D_METHOD("get_orthogonal_index_from_basis", "basis"), &GridMap::get_orthogonal_index_from_basis);
- ClassDB::bind_method(D_METHOD("world_to_map", "world_position"), &GridMap::world_to_map);
- ClassDB::bind_method(D_METHOD("map_to_world", "map_position"), &GridMap::map_to_world);
+ ClassDB::bind_method(D_METHOD("local_to_map", "local_position"), &GridMap::local_to_map);
+ ClassDB::bind_method(D_METHOD("map_to_local", "map_position"), &GridMap::map_to_local);
ClassDB::bind_method(D_METHOD("_update_octants_callback"), &GridMap::_update_octants_callback);
ClassDB::bind_method(D_METHOD("resource_changed", "resource"), &GridMap::resource_changed);
diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h
index f83ce68b09..6a53457d25 100644
--- a/modules/gridmap/grid_map.h
+++ b/modules/gridmap/grid_map.h
@@ -152,6 +152,7 @@ class GridMap : public Node3D {
uint32_t collision_mask = 1;
Ref<PhysicsMaterial> physics_material;
bool bake_navigation = false;
+ RID map_override;
uint32_t navigation_layers = 1;
Transform3D last_transform;
@@ -247,6 +248,9 @@ public:
void set_bake_navigation(bool p_bake_navigation);
bool is_baking_navigation();
+ void set_navigation_map(RID p_navigation_map);
+ RID get_navigation_map() const;
+
void set_navigation_layers(uint32_t p_navigation_layers);
uint32_t get_navigation_layers() const;
@@ -276,8 +280,8 @@ public:
Basis get_basis_with_orthogonal_index(int p_index) const;
int get_orthogonal_index_from_basis(const Basis &p_basis) const;
- Vector3i world_to_map(const Vector3 &p_world_position) const;
- Vector3 map_to_world(const Vector3i &p_map_position) const;
+ Vector3i local_to_map(const Vector3 &p_local_position) const;
+ Vector3 map_to_local(const Vector3i &p_map_position) const;
void set_cell_scale(float p_scale);
float get_cell_scale() const;
diff --git a/modules/mbedtls/crypto_mbedtls.h b/modules/mbedtls/crypto_mbedtls.h
index 5ba7e9cbf6..f129ef6f11 100644
--- a/modules/mbedtls/crypto_mbedtls.h
+++ b/modules/mbedtls/crypto_mbedtls.h
@@ -39,7 +39,7 @@
#include <mbedtls/ssl.h>
class CryptoMbedTLS;
-class SSLContextMbedTLS;
+class TLSContextMbedTLS;
class CryptoKeyMbedTLS : public CryptoKey {
private:
mbedtls_pk_context pkey;
@@ -69,7 +69,7 @@ public:
_FORCE_INLINE_ void unlock() { locks--; }
friend class CryptoMbedTLS;
- friend class SSLContextMbedTLS;
+ friend class TLSContextMbedTLS;
};
class X509CertificateMbedTLS : public X509Certificate {
@@ -98,7 +98,7 @@ public:
_FORCE_INLINE_ void unlock() { locks--; }
friend class CryptoMbedTLS;
- friend class SSLContextMbedTLS;
+ friend class TLSContextMbedTLS;
};
class HMACContextMbedTLS : public HMACContext {
diff --git a/modules/mbedtls/dtls_server_mbedtls.h b/modules/mbedtls/dtls_server_mbedtls.h
index a6626c9f65..0c9f10b5ed 100644
--- a/modules/mbedtls/dtls_server_mbedtls.h
+++ b/modules/mbedtls/dtls_server_mbedtls.h
@@ -32,7 +32,7 @@
#define DTLS_SERVER_MBEDTLS_H
#include "core/io/dtls_server.h"
-#include "ssl_context_mbedtls.h"
+#include "tls_context_mbedtls.h"
class DTLSServerMbedTLS : public DTLSServer {
private:
diff --git a/modules/mbedtls/packet_peer_mbed_dtls.cpp b/modules/mbedtls/packet_peer_mbed_dtls.cpp
index 1296a4587c..e84d95773d 100644
--- a/modules/mbedtls/packet_peer_mbed_dtls.cpp
+++ b/modules/mbedtls/packet_peer_mbed_dtls.cpp
@@ -32,7 +32,7 @@
#include "mbedtls/platform_util.h"
#include "core/io/file_access.h"
-#include "core/io/stream_peer_ssl.h"
+#include "core/io/stream_peer_tls.h"
int PacketPeerMbedDTLS::bio_send(void *ctx, const unsigned char *buf, size_t len) {
if (buf == nullptr || len == 0) {
@@ -79,7 +79,7 @@ int PacketPeerMbedDTLS::bio_recv(void *ctx, unsigned char *buf, size_t len) {
}
void PacketPeerMbedDTLS::_cleanup() {
- ssl_ctx->clear();
+ tls_ctx->clear();
base = Ref<PacketPeer>();
status = STATUS_DISCONNECTED;
}
@@ -91,16 +91,16 @@ int PacketPeerMbedDTLS::_set_cookie() {
uint16_t port = base->get_packet_port();
memcpy(client_id, addr.get_ipv6(), 16);
memcpy(&client_id[16], (uint8_t *)&port, 2);
- return mbedtls_ssl_set_client_transport_id(ssl_ctx->get_context(), client_id, 18);
+ return mbedtls_ssl_set_client_transport_id(tls_ctx->get_context(), client_id, 18);
}
Error PacketPeerMbedDTLS::_do_handshake() {
int ret = 0;
- while ((ret = mbedtls_ssl_handshake(ssl_ctx->get_context())) != 0) {
+ while ((ret = mbedtls_ssl_handshake(tls_ctx->get_context())) != 0) {
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
if (ret != MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) {
ERR_PRINT("TLS handshake error: " + itos(ret));
- SSLContextMbedTLS::print_mbedtls_error(ret);
+ TLSContextMbedTLS::print_mbedtls_error(ret);
}
_cleanup();
status = STATUS_ERROR;
@@ -121,12 +121,12 @@ Error PacketPeerMbedDTLS::connect_to_peer(Ref<PacketPeerUDP> p_base, bool p_vali
int ret = 0;
int authmode = p_validate_certs ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE;
- Error err = ssl_ctx->init_client(MBEDTLS_SSL_TRANSPORT_DATAGRAM, authmode, p_ca_certs);
+ Error err = tls_ctx->init_client(MBEDTLS_SSL_TRANSPORT_DATAGRAM, authmode, p_ca_certs);
ERR_FAIL_COND_V(err != OK, err);
- mbedtls_ssl_set_hostname(ssl_ctx->get_context(), p_for_hostname.utf8().get_data());
- mbedtls_ssl_set_bio(ssl_ctx->get_context(), this, bio_send, bio_recv, nullptr);
- mbedtls_ssl_set_timer_cb(ssl_ctx->get_context(), &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay);
+ mbedtls_ssl_set_hostname(tls_ctx->get_context(), p_for_hostname.utf8().get_data());
+ mbedtls_ssl_set_bio(tls_ctx->get_context(), this, bio_send, bio_recv, nullptr);
+ mbedtls_ssl_set_timer_cb(tls_ctx->get_context(), &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay);
status = STATUS_HANDSHAKING;
@@ -139,13 +139,13 @@ Error PacketPeerMbedDTLS::connect_to_peer(Ref<PacketPeerUDP> p_base, bool p_vali
}
Error PacketPeerMbedDTLS::accept_peer(Ref<PacketPeerUDP> p_base, Ref<CryptoKey> p_key, Ref<X509Certificate> p_cert, Ref<X509Certificate> p_ca_chain, Ref<CookieContextMbedTLS> p_cookies) {
- Error err = ssl_ctx->init_server(MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_VERIFY_NONE, p_key, p_cert, p_cookies);
+ Error err = tls_ctx->init_server(MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_VERIFY_NONE, p_key, p_cert, p_cookies);
ERR_FAIL_COND_V(err != OK, err);
base = p_base;
base->set_blocking_mode(false);
- mbedtls_ssl_session_reset(ssl_ctx->get_context());
+ mbedtls_ssl_session_reset(tls_ctx->get_context());
int ret = _set_cookie();
if (ret != 0) {
@@ -153,8 +153,8 @@ Error PacketPeerMbedDTLS::accept_peer(Ref<PacketPeerUDP> p_base, Ref<CryptoKey>
ERR_FAIL_V_MSG(FAILED, "Error setting DTLS client cookie");
}
- mbedtls_ssl_set_bio(ssl_ctx->get_context(), this, bio_send, bio_recv, nullptr);
- mbedtls_ssl_set_timer_cb(ssl_ctx->get_context(), &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay);
+ mbedtls_ssl_set_bio(tls_ctx->get_context(), this, bio_send, bio_recv, nullptr);
+ mbedtls_ssl_set_timer_cb(tls_ctx->get_context(), &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay);
status = STATUS_HANDSHAKING;
@@ -173,11 +173,11 @@ Error PacketPeerMbedDTLS::put_packet(const uint8_t *p_buffer, int p_bytes) {
return OK;
}
- int ret = mbedtls_ssl_write(ssl_ctx->get_context(), p_buffer, p_bytes);
+ int ret = mbedtls_ssl_write(tls_ctx->get_context(), p_buffer, p_bytes);
if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
ret = 0; // non blocking io
} else if (ret <= 0) {
- SSLContextMbedTLS::print_mbedtls_error(ret);
+ TLSContextMbedTLS::print_mbedtls_error(ret);
_cleanup();
return ERR_CONNECTION_ERROR;
}
@@ -190,7 +190,7 @@ Error PacketPeerMbedDTLS::get_packet(const uint8_t **r_buffer, int &r_bytes) {
r_bytes = 0;
- int ret = mbedtls_ssl_read(ssl_ctx->get_context(), packet_buffer, PACKET_BUFFER_SIZE);
+ int ret = mbedtls_ssl_read(tls_ctx->get_context(), packet_buffer, PACKET_BUFFER_SIZE);
if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
ret = 0; // non blocking io
} else if (ret <= 0) {
@@ -200,7 +200,7 @@ Error PacketPeerMbedDTLS::get_packet(const uint8_t **r_buffer, int &r_bytes) {
} else {
_cleanup();
status = STATUS_ERROR;
- SSLContextMbedTLS::print_mbedtls_error(ret);
+ TLSContextMbedTLS::print_mbedtls_error(ret);
}
return ERR_CONNECTION_ERROR;
}
@@ -220,7 +220,7 @@ void PacketPeerMbedDTLS::poll() {
ERR_FAIL_COND(!base.is_valid());
- int ret = mbedtls_ssl_read(ssl_ctx->get_context(), nullptr, 0);
+ int ret = mbedtls_ssl_read(tls_ctx->get_context(), nullptr, 0);
if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
@@ -229,7 +229,7 @@ void PacketPeerMbedDTLS::poll() {
} else {
_cleanup();
status = STATUS_ERROR;
- SSLContextMbedTLS::print_mbedtls_error(ret);
+ TLSContextMbedTLS::print_mbedtls_error(ret);
}
}
}
@@ -237,7 +237,7 @@ void PacketPeerMbedDTLS::poll() {
int PacketPeerMbedDTLS::get_available_packet_count() const {
ERR_FAIL_COND_V(status != STATUS_CONNECTED, 0);
- return mbedtls_ssl_get_bytes_avail(&(ssl_ctx->ssl)) > 0 ? 1 : 0;
+ return mbedtls_ssl_get_bytes_avail(&(tls_ctx->tls)) > 0 ? 1 : 0;
}
int PacketPeerMbedDTLS::get_max_packet_size() const {
@@ -245,7 +245,7 @@ int PacketPeerMbedDTLS::get_max_packet_size() const {
}
PacketPeerMbedDTLS::PacketPeerMbedDTLS() {
- ssl_ctx.instantiate();
+ tls_ctx.instantiate();
}
PacketPeerMbedDTLS::~PacketPeerMbedDTLS() {
@@ -261,7 +261,7 @@ void PacketPeerMbedDTLS::disconnect_from_peer() {
int ret = 0;
// Send SSL close notification, blocking, but ignore other errors.
do {
- ret = mbedtls_ssl_close_notify(ssl_ctx->get_context());
+ ret = mbedtls_ssl_close_notify(tls_ctx->get_context());
} while (ret == MBEDTLS_ERR_SSL_WANT_WRITE);
}
diff --git a/modules/mbedtls/packet_peer_mbed_dtls.h b/modules/mbedtls/packet_peer_mbed_dtls.h
index 5f2f42cd30..cc79057d67 100644
--- a/modules/mbedtls/packet_peer_mbed_dtls.h
+++ b/modules/mbedtls/packet_peer_mbed_dtls.h
@@ -32,7 +32,7 @@
#define PACKET_PEER_MBED_DTLS_H
#include "core/io/packet_peer_dtls.h"
-#include "ssl_context_mbedtls.h"
+#include "tls_context_mbedtls.h"
#include <mbedtls/timing.h>
@@ -56,7 +56,7 @@ private:
void _cleanup();
protected:
- Ref<SSLContextMbedTLS> ssl_ctx;
+ Ref<TLSContextMbedTLS> tls_ctx;
mbedtls_timing_delay_context timer;
Error _do_handshake();
diff --git a/modules/mbedtls/register_types.cpp b/modules/mbedtls/register_types.cpp
index 2d4a18b3fc..675091b617 100644
--- a/modules/mbedtls/register_types.cpp
+++ b/modules/mbedtls/register_types.cpp
@@ -45,7 +45,7 @@ void initialize_mbedtls_module(ModuleInitializationLevel p_level) {
}
CryptoMbedTLS::initialize_crypto();
- StreamPeerMbedTLS::initialize_ssl();
+ StreamPeerMbedTLS::initialize_tls();
PacketPeerMbedDTLS::initialize_dtls();
DTLSServerMbedTLS::initialize();
}
@@ -57,6 +57,6 @@ void uninitialize_mbedtls_module(ModuleInitializationLevel p_level) {
DTLSServerMbedTLS::finalize();
PacketPeerMbedDTLS::finalize_dtls();
- StreamPeerMbedTLS::finalize_ssl();
+ StreamPeerMbedTLS::finalize_tls();
CryptoMbedTLS::finalize_crypto();
}
diff --git a/modules/mbedtls/stream_peer_mbedtls.cpp b/modules/mbedtls/stream_peer_mbedtls.cpp
index 92590fbcf6..a97c6bd916 100644
--- a/modules/mbedtls/stream_peer_mbedtls.cpp
+++ b/modules/mbedtls/stream_peer_mbedtls.cpp
@@ -74,18 +74,18 @@ int StreamPeerMbedTLS::bio_recv(void *ctx, unsigned char *buf, size_t len) {
}
void StreamPeerMbedTLS::_cleanup() {
- ssl_ctx->clear();
+ tls_ctx->clear();
base = Ref<StreamPeer>();
status = STATUS_DISCONNECTED;
}
Error StreamPeerMbedTLS::_do_handshake() {
int ret = 0;
- while ((ret = mbedtls_ssl_handshake(ssl_ctx->get_context())) != 0) {
+ while ((ret = mbedtls_ssl_handshake(tls_ctx->get_context())) != 0) {
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
// An error occurred.
ERR_PRINT("TLS handshake error: " + itos(ret));
- SSLContextMbedTLS::print_mbedtls_error(ret);
+ TLSContextMbedTLS::print_mbedtls_error(ret);
disconnect_from_stream();
status = STATUS_ERROR;
return FAILED;
@@ -108,11 +108,11 @@ Error StreamPeerMbedTLS::connect_to_stream(Ref<StreamPeer> p_base, bool p_valida
base = p_base;
int authmode = p_validate_certs ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE;
- Error err = ssl_ctx->init_client(MBEDTLS_SSL_TRANSPORT_STREAM, authmode, p_ca_certs);
+ Error err = tls_ctx->init_client(MBEDTLS_SSL_TRANSPORT_STREAM, authmode, p_ca_certs);
ERR_FAIL_COND_V(err != OK, err);
- mbedtls_ssl_set_hostname(ssl_ctx->get_context(), p_for_hostname.utf8().get_data());
- mbedtls_ssl_set_bio(ssl_ctx->get_context(), this, bio_send, bio_recv, nullptr);
+ mbedtls_ssl_set_hostname(tls_ctx->get_context(), p_for_hostname.utf8().get_data());
+ mbedtls_ssl_set_bio(tls_ctx->get_context(), this, bio_send, bio_recv, nullptr);
status = STATUS_HANDSHAKING;
@@ -127,12 +127,12 @@ Error StreamPeerMbedTLS::connect_to_stream(Ref<StreamPeer> p_base, bool p_valida
Error StreamPeerMbedTLS::accept_stream(Ref<StreamPeer> p_base, Ref<CryptoKey> p_key, Ref<X509Certificate> p_cert, Ref<X509Certificate> p_ca_chain) {
ERR_FAIL_COND_V(p_base.is_null(), ERR_INVALID_PARAMETER);
- Error err = ssl_ctx->init_server(MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_VERIFY_NONE, p_key, p_cert);
+ Error err = tls_ctx->init_server(MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_VERIFY_NONE, p_key, p_cert);
ERR_FAIL_COND_V(err != OK, err);
base = p_base;
- mbedtls_ssl_set_bio(ssl_ctx->get_context(), this, bio_send, bio_recv, nullptr);
+ mbedtls_ssl_set_bio(tls_ctx->get_context(), this, bio_send, bio_recv, nullptr);
status = STATUS_HANDSHAKING;
@@ -173,7 +173,7 @@ Error StreamPeerMbedTLS::put_partial_data(const uint8_t *p_data, int p_bytes, in
return OK;
}
- int ret = mbedtls_ssl_write(ssl_ctx->get_context(), p_data, p_bytes);
+ int ret = mbedtls_ssl_write(tls_ctx->get_context(), p_data, p_bytes);
if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
// Non blocking IO
ret = 0;
@@ -182,7 +182,7 @@ Error StreamPeerMbedTLS::put_partial_data(const uint8_t *p_data, int p_bytes, in
disconnect_from_stream();
return ERR_FILE_EOF;
} else if (ret <= 0) {
- SSLContextMbedTLS::print_mbedtls_error(ret);
+ TLSContextMbedTLS::print_mbedtls_error(ret);
disconnect_from_stream();
return ERR_CONNECTION_ERROR;
}
@@ -216,7 +216,7 @@ Error StreamPeerMbedTLS::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r
r_received = 0;
- int ret = mbedtls_ssl_read(ssl_ctx->get_context(), p_buffer, p_bytes);
+ int ret = mbedtls_ssl_read(tls_ctx->get_context(), p_buffer, p_bytes);
if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
ret = 0; // non blocking io
} else if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
@@ -224,7 +224,7 @@ Error StreamPeerMbedTLS::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r
disconnect_from_stream();
return ERR_FILE_EOF;
} else if (ret <= 0) {
- SSLContextMbedTLS::print_mbedtls_error(ret);
+ TLSContextMbedTLS::print_mbedtls_error(ret);
disconnect_from_stream();
return ERR_CONNECTION_ERROR;
}
@@ -245,7 +245,7 @@ void StreamPeerMbedTLS::poll() {
// We could pass nullptr as second parameter, but some behaviour sanitizers don't seem to like that.
// Passing a 1 byte buffer to workaround it.
uint8_t byte;
- int ret = mbedtls_ssl_read(ssl_ctx->get_context(), &byte, 0);
+ int ret = mbedtls_ssl_read(tls_ctx->get_context(), &byte, 0);
if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
// Nothing to read/write (non blocking IO)
@@ -254,7 +254,7 @@ void StreamPeerMbedTLS::poll() {
disconnect_from_stream();
return;
} else if (ret < 0) {
- SSLContextMbedTLS::print_mbedtls_error(ret);
+ TLSContextMbedTLS::print_mbedtls_error(ret);
disconnect_from_stream();
return;
}
@@ -269,11 +269,11 @@ void StreamPeerMbedTLS::poll() {
int StreamPeerMbedTLS::get_available_bytes() const {
ERR_FAIL_COND_V(status != STATUS_CONNECTED, 0);
- return mbedtls_ssl_get_bytes_avail(&(ssl_ctx->ssl));
+ return mbedtls_ssl_get_bytes_avail(&(tls_ctx->tls));
}
StreamPeerMbedTLS::StreamPeerMbedTLS() {
- ssl_ctx.instantiate();
+ tls_ctx.instantiate();
}
StreamPeerMbedTLS::~StreamPeerMbedTLS() {
@@ -288,7 +288,7 @@ void StreamPeerMbedTLS::disconnect_from_stream() {
Ref<StreamPeerTCP> tcp = base;
if (tcp.is_valid() && tcp->get_status() == StreamPeerTCP::STATUS_CONNECTED) {
// We are still connected on the socket, try to send close notify.
- mbedtls_ssl_close_notify(ssl_ctx->get_context());
+ mbedtls_ssl_close_notify(tls_ctx->get_context());
}
_cleanup();
@@ -302,16 +302,16 @@ Ref<StreamPeer> StreamPeerMbedTLS::get_stream() const {
return base;
}
-StreamPeerSSL *StreamPeerMbedTLS::_create_func() {
+StreamPeerTLS *StreamPeerMbedTLS::_create_func() {
return memnew(StreamPeerMbedTLS);
}
-void StreamPeerMbedTLS::initialize_ssl() {
+void StreamPeerMbedTLS::initialize_tls() {
_create = _create_func;
available = true;
}
-void StreamPeerMbedTLS::finalize_ssl() {
+void StreamPeerMbedTLS::finalize_tls() {
available = false;
_create = nullptr;
}
diff --git a/modules/mbedtls/stream_peer_mbedtls.h b/modules/mbedtls/stream_peer_mbedtls.h
index 68b07feea9..9219269539 100644
--- a/modules/mbedtls/stream_peer_mbedtls.h
+++ b/modules/mbedtls/stream_peer_mbedtls.h
@@ -31,24 +31,24 @@
#ifndef STREAM_PEER_MBEDTLS_H
#define STREAM_PEER_MBEDTLS_H
-#include "core/io/stream_peer_ssl.h"
-#include "ssl_context_mbedtls.h"
+#include "core/io/stream_peer_tls.h"
+#include "tls_context_mbedtls.h"
-class StreamPeerMbedTLS : public StreamPeerSSL {
+class StreamPeerMbedTLS : public StreamPeerTLS {
private:
Status status = STATUS_DISCONNECTED;
String hostname;
Ref<StreamPeer> base;
- static StreamPeerSSL *_create_func();
+ static StreamPeerTLS *_create_func();
static int bio_recv(void *ctx, unsigned char *buf, size_t len);
static int bio_send(void *ctx, const unsigned char *buf, size_t len);
void _cleanup();
protected:
- Ref<SSLContextMbedTLS> ssl_ctx;
+ Ref<TLSContextMbedTLS> tls_ctx;
Error _do_handshake();
@@ -69,8 +69,8 @@ public:
virtual int get_available_bytes() const;
- static void initialize_ssl();
- static void finalize_ssl();
+ static void initialize_tls();
+ static void finalize_tls();
StreamPeerMbedTLS();
~StreamPeerMbedTLS();
diff --git a/modules/mbedtls/ssl_context_mbedtls.cpp b/modules/mbedtls/tls_context_mbedtls.cpp
index e2dad074cc..1ae7bc0436 100644
--- a/modules/mbedtls/ssl_context_mbedtls.cpp
+++ b/modules/mbedtls/tls_context_mbedtls.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* ssl_context_mbedtls.cpp */
+/* tls_context_mbedtls.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "ssl_context_mbedtls.h"
+#include "tls_context_mbedtls.h"
static void my_debug(void *ctx, int level,
const char *file, int line,
@@ -37,7 +37,7 @@ static void my_debug(void *ctx, int level,
fflush(stdout);
}
-void SSLContextMbedTLS::print_mbedtls_error(int p_ret) {
+void TLSContextMbedTLS::print_mbedtls_error(int p_ret) {
printf("mbedtls error: returned -0x%x\n\n", -p_ret);
fflush(stdout);
}
@@ -82,12 +82,12 @@ CookieContextMbedTLS::~CookieContextMbedTLS() {
clear();
}
-/// SSLContextMbedTLS
+/// TLSContextMbedTLS
-Error SSLContextMbedTLS::_setup(int p_endpoint, int p_transport, int p_authmode) {
+Error TLSContextMbedTLS::_setup(int p_endpoint, int p_transport, int p_authmode) {
ERR_FAIL_COND_V_MSG(inited, ERR_ALREADY_IN_USE, "This SSL context is already active");
- mbedtls_ssl_init(&ssl);
+ mbedtls_ssl_init(&tls);
mbedtls_ssl_config_init(&conf);
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_entropy_init(&entropy);
@@ -110,7 +110,7 @@ Error SSLContextMbedTLS::_setup(int p_endpoint, int p_transport, int p_authmode)
return OK;
}
-Error SSLContextMbedTLS::init_server(int p_transport, int p_authmode, Ref<CryptoKeyMbedTLS> p_pkey, Ref<X509CertificateMbedTLS> p_cert, Ref<CookieContextMbedTLS> p_cookies) {
+Error TLSContextMbedTLS::init_server(int p_transport, int p_authmode, Ref<CryptoKeyMbedTLS> p_pkey, Ref<X509CertificateMbedTLS> p_cert, Ref<CookieContextMbedTLS> p_cookies) {
ERR_FAIL_COND_V(!p_pkey.is_valid(), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(!p_cert.is_valid(), ERR_INVALID_PARAMETER);
@@ -146,11 +146,11 @@ Error SSLContextMbedTLS::init_server(int p_transport, int p_authmode, Ref<Crypto
cookies = p_cookies;
mbedtls_ssl_conf_dtls_cookies(&conf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, &(cookies->cookie_ctx));
}
- mbedtls_ssl_setup(&ssl, &conf);
+ mbedtls_ssl_setup(&tls, &conf);
return OK;
}
-Error SSLContextMbedTLS::init_client(int p_transport, int p_authmode, Ref<X509CertificateMbedTLS> p_valid_cas) {
+Error TLSContextMbedTLS::init_client(int p_transport, int p_authmode, Ref<X509CertificateMbedTLS> p_valid_cas) {
Error err = _setup(MBEDTLS_SSL_IS_CLIENT, p_transport, p_authmode);
ERR_FAIL_COND_V(err != OK, err);
@@ -172,15 +172,15 @@ Error SSLContextMbedTLS::init_client(int p_transport, int p_authmode, Ref<X509Ce
// Set valid CAs
mbedtls_ssl_conf_ca_chain(&conf, &(cas->cert), nullptr);
- mbedtls_ssl_setup(&ssl, &conf);
+ mbedtls_ssl_setup(&tls, &conf);
return OK;
}
-void SSLContextMbedTLS::clear() {
+void TLSContextMbedTLS::clear() {
if (!inited) {
return;
}
- mbedtls_ssl_free(&ssl);
+ mbedtls_ssl_free(&tls);
mbedtls_ssl_config_free(&conf);
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
@@ -198,14 +198,14 @@ void SSLContextMbedTLS::clear() {
inited = false;
}
-mbedtls_ssl_context *SSLContextMbedTLS::get_context() {
+mbedtls_ssl_context *TLSContextMbedTLS::get_context() {
ERR_FAIL_COND_V(!inited, nullptr);
- return &ssl;
+ return &tls;
}
-SSLContextMbedTLS::SSLContextMbedTLS() {
+TLSContextMbedTLS::TLSContextMbedTLS() {
}
-SSLContextMbedTLS::~SSLContextMbedTLS() {
+TLSContextMbedTLS::~TLSContextMbedTLS() {
clear();
}
diff --git a/modules/mbedtls/ssl_context_mbedtls.h b/modules/mbedtls/tls_context_mbedtls.h
index 5883388311..5e7b3dc46e 100644
--- a/modules/mbedtls/ssl_context_mbedtls.h
+++ b/modules/mbedtls/tls_context_mbedtls.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* ssl_context_mbedtls.h */
+/* tls_context_mbedtls.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SSL_CONTEXT_MBEDTLS_H
-#define SSL_CONTEXT_MBEDTLS_H
+#ifndef TLS_CONTEXT_MBEDTLS_H
+#define TLS_CONTEXT_MBEDTLS_H
#include "crypto_mbedtls.h"
@@ -44,10 +44,10 @@
#include <mbedtls/ssl.h>
#include <mbedtls/ssl_cookie.h>
-class SSLContextMbedTLS;
+class TLSContextMbedTLS;
class CookieContextMbedTLS : public RefCounted {
- friend class SSLContextMbedTLS;
+ friend class TLSContextMbedTLS;
protected:
bool inited = false;
@@ -63,7 +63,7 @@ public:
~CookieContextMbedTLS();
};
-class SSLContextMbedTLS : public RefCounted {
+class TLSContextMbedTLS : public RefCounted {
protected:
bool inited = false;
@@ -73,7 +73,7 @@ public:
Ref<X509CertificateMbedTLS> certs;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
- mbedtls_ssl_context ssl;
+ mbedtls_ssl_context tls;
mbedtls_ssl_config conf;
Ref<CookieContextMbedTLS> cookies;
@@ -86,8 +86,8 @@ public:
mbedtls_ssl_context *get_context();
- SSLContextMbedTLS();
- ~SSLContextMbedTLS();
+ TLSContextMbedTLS();
+ ~TLSContextMbedTLS();
};
-#endif // SSL_CONTEXT_MBEDTLS_H
+#endif // TLS_CONTEXT_MBEDTLS_H
diff --git a/modules/mono/README.md b/modules/mono/README.md
index ebbc6b0f80..366777cfc1 100644
--- a/modules/mono/README.md
+++ b/modules/mono/README.md
@@ -43,3 +43,13 @@ This option ensures the packages will be added to the specified local NuGet
source and that conflicting versions of the package are removed from the
NuGet cache. It's recommended to always use this option when building the
C# solutions during development to avoid mistakes.
+
+# Double Precision Support (REAL_T_IS_DOUBLE)
+
+Follow the above instructions but build Godot with the float=64 argument to scons
+
+When building the NuGet packages, specify `--float=64` - for example:
+```sh
+./modules/mono/build_scripts/build_assemblies.py --godot-output-dir ./bin \
+ --push-nupkgs-local ~/MyLocalNugetSource --float=64
+```
diff --git a/modules/mono/build_scripts/build_assemblies.py b/modules/mono/build_scripts/build_assemblies.py
index fa3be684bd..6f66ce9efa 100755
--- a/modules/mono/build_scripts/build_assemblies.py
+++ b/modules/mono/build_scripts/build_assemblies.py
@@ -195,7 +195,7 @@ def run_msbuild(tools: ToolsLocation, sln: str, msbuild_args: [str] = None):
return subprocess.call(args, env=msbuild_env)
-def build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local):
+def build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, float_size):
target_filenames = [
"GodotSharp.dll",
"GodotSharp.pdb",
@@ -216,6 +216,8 @@ def build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local):
args = ["/restore", "/t:Build", "/p:Configuration=" + build_config, "/p:NoWarn=1591"]
if push_nupkgs_local:
args += ["/p:ClearNuGetLocalCache=true", "/p:PushNuGetToLocalSource=" + push_nupkgs_local]
+ if float_size == "64":
+ args += ["/p:GodotFloat64=true"]
sln = os.path.join(module_dir, "glue/GodotSharp/GodotSharp.sln")
exit_code = run_msbuild(
@@ -256,9 +258,9 @@ def build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local):
return 0
-def build_all(msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, push_nupkgs_local):
+def build_all(msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, push_nupkgs_local, float_size):
# Godot API
- exit_code = build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local)
+ exit_code = build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, float_size)
if exit_code != 0:
return exit_code
@@ -269,6 +271,8 @@ def build_all(msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, p
)
if push_nupkgs_local:
args += ["/p:ClearNuGetLocalCache=true", "/p:PushNuGetToLocalSource=" + push_nupkgs_local]
+ if float_size == "64":
+ args += ["/p:GodotFloat64=true"]
exit_code = run_msbuild(msbuild_tool, sln=sln, msbuild_args=args)
if exit_code != 0:
return exit_code
@@ -277,6 +281,8 @@ def build_all(msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, p
args = ["/restore", "/t:Build", "/p:Configuration=Release"]
if push_nupkgs_local:
args += ["/p:ClearNuGetLocalCache=true", "/p:PushNuGetToLocalSource=" + push_nupkgs_local]
+ if float_size == "64":
+ args += ["/p:GodotFloat64=true"]
sln = os.path.join(module_dir, "editor/Godot.NET.Sdk/Godot.NET.Sdk.sln")
exit_code = run_msbuild(msbuild_tool, sln=sln, msbuild_args=args)
if exit_code != 0:
@@ -300,6 +306,7 @@ def main():
parser.add_argument("--godot-platform", type=str, default="")
parser.add_argument("--mono-prefix", type=str, default="")
parser.add_argument("--push-nupkgs-local", type=str, default="")
+ parser.add_argument("--float", type=str, default="32", choices=["32", "64"], help="Floating-point precision")
args = parser.parse_args()
@@ -321,6 +328,7 @@ def main():
args.godot_platform,
args.dev_debug,
args.push_nupkgs_local,
+ args.float,
)
sys.exit(exit_code)
diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py
index c2d5452837..5d63773096 100644
--- a/modules/mono/build_scripts/mono_configure.py
+++ b/modules/mono/build_scripts/mono_configure.py
@@ -27,293 +27,3 @@ def configure(env, env_mono):
if env["tools"]:
env_mono.Append(CPPDEFINES=["GD_MONO_HOT_RELOAD"])
-
- app_host_dir = find_dotnet_app_host_dir(env)
-
- def check_app_host_file_exists(file):
- file_path = os.path.join(app_host_dir, file)
- if not os.path.isfile(file_path):
- raise RuntimeError("File not found: " + file_path)
-
- # TODO:
- # All libnethost does for us is provide a function to find hostfxr.
- # If we could handle that logic ourselves we could void linking it.
-
- # nethost file names:
- # static: libnethost.a/lib
- # shared: libnethost.a/dylib and nethost.dll
- check_app_host_file_exists("libnethost.lib" if os.name == "nt" else "libnethost.a")
- check_app_host_file_exists("nethost.h")
- check_app_host_file_exists("hostfxr.h")
- check_app_host_file_exists("coreclr_delegates.h")
-
- env_mono.Prepend(CPPPATH=app_host_dir)
-
- env.Append(LIBPATH=[app_host_dir])
-
- # Only the editor build links nethost, which is needed to find hostfxr.
- # Exported games don't need this logic as hostfxr is bundled with them.
- if tools_enabled:
- libnethost_path = os.path.join(app_host_dir, "libnethost.lib" if os.name == "nt" else "libnethost.a")
-
- if env["platform"] == "windows":
- env_mono.Append(CPPDEFINES=["NETHOST_USE_AS_STATIC"])
-
- if env.msvc:
- env.Append(LINKFLAGS="libnethost.lib")
- else:
- env.Append(LINKFLAGS=["-Wl,-whole-archive", libnethost_path, "-Wl,-no-whole-archive"])
- else:
- is_apple = env["platform"] in ["macos", "ios"]
- # is_macos = is_apple and not is_ios
-
- # if is_ios and not is_ios_sim:
- # env_mono.Append(CPPDEFINES=["IOS_DEVICE"])
-
- if is_apple:
- env.Append(LINKFLAGS=["-Wl,-force_load," + libnethost_path])
- else:
- env.Append(LINKFLAGS=["-Wl,-whole-archive", libnethost_path, "-Wl,-no-whole-archive"])
-
-
-def find_dotnet_app_host_dir(env):
- dotnet_version = "6.0"
-
- dotnet_root = env["dotnet_root"]
-
- if not dotnet_root:
- dotnet_cmd = find_dotnet_executable(env["arch"])
- if dotnet_cmd:
- sdk_path = find_dotnet_sdk(dotnet_cmd, dotnet_version)
- if sdk_path:
- dotnet_root = os.path.abspath(os.path.join(sdk_path, os.pardir))
-
- if not dotnet_root:
- raise RuntimeError("Cannot find .NET Core Sdk")
-
- print("Found .NET Core Sdk root directory: " + dotnet_root)
-
- dotnet_cmd = os.path.join(dotnet_root, "dotnet.exe" if os.name == "nt" else "dotnet")
-
- runtime_identifier = determine_runtime_identifier(env)
-
- # TODO: In the future, if it can't be found this way, we want to obtain it
- # from the runtime.{runtime_identifier}.Microsoft.NETCore.DotNetAppHost NuGet package.
- app_host_version = find_app_host_version(dotnet_cmd, dotnet_version)
- if not app_host_version:
- raise RuntimeError("Cannot find .NET app host for version: " + dotnet_version)
-
- def get_runtime_path():
- return os.path.join(
- dotnet_root,
- "packs",
- "Microsoft.NETCore.App.Host." + runtime_identifier,
- app_host_version,
- "runtimes",
- runtime_identifier,
- "native",
- )
-
- app_host_dir = get_runtime_path()
-
- # Some Linux distros use their distro name as the RID in these paths.
- # If the initial generic path doesn't exist, try to get the RID from `dotnet --info`.
- # The generic RID should still be the first choice. Some platforms like Windows 10
- # define the RID as `win10-x64` but still use the generic `win-x64` for directory names.
- if not app_host_dir or not os.path.isdir(app_host_dir):
- runtime_identifier = find_dotnet_cli_rid(dotnet_cmd)
- app_host_dir = get_runtime_path()
-
- return app_host_dir
-
-
-def determine_runtime_identifier(env):
- # The keys are Godot's names, the values are the Microsoft's names.
- # List: https://docs.microsoft.com/en-us/dotnet/core/rid-catalog
- names_map = {
- "windows": "win",
- "macos": "osx",
- "linuxbsd": "linux",
- }
- arch_map = {
- "x86_64": "x64",
- "x86_32": "x86",
- "arm64": "arm64",
- "arm32": "arm",
- }
- platform = env["platform"]
- if is_desktop(platform):
- return "%s-%s" % (names_map[platform], arch_map[env["arch"]])
- else:
- raise NotImplementedError()
-
-
-def find_app_host_version(dotnet_cmd, search_version_str):
- import subprocess
- from distutils.version import LooseVersion
-
- search_version = LooseVersion(search_version_str)
- found_match = False
-
- try:
- env = dict(os.environ, DOTNET_CLI_UI_LANGUAGE="en-US")
- lines = subprocess.check_output([dotnet_cmd, "--list-runtimes"], env=env).splitlines()
-
- for line_bytes in lines:
- line = line_bytes.decode("utf-8")
- if not line.startswith("Microsoft.NETCore.App "):
- continue
-
- parts = line.split(" ", 2)
- if len(parts) < 3:
- continue
-
- version_str = parts[1]
-
- version = LooseVersion(version_str)
-
- if version >= search_version:
- search_version = version
- found_match = True
- if found_match:
- return str(search_version)
- except (subprocess.CalledProcessError, OSError) as e:
- import sys
-
- print(e, file=sys.stderr)
-
- return ""
-
-
-def find_dotnet_arch(dotnet_cmd):
- import subprocess
-
- try:
- env = dict(os.environ, DOTNET_CLI_UI_LANGUAGE="en-US")
- lines = subprocess.check_output([dotnet_cmd, "--info"], env=env).splitlines()
-
- for line_bytes in lines:
- line = line_bytes.decode("utf-8")
-
- parts = line.split(":", 1)
- if len(parts) < 2:
- continue
-
- arch_str = parts[0].strip()
- if arch_str != "Architecture":
- continue
-
- arch_value = parts[1].strip()
- arch_map = {"x64": "x86_64", "x86": "x86_32", "arm64": "arm64", "arm32": "arm32"}
- return arch_map[arch_value]
- except (subprocess.CalledProcessError, OSError) as e:
- import sys
-
- print(e, file=sys.stderr)
-
- return ""
-
-
-def find_dotnet_sdk(dotnet_cmd, search_version_str):
- import subprocess
- from distutils.version import LooseVersion
-
- search_version = LooseVersion(search_version_str)
-
- try:
- env = dict(os.environ, DOTNET_CLI_UI_LANGUAGE="en-US")
- lines = subprocess.check_output([dotnet_cmd, "--list-sdks"], env=env).splitlines()
-
- for line_bytes in lines:
- line = line_bytes.decode("utf-8")
-
- parts = line.split(" ", 1)
- if len(parts) < 2:
- continue
-
- version_str = parts[0]
-
- version = LooseVersion(version_str)
-
- if version < search_version:
- continue
-
- path_part = parts[1]
- return path_part[1 : path_part.find("]")]
- except (subprocess.CalledProcessError, OSError) as e:
- import sys
-
- print(e, file=sys.stderr)
-
- return ""
-
-
-def find_dotnet_cli_rid(dotnet_cmd):
- import subprocess
-
- try:
- env = dict(os.environ, DOTNET_CLI_UI_LANGUAGE="en-US")
- lines = subprocess.check_output([dotnet_cmd, "--info"], env=env).splitlines()
-
- for line_bytes in lines:
- line = line_bytes.decode("utf-8")
- if not line.startswith(" RID:"):
- continue
-
- parts = line.split()
- if len(parts) < 2:
- continue
-
- return parts[1]
- except (subprocess.CalledProcessError, OSError) as e:
- import sys
-
- print(e, file=sys.stderr)
-
- return ""
-
-
-ENV_PATH_SEP = ";" if os.name == "nt" else ":"
-
-
-def find_dotnet_executable(arch):
- is_windows = os.name == "nt"
- windows_exts = os.environ["PATHEXT"].split(ENV_PATH_SEP) if is_windows else None
- path_dirs = os.environ["PATH"].split(ENV_PATH_SEP)
-
- search_dirs = path_dirs + [os.getcwd()] # cwd is last in the list
-
- for dir in path_dirs:
- search_dirs += [
- os.path.join(dir, "x64"),
- os.path.join(dir, "x86"),
- os.path.join(dir, "arm64"),
- os.path.join(dir, "arm32"),
- ] # search subfolders for cross compiling
-
- # `dotnet --info` may not specify architecture. In such cases,
- # we fallback to the first one we find without architecture.
- sdk_path_unknown_arch = ""
-
- for dir in search_dirs:
- path = os.path.join(dir, "dotnet")
-
- if is_windows:
- for extension in windows_exts:
- path_with_ext = path + extension
-
- if os.path.isfile(path_with_ext) and os.access(path_with_ext, os.X_OK):
- sdk_arch = find_dotnet_arch(path_with_ext)
- if sdk_arch == arch or arch == "":
- return path_with_ext
- elif sdk_arch == "":
- sdk_path_unknown_arch = path_with_ext
- else:
- if os.path.isfile(path) and os.access(path, os.X_OK):
- sdk_arch = find_dotnet_arch(path)
- if sdk_arch == arch or arch == "":
- return path
- elif sdk_arch == "":
- sdk_path_unknown_arch = path
-
- return sdk_path_unknown_arch
diff --git a/modules/mono/config.py b/modules/mono/config.py
index ad78c8c898..15fe79ef8c 100644
--- a/modules/mono/config.py
+++ b/modules/mono/config.py
@@ -4,23 +4,13 @@ supported_platforms = ["windows", "macos", "linuxbsd"]
def can_build(env, platform):
- return not env["arch"].startswith("rv")
+ if env["arch"].startswith("rv"):
+ return False
+ if env["tools"]:
+ env.module_add_dependencies("mono", ["regex"])
-def get_opts(platform):
- from SCons.Variables import BoolVariable, PathVariable
-
- default_mono_static = platform in ["ios", "web"]
- default_mono_bundles_zlib = platform in ["web"]
-
- return [
- PathVariable(
- "dotnet_root",
- "Path to the .NET Sdk installation directory for the target platform and architecture",
- "",
- PathVariable.PathAccept,
- ),
- ]
+ return True
def configure(env):
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 2e59987fe6..990a95821e 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -784,6 +784,13 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
for (Object *obj : script->instances) {
script->pending_reload_instances.insert(obj->get_instance_id());
+ // Since this script instance wasn't a placeholder, add it to the list of placeholders
+ // that will have to be eventually replaced with a script instance in case it turns into one.
+ // This list is not cleared after the reload and the collected instances only leave
+ // the list if the script is instantiated or if it was a tool script but becomes a
+ // non-tool script in a rebuild.
+ script->pending_replace_placeholders.insert(obj->get_instance_id());
+
RefCounted *rc = Object::cast_to<RefCounted>(obj);
if (rc) {
rc_instances.push_back(Ref<RefCounted>(rc));
@@ -836,6 +843,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
obj->set_script(Ref<RefCounted>()); // Remove script and existing script instances (placeholder are not removed before domain reload)
}
+ script->was_tool_before_reload = script->tool;
script->_clear();
}
@@ -924,24 +932,34 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
ScriptInstance *si = obj->get_script_instance();
+ // Check if the script must be instantiated or kept as a placeholder
+ // when the script may not be a tool (see #65266)
+ bool replace_placeholder = script->pending_replace_placeholders.has(obj->get_instance_id());
+ if (!script->is_tool() && script->was_tool_before_reload) {
+ // The script was a tool before the rebuild so the removal was intentional.
+ replace_placeholder = false;
+ script->pending_replace_placeholders.erase(obj->get_instance_id());
+ }
+
#ifdef TOOLS_ENABLED
if (si) {
// If the script instance is not null, then it must be a placeholder.
// Non-placeholder script instances are removed in godot_icall_Object_Disposed.
CRASH_COND(!si->is_placeholder());
- if (script->is_tool() || ScriptServer::is_scripting_enabled()) {
- // Replace placeholder with a script instance
+ if (replace_placeholder || script->is_tool() || ScriptServer::is_scripting_enabled()) {
+ // Replace placeholder with a script instance.
CSharpScript::StateBackup &state_backup = script->pending_reload_state[obj_id];
- // Backup placeholder script instance state before replacing it with a script instance
+ // Backup placeholder script instance state before replacing it with a script instance.
si->get_property_state(state_backup.properties);
ScriptInstance *script_instance = script->instance_create(obj);
if (script_instance) {
script->placeholders.erase(static_cast<PlaceHolderScriptInstance *>(si));
+ script->pending_replace_placeholders.erase(obj->get_instance_id());
obj->set_script_instance(script_instance);
}
}
@@ -951,8 +969,24 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
#else
CRASH_COND(si != nullptr);
#endif
- // Re-create script instance
- obj->set_script(script); // will create the script instance as well
+
+ // Re-create the script instance.
+ if (replace_placeholder || script->is_tool() || ScriptServer::is_scripting_enabled()) {
+ // Create script instance or replace placeholder with a script instance.
+ ScriptInstance *script_instance = script->instance_create(obj);
+
+ if (script_instance) {
+ script->pending_replace_placeholders.erase(obj->get_instance_id());
+ obj->set_script_instance(script_instance);
+ continue;
+ }
+ }
+ // The script instance could not be instantiated or wasn't in the list of placeholders to replace.
+ obj->set_script(script);
+#if DEBUG_ENABLED
+ // If we reached here, the instantiated script must be a placeholder.
+ CRASH_COND(!obj->get_script_instance()->is_placeholder());
+#endif
}
}
@@ -1754,20 +1788,16 @@ void CSharpInstance::mono_object_disposed_baseref(GCHandleIntPtr p_gchandle_to_f
}
void CSharpInstance::connect_event_signals() {
- CSharpScript *top = script.ptr();
- while (top != nullptr) {
- for (CSharpScript::EventSignalInfo &signal : top->get_script_event_signals()) {
- String signal_name = signal.name;
+ // The script signals list includes the signals declared in base scripts.
+ for (CSharpScript::EventSignalInfo &signal : script->get_script_event_signals()) {
+ String signal_name = signal.name;
- // TODO: Use pooling for ManagedCallable instances.
- EventSignalCallable *event_signal_callable = memnew(EventSignalCallable(owner, signal_name));
+ // TODO: Use pooling for ManagedCallable instances.
+ EventSignalCallable *event_signal_callable = memnew(EventSignalCallable(owner, signal_name));
- Callable callable(event_signal_callable);
- connected_event_signals.push_back(callable);
- owner->connect(signal_name, callable);
- }
-
- top = top->base_script.ptr();
+ Callable callable(event_signal_callable);
+ connected_event_signals.push_back(callable);
+ owner->connect(signal_name, callable);
}
}
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 3509a5c87d..f2844a051d 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -90,6 +90,9 @@ class CSharpScript : public Script {
HashSet<ObjectID> pending_reload_instances;
RBMap<ObjectID, StateBackup> pending_reload_state;
+
+ bool was_tool_before_reload = false;
+ HashSet<ObjectID> pending_replace_placeholders;
#endif
String source;
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props
index 59ce1da17b..0459257106 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props
@@ -62,7 +62,7 @@
</PropertyGroup>
<PropertyGroup>
- <GodotRealTIsDouble Condition=" '$(GodotRealTIsDouble)' == '' ">false</GodotRealTIsDouble>
+ <GodotFloat64 Condition=" '$(GodotFloat64)' == '' ">false</GodotFloat64>
</PropertyGroup>
<!-- Godot DefineConstants. -->
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.targets b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.targets
index aad4ea4553..bff9760b32 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.targets
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.targets
@@ -10,9 +10,9 @@
<!--
Define constant to determine whether the real_t type in Godot is double precision or not.
By default this is false, like the official Godot builds. If someone is using a custom
- Godot build where real_t is double, they can override the GodotRealTIsDouble property.
+ Godot build where real_t is double, they can override the GodotFloat64 property.
-->
- <DefineConstants Condition=" '$(GodotRealTIsDouble)' == 'true' ">GODOT_REAL_T_IS_DOUBLE;$(DefineConstants)</DefineConstants>
+ <DefineConstants Condition=" '$(GodotFloat64)' == 'true' ">GODOT_REAL_T_IS_DOUBLE;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<!-- C# source generators -->
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MustBeVariantAnalyzer.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MustBeVariantAnalyzer.cs
index 7aaadb27be..98ca534c66 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MustBeVariantAnalyzer.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MustBeVariantAnalyzer.cs
@@ -39,6 +39,11 @@ namespace Godot.SourceGenerators
for (int i = 0; i < typeArgListSyntax.Arguments.Count; i++)
{
var typeSyntax = typeArgListSyntax.Arguments[i];
+
+ // Ignore omitted type arguments, e.g.: List<>, Dictionary<,>, etc
+ if (typeSyntax is OmittedTypeArgumentSyntax)
+ continue;
+
var typeSymbol = sm.GetSymbolInfo(typeSyntax).Symbol as ITypeSymbol;
Debug.Assert(typeSymbol != null);
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs
index 5ac4f4a47e..1ee31eb1a9 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs
@@ -133,7 +133,9 @@ namespace Godot.SourceGenerators
.Distinct(new MethodOverloadEqualityComparer())
.ToArray();
- source.Append(" private partial class GodotInternal {\n");
+ source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n");
+
+ source.Append($" public new class MethodName : {symbol.BaseType.FullQualifiedName()}.MethodName {{\n");
// Generate cached StringNames for methods and properties, for fast lookup
@@ -144,7 +146,7 @@ namespace Godot.SourceGenerators
foreach (string methodName in distinctMethodNames)
{
- source.Append(" public static readonly StringName MethodName_");
+ source.Append(" public new static readonly StringName ");
source.Append(methodName);
source.Append(" = \"");
source.Append(methodName);
@@ -157,8 +159,6 @@ namespace Godot.SourceGenerators
if (godotClassMethods.Length > 0)
{
- source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n");
-
const string listType = "System.Collections.Generic.List<global::Godot.Bridge.MethodInfo>";
source.Append(" internal new static ")
@@ -179,10 +179,10 @@ namespace Godot.SourceGenerators
source.Append(" return methods;\n");
source.Append(" }\n");
-
- source.Append("#pragma warning restore CS0109\n");
}
+ source.Append("#pragma warning restore CS0109\n");
+
// Generate InvokeGodotClassMethod
if (godotClassMethods.Length > 0)
@@ -242,7 +242,7 @@ namespace Godot.SourceGenerators
private static void AppendMethodInfo(StringBuilder source, MethodInfo methodInfo)
{
- source.Append(" methods.Add(new(name: GodotInternal.MethodName_")
+ source.Append(" methods.Add(new(name: MethodName.")
.Append(methodInfo.Name)
.Append(", returnVal: ");
@@ -350,7 +350,7 @@ namespace Godot.SourceGenerators
source.Append(" ");
if (!isFirstEntry)
source.Append("else ");
- source.Append("if (method == GodotInternal.MethodName_");
+ source.Append("if (method == MethodName.");
source.Append(methodName);
source.Append(") {\n return true;\n }\n");
}
@@ -362,7 +362,7 @@ namespace Godot.SourceGenerators
{
string methodName = method.Method.Name;
- source.Append(" if (method == GodotInternal.MethodName_");
+ source.Append(" if (method == MethodName.");
source.Append(methodName);
source.Append(" && argCount == ");
source.Append(method.ParamTypes.Length);
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
index fc46d82dff..b331e2e794 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
@@ -122,14 +122,16 @@ namespace Godot.SourceGenerators
var godotClassProperties = propertySymbols.WhereIsGodotCompatibleType(typeCache).ToArray();
var godotClassFields = fieldSymbols.WhereIsGodotCompatibleType(typeCache).ToArray();
- source.Append(" private partial class GodotInternal {\n");
+ source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n");
+
+ source.Append($" public new class PropertyName : {symbol.BaseType.FullQualifiedName()}.PropertyName {{\n");
// Generate cached StringNames for methods and properties, for fast lookup
foreach (var property in godotClassProperties)
{
string propertyName = property.PropertySymbol.Name;
- source.Append(" public static readonly StringName PropName_");
+ source.Append(" public new static readonly StringName ");
source.Append(propertyName);
source.Append(" = \"");
source.Append(propertyName);
@@ -139,7 +141,7 @@ namespace Godot.SourceGenerators
foreach (var field in godotClassFields)
{
string fieldName = field.FieldSymbol.Name;
- source.Append(" public static readonly StringName PropName_");
+ source.Append(" public new static readonly StringName ");
source.Append(fieldName);
source.Append(" = \"");
source.Append(fieldName);
@@ -214,8 +216,6 @@ namespace Godot.SourceGenerators
// Generate GetGodotPropertyList
- source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n");
-
string dictionaryType = "System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>";
source.Append(" internal new static ")
@@ -289,7 +289,7 @@ namespace Godot.SourceGenerators
if (!isFirstEntry)
source.Append("else ");
- source.Append("if (name == GodotInternal.PropName_")
+ source.Append("if (name == PropertyName.")
.Append(propertyMemberName)
.Append(") {\n")
.Append(" ")
@@ -313,7 +313,7 @@ namespace Godot.SourceGenerators
if (!isFirstEntry)
source.Append("else ");
- source.Append("if (name == GodotInternal.PropName_")
+ source.Append("if (name == PropertyName.")
.Append(propertyMemberName)
.Append(") {\n")
.Append(" value = ")
@@ -342,7 +342,7 @@ namespace Godot.SourceGenerators
{
source.Append(" properties.Add(new(type: (Godot.Variant.Type)")
.Append((int)propertyInfo.Type)
- .Append(", name: GodotInternal.PropName_")
+ .Append(", name: PropertyName.")
.Append(propertyInfo.Name)
.Append(", hint: (Godot.PropertyHint)")
.Append((int)propertyInfo.Hint)
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs
index c7745391d0..65dadcb801 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs
@@ -243,7 +243,7 @@ namespace Godot.SourceGenerators
source.Append(" = ");
source.Append(exportedMember.Value ?? "default");
source.Append(";\n");
- source.Append(" values.Add(GodotInternal.PropName_");
+ source.Append(" values.Add(PropertyName.");
source.Append(exportedMember.Name);
source.Append(", ");
source.Append(defaultValueLocalName);
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs
index 39a99ff8ba..a40220565f 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs
@@ -159,7 +159,7 @@ namespace Godot.SourceGenerators
{
string propertyName = property.PropertySymbol.Name;
- source.Append(" info.AddProperty(GodotInternal.PropName_")
+ source.Append(" info.AddProperty(PropertyName.")
.Append(propertyName)
.Append(", ")
.AppendManagedToVariantExpr(string.Concat("this.", propertyName), property.Type)
@@ -172,7 +172,7 @@ namespace Godot.SourceGenerators
{
string fieldName = field.FieldSymbol.Name;
- source.Append(" info.AddProperty(GodotInternal.PropName_")
+ source.Append(" info.AddProperty(PropertyName.")
.Append(fieldName)
.Append(", ")
.AppendManagedToVariantExpr(string.Concat("this.", fieldName), field.Type)
@@ -185,7 +185,7 @@ namespace Godot.SourceGenerators
{
string signalName = signalDelegate.Name;
- source.Append(" info.AddSignalEventDelegate(GodotInternal.SignalName_")
+ source.Append(" info.AddSignalEventDelegate(SignalName.")
.Append(signalName)
.Append(", this.backing_")
.Append(signalName)
@@ -204,7 +204,7 @@ namespace Godot.SourceGenerators
{
string propertyName = property.PropertySymbol.Name;
- source.Append(" if (info.TryGetProperty(GodotInternal.PropName_")
+ source.Append(" if (info.TryGetProperty(PropertyName.")
.Append(propertyName)
.Append(", out var _value_")
.Append(propertyName)
@@ -223,7 +223,7 @@ namespace Godot.SourceGenerators
{
string fieldName = field.FieldSymbol.Name;
- source.Append(" if (info.TryGetProperty(GodotInternal.PropName_")
+ source.Append(" if (info.TryGetProperty(PropertyName.")
.Append(fieldName)
.Append(", out var _value_")
.Append(fieldName)
@@ -245,7 +245,7 @@ namespace Godot.SourceGenerators
source.Append(" if (info.TryGetSignalEventDelegate<")
.Append(signalDelegateQualifiedName)
- .Append(">(GodotInternal.SignalName_")
+ .Append(">(SignalName.")
.Append(signalName)
.Append(", out var _value_")
.Append(signalName)
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs
index 6b06f10db1..1df41a905b 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs
@@ -173,14 +173,16 @@ namespace Godot.SourceGenerators
godotSignalDelegates.Add(new(signalName, signalDelegateSymbol, invokeMethodData.Value));
}
- source.Append(" private partial class GodotInternal {\n");
+ source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n");
+
+ source.Append($" public new class SignalName : {symbol.BaseType.FullQualifiedName()}.SignalName {{\n");
// Generate cached StringNames for methods and properties, for fast lookup
foreach (var signalDelegate in godotSignalDelegates)
{
string signalName = signalDelegate.Name;
- source.Append(" public static readonly StringName SignalName_");
+ source.Append(" public new static readonly StringName ");
source.Append(signalName);
source.Append(" = \"");
source.Append(signalName);
@@ -193,8 +195,6 @@ namespace Godot.SourceGenerators
if (godotSignalDelegates.Count > 0)
{
- source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n");
-
const string listType = "System.Collections.Generic.List<global::Godot.Bridge.MethodInfo>";
source.Append(" internal new static ")
@@ -215,10 +215,10 @@ namespace Godot.SourceGenerators
source.Append(" return signals;\n");
source.Append(" }\n");
-
- source.Append("#pragma warning restore CS0109\n");
}
+ source.Append("#pragma warning restore CS0109\n");
+
// Generate signal event
foreach (var signalDelegate in godotSignalDelegates)
@@ -291,7 +291,7 @@ namespace Godot.SourceGenerators
private static void AppendMethodInfo(StringBuilder source, MethodInfo methodInfo)
{
- source.Append(" signals.Add(new(name: GodotInternal.SignalName_")
+ source.Append(" signals.Add(new(name: SignalName.")
.Append(methodInfo.Name)
.Append(", returnVal: ");
@@ -400,7 +400,7 @@ namespace Godot.SourceGenerators
string signalName = signal.Name;
var invokeMethodData = signal.InvokeMethodData;
- source.Append(" if (signal == GodotInternal.SignalName_");
+ source.Append(" if (signal == SignalName.");
source.Append(signalName);
source.Append(" && argCount == ");
source.Append(invokeMethodData.ParamTypes.Length);
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs
index 4041026426..237ac85267 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs
@@ -122,7 +122,7 @@ namespace GodotTools.Build
{
base._Ready();
- CustomMinimumSize = new Vector2(0, 228) * EditorScale;
+ CustomMinimumSize = new Vector2i(0, (int)(228 * EditorScale));
SizeFlagsVertical = (int)SizeFlags.ExpandFill;
var toolBarHBox = new HBoxContainer { SizeFlagsHorizontal = (int)SizeFlags.ExpandFill };
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 15a40c8ca5..c27bb959fe 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -113,7 +113,7 @@ StringBuilder &operator<<(StringBuilder &r_sb, const char *p_cstring) {
#define C_METHOD_MANAGED_FROM_SIGNAL C_NS_MONOMARSHAL ".ConvertSignalToManaged"
// Types that will be ignored by the generator and won't be available in C#.
-const Vector<String> ignored_types = { "PhysicsServer3DExtension" };
+const Vector<String> ignored_types = { "PhysicsServer2DExtension", "PhysicsServer3DExtension" };
void BindingsGenerator::TypeInterface::postsetup_enum_type(BindingsGenerator::TypeInterface &r_enum_itype) {
// C interface for enums is the same as that of 'uint32_t'. Remember to apply
diff --git a/modules/mono/editor/hostfxr_resolver.cpp b/modules/mono/editor/hostfxr_resolver.cpp
new file mode 100644
index 0000000000..ea5978b2cd
--- /dev/null
+++ b/modules/mono/editor/hostfxr_resolver.cpp
@@ -0,0 +1,335 @@
+/*************************************************************************/
+/* hostfxr_resolver.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+/*
+Adapted to Godot from the nethost library: https://github.com/dotnet/runtime/tree/main/src/native/corehost
+*/
+
+/*
+The MIT License (MIT)
+
+Copyright (c) .NET Foundation and Contributors
+
+All rights reserved.
+
+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.
+*/
+
+#include "hostfxr_resolver.h"
+
+#include "core/config/engine.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
+#include "core/os/os.h"
+
+#ifdef WINDOWS_ENABLED
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+#include "../utils/path_utils.h"
+#include "semver.h"
+
+// We don't use libnethost as it gives us issues with some compilers.
+// This file tries to mimic libnethost's hostfxr_resolver search logic. We try to use the
+// same function names for easier comparing in case we need to update this in the future.
+
+namespace {
+
+String get_hostfxr_file_name() {
+#if defined(WINDOWS_ENABLED) || defined(UWP_ENABLED)
+ return "hostfxr.dll";
+#elif defined(MACOS_ENABLED) || defined(IOS_ENABLED)
+ return "libhostfxr.dylib";
+#else
+ return "libhostfxr.so";
+#endif
+}
+
+bool get_latest_fxr(const String &fxr_root, String &r_fxr_path) {
+ godotsharp::SemVerParser sem_ver_parser;
+
+ bool found_ver = false;
+ godotsharp::SemVer latest_ver;
+ String latest_ver_str;
+
+ Ref<DirAccess> da = DirAccess::open(fxr_root);
+ da->list_dir_begin();
+ for (String dir = da->get_next(); !dir.is_empty(); dir = da->get_next()) {
+ if (!da->current_is_dir() || dir == "." || dir == "..") {
+ continue;
+ }
+
+ String ver = dir.get_file();
+
+ godotsharp::SemVer fx_ver;
+ if (sem_ver_parser.parse(ver, fx_ver)) {
+ if (!found_ver || fx_ver > latest_ver) {
+ latest_ver = fx_ver;
+ latest_ver_str = ver;
+ found_ver = true;
+ }
+ }
+ }
+
+ if (!found_ver) {
+ return false;
+ }
+
+ String fxr_with_ver = path::join(fxr_root, latest_ver_str);
+ String hostfxr_file_path = path::join(fxr_with_ver, get_hostfxr_file_name());
+
+ ERR_FAIL_COND_V_MSG(!FileAccess::exists(hostfxr_file_path), false, "Missing hostfxr library in directory: " + fxr_with_ver);
+
+ r_fxr_path = hostfxr_file_path;
+
+ return true;
+}
+
+#ifdef WINDOWS_ENABLED
+typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
+
+BOOL is_wow64() {
+ BOOL wow64 = FALSE;
+
+ LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
+
+ if (fnIsWow64Process) {
+ if (!fnIsWow64Process(GetCurrentProcess(), &wow64)) {
+ wow64 = FALSE;
+ }
+ }
+
+ return wow64;
+}
+#endif
+
+static const char *arch_name_map[][2] = {
+ { "arm32", "arm" },
+ { "arm64", "arm64" },
+ { "rv64", "riscv64" },
+ { "x86_64", "x64" },
+ { "x86_32", "x86" },
+ { nullptr, nullptr }
+};
+
+String get_dotnet_arch() {
+ String arch = Engine::get_singleton()->get_architecture_name();
+
+ int idx = 0;
+ while (arch_name_map[idx][0] != nullptr) {
+ if (arch_name_map[idx][0] == arch) {
+ return arch_name_map[idx][1];
+ }
+ idx++;
+ }
+
+ return "";
+}
+
+bool get_default_installation_dir(String &r_dotnet_root) {
+#if defined(WINDOWS_ENABLED)
+ String program_files_env;
+ if (is_wow64()) {
+ // Running x86 on x64, looking for x86 install
+ program_files_env = "ProgramFiles(x86)";
+ } else {
+ program_files_env = "ProgramFiles";
+ }
+
+ String program_files_dir = OS::get_singleton()->get_environment(program_files_env);
+
+ if (program_files_dir.is_empty()) {
+ return false;
+ }
+
+#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(_M_X64)
+ // When emulating x64 on arm
+ String dotnet_root_emulated = path::join(program_files_dir, "dotnet", "x64");
+ if (FileAccess::exists(path::join(dotnet_root_emulated, "dotnet.exe"))) {
+ r_dotnet_root = dotnet_root_emulated;
+ return true;
+ }
+#endif
+
+ r_dotnet_root = path::join(program_files_dir, "dotnet");
+ return true;
+#elif defined(MACOS_ENABLED)
+ r_dotnet_root = "/usr/local/share/dotnet";
+
+#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(_M_X64)
+ // When emulating x64 on arm
+ String dotnet_root_emulated = path::join(r_dotnet_root, "x64");
+ if (FileAccess::exists(path::join(dotnet_root_emulated, "dotnet"))) {
+ r_dotnet_root = dotnet_root_emulated;
+ return true;
+ }
+#endif
+
+ return true;
+#else
+ r_dotnet_root = "/usr/share/dotnet";
+ return true;
+#endif
+}
+
+bool get_install_location_from_file(const String &p_file_path, String &r_dotnet_root) {
+ Error err = OK;
+ Ref<FileAccess> f = FileAccess::open(p_file_path, FileAccess::READ, &err);
+
+ if (f.is_null() || err != OK) {
+ return false;
+ }
+
+ String line = f->get_line();
+
+ if (line.is_empty()) {
+ return false;
+ }
+
+ r_dotnet_root = line;
+ return true;
+}
+
+bool get_dotnet_self_registered_dir(String &r_dotnet_root) {
+#if defined(WINDOWS_ENABLED)
+ String sub_key = "SOFTWARE\\dotnet\\Setup\\InstalledVersions\\" + get_dotnet_arch();
+ Char16String value = String("InstallLocation").utf16();
+
+ HKEY hkey = NULL;
+ LSTATUS result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, (LPCWSTR)(sub_key.utf16().get_data()), 0, KEY_READ | KEY_WOW64_32KEY, &hkey);
+ if (result != ERROR_SUCCESS) {
+ return false;
+ }
+
+ DWORD size = 0;
+ result = RegGetValueW(hkey, nullptr, (LPCWSTR)(value.get_data()), RRF_RT_REG_SZ, nullptr, nullptr, &size);
+ if (result != ERROR_SUCCESS || size == 0) {
+ RegCloseKey(hkey);
+ return false;
+ }
+
+ Vector<WCHAR> buffer;
+ buffer.resize(size / sizeof(WCHAR));
+ result = RegGetValueW(hkey, nullptr, (LPCWSTR)(value.get_data()), RRF_RT_REG_SZ, nullptr, (LPBYTE)buffer.ptrw(), &size);
+ if (result != ERROR_SUCCESS) {
+ RegCloseKey(hkey);
+ return false;
+ }
+
+ r_dotnet_root = String::utf16((const char16_t *)buffer.ptr());
+ RegCloseKey(hkey);
+ return true;
+#else
+ String install_location_file = path::join("/etc/dotnet", "install_location_" + get_dotnet_arch().to_lower());
+ if (get_install_location_from_file(install_location_file, r_dotnet_root)) {
+ return true;
+ }
+
+ if (FileAccess::exists(install_location_file)) {
+ // Don't try with the legacy location, this will fall back to the hard-coded default install location
+ return false;
+ }
+
+ String legacy_install_location_file = path::join("/etc/dotnet", "install_location");
+ return get_install_location_from_file(legacy_install_location_file, r_dotnet_root);
+#endif
+}
+
+bool get_file_path_from_env(const String &p_env_key, String &r_dotnet_root) {
+ String env_value = OS::get_singleton()->get_environment(p_env_key);
+
+ if (!env_value.is_empty()) {
+ env_value = path::realpath(env_value);
+
+ if (DirAccess::exists(env_value)) {
+ r_dotnet_root = env_value;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool get_dotnet_root_from_env(String &r_dotnet_root) {
+ String dotnet_root_env = "DOTNET_ROOT";
+ String arch_for_env = get_dotnet_arch();
+
+ if (!arch_for_env.is_empty()) {
+ // DOTNET_ROOT_<arch>
+ if (get_file_path_from_env(dotnet_root_env + "_" + arch_for_env.to_upper(), r_dotnet_root)) {
+ return true;
+ }
+ }
+
+#ifdef WINDOWS_ENABLED
+ // WoW64-only: DOTNET_ROOT(x86)
+ if (is_wow64() && get_file_path_from_env("DOTNET_ROOT(x86)", r_dotnet_root)) {
+ return true;
+ }
+#endif
+
+ // DOTNET_ROOT
+ return get_file_path_from_env(dotnet_root_env, r_dotnet_root);
+}
+
+} //namespace
+
+bool godotsharp::hostfxr_resolver::try_get_path_from_dotnet_root(const String &p_dotnet_root, String &r_fxr_path) {
+ String fxr_dir = path::join(p_dotnet_root, "host", "fxr");
+ ERR_FAIL_COND_V_MSG(!DirAccess::exists(fxr_dir), false, "The host fxr folder does not exist: " + fxr_dir);
+ return get_latest_fxr(fxr_dir, r_fxr_path);
+}
+
+bool godotsharp::hostfxr_resolver::try_get_path(String &r_dotnet_root, String &r_fxr_path) {
+ if (!get_dotnet_root_from_env(r_dotnet_root) &&
+ !get_dotnet_self_registered_dir(r_dotnet_root) &&
+ !get_default_installation_dir(r_dotnet_root)) {
+ return false;
+ }
+
+ return try_get_path_from_dotnet_root(r_dotnet_root, r_fxr_path);
+}
diff --git a/modules/mono/editor/hostfxr_resolver.h b/modules/mono/editor/hostfxr_resolver.h
new file mode 100644
index 0000000000..0f029ab7ae
--- /dev/null
+++ b/modules/mono/editor/hostfxr_resolver.h
@@ -0,0 +1,45 @@
+/*************************************************************************/
+/* hostfxr_resolver.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef HOSTFXR_RESOLVER_H
+#define HOSTFXR_RESOLVER_H
+
+#include "core/string/ustring.h"
+
+namespace godotsharp {
+namespace hostfxr_resolver {
+
+bool try_get_path_from_dotnet_root(const String &p_dotnet_root, String &r_out_fxr_path);
+bool try_get_path(String &r_out_dotnet_root, String &r_out_fxr_path);
+
+} //namespace hostfxr_resolver
+} //namespace godotsharp
+
+#endif // HOSTFXR_RESOLVER_H
diff --git a/modules/mono/editor/semver.cpp b/modules/mono/editor/semver.cpp
new file mode 100644
index 0000000000..1656d0932f
--- /dev/null
+++ b/modules/mono/editor/semver.cpp
@@ -0,0 +1,149 @@
+/*************************************************************************/
+/* semver.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "semver.h"
+
+bool godotsharp::SemVer::parse_digit_only_field(const String &p_field, uint64_t &r_result) {
+ if (p_field.is_empty()) {
+ return false;
+ }
+
+ int64_t integer = 0;
+
+ for (int i = 0; i < p_field.length(); i++) {
+ char32_t c = p_field[i];
+ if (is_digit(c)) {
+ bool overflow = ((uint64_t)integer > UINT64_MAX / 10) || ((uint64_t)integer == UINT64_MAX / 10 && c > '5');
+ ERR_FAIL_COND_V_MSG(overflow, false, "Cannot represent '" + p_field + "' as a 64-bit unsigned integer, since the value is too large.");
+ integer *= 10;
+ integer += c - '0';
+ } else {
+ return false;
+ }
+ }
+
+ r_result = (uint64_t)integer;
+ return true;
+}
+
+int godotsharp::SemVer::cmp(const godotsharp::SemVer &p_a, const godotsharp::SemVer &p_b) {
+ if (p_a.major != p_b.major) {
+ return p_a.major > p_b.major ? 1 : -1;
+ }
+
+ if (p_a.minor != p_b.minor) {
+ return p_a.minor > p_b.minor ? 1 : -1;
+ }
+
+ if (p_a.patch != p_b.patch) {
+ return p_a.patch > p_b.patch ? 1 : -1;
+ }
+
+ if (p_a.prerelease.is_empty() && p_b.prerelease.is_empty()) {
+ return 0;
+ }
+
+ if (p_a.prerelease.is_empty() || p_b.prerelease.is_empty()) {
+ return p_a.prerelease.is_empty() ? 1 : -1;
+ }
+
+ if (p_a.prerelease != p_b.prerelease) {
+ // This could be optimized, but I'm too lazy
+
+ Vector<String> a_field_set = p_a.prerelease.split(".");
+ Vector<String> b_field_set = p_b.prerelease.split(".");
+
+ int a_field_count = a_field_set.size();
+ int b_field_count = b_field_set.size();
+
+ int min_field_count = MIN(a_field_count, b_field_count);
+
+ for (int i = 0; i < min_field_count; i++) {
+ const String &a_field = a_field_set[i];
+ const String &b_field = b_field_set[i];
+
+ if (a_field == b_field) {
+ continue;
+ }
+
+ uint64_t a_num;
+ bool a_is_digit_only = parse_digit_only_field(a_field, a_num);
+
+ uint64_t b_num;
+ bool b_is_digit_only = parse_digit_only_field(b_field, b_num);
+
+ if (a_is_digit_only && b_is_digit_only) {
+ // Identifiers consisting of only digits are compared numerically.
+
+ if (a_num == b_num) {
+ continue;
+ }
+
+ return a_num > b_num ? 1 : -1;
+ }
+
+ if (a_is_digit_only || b_is_digit_only) {
+ // Numeric identifiers always have lower precedence than non-numeric identifiers.
+ return b_is_digit_only ? 1 : -1;
+ }
+
+ // Identifiers with letters or hyphens are compared lexically in ASCII sort order.
+ return a_field > b_field ? 1 : -1;
+ }
+
+ if (a_field_count != b_field_count) {
+ // A larger set of pre-release fields has a higher precedence than a smaller set, if all of the preceding identifiers are equal.
+ return a_field_count > b_field_count ? 1 : -1;
+ }
+ }
+
+ return 0;
+}
+
+bool godotsharp::SemVerParser::parse(const String &p_ver_text, godotsharp::SemVer &r_semver) {
+ if (!regex.is_valid() && regex.get_pattern().is_empty()) {
+ regex.compile("^(?P<major>0|[1-9]\\d*)\\.(?P<minor>0|[1-9]\\d*)\\.(?P<patch>0|[1-9]\\d*)(?:-(?P<prerelease>(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$");
+ ERR_FAIL_COND_V(!regex.is_valid(), false);
+ }
+
+ Ref<RegExMatch> match = regex.search(p_ver_text);
+
+ if (match.is_valid()) {
+ r_semver = SemVer(
+ match->get_string("major").to_int(),
+ match->get_string("minor").to_int(),
+ match->get_string("patch").to_int(),
+ match->get_string("prerelease"),
+ match->get_string("buildmetadata"));
+ return true;
+ }
+
+ return false;
+}
diff --git a/modules/mono/editor/semver.h b/modules/mono/editor/semver.h
new file mode 100644
index 0000000000..48ea8b043e
--- /dev/null
+++ b/modules/mono/editor/semver.h
@@ -0,0 +1,106 @@
+/*************************************************************************/
+/* semver.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef SEMVER_H
+#define SEMVER_H
+
+#include "core/string/ustring.h"
+#include "modules/regex/regex.h"
+
+// <sys/sysmacros.h> is included somewhere, which defines major(dev) to gnu_dev_major(dev)
+#if defined(major)
+#undef major
+#endif
+#if defined(minor)
+#undef minor
+#endif
+
+namespace godotsharp {
+
+struct SemVer {
+private:
+ static bool parse_digit_only_field(const String &p_field, uint64_t &r_result);
+
+ static int cmp(const SemVer &p_a, const SemVer &p_b);
+
+public:
+ int major = 0;
+ int minor = 0;
+ int patch = 0;
+ String prerelease;
+ String build_metadata;
+
+ bool operator==(const SemVer &b) const {
+ return cmp(*this, b) == 0;
+ }
+
+ bool operator!=(const SemVer &b) const {
+ return !operator==(b);
+ }
+
+ bool operator<(const SemVer &b) const {
+ return cmp(*this, b) < 0;
+ }
+
+ bool operator>(const SemVer &b) const {
+ return cmp(*this, b) > 0;
+ }
+
+ bool operator<=(const SemVer &b) const {
+ return cmp(*this, b) <= 0;
+ }
+
+ bool operator>=(const SemVer &b) const {
+ return cmp(*this, b) >= 0;
+ }
+
+ SemVer() {}
+
+ SemVer(int p_major, int p_minor, int p_patch,
+ const String &p_prerelease, const String &p_build_metadata) :
+ major(p_major),
+ minor(p_minor),
+ patch(p_patch),
+ prerelease(p_prerelease),
+ build_metadata(p_build_metadata) {
+ }
+};
+
+struct SemVerParser {
+private:
+ RegEx regex;
+
+public:
+ bool parse(const String &p_ver_text, SemVer &r_semver);
+};
+
+} //namespace godotsharp
+
+#endif // SEMVER_H
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
index 17f680361d..d8a6644a66 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
@@ -133,15 +133,6 @@ namespace Godot
}
/// <summary>
- /// Returns the area of the <see cref="AABB"/>.
- /// </summary>
- /// <returns>The area.</returns>
- public real_t GetArea()
- {
- return _size.x * _size.y * _size.z;
- }
-
- /// <summary>
/// Gets the position of one of the 8 endpoints of the <see cref="AABB"/>.
/// </summary>
/// <param name="idx">Which endpoint to get.</param>
@@ -321,6 +312,15 @@ namespace Godot
}
/// <summary>
+ /// Returns the volume of the <see cref="AABB"/>.
+ /// </summary>
+ /// <returns>The volume.</returns>
+ public real_t GetVolume()
+ {
+ return _size.x * _size.y * _size.z;
+ }
+
+ /// <summary>
/// Returns a copy of the <see cref="AABB"/> grown a given amount of units towards all the sides.
/// </summary>
/// <param name="by">The amount to grow by.</param>
@@ -340,30 +340,6 @@ namespace Godot
}
/// <summary>
- /// Returns <see langword="true"/> if the <see cref="AABB"/> is flat or empty,
- /// or <see langword="false"/> otherwise.
- /// </summary>
- /// <returns>
- /// A <see langword="bool"/> for whether or not the <see cref="AABB"/> has area.
- /// </returns>
- public bool HasNoArea()
- {
- return _size.x <= 0f || _size.y <= 0f || _size.z <= 0f;
- }
-
- /// <summary>
- /// Returns <see langword="true"/> if the <see cref="AABB"/> has no surface (no size),
- /// or <see langword="false"/> otherwise.
- /// </summary>
- /// <returns>
- /// A <see langword="bool"/> for whether or not the <see cref="AABB"/> has area.
- /// </returns>
- public bool HasNoSurface()
- {
- return _size.x <= 0f && _size.y <= 0f && _size.z <= 0f;
- }
-
- /// <summary>
/// Returns <see langword="true"/> if the <see cref="AABB"/> contains a point,
/// or <see langword="false"/> otherwise.
/// </summary>
@@ -390,6 +366,34 @@ namespace Godot
}
/// <summary>
+ /// Returns <see langword="true"/> if the <see cref="AABB"/>
+ /// has a surface or a length, and <see langword="false"/>
+ /// if the <see cref="AABB"/> is empty (all components
+ /// of <see cref="Size"/> are zero or negative).
+ /// </summary>
+ /// <returns>
+ /// A <see langword="bool"/> for whether or not the <see cref="AABB"/> has surface.
+ /// </returns>
+ public bool HasSurface()
+ {
+ return _size.x > 0.0f || _size.y > 0.0f || _size.z > 0.0f;
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if the <see cref="AABB"/> has
+ /// area, and <see langword="false"/> if the <see cref="AABB"/>
+ /// is linear, empty, or has a negative <see cref="Size"/>.
+ /// See also <see cref="GetVolume"/>.
+ /// </summary>
+ /// <returns>
+ /// A <see langword="bool"/> for whether or not the <see cref="AABB"/> has volume.
+ /// </returns>
+ public bool HasVolume()
+ {
+ return _size.x > 0.0f && _size.y > 0.0f && _size.z > 0.0f;
+ }
+
+ /// <summary>
/// Returns the intersection of this <see cref="AABB"/> and <paramref name="with"/>.
/// </summary>
/// <param name="with">The other <see cref="AABB"/>.</param>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
index 3884781988..092724a6b1 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
@@ -130,7 +130,6 @@ namespace Godot.Bridge
{
// Performance is not critical here as this will be replaced with source generators.
Type scriptType = _scriptTypeBiMap.GetScriptType(scriptPtr);
- var obj = (Object)FormatterServices.GetUninitializedObject(scriptType);
var ctor = scriptType
.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
@@ -151,6 +150,8 @@ namespace Godot.Bridge
}
}
+ var obj = (Object)FormatterServices.GetUninitializedObject(scriptType);
+
var parameters = ctor.GetParameters();
int paramCount = parameters.Length;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
index b30012d214..f2667c6807 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
@@ -634,7 +634,7 @@ namespace Godot
/// <param name="outFrom">The start value for the output interpolation.</param>
/// <param name="outTo">The destination value for the output interpolation.</param>
/// <returns>The resulting mapped value mapped.</returns>
- public static real_t RangeLerp(real_t value, real_t inFrom, real_t inTo, real_t outFrom, real_t outTo)
+ public static real_t Remap(real_t value, real_t inFrom, real_t inTo, real_t outFrom, real_t outTo)
{
return Lerp(outFrom, outTo, InverseLerp(inFrom, inTo, value));
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
index 0b475fec19..e80d75dacf 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
@@ -234,15 +234,17 @@ namespace Godot
}
/// <summary>
- /// Returns <see langword="true"/> if the <see cref="Rect2"/> is flat or empty,
- /// or <see langword="false"/> otherwise.
+ /// Returns <see langword="true"/> if the <see cref="Rect2"/> has
+ /// area, and <see langword="false"/> if the <see cref="Rect2"/>
+ /// is linear, empty, or has a negative <see cref="Size"/>.
+ /// See also <see cref="GetArea"/>.
/// </summary>
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="Rect2"/> has area.
/// </returns>
- public bool HasNoArea()
+ public bool HasArea()
{
- return _size.x <= 0 || _size.y <= 0;
+ return _size.x > 0.0f && _size.y > 0.0f;
}
/// <summary>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs
index 8a2a98d6ee..b2768476cc 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs
@@ -236,15 +236,17 @@ namespace Godot
}
/// <summary>
- /// Returns <see langword="true"/> if the <see cref="Rect2i"/> is flat or empty,
- /// or <see langword="false"/> otherwise.
+ /// Returns <see langword="true"/> if the <see cref="Rect2i"/> has
+ /// area, and <see langword="false"/> if the <see cref="Rect2i"/>
+ /// is linear, empty, or has a negative <see cref="Size"/>.
+ /// See also <see cref="GetArea"/>.
/// </summary>
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="Rect2i"/> has area.
/// </returns>
- public bool HasNoArea()
+ public bool HasArea()
{
- return _size.x <= 0 || _size.y <= 0;
+ return _size.x > 0 && _size.y > 0;
}
/// <summary>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs
index d1962c68cf..e2da41ff47 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs
@@ -187,7 +187,7 @@ namespace Godot
(
Mathf.CubicInterpolate(x, b.x, preA.x, postB.x, weight),
Mathf.CubicInterpolate(y, b.y, preA.y, postB.y, weight),
- Mathf.CubicInterpolate(y, b.z, preA.z, postB.z, weight),
+ Mathf.CubicInterpolate(z, b.z, preA.z, postB.z, weight),
Mathf.CubicInterpolate(w, b.w, preA.w, postB.w, weight)
);
}
@@ -212,7 +212,7 @@ namespace Godot
(
Mathf.CubicInterpolateInTime(x, b.x, preA.x, postB.x, weight, t, preAT, postBT),
Mathf.CubicInterpolateInTime(y, b.y, preA.y, postB.y, weight, t, preAT, postBT),
- Mathf.CubicInterpolateInTime(y, b.z, preA.z, postB.z, weight, t, preAT, postBT),
+ Mathf.CubicInterpolateInTime(z, b.z, preA.z, postB.z, weight, t, preAT, postBT),
Mathf.CubicInterpolateInTime(w, b.w, preA.w, postB.w, weight, t, preAT, postBT)
);
}
@@ -258,7 +258,7 @@ namespace Godot
/// <returns>The dot product of the two vectors.</returns>
public real_t Dot(Vector4 with)
{
- return (x * with.x) + (y * with.y) + (z * with.z) + (w + with.w);
+ return (x * with.x) + (y * with.y) + (z * with.z) + (w * with.w);
}
/// <summary>
@@ -455,6 +455,7 @@ namespace Godot
/// This can also be used to round to an arbitrary number of decimals.
/// </summary>
/// <param name="step">A vector value representing the step size to snap to.</param>
+ /// <returns>The snapped vector.</returns>
public Vector4 Snapped(Vector4 step)
{
return new Vector4(
@@ -632,6 +633,56 @@ namespace Godot
}
/// <summary>
+ /// Gets the remainder of each component of the <see cref="Vector4"/>
+ /// with the components of the given <see cref="real_t"/>.
+ /// This operation uses truncated division, which is often not desired
+ /// as it does not work well with negative numbers.
+ /// Consider using <see cref="PosMod(real_t)"/> instead
+ /// if you want to handle negative numbers.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// GD.Print(new Vector4(10, -20, 30, 40) % 7); // Prints "(3, -6, 2, 5)"
+ /// </code>
+ /// </example>
+ /// <param name="vec">The dividend vector.</param>
+ /// <param name="divisor">The divisor value.</param>
+ /// <returns>The remainder vector.</returns>
+ public static Vector4 operator %(Vector4 vec, real_t divisor)
+ {
+ vec.x %= divisor;
+ vec.y %= divisor;
+ vec.z %= divisor;
+ vec.w %= divisor;
+ return vec;
+ }
+
+ /// <summary>
+ /// Gets the remainder of each component of the <see cref="Vector4"/>
+ /// with the components of the given <see cref="Vector4"/>.
+ /// This operation uses truncated division, which is often not desired
+ /// as it does not work well with negative numbers.
+ /// Consider using <see cref="PosMod(Vector4)"/> instead
+ /// if you want to handle negative numbers.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// GD.Print(new Vector4(10, -20, 30, 10) % new Vector4(7, 8, 9, 10)); // Prints "(3, -4, 3, 0)"
+ /// </code>
+ /// </example>
+ /// <param name="vec">The dividend vector.</param>
+ /// <param name="divisorv">The divisor vector.</param>
+ /// <returns>The remainder vector.</returns>
+ public static Vector4 operator %(Vector4 vec, Vector4 divisorv)
+ {
+ vec.x %= divisorv.x;
+ vec.y %= divisorv.y;
+ vec.z %= divisorv.z;
+ vec.w %= divisorv.w;
+ return vec;
+ }
+
+ /// <summary>
/// Returns <see langword="true"/> if the vectors are exactly equal.
/// Note: Due to floating-point precision errors, consider using
/// <see cref="IsEqualApprox"/> instead, which is more reliable.
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
index aae7a5ebfa..5827d3e591 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
+++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
@@ -36,6 +36,7 @@
</ItemGroup>
<PropertyGroup>
<DefineConstants>$(DefineConstants);GODOT</DefineConstants>
+ <DefineConstants Condition=" '$(GodotFloat64)' == 'true' ">REAL_T_IS_DOUBLE;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ReflectionAnalyzers" Version="0.1.22-dev" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers" />
diff --git a/modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj b/modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj
index ebf09aab7b..5d69ad8ec6 100644
--- a/modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj
+++ b/modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj
@@ -25,6 +25,7 @@
</PropertyGroup>
<PropertyGroup>
<DefineConstants>$(DefineConstants);GODOT</DefineConstants>
+ <DefineConstants Condition=" '$(GodotFloat64)' == 'true' ">REAL_T_IS_DOUBLE;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\GodotSharp\GodotSharp.csproj">
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index e698e92d7a..3b87d9248a 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -43,12 +43,13 @@
#include "../utils/path_utils.h"
#include "gd_mono_cache.h"
+#include "../thirdparty/coreclr_delegates.h"
+#include "../thirdparty/hostfxr.h"
+
#ifdef TOOLS_ENABLED
-#include <nethost.h>
+#include "../editor/hostfxr_resolver.h"
#endif
-#include <coreclr_delegates.h>
-#include <hostfxr.h>
#ifdef UNIX_ENABLED
#include <dlfcn.h>
#endif
@@ -88,85 +89,43 @@ HostFxrCharString str_to_hostfxr(const String &p_str) {
#endif
}
-#ifdef TOOLS_ENABLED
-String str_from_hostfxr(const char_t *p_buffer) {
-#ifdef _WIN32
- return String::utf16((const char16_t *)p_buffer);
-#else
- return String::utf8((const char *)p_buffer);
-#endif
-}
-#endif
-
const char_t *get_data(const HostFxrCharString &p_char_str) {
return (const char_t *)p_char_str.get_data();
}
-#ifdef TOOLS_ENABLED
-String find_hostfxr(size_t p_known_buffer_size, get_hostfxr_parameters *p_get_hostfxr_params) {
- // Pre-allocate a large buffer for the path to hostfxr
- Vector<char_t> buffer;
- buffer.resize(p_known_buffer_size);
-
- int rc = get_hostfxr_path(buffer.ptrw(), &p_known_buffer_size, p_get_hostfxr_params);
-
- ERR_FAIL_COND_V_MSG(rc != 0, String(), "get_hostfxr_path failed with code: " + itos(rc));
-
- return str_from_hostfxr(buffer.ptr());
-}
-#endif
-
String find_hostfxr() {
#ifdef TOOLS_ENABLED
- const int CoreHostLibMissingFailure = 0x80008083;
- const int HostApiBufferTooSmall = 0x80008098;
-
- size_t buffer_size = 0;
- int rc = get_hostfxr_path(nullptr, &buffer_size, nullptr);
-
- if (rc == HostApiBufferTooSmall) {
- return find_hostfxr(buffer_size, nullptr);
+ String dotnet_root;
+ String fxr_path;
+ if (godotsharp::hostfxr_resolver::try_get_path(dotnet_root, fxr_path)) {
+ return fxr_path;
}
- if (rc == CoreHostLibMissingFailure) {
- // Apparently `get_hostfxr_path` doesn't look for dotnet in `PATH`? (I suppose it needs the
- // `DOTNET_ROOT` environment variable). If it fails, we try to find the dotnet executable
- // in `PATH` ourselves and pass its location as `dotnet_root` to `get_hostfxr_path`.
- String dotnet_exe = path::find_executable("dotnet");
-
- if (!dotnet_exe.is_empty()) {
- // The file found in PATH may be a symlink
- dotnet_exe = path::abspath(path::realpath(dotnet_exe));
-
- // TODO:
- // Sometimes, the symlink may not point to the dotnet executable in the dotnet root.
- // That's the case with snaps. The snap install should have been found with the
- // previous `get_hostfxr_path`, but it would still be better to do this properly
- // and use something like `dotnet --list-sdks/runtimes` to find the actual location.
- // This way we could also check if the proper sdk or runtime is installed. This would
- // allow us to fail gracefully and show some helpful information in the editor.
-
- HostFxrCharString dotnet_root = str_to_hostfxr(dotnet_exe.get_base_dir());
-
- get_hostfxr_parameters get_hostfxr_parameters = {
- sizeof(get_hostfxr_parameters),
- nullptr,
- get_data(dotnet_root)
- };
-
- buffer_size = 0;
- rc = get_hostfxr_path(nullptr, &buffer_size, &get_hostfxr_parameters);
- if (rc == HostApiBufferTooSmall) {
- return find_hostfxr(buffer_size, &get_hostfxr_parameters);
- }
+ // hostfxr_resolver doesn't look for dotnet in `PATH`. If it fails, we try to find the dotnet
+ // executable in `PATH` here and pass its location as `dotnet_root` to `get_hostfxr_path`.
+ String dotnet_exe = path::find_executable("dotnet");
+
+ if (!dotnet_exe.is_empty()) {
+ // The file found in PATH may be a symlink
+ dotnet_exe = path::abspath(path::realpath(dotnet_exe));
+
+ // TODO:
+ // Sometimes, the symlink may not point to the dotnet executable in the dotnet root.
+ // That's the case with snaps. The snap install should have been found with the
+ // previous `get_hostfxr_path`, but it would still be better to do this properly
+ // and use something like `dotnet --list-sdks/runtimes` to find the actual location.
+ // This way we could also check if the proper sdk or runtime is installed. This would
+ // allow us to fail gracefully and show some helpful information in the editor.
+
+ dotnet_root = dotnet_exe.get_base_dir();
+ if (godotsharp::hostfxr_resolver::try_get_path_from_dotnet_root(dotnet_root, fxr_path)) {
+ return fxr_path;
}
}
- if (rc == CoreHostLibMissingFailure) {
- ERR_PRINT(String() + ".NET: One of the dependent libraries is missing. " +
- "Typically when the `hostfxr`, `hostpolicy` or `coreclr` dynamic " +
- "libraries are not present in the expected locations.");
- }
+ ERR_PRINT(String() + ".NET: One of the dependent libraries is missing. " +
+ "Typically when the `hostfxr`, `hostpolicy` or `coreclr` dynamic " +
+ "libraries are not present in the expected locations.");
return String();
#else
diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp
index 55d2138674..66c9eca616 100644
--- a/modules/mono/signal_awaiter_utils.cpp
+++ b/modules/mono/signal_awaiter_utils.cpp
@@ -42,7 +42,7 @@ Error gd_mono_connect_signal_awaiter(Object *p_source, const StringName &p_signa
SignalAwaiterCallable *awaiter_callable = memnew(SignalAwaiterCallable(p_target, awaiter_handle, p_signal));
Callable callable = Callable(awaiter_callable);
- return p_source->connect(p_signal, callable, Object::CONNECT_ONESHOT);
+ return p_source->connect(p_signal, callable, Object::CONNECT_ONE_SHOT);
}
bool SignalAwaiterCallable::compare_equal(const CallableCustom *p_a, const CallableCustom *p_b) {
diff --git a/modules/mono/thirdparty/coreclr_delegates.h b/modules/mono/thirdparty/coreclr_delegates.h
new file mode 100644
index 0000000000..914ab592df
--- /dev/null
+++ b/modules/mono/thirdparty/coreclr_delegates.h
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#ifndef __CORECLR_DELEGATES_H__
+#define __CORECLR_DELEGATES_H__
+
+#include <stdint.h>
+
+#if defined(_WIN32)
+ #define CORECLR_DELEGATE_CALLTYPE __stdcall
+ #ifdef _WCHAR_T_DEFINED
+ typedef wchar_t char_t;
+ #else
+ typedef unsigned short char_t;
+ #endif
+#else
+ #define CORECLR_DELEGATE_CALLTYPE
+ typedef char char_t;
+#endif
+
+#define UNMANAGEDCALLERSONLY_METHOD ((const char_t*)-1)
+
+// Signature of delegate returned by coreclr_delegate_type::load_assembly_and_get_function_pointer
+typedef int (CORECLR_DELEGATE_CALLTYPE *load_assembly_and_get_function_pointer_fn)(
+ const char_t *assembly_path /* Fully qualified path to assembly */,
+ const char_t *type_name /* Assembly qualified type name */,
+ const char_t *method_name /* Public static method name compatible with delegateType */,
+ const char_t *delegate_type_name /* Assembly qualified delegate type name or null
+ or UNMANAGEDCALLERSONLY_METHOD if the method is marked with
+ the UnmanagedCallersOnlyAttribute. */,
+ void *reserved /* Extensibility parameter (currently unused and must be 0) */,
+ /*out*/ void **delegate /* Pointer where to store the function pointer result */);
+
+// Signature of delegate returned by load_assembly_and_get_function_pointer_fn when delegate_type_name == null (default)
+typedef int (CORECLR_DELEGATE_CALLTYPE *component_entry_point_fn)(void *arg, int32_t arg_size_in_bytes);
+
+typedef int (CORECLR_DELEGATE_CALLTYPE *get_function_pointer_fn)(
+ const char_t *type_name /* Assembly qualified type name */,
+ const char_t *method_name /* Public static method name compatible with delegateType */,
+ const char_t *delegate_type_name /* Assembly qualified delegate type name or null,
+ or UNMANAGEDCALLERSONLY_METHOD if the method is marked with
+ the UnmanagedCallersOnlyAttribute. */,
+ void *load_context /* Extensibility parameter (currently unused and must be 0) */,
+ void *reserved /* Extensibility parameter (currently unused and must be 0) */,
+ /*out*/ void **delegate /* Pointer where to store the function pointer result */);
+
+#endif // __CORECLR_DELEGATES_H__
diff --git a/modules/mono/thirdparty/hostfxr.h b/modules/mono/thirdparty/hostfxr.h
new file mode 100644
index 0000000000..591a8ebbea
--- /dev/null
+++ b/modules/mono/thirdparty/hostfxr.h
@@ -0,0 +1,323 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#ifndef __HOSTFXR_H__
+#define __HOSTFXR_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+#if defined(_WIN32)
+ #define HOSTFXR_CALLTYPE __cdecl
+ #ifdef _WCHAR_T_DEFINED
+ typedef wchar_t char_t;
+ #else
+ typedef unsigned short char_t;
+ #endif
+#else
+ #define HOSTFXR_CALLTYPE
+ typedef char char_t;
+#endif
+
+enum hostfxr_delegate_type
+{
+ hdt_com_activation,
+ hdt_load_in_memory_assembly,
+ hdt_winrt_activation,
+ hdt_com_register,
+ hdt_com_unregister,
+ hdt_load_assembly_and_get_function_pointer,
+ hdt_get_function_pointer,
+};
+
+typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_main_fn)(const int argc, const char_t **argv);
+typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_main_startupinfo_fn)(
+ const int argc,
+ const char_t **argv,
+ const char_t *host_path,
+ const char_t *dotnet_root,
+ const char_t *app_path);
+typedef int32_t(HOSTFXR_CALLTYPE* hostfxr_main_bundle_startupinfo_fn)(
+ const int argc,
+ const char_t** argv,
+ const char_t* host_path,
+ const char_t* dotnet_root,
+ const char_t* app_path,
+ int64_t bundle_header_offset);
+
+typedef void(HOSTFXR_CALLTYPE *hostfxr_error_writer_fn)(const char_t *message);
+
+//
+// Sets a callback which is to be used to write errors to.
+//
+// Parameters:
+// error_writer
+// A callback function which will be invoked every time an error is to be reported.
+// Or nullptr to unregister previously registered callback and return to the default behavior.
+// Return value:
+// The previously registered callback (which is now unregistered), or nullptr if no previous callback
+// was registered
+//
+// The error writer is registered per-thread, so the registration is thread-local. On each thread
+// only one callback can be registered. Subsequent registrations overwrite the previous ones.
+//
+// By default no callback is registered in which case the errors are written to stderr.
+//
+// Each call to the error writer is sort of like writing a single line (the EOL character is omitted).
+// Multiple calls to the error writer may occur for one failure.
+//
+// If the hostfxr invokes functions in hostpolicy as part of its operation, the error writer
+// will be propagated to hostpolicy for the duration of the call. This means that errors from
+// both hostfxr and hostpolicy will be reporter through the same error writer.
+//
+typedef hostfxr_error_writer_fn(HOSTFXR_CALLTYPE *hostfxr_set_error_writer_fn)(hostfxr_error_writer_fn error_writer);
+
+typedef void* hostfxr_handle;
+struct hostfxr_initialize_parameters
+{
+ size_t size;
+ const char_t *host_path;
+ const char_t *dotnet_root;
+};
+
+//
+// Initializes the hosting components for a dotnet command line running an application
+//
+// Parameters:
+// argc
+// Number of argv arguments
+// argv
+// Command-line arguments for running an application (as if through the dotnet executable).
+// Only command-line arguments which are accepted by runtime installation are supported, SDK/CLI commands are not supported.
+// For example 'app.dll app_argument_1 app_argument_2`.
+// parameters
+// Optional. Additional parameters for initialization
+// host_context_handle
+// On success, this will be populated with an opaque value representing the initialized host context
+//
+// Return value:
+// Success - Hosting components were successfully initialized
+// HostInvalidState - Hosting components are already initialized
+//
+// This function parses the specified command-line arguments to determine the application to run. It will
+// then find the corresponding .runtimeconfig.json and .deps.json with which to resolve frameworks and
+// dependencies and prepare everything needed to load the runtime.
+//
+// This function only supports arguments for running an application. It does not support SDK commands.
+//
+// This function does not load the runtime.
+//
+typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_initialize_for_dotnet_command_line_fn)(
+ int argc,
+ const char_t **argv,
+ const struct hostfxr_initialize_parameters *parameters,
+ /*out*/ hostfxr_handle *host_context_handle);
+
+//
+// Initializes the hosting components using a .runtimeconfig.json file
+//
+// Parameters:
+// runtime_config_path
+// Path to the .runtimeconfig.json file
+// parameters
+// Optional. Additional parameters for initialization
+// host_context_handle
+// On success, this will be populated with an opaque value representing the initialized host context
+//
+// Return value:
+// Success - Hosting components were successfully initialized
+// Success_HostAlreadyInitialized - Config is compatible with already initialized hosting components
+// Success_DifferentRuntimeProperties - Config has runtime properties that differ from already initialized hosting components
+// CoreHostIncompatibleConfig - Config is incompatible with already initialized hosting components
+//
+// This function will process the .runtimeconfig.json to resolve frameworks and prepare everything needed
+// to load the runtime. It will only process the .deps.json from frameworks (not any app/component that
+// may be next to the .runtimeconfig.json).
+//
+// This function does not load the runtime.
+//
+// If called when the runtime has already been loaded, this function will check if the specified runtime
+// config is compatible with the existing runtime.
+//
+// Both Success_HostAlreadyInitialized and Success_DifferentRuntimeProperties codes are considered successful
+// initializations. In the case of Success_DifferentRuntimeProperties, it is left to the consumer to verify that
+// the difference in properties is acceptable.
+//
+typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_initialize_for_runtime_config_fn)(
+ const char_t *runtime_config_path,
+ const struct hostfxr_initialize_parameters *parameters,
+ /*out*/ hostfxr_handle *host_context_handle);
+
+//
+// Gets the runtime property value for an initialized host context
+//
+// Parameters:
+// host_context_handle
+// Handle to the initialized host context
+// name
+// Runtime property name
+// value
+// Out parameter. Pointer to a buffer with the property value.
+//
+// Return value:
+// The error code result.
+//
+// The buffer pointed to by value is owned by the host context. The lifetime of the buffer is only
+// guaranteed until any of the below occur:
+// - a 'run' method is called for the host context
+// - properties are changed via hostfxr_set_runtime_property_value
+// - the host context is closed via 'hostfxr_close'
+//
+// If host_context_handle is nullptr and an active host context exists, this function will get the
+// property value for the active host context.
+//
+typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_get_runtime_property_value_fn)(
+ const hostfxr_handle host_context_handle,
+ const char_t *name,
+ /*out*/ const char_t **value);
+
+//
+// Sets the value of a runtime property for an initialized host context
+//
+// Parameters:
+// host_context_handle
+// Handle to the initialized host context
+// name
+// Runtime property name
+// value
+// Value to set
+//
+// Return value:
+// The error code result.
+//
+// Setting properties is only supported for the first host context, before the runtime has been loaded.
+//
+// If the property already exists in the host context, it will be overwritten. If value is nullptr, the
+// property will be removed.
+//
+typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_set_runtime_property_value_fn)(
+ const hostfxr_handle host_context_handle,
+ const char_t *name,
+ const char_t *value);
+
+//
+// Gets all the runtime properties for an initialized host context
+//
+// Parameters:
+// host_context_handle
+// Handle to the initialized host context
+// count
+// [in] Size of the keys and values buffers
+// [out] Number of properties returned (size of keys/values buffers used). If the input value is too
+// small or keys/values is nullptr, this is populated with the number of available properties
+// keys
+// Array of pointers to buffers with runtime property keys
+// values
+// Array of pointers to buffers with runtime property values
+//
+// Return value:
+// The error code result.
+//
+// The buffers pointed to by keys and values are owned by the host context. The lifetime of the buffers is only
+// guaranteed until any of the below occur:
+// - a 'run' method is called for the host context
+// - properties are changed via hostfxr_set_runtime_property_value
+// - the host context is closed via 'hostfxr_close'
+//
+// If host_context_handle is nullptr and an active host context exists, this function will get the
+// properties for the active host context.
+//
+typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_get_runtime_properties_fn)(
+ const hostfxr_handle host_context_handle,
+ /*inout*/ size_t * count,
+ /*out*/ const char_t **keys,
+ /*out*/ const char_t **values);
+
+//
+// Load CoreCLR and run the application for an initialized host context
+//
+// Parameters:
+// host_context_handle
+// Handle to the initialized host context
+//
+// Return value:
+// If the app was successfully run, the exit code of the application. Otherwise, the error code result.
+//
+// The host_context_handle must have been initialized using hostfxr_initialize_for_dotnet_command_line.
+//
+// This function will not return until the managed application exits.
+//
+typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_run_app_fn)(const hostfxr_handle host_context_handle);
+
+//
+// Gets a typed delegate from the currently loaded CoreCLR or from a newly created one.
+//
+// Parameters:
+// host_context_handle
+// Handle to the initialized host context
+// type
+// Type of runtime delegate requested
+// delegate
+// An out parameter that will be assigned the delegate.
+//
+// Return value:
+// The error code result.
+//
+// If the host_context_handle was initialized using hostfxr_initialize_for_runtime_config,
+// then all delegate types are supported.
+// If the host_context_handle was initialized using hostfxr_initialize_for_dotnet_command_line,
+// then only the following delegate types are currently supported:
+// hdt_load_assembly_and_get_function_pointer
+// hdt_get_function_pointer
+//
+typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_get_runtime_delegate_fn)(
+ const hostfxr_handle host_context_handle,
+ enum hostfxr_delegate_type type,
+ /*out*/ void **delegate);
+
+//
+// Closes an initialized host context
+//
+// Parameters:
+// host_context_handle
+// Handle to the initialized host context
+//
+// Return value:
+// The error code result.
+//
+typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_close_fn)(const hostfxr_handle host_context_handle);
+
+struct hostfxr_dotnet_environment_sdk_info
+{
+ size_t size;
+ const char_t* version;
+ const char_t* path;
+};
+
+typedef void(HOSTFXR_CALLTYPE* hostfxr_get_dotnet_environment_info_result_fn)(
+ const struct hostfxr_dotnet_environment_info* info,
+ void* result_context);
+
+struct hostfxr_dotnet_environment_framework_info
+{
+ size_t size;
+ const char_t* name;
+ const char_t* version;
+ const char_t* path;
+};
+
+struct hostfxr_dotnet_environment_info
+{
+ size_t size;
+
+ const char_t* hostfxr_version;
+ const char_t* hostfxr_commit_hash;
+
+ size_t sdk_count;
+ const struct hostfxr_dotnet_environment_sdk_info* sdks;
+
+ size_t framework_count;
+ const struct hostfxr_dotnet_environment_framework_info* frameworks;
+};
+
+#endif //__HOSTFXR_H__
diff --git a/modules/multiplayer/multiplayer_spawner.cpp b/modules/multiplayer/multiplayer_spawner.cpp
index e8f3aecc69..6f60318b3b 100644
--- a/modules/multiplayer/multiplayer_spawner.cpp
+++ b/modules/multiplayer/multiplayer_spawner.cpp
@@ -230,8 +230,8 @@ void MultiplayerSpawner::_track(Node *p_node, const Variant &p_argument, int p_s
ObjectID oid = p_node->get_instance_id();
if (!tracked_nodes.has(oid)) {
tracked_nodes[oid] = SpawnInfo(p_argument.duplicate(true), p_scene_id);
- p_node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &MultiplayerSpawner::_node_exit).bind(p_node->get_instance_id()), CONNECT_ONESHOT);
- p_node->connect(SceneStringNames::get_singleton()->ready, callable_mp(this, &MultiplayerSpawner::_node_ready).bind(p_node->get_instance_id()), CONNECT_ONESHOT);
+ p_node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &MultiplayerSpawner::_node_exit).bind(p_node->get_instance_id()), CONNECT_ONE_SHOT);
+ p_node->connect(SceneStringNames::get_singleton()->ready, callable_mp(this, &MultiplayerSpawner::_node_ready).bind(p_node->get_instance_id()), CONNECT_ONE_SHOT);
}
}
diff --git a/modules/multiplayer/scene_replication_state.cpp b/modules/multiplayer/scene_replication_state.cpp
index 25442bb7fa..fbcf0acadb 100644
--- a/modules/multiplayer/scene_replication_state.cpp
+++ b/modules/multiplayer/scene_replication_state.cpp
@@ -39,7 +39,7 @@ SceneReplicationState::TrackedNode &SceneReplicationState::_track(const ObjectID
if (!tracked_nodes.has(p_id)) {
tracked_nodes[p_id] = TrackedNode(p_id);
Node *node = Object::cast_to<Node>(ObjectDB::get_instance(p_id));
- node->connect(SceneStringNames::get_singleton()->tree_exited, callable_mp(this, &SceneReplicationState::_untrack).bind(p_id), Node::CONNECT_ONESHOT);
+ node->connect(SceneStringNames::get_singleton()->tree_exited, callable_mp(this, &SceneReplicationState::_untrack).bind(p_id), Node::CONNECT_ONE_SHOT);
}
return tracked_nodes[p_id];
}
diff --git a/modules/navigation/editor/navigation_mesh_editor_plugin.cpp b/modules/navigation/editor/navigation_mesh_editor_plugin.cpp
index 5cdff7b52a..32abc52017 100644
--- a/modules/navigation/editor/navigation_mesh_editor_plugin.cpp
+++ b/modules/navigation/editor/navigation_mesh_editor_plugin.cpp
@@ -145,7 +145,7 @@ void NavigationMeshEditorPlugin::make_visible(bool p_visible) {
NavigationMeshEditorPlugin::NavigationMeshEditorPlugin() {
navigation_mesh_editor = memnew(NavigationMeshEditor);
- EditorNode::get_singleton()->get_main_control()->add_child(navigation_mesh_editor);
+ EditorNode::get_singleton()->get_main_screen_control()->add_child(navigation_mesh_editor);
add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, navigation_mesh_editor->bake_hbox);
navigation_mesh_editor->hide();
navigation_mesh_editor->bake_hbox->hide();
diff --git a/modules/navigation/navigation_mesh_generator.cpp b/modules/navigation/navigation_mesh_generator.cpp
index 848e554fb0..cfb8e0cd42 100644
--- a/modules/navigation/navigation_mesh_generator.cpp
+++ b/modules/navigation/navigation_mesh_generator.cpp
@@ -572,12 +572,8 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(
cfg.bmax[2] = bmax[2];
AABB baking_aabb = p_nav_mesh->get_filter_baking_aabb();
-
- bool aabb_has_no_volume = baking_aabb.has_no_volume();
-
- if (!aabb_has_no_volume) {
+ if (baking_aabb.has_volume()) {
Vector3 baking_aabb_offset = p_nav_mesh->get_filter_baking_aabb_offset();
-
cfg.bmin[0] = baking_aabb.position[0] + baking_aabb_offset.x;
cfg.bmin[1] = baking_aabb.position[1] + baking_aabb_offset.y;
cfg.bmin[2] = baking_aabb.position[2] + baking_aabb_offset.z;
diff --git a/modules/openxr/editor/openxr_action_map_editor.cpp b/modules/openxr/editor/openxr_action_map_editor.cpp
index fcbe4d57f6..51c402d746 100644
--- a/modules/openxr/editor/openxr_action_map_editor.cpp
+++ b/modules/openxr/editor/openxr_action_map_editor.cpp
@@ -57,7 +57,7 @@ void OpenXRActionMapEditor::_notification(int p_what) {
for (int i = 0; i < tabs->get_child_count(); i++) {
Control *tab = static_cast<Control *>(tabs->get_child(i));
if (tab) {
- tab->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ tab->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree")));
}
}
} break;
@@ -113,7 +113,7 @@ OpenXRInteractionProfileEditorBase *OpenXRActionMapEditor::_add_interaction_prof
// now add it in..
ERR_FAIL_NULL_V(new_profile_editor, nullptr);
tabs->add_child(new_profile_editor);
- new_profile_editor->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ new_profile_editor->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree")));
tabs->set_tab_button_icon(tabs->get_tab_count() - 1, get_theme_icon(SNAME("close"), SNAME("TabBar")));
interaction_profiles.push_back(new_profile_editor);
diff --git a/modules/openxr/editor/openxr_select_action_dialog.cpp b/modules/openxr/editor/openxr_select_action_dialog.cpp
index 80e58044d5..5f018291d5 100644
--- a/modules/openxr/editor/openxr_select_action_dialog.cpp
+++ b/modules/openxr/editor/openxr_select_action_dialog.cpp
@@ -39,7 +39,7 @@ void OpenXRSelectActionDialog::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ scroll->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree")));
} break;
}
}
diff --git a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp
index 23b025db08..e92519aec2 100644
--- a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp
+++ b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp
@@ -38,7 +38,7 @@ void OpenXRSelectInteractionProfileDialog::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ scroll->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree")));
} break;
}
}
diff --git a/modules/websocket/doc_classes/WebSocketClient.xml b/modules/websocket/doc_classes/WebSocketClient.xml
index 7d73194ea9..1978d2e7c6 100644
--- a/modules/websocket/doc_classes/WebSocketClient.xml
+++ b/modules/websocket/doc_classes/WebSocketClient.xml
@@ -24,8 +24,8 @@
If [code]true[/code] is passed as [code]gd_mp_api[/code], the client will behave like a multiplayer peer for the [MultiplayerAPI], connections to non-Godot servers will not work, and [signal data_received] will not be emitted.
If [code]false[/code] is passed instead (default), you must call [PacketPeer] functions ([code]put_packet[/code], [code]get_packet[/code], etc.) on the [WebSocketPeer] returned via [code]get_peer(1)[/code] and not on this object directly (e.g. [code]get_peer(1).put_packet(data)[/code]).
You can optionally pass a list of [code]custom_headers[/code] to be added to the handshake HTTP request.
- [b]Note:[/b] To avoid mixed content warnings or errors in Web, you may have to use a [code]url[/code] that starts with [code]wss://[/code] (secure) instead of [code]ws://[/code]. When doing so, make sure to use the fully qualified domain name that matches the one defined in the server's SSL certificate. Do not connect directly via the IP address for [code]wss://[/code] connections, as it won't match with the SSL certificate.
- [b]Note:[/b] Specifying [code]custom_headers[/code] is not supported in Web exports due to browsers restrictions.
+ [b]Note:[/b] To avoid mixed content warnings or errors in Web, you may have to use a [code]url[/code] that starts with [code]wss://[/code] (secure) instead of [code]ws://[/code]. When doing so, make sure to use the fully qualified domain name that matches the one defined in the server's TLS certificate. Do not connect directly via the IP address for [code]wss://[/code] connections, as it won't match with the TLS certificate.
+ [b]Note:[/b] Specifying [code]custom_headers[/code] is not supported in Web exports due to browsers' restrictions.
</description>
</method>
<method name="disconnect_from_host">
@@ -50,12 +50,12 @@
</method>
</methods>
<members>
- <member name="trusted_ssl_certificate" type="X509Certificate" setter="set_trusted_ssl_certificate" getter="get_trusted_ssl_certificate">
- If specified, this [X509Certificate] will be the only one accepted when connecting to an SSL host. Any other certificate provided by the server will be regarded as invalid.
- [b]Note:[/b] Specifying a custom [code]trusted_ssl_certificate[/code] is not supported in Web exports due to browsers restrictions.
+ <member name="trusted_tls_certificate" type="X509Certificate" setter="set_trusted_tls_certificate" getter="get_trusted_tls_certificate">
+ If specified, this [X509Certificate] will be the only one accepted when connecting to an TLS host. Any other certificate provided by the server will be regarded as invalid.
+ [b]Note:[/b] Specifying a custom [code]trusted_tls_certificate[/code] is not supported in Web exports due to browsers' restrictions.
</member>
- <member name="verify_ssl" type="bool" setter="set_verify_ssl_enabled" getter="is_verify_ssl_enabled">
- If [code]true[/code], SSL certificate verification is enabled.
+ <member name="verify_tls" type="bool" setter="set_verify_tls_enabled" getter="is_verify_tls_enabled">
+ If [code]true[/code], TLS certificate verification is enabled.
[b]Note:[/b] You must specify the certificates to be used in the Project Settings for it to work when exported.
</member>
</members>
diff --git a/modules/websocket/doc_classes/WebSocketServer.xml b/modules/websocket/doc_classes/WebSocketServer.xml
index 19c36700e6..07a55b73f1 100644
--- a/modules/websocket/doc_classes/WebSocketServer.xml
+++ b/modules/websocket/doc_classes/WebSocketServer.xml
@@ -79,16 +79,16 @@
When not set to [code]*[/code] will restrict incoming connections to the specified IP address. Setting [code]bind_ip[/code] to [code]127.0.0.1[/code] will cause the server to listen only to the local host.
</member>
<member name="ca_chain" type="X509Certificate" setter="set_ca_chain" getter="get_ca_chain">
- When using SSL (see [member private_key] and [member ssl_certificate]), you can set this to a valid [X509Certificate] to be provided as additional CA chain information during the SSL handshake.
+ When using TLS (see [member private_key] and [member tls_certificate]), you can set this to a valid [X509Certificate] to be provided as additional CA chain information during the TLS handshake.
</member>
<member name="handshake_timeout" type="float" setter="set_handshake_timeout" getter="get_handshake_timeout" default="3.0">
The time in seconds before a pending client (i.e. a client that has not yet finished the HTTP handshake) is considered stale and forcefully disconnected.
</member>
<member name="private_key" type="CryptoKey" setter="set_private_key" getter="get_private_key">
- When set to a valid [CryptoKey] (along with [member ssl_certificate]) will cause the server to require SSL instead of regular TCP (i.e. the [code]wss://[/code] protocol).
+ When set to a valid [CryptoKey] (along with [member tls_certificate]) will cause the server to require TLS instead of regular TCP (i.e. the [code]wss://[/code] protocol).
</member>
- <member name="ssl_certificate" type="X509Certificate" setter="set_ssl_certificate" getter="get_ssl_certificate">
- When set to a valid [X509Certificate] (along with [member private_key]) will cause the server to require SSL instead of regular TCP (i.e. the [code]wss://[/code] protocol).
+ <member name="tls_certificate" type="X509Certificate" setter="set_tls_certificate" getter="get_tls_certificate">
+ When set to a valid [X509Certificate] (along with [member private_key]) will cause the server to require TLS instead of regular TCP (i.e. the [code]wss://[/code] protocol).
</member>
</members>
<signals>
diff --git a/modules/websocket/emws_client.cpp b/modules/websocket/emws_client.cpp
index 65e0703c00..933a1f43e9 100644
--- a/modules/websocket/emws_client.cpp
+++ b/modules/websocket/emws_client.cpp
@@ -65,7 +65,7 @@ void EMWSClient::_esws_on_close(void *obj, int code, const char *reason, int was
client->_on_disconnect(was_clean != 0);
}
-Error EMWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const Vector<String> p_protocols, const Vector<String> p_custom_headers) {
+Error EMWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_tls, const Vector<String> p_protocols, const Vector<String> p_custom_headers) {
if (_js_id) {
godot_js_websocket_destroy(_js_id);
_js_id = 0;
@@ -84,9 +84,9 @@ Error EMWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port,
if (p_custom_headers.size()) {
WARN_PRINT_ONCE("Custom headers are not supported in Web platform.");
}
- if (p_ssl) {
+ if (p_tls) {
str = "wss://";
- if (ssl_cert.is_valid()) {
+ if (tls_cert.is_valid()) {
WARN_PRINT_ONCE("Custom SSL certificate is not supported in Web platform.");
}
}
diff --git a/modules/websocket/emws_client.h b/modules/websocket/emws_client.h
index ff63a76753..cdcec31e19 100644
--- a/modules/websocket/emws_client.h
+++ b/modules/websocket/emws_client.h
@@ -54,7 +54,7 @@ private:
public:
Error set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets) override;
- Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const Vector<String> p_protocol = Vector<String>(), const Vector<String> p_custom_headers = Vector<String>()) override;
+ Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_tls, const Vector<String> p_protocol = Vector<String>(), const Vector<String> p_custom_headers = Vector<String>()) override;
Ref<WebSocketPeer> get_peer(int p_peer_id) const override;
void disconnect_from_host(int p_code = 1000, String p_reason = "") override;
IPAddress get_connected_host() const override;
diff --git a/modules/websocket/websocket_client.cpp b/modules/websocket/websocket_client.cpp
index 2734b4b88f..0b2d5d1918 100644
--- a/modules/websocket/websocket_client.cpp
+++ b/modules/websocket/websocket_client.cpp
@@ -48,34 +48,34 @@ Error WebSocketClient::connect_to_url(String p_url, const Vector<String> p_proto
Error err = p_url.parse_url(scheme, host, port, path);
ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid URL: " + p_url);
- bool ssl = false;
+ bool tls = false;
if (scheme == "wss://") {
- ssl = true;
+ tls = true;
}
if (port == 0) {
- port = ssl ? 443 : 80;
+ port = tls ? 443 : 80;
}
if (path.is_empty()) {
path = "/";
}
- return connect_to_host(host, path, port, ssl, p_protocols, p_custom_headers);
+ return connect_to_host(host, path, port, tls, p_protocols, p_custom_headers);
}
-void WebSocketClient::set_verify_ssl_enabled(bool p_verify_ssl) {
- verify_ssl = p_verify_ssl;
+void WebSocketClient::set_verify_tls_enabled(bool p_verify_tls) {
+ verify_tls = p_verify_tls;
}
-bool WebSocketClient::is_verify_ssl_enabled() const {
- return verify_ssl;
+bool WebSocketClient::is_verify_tls_enabled() const {
+ return verify_tls;
}
-Ref<X509Certificate> WebSocketClient::get_trusted_ssl_certificate() const {
- return ssl_cert;
+Ref<X509Certificate> WebSocketClient::get_trusted_tls_certificate() const {
+ return tls_cert;
}
-void WebSocketClient::set_trusted_ssl_certificate(Ref<X509Certificate> p_cert) {
+void WebSocketClient::set_trusted_tls_certificate(Ref<X509Certificate> p_cert) {
ERR_FAIL_COND(get_connection_status() != CONNECTION_DISCONNECTED);
- ssl_cert = p_cert;
+ tls_cert = p_cert;
}
bool WebSocketClient::is_server() const {
@@ -123,15 +123,15 @@ void WebSocketClient::_bind_methods() {
ClassDB::bind_method(D_METHOD("disconnect_from_host", "code", "reason"), &WebSocketClient::disconnect_from_host, DEFVAL(1000), DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_connected_host"), &WebSocketClient::get_connected_host);
ClassDB::bind_method(D_METHOD("get_connected_port"), &WebSocketClient::get_connected_port);
- ClassDB::bind_method(D_METHOD("set_verify_ssl_enabled", "enabled"), &WebSocketClient::set_verify_ssl_enabled);
- ClassDB::bind_method(D_METHOD("is_verify_ssl_enabled"), &WebSocketClient::is_verify_ssl_enabled);
+ ClassDB::bind_method(D_METHOD("set_verify_tls_enabled", "enabled"), &WebSocketClient::set_verify_tls_enabled);
+ ClassDB::bind_method(D_METHOD("is_verify_tls_enabled"), &WebSocketClient::is_verify_tls_enabled);
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "verify_ssl", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_verify_ssl_enabled", "is_verify_ssl_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "verify_tls", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_verify_tls_enabled", "is_verify_tls_enabled");
- ClassDB::bind_method(D_METHOD("get_trusted_ssl_certificate"), &WebSocketClient::get_trusted_ssl_certificate);
- ClassDB::bind_method(D_METHOD("set_trusted_ssl_certificate", "cert"), &WebSocketClient::set_trusted_ssl_certificate);
+ ClassDB::bind_method(D_METHOD("get_trusted_tls_certificate"), &WebSocketClient::get_trusted_tls_certificate);
+ ClassDB::bind_method(D_METHOD("set_trusted_tls_certificate", "cert"), &WebSocketClient::set_trusted_tls_certificate);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trusted_ssl_certificate", PROPERTY_HINT_RESOURCE_TYPE, "X509Certificate", PROPERTY_USAGE_NONE), "set_trusted_ssl_certificate", "get_trusted_ssl_certificate");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trusted_tls_certificate", PROPERTY_HINT_RESOURCE_TYPE, "X509Certificate", PROPERTY_USAGE_NONE), "set_trusted_tls_certificate", "get_trusted_tls_certificate");
ADD_SIGNAL(MethodInfo("data_received"));
ADD_SIGNAL(MethodInfo("connection_established", PropertyInfo(Variant::STRING, "protocol")));
diff --git a/modules/websocket/websocket_client.h b/modules/websocket/websocket_client.h
index d6c072ae16..e747aee4e4 100644
--- a/modules/websocket/websocket_client.h
+++ b/modules/websocket/websocket_client.h
@@ -42,20 +42,20 @@ class WebSocketClient : public WebSocketMultiplayerPeer {
protected:
Ref<WebSocketPeer> _peer;
- bool verify_ssl = true;
- Ref<X509Certificate> ssl_cert;
+ bool verify_tls = true;
+ Ref<X509Certificate> tls_cert;
static void _bind_methods();
public:
Error connect_to_url(String p_url, const Vector<String> p_protocols = Vector<String>(), bool gd_mp_api = false, const Vector<String> p_custom_headers = Vector<String>());
- void set_verify_ssl_enabled(bool p_verify_ssl);
- bool is_verify_ssl_enabled() const;
- Ref<X509Certificate> get_trusted_ssl_certificate() const;
- void set_trusted_ssl_certificate(Ref<X509Certificate> p_cert);
+ void set_verify_tls_enabled(bool p_verify_tls);
+ bool is_verify_tls_enabled() const;
+ Ref<X509Certificate> get_trusted_tls_certificate() const;
+ void set_trusted_tls_certificate(Ref<X509Certificate> p_cert);
- virtual Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const Vector<String> p_protocol = Vector<String>(), const Vector<String> p_custom_headers = Vector<String>()) = 0;
+ virtual Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_tls, const Vector<String> p_protocol = Vector<String>(), const Vector<String> p_custom_headers = Vector<String>()) = 0;
virtual void disconnect_from_host(int p_code = 1000, String p_reason = "") = 0;
virtual IPAddress get_connected_host() const = 0;
virtual uint16_t get_connected_port() const = 0;
diff --git a/modules/websocket/websocket_server.cpp b/modules/websocket/websocket_server.cpp
index b7851b02c4..25a6e420fc 100644
--- a/modules/websocket/websocket_server.cpp
+++ b/modules/websocket/websocket_server.cpp
@@ -58,9 +58,9 @@ void WebSocketServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_private_key", "key"), &WebSocketServer::set_private_key);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "private_key", PROPERTY_HINT_RESOURCE_TYPE, "CryptoKey", PROPERTY_USAGE_NONE), "set_private_key", "get_private_key");
- ClassDB::bind_method(D_METHOD("get_ssl_certificate"), &WebSocketServer::get_ssl_certificate);
- ClassDB::bind_method(D_METHOD("set_ssl_certificate", "cert"), &WebSocketServer::set_ssl_certificate);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "ssl_certificate", PROPERTY_HINT_RESOURCE_TYPE, "X509Certificate", PROPERTY_USAGE_NONE), "set_ssl_certificate", "get_ssl_certificate");
+ ClassDB::bind_method(D_METHOD("get_tls_certificate"), &WebSocketServer::get_tls_certificate);
+ ClassDB::bind_method(D_METHOD("set_tls_certificate", "cert"), &WebSocketServer::set_tls_certificate);
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "tls_certificate", PROPERTY_HINT_RESOURCE_TYPE, "X509Certificate", PROPERTY_USAGE_NONE), "set_tls_certificate", "get_tls_certificate");
ClassDB::bind_method(D_METHOD("get_ca_chain"), &WebSocketServer::get_ca_chain);
ClassDB::bind_method(D_METHOD("set_ca_chain", "ca_chain"), &WebSocketServer::set_ca_chain);
@@ -95,13 +95,13 @@ void WebSocketServer::set_private_key(Ref<CryptoKey> p_key) {
private_key = p_key;
}
-Ref<X509Certificate> WebSocketServer::get_ssl_certificate() const {
- return ssl_cert;
+Ref<X509Certificate> WebSocketServer::get_tls_certificate() const {
+ return tls_cert;
}
-void WebSocketServer::set_ssl_certificate(Ref<X509Certificate> p_cert) {
+void WebSocketServer::set_tls_certificate(Ref<X509Certificate> p_cert) {
ERR_FAIL_COND(is_listening());
- ssl_cert = p_cert;
+ tls_cert = p_cert;
}
Ref<X509Certificate> WebSocketServer::get_ca_chain() const {
diff --git a/modules/websocket/websocket_server.h b/modules/websocket/websocket_server.h
index ac04c4e57e..de23ee884d 100644
--- a/modules/websocket/websocket_server.h
+++ b/modules/websocket/websocket_server.h
@@ -46,7 +46,7 @@ protected:
static void _bind_methods();
Ref<CryptoKey> private_key;
- Ref<X509Certificate> ssl_cert;
+ Ref<X509Certificate> tls_cert;
Ref<X509Certificate> ca_chain;
uint32_t handshake_timeout = 3000;
@@ -74,8 +74,8 @@ public:
Ref<CryptoKey> get_private_key() const;
void set_private_key(Ref<CryptoKey> p_key);
- Ref<X509Certificate> get_ssl_certificate() const;
- void set_ssl_certificate(Ref<X509Certificate> p_cert);
+ Ref<X509Certificate> get_tls_certificate() const;
+ void set_tls_certificate(Ref<X509Certificate> p_cert);
Ref<X509Certificate> get_ca_chain() const;
void set_ca_chain(Ref<X509Certificate> p_ca_chain);
diff --git a/modules/websocket/wsl_client.cpp b/modules/websocket/wsl_client.cpp
index 2bb57226ea..50ef53e267 100644
--- a/modules/websocket/wsl_client.cpp
+++ b/modules/websocket/wsl_client.cpp
@@ -161,7 +161,7 @@ bool WSLClient::_verify_headers(String &r_protocol) {
return true;
}
-Error WSLClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const Vector<String> p_protocols, const Vector<String> p_custom_headers) {
+Error WSLClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_tls, const Vector<String> p_protocols, const Vector<String> p_custom_headers) {
ERR_FAIL_COND_V(_connection.is_valid(), ERR_ALREADY_IN_USE);
ERR_FAIL_COND_V(p_path.is_empty(), ERR_INVALID_PARAMETER);
@@ -196,7 +196,7 @@ Error WSLClient::connect_to_host(String p_host, String p_path, uint16_t p_port,
return err;
}
_connection = _tcp;
- _use_ssl = p_ssl;
+ _use_tls = p_tls;
_host = p_host;
_port = p_port;
// Strip edges from protocols.
@@ -209,7 +209,7 @@ Error WSLClient::connect_to_host(String p_host, String p_path, uint16_t p_port,
_key = WSLPeer::generate_key();
String request = "GET " + p_path + " HTTP/1.1\r\n";
String port = "";
- if ((p_port != 80 && !p_ssl) || (p_port != 443 && p_ssl)) {
+ if ((p_port != 80 && !p_tls) || (p_port != 443 && p_tls)) {
port = ":" + itos(p_port);
}
request += "Host: " + p_host + port + "\r\n";
@@ -288,27 +288,27 @@ void WSLClient::poll() {
break;
case StreamPeerTCP::STATUS_CONNECTED: {
_ip_candidates.clear();
- Ref<StreamPeerSSL> ssl;
- if (_use_ssl) {
+ Ref<StreamPeerTLS> tls;
+ if (_use_tls) {
if (_connection == _tcp) {
// Start SSL handshake
- ssl = Ref<StreamPeerSSL>(StreamPeerSSL::create());
- ERR_FAIL_COND_MSG(ssl.is_null(), "SSL is not available in this build.");
- ssl->set_blocking_handshake_enabled(false);
- if (ssl->connect_to_stream(_tcp, verify_ssl, _host, ssl_cert) != OK) {
+ tls = Ref<StreamPeerTLS>(StreamPeerTLS::create());
+ ERR_FAIL_COND_MSG(tls.is_null(), "SSL is not available in this build.");
+ tls->set_blocking_handshake_enabled(false);
+ if (tls->connect_to_stream(_tcp, verify_tls, _host, tls_cert) != OK) {
disconnect_from_host();
_on_error();
return;
}
- _connection = ssl;
+ _connection = tls;
} else {
- ssl = static_cast<Ref<StreamPeerSSL>>(_connection);
- ERR_FAIL_COND(ssl.is_null()); // Bug?
- ssl->poll();
+ tls = static_cast<Ref<StreamPeerTLS>>(_connection);
+ ERR_FAIL_COND(tls.is_null()); // Bug?
+ tls->poll();
}
- if (ssl->get_status() == StreamPeerSSL::STATUS_HANDSHAKING) {
+ if (tls->get_status() == StreamPeerTLS::STATUS_HANDSHAKING) {
return; // Need more polling.
- } else if (ssl->get_status() != StreamPeerSSL::STATUS_CONNECTED) {
+ } else if (tls->get_status() != StreamPeerTLS::STATUS_CONNECTED) {
disconnect_from_host();
_on_error();
return; // Error.
@@ -356,7 +356,7 @@ void WSLClient::disconnect_from_host(int p_code, String p_reason) {
_key = "";
_host = "";
_protocols.clear();
- _use_ssl = false;
+ _use_tls = false;
_request = "";
_requested = 0;
diff --git a/modules/websocket/wsl_client.h b/modules/websocket/wsl_client.h
index 5d90bc4034..dfb989fdd3 100644
--- a/modules/websocket/wsl_client.h
+++ b/modules/websocket/wsl_client.h
@@ -34,8 +34,8 @@
#ifndef WEB_ENABLED
#include "core/error/error_list.h"
-#include "core/io/stream_peer_ssl.h"
#include "core/io/stream_peer_tcp.h"
+#include "core/io/stream_peer_tls.h"
#include "websocket_client.h"
#include "wsl_peer.h"
#include "wslay/wslay.h"
@@ -65,7 +65,7 @@ private:
uint16_t _port = 0;
Array _ip_candidates;
Vector<String> _protocols;
- bool _use_ssl = false;
+ bool _use_tls = false;
IP::ResolverID _resolver_id = IP::RESOLVER_INVALID_ID;
void _do_handshake();
@@ -73,7 +73,7 @@ private:
public:
Error set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets) override;
- Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const Vector<String> p_protocol = Vector<String>(), const Vector<String> p_custom_headers = Vector<String>()) override;
+ Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_tls, const Vector<String> p_protocol = Vector<String>(), const Vector<String> p_custom_headers = Vector<String>()) override;
int get_max_packet_size() const override;
Ref<WebSocketPeer> get_peer(int p_peer_id) const override;
void disconnect_from_host(int p_code = 1000, String p_reason = "") override;
diff --git a/modules/websocket/wsl_server.cpp b/modules/websocket/wsl_server.cpp
index 7457ac7087..01dcd53839 100644
--- a/modules/websocket/wsl_server.cpp
+++ b/modules/websocket/wsl_server.cpp
@@ -102,16 +102,16 @@ Error WSLServer::PendingPeer::do_handshake(const Vector<String> p_protocols, uin
return ERR_TIMEOUT;
}
- if (use_ssl) {
- Ref<StreamPeerSSL> ssl = static_cast<Ref<StreamPeerSSL>>(connection);
- if (ssl.is_null()) {
- ERR_FAIL_V_MSG(ERR_BUG, "Couldn't get StreamPeerSSL for WebSocket handshake.");
+ if (use_tls) {
+ Ref<StreamPeerTLS> tls = static_cast<Ref<StreamPeerTLS>>(connection);
+ if (tls.is_null()) {
+ ERR_FAIL_V_MSG(ERR_BUG, "Couldn't get StreamPeerTLS for WebSocket handshake.");
}
- ssl->poll();
- if (ssl->get_status() == StreamPeerSSL::STATUS_HANDSHAKING) {
+ tls->poll();
+ if (tls->get_status() == StreamPeerTLS::STATUS_HANDSHAKING) {
return ERR_BUSY;
- } else if (ssl->get_status() != StreamPeerSSL::STATUS_CONNECTED) {
- print_verbose(vformat("WebSocket SSL connection error during handshake (StreamPeerSSL status code %d).", ssl->get_status()));
+ } else if (tls->get_status() != StreamPeerTLS::STATUS_CONNECTED) {
+ print_verbose(vformat("WebSocket SSL connection error during handshake (StreamPeerTLS status code %d).", tls->get_status()));
return FAILED;
}
}
@@ -247,12 +247,12 @@ void WSLServer::poll() {
}
Ref<PendingPeer> peer = memnew(PendingPeer);
- if (private_key.is_valid() && ssl_cert.is_valid()) {
- Ref<StreamPeerSSL> ssl = Ref<StreamPeerSSL>(StreamPeerSSL::create());
- ssl->set_blocking_handshake_enabled(false);
- ssl->accept_stream(conn, private_key, ssl_cert, ca_chain);
- peer->connection = ssl;
- peer->use_ssl = true;
+ if (private_key.is_valid() && tls_cert.is_valid()) {
+ Ref<StreamPeerTLS> tls = Ref<StreamPeerTLS>(StreamPeerTLS::create());
+ tls->set_blocking_handshake_enabled(false);
+ tls->accept_stream(conn, private_key, tls_cert, ca_chain);
+ peer->connection = tls;
+ peer->use_tls = true;
} else {
peer->connection = conn;
}
diff --git a/modules/websocket/wsl_server.h b/modules/websocket/wsl_server.h
index b0b7a6a5c9..df0c1dc68a 100644
--- a/modules/websocket/wsl_server.h
+++ b/modules/websocket/wsl_server.h
@@ -36,8 +36,8 @@
#include "websocket_server.h"
#include "wsl_peer.h"
-#include "core/io/stream_peer_ssl.h"
#include "core/io/stream_peer_tcp.h"
+#include "core/io/stream_peer_tls.h"
#include "core/io/tcp_server.h"
class WSLServer : public WebSocketServer {
@@ -51,7 +51,7 @@ private:
public:
Ref<StreamPeerTCP> tcp;
Ref<StreamPeer> connection;
- bool use_ssl = false;
+ bool use_tls = false;
uint64_t time = 0;
uint8_t req_buf[WSL_MAX_HEADER_SIZE] = {};