From dca2fb7a9a8a6878501d7b858c3effe8d12dc64d Mon Sep 17 00:00:00 2001 From: AleaJactaEst Date: Tue, 3 Mar 2020 22:45:30 +0100 Subject: [PATCH] update network part --- assets/Scripts/Network/net_low_level.gd | 16 +- gdnative/test/bitstreamqueue.gd | 186 +++++++- gui_scene/GUI/login/login_menu.tscn | 1 - modules/bitstream/bitstream.cpp | 8 + modules/bitstream/bitstream.h | 2 + modules/bitstreamqueue/bitstreamqueue.cpp | 152 +++---- modules/bitstreamqueue/bitstreamqueue.h | 34 +- modules/bitstreamqueue/config.py | 2 +- modules/bitstreamqueue/register_types.cpp | 1 + modules/networkconnection/check_memory.cpp | 40 ++ modules/networkconnection/check_memory.h | 32 ++ modules/networkconnection/messagequeue.cpp | 19 + modules/networkconnection/messagequeue.h | 46 ++ .../networkconnection/network_connection.cpp | 18 +- .../networkconnection/network_connection.h | 4 +- .../network_connection_core.cpp | 203 +++++---- .../network_connection_core.h | 81 ++-- modules/networkconnection/network_data.cpp | 70 +++ modules/networkconnection/network_data.h | 74 ++++ modules/networkconnection/state_connexion.cpp | 417 ++++++++++++++++++ modules/networkconnection/state_connexion.h | 144 ++++++ project.godot | 5 + 22 files changed, 1273 insertions(+), 282 deletions(-) create mode 100644 modules/networkconnection/check_memory.cpp create mode 100644 modules/networkconnection/check_memory.h create mode 100644 modules/networkconnection/messagequeue.cpp create mode 100644 modules/networkconnection/messagequeue.h create mode 100644 modules/networkconnection/network_data.cpp create mode 100644 modules/networkconnection/network_data.h create mode 100644 modules/networkconnection/state_connexion.cpp create mode 100644 modules/networkconnection/state_connexion.h diff --git a/assets/Scripts/Network/net_low_level.gd b/assets/Scripts/Network/net_low_level.gd index 92c243f..3b74b12 100644 --- a/assets/Scripts/Network/net_low_level.gd +++ b/assets/Scripts/Network/net_low_level.gd @@ -22,11 +22,11 @@ var _networkconnection = NetworkConnection.new() func _ready(): pass -func send_system_login(host, port, user_addr, user_key, user_id, lang): - _networkconnection.define_server(host, port) - _networkconnection.define_user(user_addr, user_key, user_id) - _networkconnection.define_lang(lang) - _networkconnection.send_system_login() +#func send_system_login(host, port, user_addr, user_key, user_id, lang): +# _networkconnection.define_server(host, port) +# _networkconnection.define_user(user_addr, user_key, user_id) +# _networkconnection.define_lang(lang) +# _networkconnection.connect_to_server() func send_system_quit(): _networkconnection.send_system_quit() @@ -38,7 +38,11 @@ func disconnect_server(): _networkconnection.disconnect_server() func connect_to_server(host, port, user_addr, user_key, user_id, lang): - send_system_login(host, port, user_addr, user_key, user_id, lang) + _networkconnection.define_server(host, port) + _networkconnection.define_user(user_addr, user_key, user_id) + _networkconnection.define_lang(lang) + _networkconnection.connect_to_server() + #send_system_login(host, port, user_addr, user_key, user_id, lang) func _process(delta): _networkconnection.process(delta) diff --git a/gdnative/test/bitstreamqueue.gd b/gdnative/test/bitstreamqueue.gd index 28d42eb..7b39b58 100644 --- a/gdnative/test/bitstreamqueue.gd +++ b/gdnative/test/bitstreamqueue.gd @@ -18,12 +18,12 @@ func test_init(): assert(res == 0) bitstreamqueue.clear() - res = bitstreamqueue.get_received_number(0) + res = bitstreamqueue.length() assert(res == 0) func test_msg_1(): var bitstreamqueue = BitStreamQueue.new() - var pos + var index var res var tmp = PoolByteArray() tmp.append(0) @@ -32,29 +32,39 @@ func test_msg_1(): tmp.append(3) tmp.append(2) - res = bitstreamqueue.length() - assert(res == 0) + var data = BitStream.new() + assert(bitstreamqueue.length() == 0) - pos = bitstreamqueue.put_msgbytes(tmp) + data.put_data(tmp) + var id = data.get_uint32() + assert(id == 3) - res = bitstreamqueue.get_received_number(pos) - assert(res == 3) + var bitstreamfield = BitStreamField.new() + bitstreamfield.put_id(id) + bitstreamfield.put_msgin(data) - res = bitstreamqueue.get_msg(pos) + index = bitstreamqueue.put_bitstreamfield(bitstreamfield) + assert(index == 0) + + assert(bitstreamqueue.length() == 1) + #res = bitstreamqueue.get_received_number(pos) + #assert(res == 3) + + res = bitstreamqueue.get_msg(index) #print(res.show()) - assert(res.show() == "0000000000000000000000000000001100000010") + assert(res.get_msgin().show() == "0000000000000000000000000000001100000010") - res = bitstreamqueue.get_received_number(pos) - assert(res == 3) + #res = bitstreamqueue.get_msg_withid(id) + #assert(res == 3) res = bitstreamqueue.length() assert(res == 1) - bitstreamqueue.erase(pos) + bitstreamqueue.erase_index(index) res = bitstreamqueue.length() assert(res == 0) func test_msg_2(): var bitstreamqueue = BitStreamQueue.new() - var pos + var index var res var tmp = PoolByteArray() tmp.append(0) @@ -63,17 +73,151 @@ func test_msg_2(): tmp.append(2) tmp.append(7) - pos = bitstreamqueue.put_msgbytes(tmp) - res = bitstreamqueue.get_received_number(pos) - assert(res == 2) + var data = BitStream.new() + assert(bitstreamqueue.length() == 0) - res = bitstreamqueue.get_msg(pos) + data.put_data(tmp) + var id = data.get_uint32() + assert(id == 2) + + var bitstreamfield = BitStreamField.new() + bitstreamfield.put_id(id) + bitstreamfield.put_msgin(data) + + index = bitstreamqueue.put_bitstreamfield(bitstreamfield) + assert(index == 0) + + assert(bitstreamqueue.length() == 1) + + res = bitstreamqueue.get_msg(index) #print(res.show()) - assert(res.show() == "0000000000000000000000000000001000000111") + assert(res.get_msgin().show() == "0000000000000000000000000000001000000111") + assert(res.get_id() == 2) + +func test_msg_3(): + var bitstreamqueue = BitStreamQueue.new() + var index + var res + var tmp = PoolByteArray() + tmp.append(0) + tmp.append(0) + tmp.append(0) + tmp.append(2) + tmp.append(7) + + var data = BitStream.new() + assert(bitstreamqueue.length() == 0) + + data.put_data(tmp) + var id = data.get_uint32() + assert(id == 2) + + var bitstreamfield = BitStreamField.new() + bitstreamfield.put_id(id) + bitstreamfield.put_msgin(data) + + index = bitstreamqueue.put_bitstreamfield(bitstreamfield) + assert(index == 0) + + assert(bitstreamqueue.length() == 1) + + res = bitstreamqueue.get_msg(index) + #print(res.show()) + assert(res.get_msgin().show() == "0000000000000000000000000000001000000111") + assert(res.get_id() == 2) + + tmp = PoolByteArray() + tmp.append(0) + tmp.append(0) + tmp.append(0) + tmp.append(3) + tmp.append(2) + + data = BitStream.new() + assert(bitstreamqueue.length() == 1) + data.put_data(tmp) + id = data.get_uint32() + assert(id == 3) + bitstreamfield = BitStreamField.new() + bitstreamfield.put_id(id) + bitstreamfield.put_msgin(data) + index = bitstreamqueue.put_bitstreamfield(bitstreamfield) + assert(index == 1) + assert(bitstreamqueue.length() == 2) + res = bitstreamqueue.get_msg(index) + #print(res.show()) + assert(res.get_msgin().show() == "0000000000000000000000000000001100000010") + assert(res.get_id() == 3) + + tmp = PoolByteArray() + tmp.append(0) + tmp.append(0) + tmp.append(0) + tmp.append(1) + tmp.append(2) + + data = BitStream.new() + assert(bitstreamqueue.length() == 2) + data.put_data(tmp) + id = data.get_uint32() + assert(id == 1) + bitstreamfield = BitStreamField.new() + bitstreamfield.put_id(id) + bitstreamfield.put_msgin(data) + index = bitstreamqueue.put_bitstreamfield(bitstreamfield) + assert(index == 2) + assert(bitstreamqueue.length() == 3) + res = bitstreamqueue.get_msg(index) + #print(res.show()) + assert(res.get_msgin().show() == "0000000000000000000000000000000100000010") + assert(res.get_id() == 1) + + assert(bitstreamqueue.length() == 3) + + bitstreamqueue.erase_id(1) + assert(bitstreamqueue.length() == 2) + + +func step(id, data, bitstreamqueue): + var tmp = PoolByteArray() + tmp.append(0) + tmp.append(0) + tmp.append(0) + tmp.append(id) + tmp.append(data) + + data = BitStream.new() + data.put_data(tmp) + var lid = data.get_uint32() + assert(lid == id) + var bitstreamfield = BitStreamField.new() + bitstreamfield.put_id(id) + bitstreamfield.put_msgin(data) + return bitstreamqueue.put_bitstreamfield(bitstreamfield) + +func test_msg_4(): + var bitstreamqueue = BitStreamQueue.new() + var index1 + var index2 + var index3 + var index4 + + assert(bitstreamqueue.length() == 0) + index1 = step(1,1,bitstreamqueue) + assert(bitstreamqueue.length() == 1) + index2 = step(2,2,bitstreamqueue) + assert(bitstreamqueue.length() == 2) + index3 = step(3,3,bitstreamqueue) + assert(bitstreamqueue.length() == 3) + bitstreamqueue.erase_id(2) + assert(bitstreamqueue.length() == 2) + index4 = step(4,4,bitstreamqueue) + assert(bitstreamqueue.length() == 3) + + index3 = step(5,5,bitstreamqueue) + assert(bitstreamqueue.length() == 4) - res = bitstreamqueue.get_received_number(pos) - assert(res == 2) func test(): @@ -81,4 +225,6 @@ func test(): test_init() test_msg_1() test_msg_2() + test_msg_3() + test_msg_4() print("[bitstreamqueue] Start check -> end") diff --git a/gui_scene/GUI/login/login_menu.tscn b/gui_scene/GUI/login/login_menu.tscn index 2d53a01..2e6fa72 100644 --- a/gui_scene/GUI/login/login_menu.tscn +++ b/gui_scene/GUI/login/login_menu.tscn @@ -147,7 +147,6 @@ margin_right = 627.0 margin_bottom = 188.0 [node name="checkboxs_box" type="VBoxContainer" parent="h_box_container/v_box_container/margin_container/login_box/h_box_container"] -editor/display_folded = true margin_right = 228.0 margin_bottom = 40.0 diff --git a/modules/bitstream/bitstream.cpp b/modules/bitstream/bitstream.cpp index d8ff1f8..18f0431 100644 --- a/modules/bitstream/bitstream.cpp +++ b/modules/bitstream/bitstream.cpp @@ -336,6 +336,14 @@ void BitStream::put_data(PoolByteArray value) this->_pos = value.size() * 8; } + +void BitStream::put_bitstream(Ref value) +{ + this->_data = value->_data; //*value.ptr(); + this->_pos = value->_pos; // ->size() * 8; + this->_read = value->_read; +} + uint32_t BitStream::get_serial(uint32_t nbits) { uint32_t value; diff --git a/modules/bitstream/bitstream.h b/modules/bitstream/bitstream.h index a1d46e6..84c237c 100644 --- a/modules/bitstream/bitstream.h +++ b/modules/bitstream/bitstream.h @@ -64,6 +64,8 @@ public: PoolByteArray get_data(); void put_data(PoolByteArray value); + + void put_bitstream(Ref value); uint32_t get_serial(uint32_t nbits); bool get_bool(); diff --git a/modules/bitstreamqueue/bitstreamqueue.cpp b/modules/bitstreamqueue/bitstreamqueue.cpp index 2ea0564..9fa7586 100644 --- a/modules/bitstreamqueue/bitstreamqueue.cpp +++ b/modules/bitstreamqueue/bitstreamqueue.cpp @@ -23,130 +23,116 @@ #include "bitstreamqueue.h" #include "core/os/os.h" +void BitStreamField::_bind_methods() +{ + ClassDB::bind_method(D_METHOD("get_id"), &BitStreamField::get_id); + ClassDB::bind_method(D_METHOD("get_msgin"), &BitStreamField::get_msgin); + ClassDB::bind_method(D_METHOD("put_id", "id"), &BitStreamField::put_id); + ClassDB::bind_method(D_METHOD("put_msgin", "msgin"), &BitStreamField::put_msgin); +} + void BitStreamQueue::_bind_methods() { ClassDB::bind_method(D_METHOD("clear"), &BitStreamQueue::clear); ClassDB::bind_method(D_METHOD("length"), &BitStreamQueue::length); - ClassDB::bind_method(D_METHOD("put_msgbytes", "msgbytes"), &BitStreamQueue::put_msgbytes); - ClassDB::bind_method(D_METHOD("get_msg", "pos"), &BitStreamQueue::get_msg); - ClassDB::bind_method(D_METHOD("get_received_number", "pos"), &BitStreamQueue::get_received_number); - ClassDB::bind_method(D_METHOD("erase", "pos"), &BitStreamQueue::erase); + // ClassDB::bind_method(D_METHOD("put_msgbytes", "msgbytes"), &BitStreamQueue::put_msgbytes); + ClassDB::bind_method(D_METHOD("get_msg", "index"), &BitStreamQueue::get_msg); + ClassDB::bind_method(D_METHOD("get_msg_withid", "id"), &BitStreamQueue::get_msg_withid); + ClassDB::bind_method(D_METHOD("put_bitstreamfield", "data"), &BitStreamQueue::put_bitstreamfield); + ClassDB::bind_method(D_METHOD("erase_index", "index"), &BitStreamQueue::erase_index); + ClassDB::bind_method(D_METHOD("erase_id", "id"), &BitStreamQueue::erase_id); + ClassDB::bind_method(D_METHOD("get_index", "id"), &BitStreamQueue::get_index); + ClassDB::bind_method(D_METHOD("is_index", "id"), &BitStreamQueue::is_index); } BitStreamQueue::BitStreamQueue() { OS::get_singleton()->print("[%s:%d] new BitStreamQueue\n", __FILE__, __LINE__); - for(int i = 0 ; i < SIZE_QUEUE_MESSAGE ; ++i ) - this->_msgin[i].instance(); - //this->_msgin.resize(SIZE_QUEUE_MESSAGE); this->clear(); } BitStreamQueue::~BitStreamQueue() { OS::get_singleton()->print("[%s:%d] delete BitStreamQueue\n", __FILE__, __LINE__); - this->clear(); - //for(int i = 0 ; i < SIZE_QUEUE_MESSAGE ; ++i ) this->_msgin[i].unref(); - - for(int i = 0 ; i < SIZE_QUEUE_MESSAGE ; ++i ) - { - //OS::get_singleton()->print("[%s:%d] delete BitStreamQueue %d\n", __FILE__, __LINE__, i); - this->_msgin[i].unref(); - if (this->_msgin[i] != nullptr) - { - OS::get_singleton()->print("[%s:%d] delete BitStreamQueue %d : KO\n", __FILE__, __LINE__, i); - //memdelete(this->_msgin[i]); - //this->_msgin[i] = nullptr; - } - else - { - OS::get_singleton()->print("[%s:%d] delete BitStreamQueue %d : ok\n", __FILE__, __LINE__, i); - } - } } void BitStreamQueue::clear() { - for(int i = 0 ; i < SIZE_QUEUE_MESSAGE ; ++i ) - { - this->_received_number[i] = 0; - //this->_msgin[i].nref(); - this->_msgin[i]->clear(); - } - this->_size = 0; + this->_msg.clear(); } int BitStreamQueue::length() { - return this->_size; + return this->_msg.size(); } -int BitStreamQueue::put_msgbytes(PoolByteArray msgbytes) +int BitStreamQueue::get_index(uint32_t id) { - int i = 0; - int ii ; - - while((i < SIZE_QUEUE_MESSAGE)&&(this->_msgin[i]->size_data() != 0)) - ++i; - - if(i >= SIZE_QUEUE_MESSAGE) // Out of memory + for (int i = 0; i < this->_msg.size(); i++) { - ERR_PRINTS("Network queue is full (" + itos(i) + " / " + itos(SIZE_QUEUE_MESSAGE) + ")"); - throw "Out of memory"; - } - this->_msgin[i]->put_data(msgbytes); - uint32_t current_received_number = this->_msgin[i]->get_uint32(); - this->_received_number[i] = current_received_number; + if (this->_msg[i]->get_id() == id) + { + return i; + }; + }; + return -1; +} - // Check we don't have other message with same _received_number (also remove it) - ii = i + 1; - while(ii < SIZE_QUEUE_MESSAGE) +bool BitStreamQueue::is_index(uint32_t id) +{ + for (int i = 0; i < this->_msg.size(); i++) { - if ( this->_received_number[ii] == current_received_number) - this->erase(ii); - ++ii; + if (this->_msg[i]->get_id() == id) + { + return true; + }; + }; + return false; +} + +int BitStreamQueue::put_bitstreamfield(Ref data) +{ + int i = this->get_index(data->get_id()); + if (i == -1) + { + this->_msg.push_back(data); + i = this->get_index(data->get_id()); } - this->_size ++; return i; } -Ref BitStreamQueue::get_msg(int pos) +Ref BitStreamQueue::get_msg_withid(uint32_t id) { - //Ref ret; - if ( pos >= SIZE_QUEUE_MESSAGE ) + for (int i = 0; i < this->_msg.size(); i++) { - ERR_PRINT("Try to get data out of memory"); - throw "Out of memory"; - } - //ret.instance(); - //*ret = &(this->_msgin[pos]); - //return ret; - //return Ref(this->_msgin[pos]); - - //return & (this->_msgin[pos]); - return this->_msgin[pos]; + if (this->_msg[i]->get_id() == id) + { + return this->_msg[i]; + }; + }; + return NULL; } -uint32_t BitStreamQueue::get_received_number(int pos) +Ref BitStreamQueue::get_msg(int index) { - if ( pos >= SIZE_QUEUE_MESSAGE ) - { - ERR_PRINT("Try to get data out of memory"); - throw "Out of memory"; - } - return this->_received_number[pos]; + ERR_FAIL_INDEX_V(index, this->_msg.size(), NULL); + return this->_msg[index]; } -void BitStreamQueue::erase(int pos) +void BitStreamQueue::erase_index(int index) { - if ( pos >= SIZE_QUEUE_MESSAGE ) - { - ERR_PRINT("Try to erase data out of memory"); - return; - } - this->_received_number[pos] = 0; - this->_msgin[pos]->clear(); - this->_size -- ; + ERR_FAIL_INDEX(index, this->_msg.size()); + this->_msg.remove(index); } +void BitStreamQueue::erase_id(uint32_t id) +{ + for (int i = 0; i < this->_msg.size(); i++) + { + if (this->_msg[i]->get_id() == id) { + this->_msg.remove(i); + return; + }; + }; +} \ No newline at end of file diff --git a/modules/bitstreamqueue/bitstreamqueue.h b/modules/bitstreamqueue/bitstreamqueue.h index b19df50..a0901a3 100644 --- a/modules/bitstreamqueue/bitstreamqueue.h +++ b/modules/bitstreamqueue/bitstreamqueue.h @@ -26,25 +26,41 @@ #include "core/reference.h" #include "modules/bitstream/bitstream.h" -class BitStreamQueue : public Reference { +class BitStreamField : public Reference +{ + GDCLASS(BitStreamField, Reference) +protected: + static void _bind_methods(); +private: + uint32_t _id; + Ref _msgin; +public: + uint32_t get_id() const { return this->_id; } + Ref get_msgin() { return this->_msgin; } + void put_id(uint32_t id) { this->_id = id; } + void put_msgin(const Ref & msgin) { this->_msgin = msgin; } +}; + +class BitStreamQueue : public Reference +{ GDCLASS(BitStreamQueue, Reference) protected: static void _bind_methods(); private: - int _size; - uint32_t _received_number[SIZE_QUEUE_MESSAGE]; - Ref _msgin[SIZE_QUEUE_MESSAGE]; - //Vector _msgin; + Vector > _msg; public: BitStreamQueue(); ~BitStreamQueue(); void clear(); int length(); - int put_msgbytes(PoolByteArray msgbytes); - Ref get_msg(int pos); - uint32_t get_received_number(int pos); - void erase(int pos); + bool is_index(uint32_t id); + int get_index(uint32_t id); + int put_bitstreamfield(Ref data); + Ref get_msg(int index); + Ref get_msg_withid(uint32_t id); + void erase_index(int index); + void erase_id(uint32_t id); }; #endif // BIT_STREAM_QUEUE_H diff --git a/modules/bitstreamqueue/config.py b/modules/bitstreamqueue/config.py index e1cb267..e6d95ae 100644 --- a/modules/bitstreamqueue/config.py +++ b/modules/bitstreamqueue/config.py @@ -8,7 +8,7 @@ def configure(env): def get_doc_classes(): return [ - "BitStreamQueue", + "BitStreamQueue", "BitStreamField" ] def get_doc_path(): diff --git a/modules/bitstreamqueue/register_types.cpp b/modules/bitstreamqueue/register_types.cpp index 99d7b2e..e041b2c 100644 --- a/modules/bitstreamqueue/register_types.cpp +++ b/modules/bitstreamqueue/register_types.cpp @@ -6,6 +6,7 @@ #include "bitstreamqueue.h" void register_bitstreamqueue_types() { + ClassDB::register_class(); ClassDB::register_class(); } diff --git a/modules/networkconnection/check_memory.cpp b/modules/networkconnection/check_memory.cpp new file mode 100644 index 0000000..98d5588 --- /dev/null +++ b/modules/networkconnection/check_memory.cpp @@ -0,0 +1,40 @@ +/* + Check Memory + + Copyright (C) 2019 AleaJactaEst + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +#include "check_memory.h" +#include "core/os/os.h" + +uint64_t memstaticold = 0; +uint64_t memdynamicold = 0; +uint64_t mempeakold = 0; + +void show_memory_usage() +{ + uint64_t memstatic = OS::get_singleton()->get_static_memory_usage(); + uint64_t memdynamic = OS::get_singleton()->get_dynamic_memory_usage(); + uint64_t mempeak = OS::get_singleton()->get_static_memory_peak_usage(); + OS::get_singleton()->print("[%s:%d] Usage Memory - Current [Static:%ld, Dynamic:%ld, Peak:%ld] Delta [Static:%ld, Dynamic:%ld, Peak:%ld]\n", + __FILE__, __LINE__, + memstatic, memdynamic, mempeak, + memstatic - memstaticold, memdynamic - memdynamicold, mempeak - mempeakold); + memstaticold = memstatic; + memdynamicold = memdynamic; + mempeakold = mempeak; +} \ No newline at end of file diff --git a/modules/networkconnection/check_memory.h b/modules/networkconnection/check_memory.h new file mode 100644 index 0000000..185b325 --- /dev/null +++ b/modules/networkconnection/check_memory.h @@ -0,0 +1,32 @@ +/* + Check Memory + + Copyright (C) 2019 AleaJactaEst + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +#ifndef MEMORY_CHECK_H +#define MEMORY_CHECK_H + +void show_memory_usage(); + +#ifdef ENABLE_CHECK_MEMORY_USAGE + #define SHOW_USAGE_MEMORY show_memory_usage(); +#else + #define SHOW_USAGE_MEMORY +#endif + +#endif \ No newline at end of file diff --git a/modules/networkconnection/messagequeue.cpp b/modules/networkconnection/messagequeue.cpp new file mode 100644 index 0000000..9efdbba --- /dev/null +++ b/modules/networkconnection/messagequeue.cpp @@ -0,0 +1,19 @@ +/* + Library to manage message received from server + + Copyright (C) 2019 AleaJactaEst + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + */ diff --git a/modules/networkconnection/messagequeue.h b/modules/networkconnection/messagequeue.h new file mode 100644 index 0000000..ee7cb6c --- /dev/null +++ b/modules/networkconnection/messagequeue.h @@ -0,0 +1,46 @@ +/* + Header MessageQueue + + Copyright (C) 2019 AleaJactaEst + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + + +#ifndef MESSAGEQUEUE_H +#define MESSAGEQUEUE_H + +/* +class Message +{ +public: + virtual void send_message(PoolByteArray & msgbytes); +}; + +class MessageDirect : public Message +{ +public: + void send_message(uint32_t msgid, PoolByteArray & msgbytes); +}; + +// Class store message and execute if is correct ID +class MessageQueue : public Message +{ + BitStreamQueue queue; +public: + void send_message(uint32_t msgid, PoolByteArray & msgbytes); +}; +*/ +#endif // MESSAGEQUEUE_H diff --git a/modules/networkconnection/network_connection.cpp b/modules/networkconnection/network_connection.cpp index 76cf233..27734eb 100644 --- a/modules/networkconnection/network_connection.cpp +++ b/modules/networkconnection/network_connection.cpp @@ -27,12 +27,10 @@ void NetworkConnection::_bind_methods() ClassDB::bind_method(D_METHOD("define_server", "host", "port"), &NetworkConnection::define_server); ClassDB::bind_method(D_METHOD("define_user", "user_addr", "user_key", "user_id"), &NetworkConnection::define_user); ClassDB::bind_method(D_METHOD("define_lang", "lang"), &NetworkConnection::define_lang); - ClassDB::bind_method(D_METHOD("send_system_login"), &NetworkConnection::send_system_login); - ClassDB::bind_method(D_METHOD("send_system_disconnect"), &NetworkConnection::send_system_disconnect); - ClassDB::bind_method(D_METHOD("send_system_quit"), &NetworkConnection::send_system_quit); ClassDB::bind_method(D_METHOD("disconnect_server"), &NetworkConnection::disconnect_server); ClassDB::bind_method(D_METHOD("process", "delta"), &NetworkConnection::process); ClassDB::bind_method(D_METHOD("get_state"), &NetworkConnection::get_state); + ClassDB::bind_method(D_METHOD("connect_to_server"), &NetworkConnection::connect_to_server); ClassDB::bind_method(D_METHOD("terminate_network_connection"), &NetworkConnection::terminate_network_connection); //ClassDB::bind_method(D_METHOD("get_master_message_description_node"), &NetworkConnection::get_master_message_description_node); } @@ -70,21 +68,11 @@ void NetworkConnection::define_lang(String lang) NetworkConnectionCore::get_singleton()->define_lang(lang); } -void NetworkConnection::send_system_login() +void NetworkConnection::connect_to_server() { - NetworkConnectionCore::get_singleton()->send_system_login(); + NetworkConnectionCore::get_singleton()->connect_to_server(); } -void NetworkConnection::send_system_disconnect() -{ - NetworkConnectionCore::get_singleton()->send_system_disconnect(); -} - - void NetworkConnection::send_system_quit() - { - NetworkConnectionCore::get_singleton()->send_system_quit(); - } - void NetworkConnection::disconnect_server() { NetworkConnectionCore::get_singleton()->disconnect_server(); diff --git a/modules/networkconnection/network_connection.h b/modules/networkconnection/network_connection.h index 2a32424..24a3f18 100644 --- a/modules/networkconnection/network_connection.h +++ b/modules/networkconnection/network_connection.h @@ -40,9 +40,7 @@ public: void define_server(String host, int64_t port); void define_user(String user_addr, String user_key, String user_id); void define_lang(String lang); - void send_system_login(); - void send_system_disconnect(); - void send_system_quit(); + void connect_to_server(); void disconnect_server(); void process(int delta); int get_state(); diff --git a/modules/networkconnection/network_connection_core.cpp b/modules/networkconnection/network_connection_core.cpp index 083a592..f49b6ea 100644 --- a/modules/networkconnection/network_connection_core.cpp +++ b/modules/networkconnection/network_connection_core.cpp @@ -18,6 +18,9 @@ */ +#define ENABLE_CHECK_MEMORY_USAGE + +#include "check_memory.h" #include "network_connection_core.h" NetworkConnectionCore *NetworkConnectionCore::singleton = nullptr; @@ -38,10 +41,9 @@ void NetworkConnectionCore::cleanup() OS::get_singleton()->print("NetworkConnectionCore::cleanup\n"); } -NetworkConnectionCore::NetworkConnectionCore() +NetworkConnectionCore::NetworkConnectionCore() : _state_not_initialized(this), _state_login(this), _state_synchronize(this), _state_connected(this), _state_quit(this) { - //this->_socketUDP = nullptr; - this->_state = STATE::NotInitialised; + this->_state_connexion = & this->_state_not_initialized; } NetworkConnectionCore::~NetworkConnectionCore() @@ -59,12 +61,15 @@ NetworkConnectionCore::~NetworkConnectionCore() } NetworkConnectionCore::singleton = nullptr; - this->_state = STATE::NotInitialised; + + this->_state_connexion = & this->_state_not_initialized; + + //this->_state = STATE::NotInitialised; } int NetworkConnectionCore::get_state() { - return this->_state; + return this->_state_connexion->get_state(); } void NetworkConnectionCore::autodefine_socket_udp() @@ -81,10 +86,23 @@ void NetworkConnectionCore::autodefine_socket_udp() } } +void NetworkConnectionCore::open_network() +{ + this->autodefine_socket_udp(); + OS::get_singleton()->print("Connect to %s:%ld\n", this->_host.ascii().get_data(), this->_port); + this->_socketUDP->set_dest_address(this->_host, this->_port); +} +void NetworkConnectionCore::close_network() +{ + this->_socketUDP->close(); + this->_socketUDP.unref(); +} + void NetworkConnectionCore::define_checksum_msg_xml(Array & checksum_msg_xml) { + this->_network_data.define_checksum_msg_xml(checksum_msg_xml); //DEBUG_PRINT("Received msg.xml checksum"); - this->_checksum_msg_xml = checksum_msg_xml; + //this->_checksum_msg_xml = checksum_msg_xml; //DEBUG_PRINT("Received msg.xml checksum " + itos(checksum_msg_xml.size())); //DEBUG_PRINT("Received msg.xml checksum " + itos(this->_checksum_msg_xml.size())); } @@ -97,77 +115,22 @@ void NetworkConnectionCore::define_server(String host, int64_t port) void NetworkConnectionCore::define_user(String user_addr, String user_key, String user_id) { - this->_user_addr = user_addr; - this->_user_key = user_key; - this->_user_id = user_id; + this->_network_data.define_user(user_addr, user_key, user_id); } void NetworkConnectionCore::define_lang(String lang) { - this->_lang = lang; + this->_network_data.define_lang(lang); } void NetworkConnectionCore::initialize() { - // Initialize counter - this->_current_received_number = 0; - this->_last_received_number = 0; - this->_quit_id = 0; - this->_long_ack_bit_field.resize(NUM_BITS_IN_LONG_ACK); - this->_latest_probes.clear(); - this->_ack_bit_mask = 0; - this->_last_ack_bit = 0; - this->_last_ack_in_long_ack = 0; - this->_current_server_tick = 0; - this->_current_client_tick = 0; - this->_ms_per_tick = 100; - this->_current_client_time = 0; + this->_network_data.initialize(); } -/* - * Login - */ - -void NetworkConnectionCore::send_system_login() +void NetworkConnectionCore::connect_to_server() { - // Configure socket UDP - this->autodefine_socket_udp(); - if ( this->_state != STATE::NotInitialised ) - { - // DEBUG_PRINT("Close old network socket"); - this->_socketUDP->close(); - } - - OS::get_singleton()->print("Connect to %s:%ld\n", this->_host.ascii().get_data(), this->_port); - this->_socketUDP->set_dest_address(this->_host, this->_port); - // Open connection and send ID - - BitStream msgout; - msgout.put_uint32(_current_received_number); - msgout.put_bool(true); - msgout.put_uint8(CLFECOMMON::SYSTEM_LOGIN_CODE); - msgout.put_string_hexa32(this->_user_addr); - msgout.put_string_hexa32(this->_user_key); - msgout.put_string_hexa32(this->_user_id); - msgout.put_string(this->_lang); - Error ret; - ret = this->_socketUDP->put_packet_buffer(msgout.get_data()); // , msgout.get_data().size() - if ( ret != Error::OK) - { - this->_socketUDP->close(); - switch(ret) - { - case Error::ERR_CANT_CONNECT: - ERR_PRINT("network connexion - Can't connect"); - default: - ERR_PRINT("network connexion - Unknown error"); - } - return; - } - OS::get_singleton()->print("Connected to khganat\n"); - this->_state = STATE::Login; - // Initialize counter - this->initialize(); + this->_state_connexion->connect_to_server(); } /* @@ -176,6 +139,8 @@ void NetworkConnectionCore::send_system_login() void NetworkConnectionCore::send_system_quit() { + this->_state_connexion->send_system_quit(); +/* // TODO - check why we send quit_id if ( this->_state != STATE::Connected && this->_state != STATE::ForceSynchronize ) return; @@ -190,7 +155,8 @@ void NetworkConnectionCore::send_system_quit() { ERR_PRINT("Error to send disconnect"); } - this->_state = STATE::Quit; + //this->_state = STATE::Quit; +*/ } /* @@ -199,6 +165,8 @@ void NetworkConnectionCore::send_system_quit() void NetworkConnectionCore::send_system_disconnect() { + this->_state_connexion->send_system_disconnect(); +/* if ( this->_state != STATE::Connected && this->_state != STATE::ForceSynchronize ) return; OS::get_singleton()->print("[%s:%d] send disconnect to server\n", __FILE__, __LINE__); @@ -213,6 +181,7 @@ void NetworkConnectionCore::send_system_disconnect() } this->_socketUDP->close(); this->_state = STATE::Disconnect; +*/ } /* @@ -221,17 +190,18 @@ void NetworkConnectionCore::send_system_disconnect() void NetworkConnectionCore::disconnect_server() { - if (this->_state != STATE::Connected && this->_state != STATE::ForceSynchronize) - return; + // if (this->_state != STATE::Connected && this->_state != STATE::ForceSynchronize) return; send_system_disconnect(); } /* * Synchronize */ - +/* void NetworkConnectionCore::send_system_ack_sync() { + + this->_state_connexion->send_system_ack_sync(); // khanat-opennel-code/code/ryzom/server/src/frontend_service/fe_receive_sub.cpp:1121 void CFeReceiveSub::handleReceivedMsg( CClientHost *clienthost ) OS::get_singleton()->print("[%s:%d] Send system ACK sync\n", __FILE__, __LINE__); @@ -257,9 +227,11 @@ void NetworkConnectionCore::send_system_ack_sync() msgout.unref(); this->_state = STATE::Connected; } +*/ void NetworkConnectionCore::receive_system_sync(Ref msgin) { + /* int i; bool valide = true; @@ -301,6 +273,7 @@ void NetworkConnectionCore::receive_system_sync(Ref msgin) } else ERR_PRINTS("MSG.XML is wrong"); + */ } /* @@ -309,12 +282,15 @@ void NetworkConnectionCore::receive_system_sync(Ref msgin) void NetworkConnectionCore::receive_system_probe(Ref msgin) { + /* OS::get_singleton()->print("[%s:%d] SYSTEM_PROBE_CODE size:%d\n", __FILE__, __LINE__, this->_latest_probes.size()); this->_latest_probes.append(msgin->get_sint32()); + */ } void NetworkConnectionCore::send_system_ack_probe() { + /* OS::get_singleton()->print("[%s:%d] Send system ACK probe\n", __FILE__, __LINE__); // khanat-opennel-code/code/ryzom/server/src/frontend_service/fe_receive_sub.cpp:1121 void CFeReceiveSub::handleReceivedMsg( CClientHost *clienthost ) if (this->_state != STATE::Connected && this->_state != STATE::ForceSynchronize) @@ -347,9 +323,10 @@ void NetworkConnectionCore::send_system_ack_probe() if (this->_state == STATE::ForceSynchronize && max >= 5) { // We have send ACK, so now we clean all queue and received all message to synchronize - this->queue.clear(); + this->_queue.clear(); this->_state = STATE::Connected; } + */ } /* @@ -358,6 +335,7 @@ void NetworkConnectionCore::send_system_ack_probe() void NetworkConnectionCore::wait_resynchronize(uint32_t current_received_number, Ref msgin) { + /* bool system_mode; this->_current_received_number = current_received_number; system_mode = msgin->get_bool(); @@ -387,6 +365,7 @@ void NetworkConnectionCore::wait_resynchronize(uint32_t current_received_number, } } this->_last_received_number = current_received_number; + */ } /* @@ -395,6 +374,7 @@ void NetworkConnectionCore::wait_resynchronize(uint32_t current_received_number, void NetworkConnectionCore::decode_system_message(Ref msgin) { + /* int message = msgin->get_uint8(); switch (message) { @@ -419,6 +399,7 @@ void NetworkConnectionCore::decode_system_message(Ref msgin) ERR_PRINTS("Received unknown message [" + itos(message) + "]"); break; } + */ } void NetworkConnectionCore::decode_normal_message(Ref msgin) @@ -432,6 +413,7 @@ void NetworkConnectionCore::decode_normal_message(Ref msgin) void NetworkConnectionCore::analyze_message_received(uint32_t current_received_number, Ref msgin) { + /* bool system_mode; bool ackBool = false; int ackBit = 0; @@ -501,66 +483,109 @@ void NetworkConnectionCore::analyze_message_received(uint32_t current_received_n this->decode_system_message(msgin); else this->decode_normal_message(msgin); + */ } -void NetworkConnectionCore::store_message_received(PoolByteArray & msgbytes) +void NetworkConnectionCore::store_message_received(PoolByteArray msgbytes) { - int pos = this->queue.put_msgbytes(msgbytes); + /* + Ref msgin; + msgin.instance(); + msgin->put_data(msgbytes); + uint32_t current_received_number = msgin->get_uint32(); - Ref msgin = this->queue.get_msg(pos); - uint32_t current_received_number = this->queue.get_received_number(pos); + //msgin.put_data(msgbytes); + //uint32_t current_received_number = msgin.get_uint32(); + + OS::get_singleton()->print("[%s:%d] store message (%d)\n", __FILE__, __LINE__, (int)current_received_number); + SHOW_USAGE_MEMORY + + show_memory_usage(); + + Ref msg; + msg.instance(); + msg->put_id(current_received_number); + msg->put_msgin(msgin); + int index = this->_queue.put_bitstreamfield(msg); + msg.unref(); /// TODO - check if max int execeded current_received_number < 1000 this->_last_received_number > 0x80000000 if ( this->_state == STATE::ForceSynchronize ) { - // We have detected a problem of synchro, we wait message ack probe and after server launch a re-sync - wait_resynchronize(current_received_number, msgin); + // We have detected a problem of synchro, we wait message ack probe and after server launch a re-sync + //wait_resynchronize(current_received_number, msgin); + this->_queue.erase_index(index); } else if ( current_received_number - this->_last_received_number <= 0 ) // Received old message { - OS::get_singleton()->print("[%s:%d] current_received_number:%d / queue size:%d\n", __FILE__, __LINE__, current_received_number, this->queue.length()); - this->queue.erase(pos); + OS::get_singleton()->print("[%s:%d] current_received_number:%d / queue size:%d\n", __FILE__, __LINE__, current_received_number, this->_queue.length()); + this->_queue.erase_index(index); return; } else if ( this->_last_received_number + 1 == current_received_number ) // Received next message { - OS::get_singleton()->print("[%s:%d] current_received_number:%u / queue size:%d\n", __FILE__, __LINE__, current_received_number, this->queue.length()); - analyze_message_received(current_received_number, msgin); - this->queue.erase(pos); + OS::get_singleton()->print("[%s:%d] current_received_number:%u / queue size:%d\n", __FILE__, __LINE__, current_received_number, this->_queue.length()); + //analyze_message_received(current_received_number, msgin); + this->_queue.erase_index(index); } else // Received new message (but missing some message between) -> go to queue and cross finger to received the next message (for _last_received_number) { - OS::get_singleton()->print("[%s:%d] current_received_number:%d / queue size:%d\n", __FILE__, __LINE__, current_received_number, this->queue.length()); - if (this->queue.length() >= SIZE_QUEUE_MESSAGE) + OS::get_singleton()->print("[%s:%d] current_received_number:%d / queue size:%d\n", __FILE__, __LINE__, current_received_number, this->_queue.length()); + if (this->_queue.length() >= SIZE_QUEUE_MESSAGE) { ERR_PRINT("Network queue is full / wait re-synchronize"); this->_state = STATE::ForceSynchronize ; return; } } + */ } void NetworkConnectionCore::send_message() { + /* if (this->_latest_probes.size() > 0) send_system_ack_probe(); else if (this->_state == STATE::Synchronize) send_system_ack_sync(); + */ } void NetworkConnectionCore::process(int delta) { - if (this->_state == STATE::Disconnect || this->_state == STATE::NotInitialised) + // this->_state_connexion->process(delta); + if ( this->_socketUDP.is_null() ) return; - OS::get_singleton()->print( "[%s:%d] Process - delta : %d\n", __FILE__, __LINE__, delta); + //OS::get_singleton()->print("[%s:%d] process ...\n", __FILE__, __LINE__); + + // if (this->_state == STATE::Disconnect || this->_state == STATE::NotInitialised) return; + //OS::get_singleton()->print( "[%s:%d] Process - delta : %d\n", __FILE__, __LINE__, delta); + for(int i = 0; (this->_socketUDP->get_available_packet_count() > 0) && (i < MAX_LOOP_READ_BY_STEP) ; ++i) { PoolByteArray msgbytes ; this->_socketUDP->get_packet_buffer(msgbytes); - OS::get_singleton()->print("[%s:%d] Size msg received: %d\n", __FILE__, __LINE__, msgbytes.size()); - store_message_received(msgbytes); + OS::get_singleton()->print("[%s:%d] Size msg received: %d (i:%d, state:%d, size queue:%d)\n", __FILE__, __LINE__, msgbytes.size(), i, this->get_state(), this->_queue.length()); + + SHOW_USAGE_MEMORY + + // store_message_received(msgbytes); + + Ref msgin; + msgin.instance(); + msgin->put_data(msgbytes); + uint32_t current_received_number = msgin->get_uint32(); + Ref msg; + msg.instance(); + msg->put_id(current_received_number); + msg->put_msgin(msgin); + int index = this->_queue.put_bitstreamfield(msg); + msgin.unref(); + msg.unref(); + this->_state_connexion->receive_message(index); } - send_message(); + this->_state_connexion->send_message(); + //OS::get_singleton()->print("[%s:%d] --------------------------------\n", __FILE__, __LINE__); } bool NetworkConnectionCore::is_active() diff --git a/modules/networkconnection/network_connection_core.h b/modules/networkconnection/network_connection_core.h index b0843e7..6fd0ead 100644 --- a/modules/networkconnection/network_connection_core.h +++ b/modules/networkconnection/network_connection_core.h @@ -25,37 +25,10 @@ #include "core/io/packet_peer_udp.h" #include "modules/bitset/bitset.h" #include "modules/bitstreamqueue/bitstreamqueue.h" +#include "state_connexion.h" +#include "network_data.h" #define MAX_LOOP_READ_BY_STEP 10 -#define NUM_BITS_IN_LONG_ACK 512 - -enum STATE { - NotInitialised = 0, - //NotConnected = 1, // When received a cookie - not used here - //Authenticate = 2, - Login = 3, - Synchronize = 4, - Connected = 5, // State when we are connecte - //Probe = 6, - //Stalled = 7, - Disconnect = 8, - Quit = 9, - ForceSynchronize = 10 -}; - -enum CLFECOMMON { - SYSTEM_LOGIN_CODE = 0, - SYSTEM_SYNC_CODE = 1, - SYSTEM_ACK_SYNC_CODE = 2, - SYSTEM_PROBE_CODE = 3, - SYSTEM_ACK_PROBE_CODE = 4, - SYSTEM_DISCONNECTION_CODE = 5, - SYSTEM_STALLED_CODE = 6, - SYSTEM_SERVER_DOWN_CODE = 7, - SYSTEM_QUIT_CODE = 8, - SYSTEM_ACK_QUIT_CODE = 9, - NUMBITSINLONGACK = 512 -}; #define LCT 100 @@ -63,35 +36,34 @@ class NetworkConnectionCore : public Reference { GDCLASS(NetworkConnectionCore, Reference) private: static NetworkConnectionCore *singleton; + friend class StateConnectionBase; + friend class StateConnectionNotInitialized; + friend class StateConnectionLogin; + friend class StateConnectionSynchronize; + friend class StateConnectionConnected; + friend class StateConnectionQuit; - STATE _state; - uint32_t _ack_bit_mask; - uint32_t _current_server_tick; - uint32_t _current_client_tick; - uint32_t _synchronize; - uint32_t _current_received_number; - uint32_t _last_received_number; - uint32_t _ms_per_tick; - uint32_t _current_client_time; - uint32_t _update_time; - int32_t _quit_id; - int32_t _last_ack_bit; - uint32_t _last_ack_in_long_ack; - int32_t _latest_sync; +protected: int64_t _port; - String _host; - String _lang; - String _user_addr; - String _user_key; - String _user_id; + Ref _socketUDP; - BitSet _long_ack_bit_field; - Array _latest_probes; - Array _checksum_msg_xml; - BitStreamQueue queue; + BitStreamQueue _queue; + + StateConnectionNotInitialized _state_not_initialized; + StateConnectionLogin _state_login; + StateConnectionSynchronize _state_synchronize; + StateConnectionConnected _state_connected; + StateConnectionQuit _state_quit; + + StateConnectionBase * _state_connexion; + + NetworkData _network_data; + //MessageDescriptionNode _message_description_node; + void open_network(); + void close_network(); public: static NetworkConnectionCore * get_singleton(); @@ -110,8 +82,8 @@ public: void define_lang(String lang); void initialize(); + void connect_to_server(); - void send_system_login(); void send_system_disconnect(); void send_system_quit(); void disconnect_server(); @@ -126,7 +98,7 @@ public: void decode_normal_message(Ref msgin); void wait_resynchronize(uint32_t current_received_number, Ref msgin); void analyze_message_received(uint32_t current_received_number, Ref msgin); - void store_message_received(PoolByteArray & msgbytes); + void store_message_received(PoolByteArray msgbytes); void send_message(); void process(int delta); bool connected(); @@ -135,5 +107,4 @@ public: //MessageDescriptionNode & get_master_message_description_node(); }; - #endif diff --git a/modules/networkconnection/network_data.cpp b/modules/networkconnection/network_data.cpp new file mode 100644 index 0000000..405068e --- /dev/null +++ b/modules/networkconnection/network_data.cpp @@ -0,0 +1,70 @@ +/* + Library NetworkData + + Copyright (C) 2019 AleaJactaEst + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +#include "network_data.h" + +NetworkData::NetworkData() +{ + this->initialize(); +} + +NetworkData::~NetworkData() +{ +} + +void NetworkData::initialize() +{ + // Initialize counter + this->_current_received_number = 0; + this->_last_received_number = 0; + this->_quit_id = 0; + this->_long_ack_bit_field.resize(NUM_BITS_IN_LONG_ACK); + this->_latest_probes.clear(); + this->_ack_bit_mask = 0; + this->_last_ack_bit = 0; + this->_last_ack_in_long_ack = 0; + this->_current_server_tick = 0; + this->_current_client_tick = 0; + this->_ms_per_tick = 100; + this->_current_client_time = 0; + + this->_server_sync = 0; + this->_client_sync = 0; +} + +void NetworkData::define_lang(String lang) +{ + this->_lang = lang; +} + +void NetworkData::define_user(String user_addr, String user_key, String user_id) +{ + this->_user_addr = user_addr; + this->_user_key = user_key; + this->_user_id = user_id; +} + +void NetworkData::define_checksum_msg_xml(Array & checksum_msg_xml) +{ + //DEBUG_PRINT("Received msg.xml checksum"); + this->_checksum_msg_xml = checksum_msg_xml; + //DEBUG_PRINT("Received msg.xml checksum " + itos(checksum_msg_xml.size())); + //DEBUG_PRINT("Received msg.xml checksum " + itos(this->_checksum_msg_xml.size())); +} \ No newline at end of file diff --git a/modules/networkconnection/network_data.h b/modules/networkconnection/network_data.h new file mode 100644 index 0000000..1204a80 --- /dev/null +++ b/modules/networkconnection/network_data.h @@ -0,0 +1,74 @@ +/* + Header NetworkData + + Copyright (C) 2019 AleaJactaEst + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +#ifndef NETWORK_DATA_H +#define NETWORK_DATA_H + +// #include "core/reference.h" +// #include "core/io/packet_peer_udp.h" +#include "modules/bitset/bitset.h" +#include "core/ustring.h" + +#define MAX_LOOP_READ_BY_STEP 10 +#define NUM_BITS_IN_LONG_ACK 512 + +class NetworkData +{ +public: + uint32_t _ack_bit_mask; + + uint32_t _current_server_tick; + uint32_t _current_client_tick; + + uint32_t _synchronize; + + uint32_t _current_received_number; + uint32_t _last_received_number; + + uint32_t _ms_per_tick; + uint32_t _current_client_time; + uint32_t _update_time; + int32_t _quit_id; + int32_t _last_ack_bit; + uint32_t _last_ack_in_long_ack; + + int32_t _client_sync; + int32_t _server_sync; + + String _lang; + String _user_addr; + String _user_key; + String _user_id; + + BitSet _long_ack_bit_field; + Array _latest_probes; + Array _checksum_msg_xml; + + NetworkData(); + ~NetworkData(); + + void initialize(); + void define_lang(String lang); + void define_user(String user_addr, String user_key, String user_id); + void define_checksum_msg_xml(Array & checksum_msg_xml); + +}; + +#endif \ No newline at end of file diff --git a/modules/networkconnection/state_connexion.cpp b/modules/networkconnection/state_connexion.cpp new file mode 100644 index 0000000..704596c --- /dev/null +++ b/modules/networkconnection/state_connexion.cpp @@ -0,0 +1,417 @@ +/* + Library to manage state connexion + + Copyright (C) 2019 AleaJactaEst + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + */ + +#include "check_memory.h" +#include "state_connexion.h" +#include "network_connection_core.h" + +/* + * StateConnectionBase + */ + +StateConnectionBase::StateConnectionBase(NetworkConnectionCore * network) +{ + this->_network = network; + this->_data = & (network->_network_data); +} + +/* + * StateConnectionNotInitialized + */ + +void StateConnectionNotInitialized::connect_to_server() +{ + this->_network->_queue.clear(); + this->_network->open_network(); + this->_network->_state_connexion = & this->_network->_state_login; + OS::get_singleton()->print("[%s:%d] connect_to_server\n", __FILE__, __LINE__); +} + +/* + * StateConnectionLogin + */ +void StateConnectionLogin::send_system_quit() +{ + OS::get_singleton()->print("[%s:%d] send quit to server\n", __FILE__, __LINE__); + BitStream msgout; + msgout.put_uint32(this->_data->_current_received_number); + msgout.put_bool(true); + msgout.put_uint8(CLFECOMMON::SYSTEM_QUIT_CODE); + msgout.put_sint32(this->_data->_quit_id); + + if ( this->_network->_socketUDP->put_packet_buffer(msgout.get_data()) != Error::OK ) + { + ERR_PRINT("Error to send disconnect"); + } + this->_network->_state_connexion = & this->_network->_state_quit; +} + +void StateConnectionLogin::send_message() +{ + BitStream msgout; + msgout.put_uint32(this->_data->_current_received_number); + msgout.put_bool(true); + msgout.put_uint8(CLFECOMMON::SYSTEM_LOGIN_CODE); + msgout.put_string_hexa32(this->_data->_user_addr); + msgout.put_string_hexa32(this->_data->_user_key); + msgout.put_string_hexa32(this->_data->_user_id); + msgout.put_string(this->_data->_lang); + Error ret; + ret = this->_network->_socketUDP->put_packet_buffer(msgout.get_data()); // , msgout.get_data().size() + if ( ret != Error::OK) + { + this->_network->close_network(); + switch(ret) + { + case Error::ERR_CANT_CONNECT: + ERR_PRINT("network connexion - Can't connect"); + default: + ERR_PRINT("network connexion - Unknown error"); + } + return; + } + OS::get_singleton()->print("[%s:%d] Connected to khganat\n", __FILE__, __LINE__); + this->_network->_state_connexion = & this->_network->_state_synchronize; +} + +/* + * StateConnectionSynchronize + */ + +void StateConnectionSynchronize::send_system_quit() +{ + OS::get_singleton()->print("[%s:%d] send quit to server\n", __FILE__, __LINE__); + BitStream msgout; + msgout.put_uint32(this->_data->_current_received_number); + msgout.put_bool(true); + msgout.put_uint8(CLFECOMMON::SYSTEM_QUIT_CODE); + msgout.put_sint32(this->_data->_quit_id); + + if ( this->_network->_socketUDP->put_packet_buffer(msgout.get_data()) != Error::OK ) + { + ERR_PRINT("Error to send quit"); + } + this->_network->_state_connexion = & this->_network->_state_quit; +} + +void StateConnectionSynchronize::send_system_ack_sync() +{ + OS::get_singleton()->print("[%s:%d] send system ACK Sync to server\n", __FILE__, __LINE__); + Ref msgout; + msgout.instance(); + msgout->put_uint32(this->_data->_current_received_number); + msgout->put_bool(true); + msgout->put_uint8(CLFECOMMON::SYSTEM_ACK_SYNC_CODE); + msgout->put_sint32(this->_data->_last_received_number); + msgout->put_sint32(this->_data->_last_ack_in_long_ack); + this->_data->_long_ack_bit_field.write_serial(msgout); + msgout->put_sint32(this->_data->_server_sync); + if (this->_network->_socketUDP->put_packet_buffer(msgout->get_data()) != Error::OK) + { + ERR_PRINT("Error to send ack sync"); + return; + } + msgout.unref(); + this->_data->_client_sync = this->_data->_server_sync; + this->_network->_state_connexion = & this->_network->_state_connected; +} + +void StateConnectionSynchronize::receive_system_sync(Ref msgin) +{ + bool valide = true; + int i; + OS::get_singleton()->print("[%s:%d] SYSTEM_SYNC_CODE\n", __FILE__, __LINE__); + + uint32_t synchronize = msgin->get_uint32(); + int64_t stime = msgin->get_sint64(); + uint32_t latestsync = msgin->get_uint32(); + PoolByteArray msg_xml = msgin->get_array_uint8(16); + PoolByteArray database_xml = msgin->get_array_uint8(16); + + OS::get_singleton()->print("[%s:%d] SYSTEM_SYNC_CODE synchronize:%u, stime:%ld, latestsync:%u\n", __FILE__, __LINE__, synchronize, stime, latestsync); + + if ( msg_xml.size() != this->_data->_checksum_msg_xml.size() ) + { + valide = false; + ERR_PRINTS("MSG XML is incorrect (server:" + itos(msg_xml.size()) +", client:" + itos(this->_data->_checksum_msg_xml.size()) + ")"); + } + else + { + for(i=0; i_data->_checksum_msg_xml[i] ) + { + valide = false; + ERR_PRINTS("MSG XML is incorrect (pos:" + itos(i) +")"); + } + } + } + + if ( valide == true ) + { + OS::get_singleton()->print("[%s:%d] MSG XML is correct\n", __FILE__, __LINE__); + this->_data->_server_sync = latestsync; + this->_data->_synchronize = synchronize; + this->_data->_current_server_tick = this->_data->_synchronize + this->_data->_current_received_number + 2; + this->_data->_current_client_tick = this->_data->_current_server_tick + (LCT + this->_data->_ms_per_tick) / this->_data->_ms_per_tick; + this->_data->_current_client_time = this->_data->_update_time - (LCT + this->_data->_ms_per_tick); + //this->_state = STATE::Synchronize; + } + else + ERR_PRINTS("MSG.XML is wrong"); +} + +void StateConnectionSynchronize::receive_message(int index) +{ + bool system_mode; + + OS::get_singleton()->print("[%s:%d] receive_message ...\n", __FILE__, __LINE__); + + //this->_data->_current_received_number = current_received_number; + Ref field = this->_network->_queue.get_msg(index); + uint32_t current_received_number = field->get_id(); + Ref msgin = field->get_msgin(); + + this->_data->_current_received_number = current_received_number; + + //Ref msgin = this->_network->_queue.get_msg(index)->get_msgin(); + system_mode = msgin->get_bool(); + if ( system_mode == true ) + { + int message = msgin->get_uint8(); + switch (message) + { + case CLFECOMMON::SYSTEM_LOGIN_CODE: + OS::get_singleton()->print("[%s:%d] SYSTEM_LOGIN_CODE\n", __FILE__, __LINE__); + break; + case CLFECOMMON::SYSTEM_SYNC_CODE: + this->receive_system_sync(msgin); + break; + case CLFECOMMON::SYSTEM_STALLED_CODE: + OS::get_singleton()->print("[%s:%d] SYSTEM_STALLED_CODE\n", __FILE__, __LINE__); + break; + case CLFECOMMON::SYSTEM_SERVER_DOWN_CODE: + OS::get_singleton()->print("[%s:%d] SYSTEM_SERVER_DOWN_CODE\n", __FILE__, __LINE__); + break; + case CLFECOMMON::SYSTEM_PROBE_CODE: + OS::get_singleton()->print("[%s:%d] SYSTEM_PROBE_CODE\n", __FILE__, __LINE__); + break; + default: + ERR_PRINTS("Received unknown message [" + itos(message) + "]"); + break; + } + } + // this->_last_received_number = current_received_number; + this->_network->_queue.erase_index(index); +} + +void StateConnectionSynchronize::send_message() +{ + //OS::get_singleton()->print("[%s:%d] send_system %d / %d \n", __FILE__, __LINE__, this->_data->_server_sync, this->_data->_client_sync); + if ( this->_data->_server_sync != this->_data->_client_sync ) + this->send_system_ack_sync(); +} + +/* + * StateConnectionConnected + */ + +void StateConnectionConnected::send_system_quit() +{ + OS::get_singleton()->print("[%s:%d] send quit to server\n", __FILE__, __LINE__); + BitStream msgout; + msgout.put_uint32(this->_data->_current_received_number); + msgout.put_bool(true); + msgout.put_uint8(CLFECOMMON::SYSTEM_QUIT_CODE); + msgout.put_sint32(this->_data->_quit_id); + + if ( this->_network->_socketUDP->put_packet_buffer(msgout.get_data()) != Error::OK ) + { + ERR_PRINT("Error to send disconnect"); + } + this->_network->_state_connexion = & this->_network->_state_quit; +} + +void StateConnectionConnected::send_system_disconnect() +{ + //if ( this->_state != STATE::Connected && this->_state != STATE::ForceSynchronize ) return; + OS::get_singleton()->print("[%s:%d] send disconnect to server\n", __FILE__, __LINE__); + BitStream msgout; + msgout.put_uint32(this->_data->_current_received_number); + msgout.put_bool(true); + msgout.put_uint8(CLFECOMMON::SYSTEM_DISCONNECTION_CODE); + + if ( this->_network->_socketUDP->put_packet_buffer(msgout.get_data()) != Error::OK ) + { + ERR_PRINT("Error to send disconnect"); + } + this->_network->_socketUDP->close(); + // this->_state = STATE::Disconnect; + this->_network->_state_connexion = & this->_network->_state_not_initialized; +} + +void StateConnectionConnected::send_system_ack_sync() +{ + OS::get_singleton()->print("[%s:%d] send system ACK Sync to server\n", __FILE__, __LINE__); + + Ref msgout; + msgout.instance(); + msgout->put_uint32(this->_data->_current_received_number); + msgout->put_bool(true); + msgout->put_uint8(CLFECOMMON::SYSTEM_ACK_SYNC_CODE); + msgout->put_sint32(this->_data->_last_received_number); + msgout->put_sint32(this->_data->_last_ack_in_long_ack); + this->_data->_long_ack_bit_field.write_serial(msgout); + msgout->put_sint32(this->_data->_server_sync); + if (this->_network->_socketUDP->put_packet_buffer(msgout->get_data()) != Error::OK) + { + ERR_PRINT("Error to send ack sync"); + return; + } + msgout.unref(); + this->_data->_client_sync = this->_data->_server_sync; +} + +void StateConnectionConnected::send_system_ack_probe() +{ + // khanat-opennel-code/code/ryzom/server/src/frontend_service/fe_receive_sub.cpp:1121 void CFeReceiveSub::handleReceivedMsg( CClientHost *clienthost ) + OS::get_singleton()->print("[%s:%d] send system ACK PROBE to server\n", __FILE__, __LINE__); + int max = this->_data->_latest_probes.size() ; + + BitStream msgout; + msgout.put_uint32(this->_data->_current_received_number); + msgout.put_bool(true); + msgout.put_uint8(CLFECOMMON::SYSTEM_ACK_PROBE_CODE); + msgout.put_sint32(max); + for(int i=0; i < max ; ++i ) + { + int data = this->_data->_latest_probes[i]; + msgout.put_sint32(data); + } + if (this->_network->_socketUDP->put_packet_buffer(msgout.get_data()) != Error::OK) + { + ERR_PRINT("Error to send disconnect"); + return; + } + this->_data->_latest_probes.clear(); +} + +void StateConnectionConnected::receive_system_sync(Ref msgin) +{ + bool valide = true; + int i; + OS::get_singleton()->print("[%s:%d] SYSTEM_SYNC_CODE\n", __FILE__, __LINE__); + + uint32_t synchronize = msgin->get_uint32(); + int64_t stime = msgin->get_sint64(); + uint32_t latestsync = msgin->get_uint32(); + PoolByteArray msg_xml = msgin->get_array_uint8(16); + PoolByteArray database_xml = msgin->get_array_uint8(16); + + OS::get_singleton()->print("[%s:%d] SYSTEM_SYNC_CODE synchronize:%u, stime:%ld, latestsync:%u\n", __FILE__, __LINE__, synchronize, stime, latestsync); + + if ( msg_xml.size() != this->_data->_checksum_msg_xml.size() ) + { + valide = false; + ERR_PRINTS("MSG XML is incorrect (server:" + itos(msg_xml.size()) +", client:" + itos(this->_data->_checksum_msg_xml.size()) + ")"); + } + else + { + for(i=0; i_data->_checksum_msg_xml[i] ) + { + valide = false; + ERR_PRINTS("MSG XML is incorrect (pos:" + itos(i) +")"); + } + } + } + + if ( valide == true ) + { + OS::get_singleton()->print("[%s:%d] MSG XML is correct\n", __FILE__, __LINE__); + this->_data->_server_sync = latestsync; + this->_data->_synchronize = synchronize; + this->_data->_current_server_tick = this->_data->_synchronize + this->_data->_current_received_number + 2; + this->_data->_current_client_tick = this->_data->_current_server_tick + (LCT + this->_data->_ms_per_tick) / this->_data->_ms_per_tick; + this->_data->_current_client_time = this->_data->_update_time - (LCT + this->_data->_ms_per_tick); + //this->_state = STATE::Synchronize; + } + else + ERR_PRINTS("MSG.XML is wrong"); +} + +void StateConnectionConnected::receive_message(int index) +{ + // SHOW_USAGE_MEMORY + bool system_mode; + + Ref field = this->_network->_queue.get_msg(index); + uint32_t current_received_number = field->get_id(); + this->_data->_current_received_number = current_received_number; + Ref msgin = field->get_msgin(); + + system_mode = msgin->get_bool(); + if ( system_mode == true ) + { + //OS::get_singleton()->print("[%s:%d] system message (%d) [%d]\n", __FILE__, __LINE__, (int)current_received_number, this->_network->_queue.length()); + int message = msgin->get_uint8(); + switch (message) + { + case CLFECOMMON::SYSTEM_LOGIN_CODE: + OS::get_singleton()->print("[%s:%d] Receive SYSTEM_LOGIN_CODE (%d) [%d]\n", __FILE__, __LINE__, (int)current_received_number, this->_network->_queue.length()); + break; + case CLFECOMMON::SYSTEM_SYNC_CODE: + OS::get_singleton()->print("[%s:%d] Receive SYSTEM_SYNC_CODE (%d) [%d]\n", __FILE__, __LINE__, (int)current_received_number, this->_network->_queue.length()); + this->receive_system_sync(msgin); + break; + case CLFECOMMON::SYSTEM_STALLED_CODE: + OS::get_singleton()->print("[%s:%d] Receive SYSTEM_STALLED_CODE (%d) [%d]\n", __FILE__, __LINE__, (int)current_received_number, this->_network->_queue.length()); + break; + case CLFECOMMON::SYSTEM_SERVER_DOWN_CODE: + OS::get_singleton()->print("[%s:%d] Receive SYSTEM_SERVER_DOWN_CODE (%d) [%d]\n", __FILE__, __LINE__, (int)current_received_number, this->_network->_queue.length()); + break; + case CLFECOMMON::SYSTEM_PROBE_CODE: + OS::get_singleton()->print("[%s:%d] Receive SYSTEM_PROBE_CODE (%d) [%d]\n", __FILE__, __LINE__, (int)current_received_number, this->_network->_queue.length()); + this->_data->_latest_probes.append(msgin->get_sint32()); + break; + default: + OS::get_singleton()->print("[%s:%d] Receive UNKNOWN SYSTEM MESSAGE [id:%d] (%d) [%d]\n", __FILE__, __LINE__, message, (int)current_received_number, this->_network->_queue.length()); + //ERR_PRINTS("Received unknown message [" + itos(message) + "]"); + break; + } + } + else + { + OS::get_singleton()->print("[%s:%d] application message (%d) [%d]\n", __FILE__, __LINE__, (int)current_received_number, this->_network->_queue.length()); + } + this->_network->_queue.erase_index(index); +} + +void StateConnectionConnected::send_message() +{ + if ( this->_data->_server_sync != this->_data->_client_sync ) + this->send_system_ack_sync(); + if (this->_data->_latest_probes.size() != 0 ) + this->send_system_ack_probe(); +} +/* + * + */ \ No newline at end of file diff --git a/modules/networkconnection/state_connexion.h b/modules/networkconnection/state_connexion.h new file mode 100644 index 0000000..7b5856f --- /dev/null +++ b/modules/networkconnection/state_connexion.h @@ -0,0 +1,144 @@ +/* + Header NetworkConnectionCore + + Copyright (C) 2019 AleaJactaEst + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +#ifndef STATE_CONNEXION_H +#define STATE_CONNEXION_H + +#include "core/reference.h" +#include "core/io/packet_peer_udp.h" +#include "modules/bitset/bitset.h" +#include "modules/bitstreamqueue/bitstreamqueue.h" +#include "network_data.h" + +#define NUM_BITS_IN_LONG_ACK 512 + +enum STATE { + NotInitialised = 0, + //NotConnected = 1, // When received a cookie - not used here + //Authenticate = 2, + Login = 3, + Synchronize = 4, + Connected = 5, // State when we are connecte + //Probe = 6, + //Stalled = 7, + Disconnect = 8, + Quit = 9, + ForceSynchronize = 10 +}; + +enum CLFECOMMON { + SYSTEM_LOGIN_CODE = 0, + SYSTEM_SYNC_CODE = 1, + SYSTEM_ACK_SYNC_CODE = 2, + SYSTEM_PROBE_CODE = 3, + SYSTEM_ACK_PROBE_CODE = 4, + SYSTEM_DISCONNECTION_CODE = 5, + SYSTEM_STALLED_CODE = 6, + SYSTEM_SERVER_DOWN_CODE = 7, + SYSTEM_QUIT_CODE = 8, + SYSTEM_ACK_QUIT_CODE = 9, + NUMBITSINLONGACK = 512 +}; + + +class NetworkConnectionCore; + +// Virtual class reference for network state +class StateConnectionBase +{ +protected: + NetworkConnectionCore * _network; + NetworkData * _data; +public: + StateConnectionBase(NetworkConnectionCore * network); + ~StateConnectionBase() {} + virtual int get_state() {return STATE::NotInitialised;} + virtual void connect_to_server() {} + virtual void send_message() {} + //virtual void send_system_login() {} + virtual void send_system_quit() {} + virtual void send_system_disconnect() {} + // virtual void send_system_ack_sync() {} + + virtual void receive_message(int index) {} + virtual void send_system() {} +}; + +// class define state not initialized +class StateConnectionNotInitialized : public StateConnectionBase +{ +public: + StateConnectionNotInitialized(NetworkConnectionCore * network) : StateConnectionBase(network) {} + ~StateConnectionNotInitialized() {} + int get_state() {return STATE::NotInitialised;} + void connect_to_server(); +}; + +// class define state login +class StateConnectionLogin : public StateConnectionBase +{ +public: + StateConnectionLogin(NetworkConnectionCore * network) : StateConnectionBase(network) {} + ~StateConnectionLogin() {} + int get_state() {return STATE::Login;} + void send_system_quit(); + void send_message(); +}; + +// class define state synchronize +class StateConnectionSynchronize : public StateConnectionBase +{ +public: + StateConnectionSynchronize(NetworkConnectionCore * network) : StateConnectionBase(network) {} + ~StateConnectionSynchronize() {} + int get_state() {return STATE::Synchronize;} + void receive_system_sync(Ref msgin); + void send_system_quit(); + void send_system_ack_sync(); + void receive_message(int index); + void send_message(); +}; + +// class define state connected +class StateConnectionConnected : public StateConnectionBase +{ +public: + StateConnectionConnected(NetworkConnectionCore * network) : StateConnectionBase(network) {} + ~StateConnectionConnected() {} + int get_state() {return STATE::Connected;} + void send_system_quit(); + void send_system_disconnect(); + void send_system_ack_sync(); + void send_system_ack_probe(); + void receive_system_sync(Ref msgin); + void receive_message(int index); + void send_message(); +}; + +// class define state quit +class StateConnectionQuit : public StateConnectionBase +{ +public: + StateConnectionQuit(NetworkConnectionCore * network) : StateConnectionBase(network) {} + ~StateConnectionQuit() {} + int get_state() {return STATE::Quit;} +}; + +#endif \ No newline at end of file diff --git a/project.godot b/project.godot index 6e8097d..4e32a18 100644 --- a/project.godot +++ b/project.godot @@ -30,6 +30,11 @@ msg="*res://assets/Scripts/Definition/msg.gd" [debug] settings/stdout/verbose_stdout=true +gdscript/warnings/unused_class_variable=true +gdscript/warnings/unsafe_property_access=true +gdscript/warnings/unsafe_method_access=true +gdscript/warnings/unsafe_cast=true +gdscript/warnings/unsafe_call_argument=true [display]