feat: modules moved and engine moved to submodule
This commit is contained in:
parent
dfb5e645cd
commit
c33d2130cc
5136 changed files with 225275 additions and 64485 deletions
|
|
@ -35,6 +35,7 @@
|
|||
#include "editor/gui/editor_run_bar.h"
|
||||
#include "editor/themes/editor_scale.h"
|
||||
#include "scene/gui/check_box.h"
|
||||
#include "scene/gui/flow_container.h"
|
||||
|
||||
void EditorNetworkProfiler::_bind_methods() {
|
||||
ADD_SIGNAL(MethodInfo("enable_profiling", PropertyInfo(Variant::BOOL, "enable")));
|
||||
|
|
@ -297,30 +298,37 @@ bool EditorNetworkProfiler::is_profiling() {
|
|||
}
|
||||
|
||||
EditorNetworkProfiler::EditorNetworkProfiler() {
|
||||
HBoxContainer *hb = memnew(HBoxContainer);
|
||||
hb->add_theme_constant_override("separation", 8 * EDSCALE);
|
||||
add_child(hb);
|
||||
FlowContainer *container = memnew(FlowContainer);
|
||||
container->add_theme_constant_override(SNAME("h_separation"), 8 * EDSCALE);
|
||||
container->add_theme_constant_override(SNAME("v_separation"), 2 * EDSCALE);
|
||||
add_child(container);
|
||||
|
||||
activate = memnew(Button);
|
||||
activate->set_toggle_mode(true);
|
||||
activate->set_text(TTR("Start"));
|
||||
activate->set_disabled(true);
|
||||
activate->connect(SceneStringName(pressed), callable_mp(this, &EditorNetworkProfiler::_activate_pressed));
|
||||
hb->add_child(activate);
|
||||
container->add_child(activate);
|
||||
|
||||
clear_button = memnew(Button);
|
||||
clear_button->set_text(TTR("Clear"));
|
||||
clear_button->set_disabled(true);
|
||||
clear_button->connect(SceneStringName(pressed), callable_mp(this, &EditorNetworkProfiler::_clear_pressed));
|
||||
hb->add_child(clear_button);
|
||||
container->add_child(clear_button);
|
||||
|
||||
CheckBox *autostart_checkbox = memnew(CheckBox);
|
||||
autostart_checkbox->set_text(TTR("Autostart"));
|
||||
autostart_checkbox->set_pressed(EditorSettings::get_singleton()->get_project_metadata("debug_options", "autostart_network_profiler", false));
|
||||
autostart_checkbox->connect(SceneStringName(toggled), callable_mp(this, &EditorNetworkProfiler::_autostart_toggled));
|
||||
hb->add_child(autostart_checkbox);
|
||||
container->add_child(autostart_checkbox);
|
||||
|
||||
hb->add_spacer();
|
||||
Control *c = memnew(Control);
|
||||
c->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
container->add_child(c);
|
||||
|
||||
HBoxContainer *hb = memnew(HBoxContainer);
|
||||
hb->add_theme_constant_override(SNAME("separation"), 8 * EDSCALE);
|
||||
container->add_child(hb);
|
||||
|
||||
Label *lb = memnew(Label);
|
||||
// TRANSLATORS: This is the label for the network profiler's incoming bandwidth.
|
||||
|
|
@ -331,6 +339,7 @@ EditorNetworkProfiler::EditorNetworkProfiler() {
|
|||
incoming_bandwidth_text->set_editable(false);
|
||||
incoming_bandwidth_text->set_custom_minimum_size(Size2(120, 0) * EDSCALE);
|
||||
incoming_bandwidth_text->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT);
|
||||
incoming_bandwidth_text->set_accessibility_name(TTRC("Incoming Bandwidth"));
|
||||
hb->add_child(incoming_bandwidth_text);
|
||||
|
||||
Control *down_up_spacer = memnew(Control);
|
||||
|
|
@ -346,6 +355,7 @@ EditorNetworkProfiler::EditorNetworkProfiler() {
|
|||
outgoing_bandwidth_text->set_editable(false);
|
||||
outgoing_bandwidth_text->set_custom_minimum_size(Size2(120, 0) * EDSCALE);
|
||||
outgoing_bandwidth_text->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT);
|
||||
outgoing_bandwidth_text->set_accessibility_name(TTRC("Outgoing Bandwidth"));
|
||||
hb->add_child(outgoing_bandwidth_text);
|
||||
|
||||
// Set initial texts in the incoming/outgoing bandwidth labels
|
||||
|
|
@ -359,7 +369,7 @@ EditorNetworkProfiler::EditorNetworkProfiler() {
|
|||
|
||||
// RPC
|
||||
counters_display = memnew(Tree);
|
||||
counters_display->set_custom_minimum_size(Size2(320, 0) * EDSCALE);
|
||||
counters_display->set_custom_minimum_size(Size2(280, 0) * EDSCALE);
|
||||
counters_display->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
counters_display->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
counters_display->set_hide_folding(true);
|
||||
|
|
@ -382,7 +392,7 @@ EditorNetworkProfiler::EditorNetworkProfiler() {
|
|||
|
||||
// Replication
|
||||
replication_display = memnew(Tree);
|
||||
replication_display->set_custom_minimum_size(Size2(320, 0) * EDSCALE);
|
||||
replication_display->set_custom_minimum_size(Size2(280, 0) * EDSCALE);
|
||||
replication_display->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
replication_display->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
replication_display->set_hide_folding(true);
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef EDITOR_NETWORK_PROFILER_H
|
||||
#define EDITOR_NETWORK_PROFILER_H
|
||||
#pragma once
|
||||
|
||||
#include "../multiplayer_debugger.h"
|
||||
|
||||
|
|
@ -120,5 +119,3 @@ public:
|
|||
|
||||
EditorNetworkProfiler();
|
||||
};
|
||||
|
||||
#endif // EDITOR_NETWORK_PROFILER_H
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef MULTIPLAYER_EDITOR_PLUGIN_H
|
||||
#define MULTIPLAYER_EDITOR_PLUGIN_H
|
||||
#pragma once
|
||||
|
||||
#include "editor/plugins/editor_debugger_plugin.h"
|
||||
#include "editor/plugins/editor_plugin.h"
|
||||
|
|
@ -51,8 +50,6 @@ public:
|
|||
virtual bool has_capture(const String &p_capture) const override;
|
||||
virtual bool capture(const String &p_message, const Array &p_data, int p_index) override;
|
||||
virtual void setup_session(int p_session_id) override;
|
||||
|
||||
MultiplayerEditorDebugger() {}
|
||||
};
|
||||
|
||||
class ReplicationEditor;
|
||||
|
|
@ -80,5 +77,3 @@ public:
|
|||
|
||||
MultiplayerEditorPlugin();
|
||||
};
|
||||
|
||||
#endif // MULTIPLAYER_EDITOR_PLUGIN_H
|
||||
|
|
|
|||
|
|
@ -234,6 +234,7 @@ ReplicationEditor::ReplicationEditor() {
|
|||
|
||||
np_line_edit = memnew(LineEdit);
|
||||
np_line_edit->set_placeholder(":property");
|
||||
np_line_edit->set_accessibility_name(TTRC("Path"));
|
||||
np_line_edit->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
np_line_edit->connect(SceneStringName(text_submitted), callable_mp(this, &ReplicationEditor::_np_text_submitted));
|
||||
hb->add_child(np_line_edit);
|
||||
|
|
@ -251,6 +252,7 @@ ReplicationEditor::ReplicationEditor() {
|
|||
pin->set_theme_type_variation(SceneStringName(FlatButton));
|
||||
pin->set_toggle_mode(true);
|
||||
pin->set_tooltip_text(TTR("Pin replication editor"));
|
||||
pin->set_accessibility_name(TTRC("Pin"));
|
||||
hb->add_child(pin);
|
||||
|
||||
tree = memnew(Tree);
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef REPLICATION_EDITOR_H
|
||||
#define REPLICATION_EDITOR_H
|
||||
#pragma once
|
||||
|
||||
#include "../scene_replication_config.h"
|
||||
|
||||
|
|
@ -102,7 +101,4 @@ public:
|
|||
|
||||
Button *get_pin() { return pin; }
|
||||
ReplicationEditor();
|
||||
~ReplicationEditor() {}
|
||||
};
|
||||
|
||||
#endif // REPLICATION_EDITOR_H
|
||||
|
|
|
|||
|
|
@ -150,9 +150,7 @@ void MultiplayerDebugger::BandwidthProfiler::tick(double p_frame_time, double p_
|
|||
int incoming_bandwidth = bandwidth_usage(bandwidth_in, bandwidth_in_ptr);
|
||||
int outgoing_bandwidth = bandwidth_usage(bandwidth_out, bandwidth_out_ptr);
|
||||
|
||||
Array arr;
|
||||
arr.push_back(incoming_bandwidth);
|
||||
arr.push_back(outgoing_bandwidth);
|
||||
Array arr = { incoming_bandwidth, outgoing_bandwidth };
|
||||
EngineDebugger::get_singleton()->send_message("multiplayer:bandwidth", arr);
|
||||
}
|
||||
}
|
||||
|
|
@ -160,8 +158,7 @@ void MultiplayerDebugger::BandwidthProfiler::tick(double p_frame_time, double p_
|
|||
// RPCProfiler
|
||||
|
||||
Array MultiplayerDebugger::RPCFrame::serialize() {
|
||||
Array arr;
|
||||
arr.push_back(infos.size() * 6);
|
||||
Array arr = { infos.size() * 6 };
|
||||
for (int i = 0; i < infos.size(); ++i) {
|
||||
arr.push_back(uint64_t(infos[i].node));
|
||||
arr.push_back(infos[i].node_path);
|
||||
|
|
@ -198,7 +195,7 @@ void MultiplayerDebugger::RPCProfiler::init_node(const ObjectID p_node) {
|
|||
}
|
||||
rpc_node_data.insert(p_node, RPCNodeInfo());
|
||||
rpc_node_data[p_node].node = p_node;
|
||||
rpc_node_data[p_node].node_path = Object::cast_to<Node>(ObjectDB::get_instance(p_node))->get_path();
|
||||
rpc_node_data[p_node].node_path = ObjectDB::get_instance<Node>(p_node)->get_path();
|
||||
}
|
||||
|
||||
void MultiplayerDebugger::RPCProfiler::toggle(bool p_enable, const Array &p_opts) {
|
||||
|
|
@ -270,8 +267,7 @@ bool MultiplayerDebugger::SyncInfo::read_from_array(const Array &p_arr, int p_of
|
|||
}
|
||||
|
||||
Array MultiplayerDebugger::ReplicationFrame::serialize() {
|
||||
Array arr;
|
||||
arr.push_back(infos.size() * 7);
|
||||
Array arr = { infos.size() * 7 };
|
||||
for (const KeyValue<ObjectID, SyncInfo> &E : infos) {
|
||||
E.value.write_to_array(arr);
|
||||
}
|
||||
|
|
@ -304,7 +300,7 @@ void MultiplayerDebugger::ReplicationProfiler::add(const Array &p_data) {
|
|||
const String what = p_data[0];
|
||||
const ObjectID id = p_data[1];
|
||||
const uint64_t size = p_data[2];
|
||||
MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(ObjectDB::get_instance(id));
|
||||
MultiplayerSynchronizer *sync = ObjectDB::get_instance<MultiplayerSynchronizer>(id);
|
||||
ERR_FAIL_NULL(sync);
|
||||
if (!sync_data.has(id)) {
|
||||
sync_data[id] = SyncInfo(sync);
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef MULTIPLAYER_DEBUGGER_H
|
||||
#define MULTIPLAYER_DEBUGGER_H
|
||||
#pragma once
|
||||
|
||||
#include "core/debugger/engine_profiler.h"
|
||||
|
||||
|
|
@ -128,5 +127,3 @@ public:
|
|||
static void initialize();
|
||||
static void deinitialize();
|
||||
};
|
||||
|
||||
#endif // MULTIPLAYER_DEBUGGER_H
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ void MultiplayerSpawner::_update_spawn_node() {
|
|||
}
|
||||
#endif
|
||||
if (spawn_node.is_valid()) {
|
||||
Node *node = Object::cast_to<Node>(ObjectDB::get_instance(spawn_node));
|
||||
Node *node = ObjectDB::get_instance<Node>(spawn_node);
|
||||
if (node && node->is_connected("child_entered_tree", callable_mp(this, &MultiplayerSpawner::_node_added))) {
|
||||
node->disconnect("child_entered_tree", callable_mp(this, &MultiplayerSpawner::_node_added));
|
||||
}
|
||||
|
|
@ -211,7 +211,7 @@ void MultiplayerSpawner::_notification(int p_what) {
|
|||
_update_spawn_node();
|
||||
|
||||
for (const KeyValue<ObjectID, SpawnInfo> &E : tracked_nodes) {
|
||||
Node *node = Object::cast_to<Node>(ObjectDB::get_instance(E.key));
|
||||
Node *node = ObjectDB::get_instance<Node>(E.key);
|
||||
ERR_CONTINUE(!node);
|
||||
node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &MultiplayerSpawner::_node_exit));
|
||||
get_multiplayer()->object_configuration_remove(node, this);
|
||||
|
|
@ -265,7 +265,7 @@ void MultiplayerSpawner::_spawn_notify(ObjectID p_id) {
|
|||
}
|
||||
|
||||
void MultiplayerSpawner::_node_exit(ObjectID p_id) {
|
||||
Node *node = Object::cast_to<Node>(ObjectDB::get_instance(p_id));
|
||||
Node *node = ObjectDB::get_instance<Node>(p_id);
|
||||
ERR_FAIL_NULL(node);
|
||||
if (tracked_nodes.has(p_id)) {
|
||||
tracked_nodes.erase(p_id);
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef MULTIPLAYER_SPAWNER_H
|
||||
#define MULTIPLAYER_SPAWNER_H
|
||||
#pragma once
|
||||
|
||||
#include "core/templates/local_vector.h"
|
||||
#include "scene/main/node.h"
|
||||
|
|
@ -91,7 +90,7 @@ public:
|
|||
PackedStringArray get_configuration_warnings() const override;
|
||||
|
||||
Node *get_spawn_node() const {
|
||||
return spawn_node.is_valid() ? Object::cast_to<Node>(ObjectDB::get_instance(spawn_node)) : nullptr;
|
||||
return spawn_node.is_valid() ? ObjectDB::get_instance<Node>(spawn_node) : nullptr;
|
||||
}
|
||||
|
||||
void add_spawnable_scene(const String &p_path);
|
||||
|
|
@ -115,5 +114,3 @@ public:
|
|||
|
||||
MultiplayerSpawner() {}
|
||||
};
|
||||
|
||||
#endif // MULTIPLAYER_SPAWNER_H
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ void MultiplayerSynchronizer::_update_process() {
|
|||
}
|
||||
|
||||
Node *MultiplayerSynchronizer::get_root_node() {
|
||||
return root_node_cache.is_valid() ? Object::cast_to<Node>(ObjectDB::get_instance(root_node_cache)) : nullptr;
|
||||
return root_node_cache.is_valid() ? ObjectDB::get_instance<Node>(root_node_cache) : nullptr;
|
||||
}
|
||||
|
||||
void MultiplayerSynchronizer::reset() {
|
||||
|
|
@ -376,7 +376,7 @@ Error MultiplayerSynchronizer::_watch_changes(uint64_t p_usec) {
|
|||
if (props.size() != watchers.size()) {
|
||||
watchers.resize(props.size());
|
||||
}
|
||||
if (props.size() == 0) {
|
||||
if (props.is_empty()) {
|
||||
return OK;
|
||||
}
|
||||
Node *node = get_root_node();
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef MULTIPLAYER_SYNCHRONIZER_H
|
||||
#define MULTIPLAYER_SYNCHRONIZER_H
|
||||
#pragma once
|
||||
|
||||
#include "scene_replication_config.h"
|
||||
|
||||
|
|
@ -125,5 +124,3 @@ public:
|
|||
};
|
||||
|
||||
VARIANT_ENUM_CAST(MultiplayerSynchronizer::VisibilityUpdateMode);
|
||||
|
||||
#endif // MULTIPLAYER_SYNCHRONIZER_H
|
||||
|
|
|
|||
|
|
@ -48,8 +48,10 @@ void initialize_multiplayer_module(ModuleInitializationLevel p_level) {
|
|||
GDREGISTER_CLASS(MultiplayerSynchronizer);
|
||||
GDREGISTER_CLASS(OfflineMultiplayerPeer);
|
||||
GDREGISTER_CLASS(SceneMultiplayer);
|
||||
MultiplayerAPI::set_default_interface("SceneMultiplayer");
|
||||
MultiplayerDebugger::initialize();
|
||||
if (GD_IS_CLASS_ENABLED(MultiplayerAPI)) {
|
||||
MultiplayerAPI::set_default_interface("SceneMultiplayer");
|
||||
MultiplayerDebugger::initialize();
|
||||
}
|
||||
}
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) {
|
||||
|
|
@ -59,5 +61,7 @@ void initialize_multiplayer_module(ModuleInitializationLevel p_level) {
|
|||
}
|
||||
|
||||
void uninitialize_multiplayer_module(ModuleInitializationLevel p_level) {
|
||||
MultiplayerDebugger::deinitialize();
|
||||
if (GD_IS_CLASS_ENABLED(MultiplayerAPI)) {
|
||||
MultiplayerDebugger::deinitialize();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,12 +28,9 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef MULTIPLAYER_REGISTER_TYPES_H
|
||||
#define MULTIPLAYER_REGISTER_TYPES_H
|
||||
#pragma once
|
||||
|
||||
#include "modules/register_module_types.h"
|
||||
|
||||
void initialize_multiplayer_module(ModuleInitializationLevel p_level);
|
||||
void uninitialize_multiplayer_module(ModuleInitializationLevel p_level);
|
||||
|
||||
#endif // MULTIPLAYER_REGISTER_TYPES_H
|
||||
|
|
|
|||
|
|
@ -100,8 +100,7 @@ void SceneCacheInterface::process_simplify_path(int p_from, const uint8_t *p_pac
|
|||
ERR_FAIL_NULL(root_node);
|
||||
int ofs = 1;
|
||||
|
||||
String methods_md5;
|
||||
methods_md5.parse_utf8((const char *)(p_packet + ofs), 32);
|
||||
String methods_md5 = String::utf8((const char *)(p_packet + ofs), 32);
|
||||
ofs += 33;
|
||||
|
||||
int id = decode_uint32(&p_packet[ofs]);
|
||||
|
|
@ -109,8 +108,7 @@ void SceneCacheInterface::process_simplify_path(int p_from, const uint8_t *p_pac
|
|||
|
||||
ERR_FAIL_COND_MSG(peers_info[p_from].recv_nodes.has(id), vformat("Duplicate remote cache ID %d for peer %d", id, p_from));
|
||||
|
||||
String paths;
|
||||
paths.parse_utf8((const char *)(p_packet + ofs), p_packet_len - ofs);
|
||||
String paths = String::utf8((const char *)(p_packet + ofs), p_packet_len - ofs);
|
||||
|
||||
const NodePath path = paths;
|
||||
|
||||
|
|
@ -154,7 +152,7 @@ void SceneCacheInterface::process_confirm_path(int p_from, const uint8_t *p_pack
|
|||
}
|
||||
|
||||
if (valid_rpc_checksum == false) {
|
||||
const Node *node = Object::cast_to<Node>(ObjectDB::get_instance(*oid));
|
||||
const Node *node = ObjectDB::get_instance<Node>(*oid);
|
||||
ERR_FAIL_NULL(node); // Bug.
|
||||
ERR_PRINT("The rpc node checksum failed. Make sure to have the same methods on both nodes. Node path: " + node->get_path());
|
||||
}
|
||||
|
|
@ -280,7 +278,7 @@ Object *SceneCacheInterface::get_cached_object(int p_from, uint32_t p_cache_id)
|
|||
|
||||
RecvNode *recv_node = pinfo->recv_nodes.getptr(p_cache_id);
|
||||
ERR_FAIL_NULL_V_MSG(recv_node, nullptr, vformat("ID %d not found in cache of peer %d.", p_cache_id, p_from));
|
||||
Node *node = Object::cast_to<Node>(ObjectDB::get_instance(recv_node->oid));
|
||||
Node *node = ObjectDB::get_instance<Node>(recv_node->oid);
|
||||
if (!node) {
|
||||
// Fallback to path lookup.
|
||||
Node *root_node = SceneTree::get_singleton()->get_root()->get_node(multiplayer->get_root_path());
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef SCENE_CACHE_INTERFACE_H
|
||||
#define SCENE_CACHE_INTERFACE_H
|
||||
#pragma once
|
||||
|
||||
#include "core/object/ref_counted.h"
|
||||
|
||||
|
|
@ -89,5 +88,3 @@ public:
|
|||
|
||||
SceneCacheInterface(SceneMultiplayer *p_multiplayer) { multiplayer = p_multiplayer; }
|
||||
};
|
||||
|
||||
#endif // SCENE_CACHE_INTERFACE_H
|
||||
|
|
|
|||
|
|
@ -37,15 +37,14 @@
|
|||
#include "core/os/os.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
_FORCE_INLINE_ void SceneMultiplayer::_profile_bandwidth(const String &p_what, int p_value) {
|
||||
if (EngineDebugger::is_profiling("multiplayer:bandwidth")) {
|
||||
Array values;
|
||||
values.push_back(p_what);
|
||||
values.push_back(OS::get_singleton()->get_ticks_msec());
|
||||
values.push_back(p_value);
|
||||
Array values = {
|
||||
p_what,
|
||||
OS::get_singleton()->get_ticks_msec(),
|
||||
p_value
|
||||
};
|
||||
EngineDebugger::profiler_add_frame_data("multiplayer:bandwidth", values);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef SCENE_MULTIPLAYER_H
|
||||
#define SCENE_MULTIPLAYER_H
|
||||
#pragma once
|
||||
|
||||
#include "scene_cache_interface.h"
|
||||
#include "scene_replication_interface.h"
|
||||
|
|
@ -204,5 +203,3 @@ public:
|
|||
SceneMultiplayer();
|
||||
~SceneMultiplayer();
|
||||
};
|
||||
|
||||
#endif // SCENE_MULTIPLAYER_H
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef SCENE_REPLICATION_CONFIG_H
|
||||
#define SCENE_REPLICATION_CONFIG_H
|
||||
#pragma once
|
||||
|
||||
#include "core/io/resource.h"
|
||||
#include "core/variant/typed_array.h"
|
||||
|
|
@ -108,5 +107,3 @@ public:
|
|||
};
|
||||
|
||||
VARIANT_ENUM_CAST(SceneReplicationConfig::ReplicationMode);
|
||||
|
||||
#endif // SCENE_REPLICATION_CONFIG_H
|
||||
|
|
|
|||
|
|
@ -43,10 +43,7 @@
|
|||
#ifdef DEBUG_ENABLED
|
||||
_FORCE_INLINE_ void SceneReplicationInterface::_profile_node_data(const String &p_what, ObjectID p_id, int p_size) {
|
||||
if (EngineDebugger::is_profiling("multiplayer:replication")) {
|
||||
Array values;
|
||||
values.push_back(p_what);
|
||||
values.push_back(p_id);
|
||||
values.push_back(p_size);
|
||||
Array values = { p_what, p_id, p_size };
|
||||
EngineDebugger::profiler_add_frame_data("multiplayer:replication", values);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef SCENE_REPLICATION_INTERFACE_H
|
||||
#define SCENE_REPLICATION_INTERFACE_H
|
||||
#pragma once
|
||||
|
||||
#include "multiplayer_spawner.h"
|
||||
#include "multiplayer_synchronizer.h"
|
||||
|
|
@ -114,7 +113,7 @@ private:
|
|||
|
||||
template <typename T>
|
||||
static T *get_id_as(const ObjectID &p_id) {
|
||||
return p_id.is_valid() ? Object::cast_to<T>(ObjectDB::get_instance(p_id)) : nullptr;
|
||||
return p_id.is_valid() ? ObjectDB::get_instance<T>(p_id) : nullptr;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
|
@ -151,5 +150,3 @@ public:
|
|||
multiplayer_cache = p_cache;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SCENE_REPLICATION_INTERFACE_H
|
||||
|
|
|
|||
|
|
@ -54,10 +54,7 @@
|
|||
#ifdef DEBUG_ENABLED
|
||||
_FORCE_INLINE_ void SceneRPCInterface::_profile_node_data(const String &p_what, ObjectID p_id, int p_size) {
|
||||
if (EngineDebugger::is_profiling("multiplayer:rpc")) {
|
||||
Array values;
|
||||
values.push_back(p_what);
|
||||
values.push_back(p_id);
|
||||
values.push_back(p_size);
|
||||
Array values = { p_what, p_id, p_size };
|
||||
EngineDebugger::profiler_add_frame_data("multiplayer:rpc", values);
|
||||
}
|
||||
}
|
||||
|
|
@ -138,8 +135,7 @@ Node *SceneRPCInterface::_process_get_node(int p_from, const uint8_t *p_packet,
|
|||
|
||||
ERR_FAIL_COND_V_MSG(ofs >= p_packet_len, nullptr, "Invalid packet received. Size smaller than declared.");
|
||||
|
||||
String paths;
|
||||
paths.parse_utf8((const char *)&p_packet[ofs], p_packet_len - ofs);
|
||||
String paths = String::utf8((const char *)&p_packet[ofs], p_packet_len - ofs);
|
||||
|
||||
NodePath np = paths;
|
||||
|
||||
|
|
@ -301,7 +297,7 @@ void SceneRPCInterface::_send_rpc(Node *p_node, int p_to, uint16_t p_rpc_id, con
|
|||
|
||||
ERR_FAIL_COND_MSG(p_argcount > 255, "Too many arguments (>255).");
|
||||
|
||||
if (p_to != 0 && !multiplayer->get_connected_peers().has(ABS(p_to))) {
|
||||
if (p_to != 0 && !multiplayer->get_connected_peers().has(Math::abs(p_to))) {
|
||||
ERR_FAIL_COND_MSG(p_to == multiplayer->get_unique_id(), "Attempt to call RPC on yourself! Peer unique ID: " + itos(multiplayer->get_unique_id()) + ".");
|
||||
|
||||
ERR_FAIL_MSG("Attempt to call RPC with unknown peer ID: " + itos(p_to) + ".");
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef SCENE_RPC_INTERFACE_H
|
||||
#define SCENE_RPC_INTERFACE_H
|
||||
#pragma once
|
||||
|
||||
#include "core/object/ref_counted.h"
|
||||
#include "scene/main/multiplayer_api.h"
|
||||
|
|
@ -110,5 +109,3 @@ public:
|
|||
multiplayer_replicator = p_replicator;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SCENE_RPC_INTERFACE_H
|
||||
|
|
|
|||
445
engine/modules/multiplayer/tests/test_multiplayer_spawner.h
Normal file
445
engine/modules/multiplayer/tests/test_multiplayer_spawner.h
Normal file
|
|
@ -0,0 +1,445 @@
|
|||
/**************************************************************************/
|
||||
/* test_multiplayer_spawner.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tests/test_macros.h"
|
||||
#include "tests/test_utils.h"
|
||||
|
||||
#include "../multiplayer_spawner.h"
|
||||
|
||||
namespace TestMultiplayerSpawner {
|
||||
|
||||
static inline Array build_array() {
|
||||
return Array();
|
||||
}
|
||||
template <typename... Targs>
|
||||
static inline Array build_array(Variant item, Targs... Fargs) {
|
||||
Array a = build_array(Fargs...);
|
||||
a.push_front(item);
|
||||
return a;
|
||||
}
|
||||
|
||||
class Wasp : public Node {
|
||||
GDCLASS(Wasp, Node);
|
||||
|
||||
int _size = 0;
|
||||
|
||||
public:
|
||||
int get_size() const {
|
||||
return _size;
|
||||
}
|
||||
void set_size(int p_size) {
|
||||
_size = p_size;
|
||||
}
|
||||
|
||||
Wasp() {
|
||||
set_name("Wasp");
|
||||
set_scene_file_path("wasp.tscn");
|
||||
}
|
||||
};
|
||||
|
||||
class SpawnWasps : public Object {
|
||||
GDCLASS(SpawnWasps, Object);
|
||||
|
||||
protected:
|
||||
static void _bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("wasp", "size"), &SpawnWasps::create_wasps);
|
||||
{
|
||||
MethodInfo mi;
|
||||
mi.name = "wasp_error";
|
||||
mi.arguments.push_back(PropertyInfo(Variant::INT, "size"));
|
||||
|
||||
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "wasp_error", &SpawnWasps::create_wasps_error, mi, varray(), false);
|
||||
}
|
||||
ClassDB::bind_method(D_METHOD("echo", "size"), &SpawnWasps::echo_size);
|
||||
}
|
||||
|
||||
public:
|
||||
Wasp *create_wasps(int p_size) {
|
||||
Wasp *wasp = memnew(Wasp);
|
||||
wasp->set_size(p_size);
|
||||
return wasp;
|
||||
}
|
||||
|
||||
Wasp *create_wasps_error(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
|
||||
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int echo_size(int p_size) {
|
||||
return p_size;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CASE("[Multiplayer][MultiplayerSpawner] Defaults") {
|
||||
MultiplayerSpawner *multiplayer_spawner = memnew(MultiplayerSpawner);
|
||||
|
||||
CHECK_EQ(multiplayer_spawner->get_configuration_warnings().size(), 1);
|
||||
CHECK_EQ(multiplayer_spawner->get_spawn_node(), nullptr);
|
||||
CHECK_EQ(multiplayer_spawner->get_spawnable_scene_count(), 0);
|
||||
CHECK_EQ(multiplayer_spawner->get_spawn_path(), NodePath());
|
||||
CHECK_EQ(multiplayer_spawner->get_spawn_limit(), 0);
|
||||
CHECK_EQ(multiplayer_spawner->get_spawn_function(), Callable());
|
||||
|
||||
memdelete(multiplayer_spawner);
|
||||
}
|
||||
|
||||
TEST_CASE("[Multiplayer][MultiplayerSpawner][SceneTree] Spawn Path warning") {
|
||||
MultiplayerSpawner *multiplayer_spawner = memnew(MultiplayerSpawner);
|
||||
SceneTree::get_singleton()->get_root()->add_child(multiplayer_spawner);
|
||||
|
||||
// If there is no spawn path, there should be a warning.
|
||||
PackedStringArray warning_messages = multiplayer_spawner->get_configuration_warnings();
|
||||
REQUIRE_EQ(warning_messages.size(), 1);
|
||||
CHECK_MESSAGE(warning_messages[0].contains("\"Spawn Path\""), "Invalid configuration warning");
|
||||
|
||||
// If there is a spawn path, but it doesn't exist a node on it, there should be a warning.
|
||||
multiplayer_spawner->set_spawn_path(NodePath("/root/Foo"));
|
||||
warning_messages = multiplayer_spawner->get_configuration_warnings();
|
||||
REQUIRE_EQ(warning_messages.size(), 1);
|
||||
CHECK_MESSAGE(warning_messages[0].contains("\"Spawn Path\""), "Invalid configuration warning");
|
||||
|
||||
// If there is a spawn path and a node on it, shouldn't be a warning.
|
||||
Node *foo = memnew(Node);
|
||||
foo->set_name("Foo");
|
||||
SceneTree::get_singleton()->get_root()->add_child(foo);
|
||||
warning_messages = multiplayer_spawner->get_configuration_warnings();
|
||||
CHECK_EQ(warning_messages.size(), 0);
|
||||
|
||||
memdelete(foo);
|
||||
memdelete(multiplayer_spawner);
|
||||
}
|
||||
|
||||
TEST_CASE("[Multiplayer][MultiplayerSpawner][SceneTree] Spawn node") {
|
||||
MultiplayerSpawner *multiplayer_spawner = memnew(MultiplayerSpawner);
|
||||
SceneTree::get_singleton()->get_root()->add_child(multiplayer_spawner);
|
||||
CHECK_EQ(multiplayer_spawner->get_spawn_node(), nullptr);
|
||||
|
||||
Node *foo = memnew(Node);
|
||||
foo->set_name("Foo");
|
||||
SceneTree::get_singleton()->get_root()->add_child(foo);
|
||||
|
||||
SUBCASE("nullptr if spawn path doesn't exists") {
|
||||
multiplayer_spawner->set_spawn_path(NodePath("/root/NotExists"));
|
||||
|
||||
CHECK_EQ(multiplayer_spawner->get_spawn_node(), nullptr);
|
||||
}
|
||||
|
||||
SUBCASE("Get it after setting spawn path with no signal connections") {
|
||||
multiplayer_spawner->set_spawn_path(NodePath("/root/Foo"));
|
||||
|
||||
CHECK_EQ(multiplayer_spawner->get_spawn_node(), foo);
|
||||
CHECK_FALSE(foo->has_connections("child_entered_tree"));
|
||||
}
|
||||
|
||||
SUBCASE("Get it after setting spawn path with signal connections") {
|
||||
multiplayer_spawner->add_spawnable_scene("scene.tscn");
|
||||
multiplayer_spawner->set_spawn_path(NodePath("/root/Foo"));
|
||||
|
||||
CHECK_EQ(multiplayer_spawner->get_spawn_node(), foo);
|
||||
CHECK(foo->has_connections("child_entered_tree"));
|
||||
}
|
||||
|
||||
SUBCASE("Set a new one should disconnect signals from the old one") {
|
||||
multiplayer_spawner->add_spawnable_scene("scene.tscn");
|
||||
multiplayer_spawner->set_spawn_path(NodePath("/root/Foo"));
|
||||
|
||||
CHECK_EQ(multiplayer_spawner->get_spawn_node(), foo);
|
||||
CHECK(foo->has_connections("child_entered_tree"));
|
||||
|
||||
Node *bar = memnew(Node);
|
||||
bar->set_name("Bar");
|
||||
SceneTree::get_singleton()->get_root()->add_child(bar);
|
||||
multiplayer_spawner->set_spawn_path(NodePath("/root/Bar"));
|
||||
|
||||
CHECK_EQ(multiplayer_spawner->get_spawn_node(), bar);
|
||||
CHECK(bar->has_connections("child_entered_tree"));
|
||||
CHECK_FALSE(foo->has_connections("child_entered_tree"));
|
||||
|
||||
memdelete(bar);
|
||||
}
|
||||
|
||||
memdelete(foo);
|
||||
memdelete(multiplayer_spawner);
|
||||
}
|
||||
|
||||
TEST_CASE("[Multiplayer][MultiplayerSpawner][SceneTree] Spawnable scene") {
|
||||
MultiplayerSpawner *multiplayer_spawner = memnew(MultiplayerSpawner);
|
||||
SceneTree::get_singleton()->get_root()->add_child(multiplayer_spawner);
|
||||
CHECK_EQ(multiplayer_spawner->get_spawnable_scene_count(), 0);
|
||||
|
||||
SUBCASE("Add one") {
|
||||
multiplayer_spawner->add_spawnable_scene("scene.tscn");
|
||||
|
||||
CHECK_EQ(multiplayer_spawner->get_spawnable_scene_count(), 1);
|
||||
CHECK_EQ(multiplayer_spawner->get_spawnable_scene(0), "scene.tscn");
|
||||
}
|
||||
|
||||
SUBCASE("Add one and if there is a valid spawn path add a connection to it") {
|
||||
Node *foo = memnew(Node);
|
||||
foo->set_name("Foo");
|
||||
multiplayer_spawner->set_spawn_path(NodePath("/root/Foo"));
|
||||
CHECK_FALSE(foo->has_connections("child_entered_tree"));
|
||||
|
||||
// Adding now foo to the tree to avoid set_spawn_path() making the connection.
|
||||
SceneTree::get_singleton()->get_root()->add_child(foo);
|
||||
multiplayer_spawner->notification(Node::NOTIFICATION_POST_ENTER_TREE);
|
||||
CHECK_FALSE(foo->has_connections("child_entered_tree"));
|
||||
multiplayer_spawner->add_spawnable_scene("scene.tscn");
|
||||
CHECK(foo->has_connections("child_entered_tree"));
|
||||
|
||||
memdelete(foo);
|
||||
}
|
||||
|
||||
SUBCASE("Add multiple") {
|
||||
multiplayer_spawner->add_spawnable_scene("scene.tscn");
|
||||
multiplayer_spawner->add_spawnable_scene("other_scene.tscn");
|
||||
multiplayer_spawner->add_spawnable_scene("yet_another_scene.tscn");
|
||||
|
||||
CHECK_EQ(multiplayer_spawner->get_spawnable_scene_count(), 3);
|
||||
CHECK_EQ(multiplayer_spawner->get_spawnable_scene(0), "scene.tscn");
|
||||
CHECK_EQ(multiplayer_spawner->get_spawnable_scene(1), "other_scene.tscn");
|
||||
CHECK_EQ(multiplayer_spawner->get_spawnable_scene(2), "yet_another_scene.tscn");
|
||||
}
|
||||
|
||||
SUBCASE("Clear") {
|
||||
Node *foo = memnew(Node);
|
||||
foo->set_name("Foo");
|
||||
SceneTree::get_singleton()->get_root()->add_child(foo);
|
||||
multiplayer_spawner->set_spawn_path(NodePath("/root/Foo"));
|
||||
|
||||
multiplayer_spawner->add_spawnable_scene("scene.tscn");
|
||||
multiplayer_spawner->add_spawnable_scene("other_scene.tscn");
|
||||
multiplayer_spawner->add_spawnable_scene("yet_another_scene.tscn");
|
||||
CHECK_EQ(multiplayer_spawner->get_spawnable_scene_count(), 3);
|
||||
CHECK(foo->has_connections("child_entered_tree"));
|
||||
|
||||
multiplayer_spawner->clear_spawnable_scenes();
|
||||
|
||||
CHECK_EQ(multiplayer_spawner->get_spawnable_scene_count(), 0);
|
||||
CHECK_FALSE(foo->has_connections("child_entered_tree"));
|
||||
}
|
||||
|
||||
memdelete(multiplayer_spawner);
|
||||
}
|
||||
|
||||
TEST_CASE("[Multiplayer][MultiplayerSpawner][SceneTree] Instantiate custom") {
|
||||
MultiplayerSpawner *multiplayer_spawner = memnew(MultiplayerSpawner);
|
||||
SceneTree::get_singleton()->get_root()->add_child(multiplayer_spawner);
|
||||
CHECK_EQ(multiplayer_spawner->get_spawn_node(), nullptr);
|
||||
|
||||
Node *nest = memnew(Node);
|
||||
nest->set_name("Nest");
|
||||
SceneTree::get_singleton()->get_root()->add_child(nest);
|
||||
multiplayer_spawner->set_spawn_path(NodePath("/root/Nest"));
|
||||
|
||||
SpawnWasps *spawn_wasps = memnew(SpawnWasps);
|
||||
|
||||
SUBCASE("Instantiates a node properly") {
|
||||
multiplayer_spawner->add_spawnable_scene("wasp.tscn");
|
||||
|
||||
multiplayer_spawner->set_spawn_limit(1);
|
||||
multiplayer_spawner->set_spawn_function(Callable(spawn_wasps, "wasp"));
|
||||
Wasp *wasp = Object::cast_to<Wasp>(multiplayer_spawner->instantiate_custom(Variant(42)));
|
||||
CHECK_NE(wasp, nullptr);
|
||||
CHECK_EQ(wasp->get_name(), "Wasp");
|
||||
CHECK_EQ(wasp->get_size(), 42);
|
||||
|
||||
memdelete(wasp);
|
||||
}
|
||||
|
||||
SUBCASE("Instantiates multiple nodes properly if there is no spawn limit") {
|
||||
multiplayer_spawner->add_spawnable_scene("wasp.tscn");
|
||||
multiplayer_spawner->set_spawn_function(Callable(spawn_wasps, "wasp"));
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Wasp *wasp = Object::cast_to<Wasp>(multiplayer_spawner->instantiate_custom(Variant(i)));
|
||||
CHECK_NE(wasp, nullptr);
|
||||
CHECK_EQ(wasp->get_name(), "Wasp");
|
||||
CHECK_EQ(wasp->get_size(), i);
|
||||
nest->add_child(wasp, true);
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("Fails if spawn limit is reached") {
|
||||
multiplayer_spawner->add_spawnable_scene("wasp.tscn");
|
||||
|
||||
multiplayer_spawner->set_spawn_limit(1);
|
||||
multiplayer_spawner->set_spawn_function(Callable(spawn_wasps, "wasp"));
|
||||
|
||||
// This one works.
|
||||
Wasp *wasp = Object::cast_to<Wasp>(multiplayer_spawner->instantiate_custom(Variant(42)));
|
||||
CHECK_NE(wasp, nullptr);
|
||||
CHECK_EQ(wasp->get_name(), "Wasp");
|
||||
CHECK_EQ(wasp->get_size(), 42);
|
||||
// Adding to the spawner node to get it tracked.
|
||||
nest->add_child(wasp);
|
||||
|
||||
// This one fails because spawn limit is reached.
|
||||
ERR_PRINT_OFF;
|
||||
CHECK_EQ(multiplayer_spawner->instantiate_custom(Variant(255)), nullptr);
|
||||
ERR_PRINT_ON;
|
||||
|
||||
memdelete(wasp);
|
||||
}
|
||||
|
||||
SUBCASE("Fails if spawn function is not set") {
|
||||
ERR_PRINT_OFF;
|
||||
CHECK_EQ(multiplayer_spawner->instantiate_custom(Variant(42)), nullptr);
|
||||
ERR_PRINT_ON;
|
||||
}
|
||||
|
||||
SUBCASE("Fails when spawn function fails") {
|
||||
multiplayer_spawner->add_spawnable_scene("wasp.tscn");
|
||||
|
||||
multiplayer_spawner->set_spawn_limit(1);
|
||||
multiplayer_spawner->set_spawn_function(Callable(spawn_wasps, "wasp_error"));
|
||||
|
||||
ERR_PRINT_OFF;
|
||||
CHECK_EQ(multiplayer_spawner->instantiate_custom(Variant(42)), nullptr);
|
||||
ERR_PRINT_ON;
|
||||
}
|
||||
|
||||
SUBCASE("Fails when spawn function not returns a node") {
|
||||
multiplayer_spawner->add_spawnable_scene("wasp.tscn");
|
||||
|
||||
multiplayer_spawner->set_spawn_limit(1);
|
||||
multiplayer_spawner->set_spawn_function(Callable(spawn_wasps, "echo"));
|
||||
|
||||
ERR_PRINT_OFF;
|
||||
CHECK_EQ(multiplayer_spawner->instantiate_custom(Variant(42)), nullptr);
|
||||
ERR_PRINT_ON;
|
||||
}
|
||||
|
||||
memdelete(spawn_wasps);
|
||||
memdelete(nest);
|
||||
memdelete(multiplayer_spawner);
|
||||
}
|
||||
|
||||
TEST_CASE("[Multiplayer][MultiplayerSpawner][SceneTree] Spawn") {
|
||||
MultiplayerSpawner *multiplayer_spawner = memnew(MultiplayerSpawner);
|
||||
|
||||
SUBCASE("Fails because is not inside tree") {
|
||||
ERR_PRINT_OFF;
|
||||
CHECK_EQ(multiplayer_spawner->spawn(Variant(42)), nullptr);
|
||||
ERR_PRINT_ON;
|
||||
}
|
||||
|
||||
SceneTree::get_singleton()->get_root()->add_child(multiplayer_spawner);
|
||||
CHECK_EQ(multiplayer_spawner->get_spawn_node(), nullptr);
|
||||
|
||||
Node *nest = memnew(Node);
|
||||
nest->set_name("Nest");
|
||||
SceneTree::get_singleton()->get_root()->add_child(nest);
|
||||
multiplayer_spawner->set_spawn_path(NodePath("/root/Nest"));
|
||||
|
||||
SpawnWasps *spawn_wasps = memnew(SpawnWasps);
|
||||
multiplayer_spawner->add_spawnable_scene("wasp.tscn");
|
||||
|
||||
SUBCASE("Spawns a node, track it and add it to spawn node") {
|
||||
multiplayer_spawner->set_spawn_limit(1);
|
||||
multiplayer_spawner->set_spawn_function(Callable(spawn_wasps, "wasp"));
|
||||
Wasp *wasp = Object::cast_to<Wasp>(multiplayer_spawner->spawn(Variant(42)));
|
||||
CHECK_NE(wasp, nullptr);
|
||||
CHECK_EQ(wasp->get_name(), "Wasp");
|
||||
CHECK_EQ(wasp->get_size(), 42);
|
||||
CHECK_EQ(wasp->get_parent(), nest);
|
||||
CHECK_EQ(nest->get_child_count(), 1);
|
||||
CHECK_EQ(nest->get_child(0), wasp);
|
||||
}
|
||||
|
||||
SUBCASE("Spawns multiple nodes properly if there is no spawn limit") {
|
||||
multiplayer_spawner->set_spawn_function(Callable(spawn_wasps, "wasp"));
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Wasp *wasp = Object::cast_to<Wasp>(multiplayer_spawner->spawn(Variant(i)));
|
||||
CHECK_NE(wasp, nullptr);
|
||||
CHECK_EQ(wasp->get_name(), "Wasp" + String((i == 0) ? "" : itos(i + 1)));
|
||||
CHECK_EQ(wasp->get_size(), i);
|
||||
CHECK_EQ(wasp->get_parent(), nest);
|
||||
CHECK_EQ(nest->get_child_count(), i + 1);
|
||||
CHECK_EQ(nest->get_child(i), wasp);
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("Fails if spawn limit is reached") {
|
||||
multiplayer_spawner->set_spawn_limit(1);
|
||||
multiplayer_spawner->set_spawn_function(Callable(spawn_wasps, "wasp"));
|
||||
|
||||
// This one works.
|
||||
Wasp *wasp = Object::cast_to<Wasp>(multiplayer_spawner->spawn(Variant(42)));
|
||||
CHECK_NE(wasp, nullptr);
|
||||
CHECK_EQ(wasp->get_name(), "Wasp");
|
||||
CHECK_EQ(wasp->get_size(), 42);
|
||||
CHECK_EQ(wasp->get_parent(), nest);
|
||||
CHECK_EQ(nest->get_child_count(), 1);
|
||||
CHECK_EQ(nest->get_child(0), wasp);
|
||||
|
||||
// This one fails because spawn limit is reached.
|
||||
ERR_PRINT_OFF;
|
||||
CHECK_EQ(multiplayer_spawner->spawn(Variant(255)), nullptr);
|
||||
ERR_PRINT_ON;
|
||||
|
||||
memdelete(wasp);
|
||||
}
|
||||
|
||||
SUBCASE("Fails if spawn function is not set") {
|
||||
ERR_PRINT_OFF;
|
||||
CHECK_EQ(multiplayer_spawner->spawn(Variant(42)), nullptr);
|
||||
ERR_PRINT_ON;
|
||||
}
|
||||
|
||||
SUBCASE("Fails if spawn node cannot be found") {
|
||||
multiplayer_spawner->set_spawn_function(Callable(spawn_wasps, "wasp"));
|
||||
multiplayer_spawner->set_spawn_path(NodePath(""));
|
||||
|
||||
ERR_PRINT_OFF;
|
||||
CHECK_EQ(multiplayer_spawner->spawn(Variant(42)), nullptr);
|
||||
ERR_PRINT_ON;
|
||||
}
|
||||
|
||||
SUBCASE("Fails when instantiate_custom not returns a node") {
|
||||
multiplayer_spawner->add_spawnable_scene("wasp.tscn");
|
||||
|
||||
multiplayer_spawner->set_spawn_limit(1);
|
||||
multiplayer_spawner->set_spawn_function(Callable(spawn_wasps, "echo"));
|
||||
|
||||
ERR_PRINT_OFF;
|
||||
CHECK_EQ(multiplayer_spawner->spawn(Variant(42)), nullptr);
|
||||
ERR_PRINT_ON;
|
||||
}
|
||||
|
||||
memdelete(spawn_wasps);
|
||||
memdelete(nest);
|
||||
memdelete(multiplayer_spawner);
|
||||
}
|
||||
|
||||
} // namespace TestMultiplayerSpawner
|
||||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TEST_SCENE_MULTIPLAYER_H
|
||||
#define TEST_SCENE_MULTIPLAYER_H
|
||||
#pragma once
|
||||
|
||||
#include "tests/test_macros.h"
|
||||
#include "tests/test_utils.h"
|
||||
|
|
@ -280,5 +279,3 @@ TEST_CASE("[Multiplayer][SceneMultiplayer][SceneTree] Complete Authentication")
|
|||
}
|
||||
|
||||
} // namespace TestSceneMultiplayer
|
||||
|
||||
#endif // TEST_SCENE_MULTIPLAYER_H
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue