diff --git a/README.md b/README.md
index d03a004..8d51262 100644
--- a/README.md
+++ b/README.md
@@ -31,13 +31,15 @@ scons -C godot-cpp platform=linux generate_bindings=yes custom_api_file=godot_he
### Build on 64bits
```
-scons -C gdnative platform=linux bits=64
+scons -C gdnative platform=linux bits=64 target=debug
+scons -C gdnative platform=linux bits=64 target=release
```
### Build on 32bits
```
-scons -C gdnative platform=linux bits=32
+scons -C gdnative platform=linux bits=32 target=debug
+scons -C gdnative platform=linux bits=64 target=release
```
## Package client khaganat
diff --git a/addons/ui_window/ui_window.gd b/addons/ui_window/ui_window.gd
index f89168b..ed0845d 100644
--- a/addons/ui_window/ui_window.gd
+++ b/addons/ui_window/ui_window.gd
@@ -111,7 +111,6 @@ func _enter_tree():
background.self_modulate = background_color
self.add_window_part( background )
- print("[ui_window:3]")
# background.set_owner( self )
###
###
diff --git a/assets/Scripts/Definition/msg.gd b/assets/Scripts/Definition/msg.gd
index 2bce062..4940478 100644
--- a/assets/Scripts/Definition/msg.gd
+++ b/assets/Scripts/Definition/msg.gd
@@ -10,12 +10,16 @@ var _msg_data = {}
func open_message_xml():
var file = File.new()
+ # Calculate MD5SUM
file.open("res://assets/Definition/msg.xml", File.READ)
var content = file.get_as_text()
_msg_md5sum = content.md5_text()
file.close()
+ print("[res://assets/Scripts/Definition/msg.gd:open_message_xml] checksum for msg.xml:" + _msg_md5sum)
+ var NetworkConnexion = preload("res://networkconnexion.gdns").new()
+ NetworkConnexion.define_checksum_msg_xml(content.md5_buffer())
+ # Load XML data
_msg_xml.open("res://assets/Definition/msg.xml")
- print("[msg:open_message_xml] " + _msg_md5sum)
func is_correct_md5(value):
return (_msg_md5sum == value)
@@ -26,6 +30,8 @@ func read_all_node():
var ret = _msg_xml.read()
var branch = ""
var leaf = ""
+ var ibranch = 0
+ var ileaf = 0
while ret == OK:
#print("Node: Name:" + _msg_xml.get_node_name() + ", Type:" + str(_msg_xml.get_node_type()) + ", Data:" + str(_msg_xml.get_node_data()) + ", attribut count:" + str(_msg_xml.get_attribute_count()) )
#i = 0
@@ -44,7 +50,9 @@ func read_all_node():
if i < _msg_xml.get_attribute_count():
branch = _msg_xml.get_attribute_value(i)
#print(branch + " " + str(_msg_xml.get_node_type()))
- _msg_data[branch] = []
+ _msg_data[branch] = {"leaf": {}, "pos": ibranch}
+ ibranch += 1
+ ileaf = 0
"leaf":
i = 0
while i < _msg_xml.get_attribute_count() and _msg_xml.get_attribute_name(i) != "name":
@@ -52,21 +60,35 @@ func read_all_node():
if i < _msg_xml.get_attribute_count():
leaf = _msg_xml.get_attribute_value(i)
#print(branch + ":" + leaf + str(_msg_xml.get_node_type()))
- _msg_data[branch].append(leaf)
+ _msg_data[branch]["leaf"][leaf] = ileaf
+ ileaf += 1
ret = _msg_xml.read()
- print("Branch:" + str(_msg_data.size()))
- for key in _msg_data:
- print(" " + key + ":" + str(_msg_data[key].size()))
- for leaf in _msg_data[key]:
- print(" " + key + ":" + leaf)
+ if ProjectSettings.get_setting("khaganat/debug_mode"):
+ #print("Branch:" + str(_msg_data.size()))
+ var sizebranch = _msg_data.size()
+ for key in _msg_data:
+ var sizeleaf = _msg_data[key]["leaf"].size()
+ print(" " + key + " -> " + str(_msg_data[key]["pos"]) + "/" + str(sizebranch))
+ for leaf in _msg_data[key]["leaf"]:
+ var opt = str(_msg_data[key]["pos"]) + "/" + str(sizebranch) + " : " + str(_msg_data[key]["leaf"][leaf]) + "/" + str(sizeleaf)
+ print(" " + key + ":" + leaf + " -> " + opt)
# Called when the node enters the scene tree for the first time.
func _ready():
open_message_xml()
read_all_node()
- print("[msg] ready")
+ print("[res://assets/Scripts/Definition/msg.gd] ready")
+
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass
+
+
+func read_msg(msgin):
+ pass
+
+
+func write_msg(value):
+ pass
\ No newline at end of file
diff --git a/assets/Scripts/Network/net_low_level.gd b/assets/Scripts/Network/net_low_level.gd
index 6a36314..a2a4e93 100644
--- a/assets/Scripts/Network/net_low_level.gd
+++ b/assets/Scripts/Network/net_low_level.gd
@@ -20,292 +20,32 @@
extends Control
-enum TCONNECTIONSTATE {
- NOTINITIALISED = 0, # nothing happened yet
- NOTCONNECTED = 1, # init() called
- AUTHENTICATE = 2, # connect() called, identified by the login server
- LOGIN = 3, # connecting to the frontend, sending identification
- SYNCHRONIZE = 4, # connection accepted by the frontend, synchronizing
- CONNECTED = 5, # synchronized, connected, ready to work
- PROBE = 6, # connection lost by frontend, probing for response
- STALLED = 7, # server is stalled
- DISCONNECT = 8, # disconnect() called, or timeout, or connection closed by frontend
- QUIT = 9}
-
-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}
-
-const NUM_BITS_IN_LONG_ACK = 512
-
-var _connection_state
-
-var _socketUDP
-
-var _user_addr
-var _user_key
-var _user_id
-
-var _current_received_number
-var _last_received_number
-var _confirmed_received_number
-
-var _last_ack_bit
-var _ack_bit_mask
-var _long_ack_bit_field
-var _last_ack_in_long_ack
-var _latest_sync
-
-var _latest_probe_time
-var _latest_probe
-var _latest_probes
-
-var _quit_id
-var _update_time
-var _queue_message_system
-
-var _khaganat_host = "localhost"
-var _khaganat_port = "47851"
-
onready var BitStream = preload("res://bitstream.gdns")
onready var BitSet = preload("res://bitset.gdns")
+onready var NetworkConnexion = preload("res://networkconnexion.gdns")
+
+var _networkconnexion
func _ready():
- _current_received_number = 0
- _last_received_number = 0
- _confirmed_received_number = 0
- _last_ack_bit = 0
- _ack_bit_mask = 0
- _connection_state = TCONNECTIONSTATE.NOTINITIALISED
- _socketUDP = PacketPeerUDP.new()
- _queue_message_system = Array()
- _long_ack_bit_field = BitSet.new()
- _long_ack_bit_field.resize(512)
- _last_ack_in_long_ack = 0
- _latest_sync = 0
- _latest_probe_time = 0
- _latest_probe = 0
- _latest_probes = Array()
- _update_time = 0
- _quit_id = 0
+ _networkconnexion = NetworkConnexion.new()
-func send_system_login(user_addr, user_key, user_id, lang):
- var msgout = BitStream.new()
- msgout.put_sint32(_current_received_number)
- msgout.put_bool(true)
- msgout.put_uint8(CLFECOMMON.SYSTEM_LOGIN_CODE)
- msgout.put_string_hexa32(user_addr)
- msgout.put_string_hexa32(user_key)
- msgout.put_string_hexa32(user_id)
- msgout.put_string(lang)
- print("[net_low_level:send_system_login] Send System Login :" + msgout.show())
- # To connect you need send 1st message
- var res = _socketUDP.put_packet(msgout.get_data())
- if ( res != OK):
- print("[net_low_level:send_system_login] Error to send system login : " + str(res))
- return
- _connection_state = TCONNECTIONSTATE.CONNECTED
-
-func send_system_sync():
- var msgout = BitStream.new()
- msgout.put_sint32(_current_received_number)
- msgout.put_bool(true)
- msgout.put_uint8(CLFECOMMON.SYSTEM_ACK_SYNC_CODE)
- msgout.put_sint32(_last_received_number)
- msgout.put_sint32(_last_ack_in_long_ack)
- _long_ack_bit_field.write_serial(msgout)
- msgout.put_sint32(_latest_sync)
- _queue_message_system.append(msgout)
-
-func send_system_ack_probe():
- var msgout = BitStream.new()
- msgout.put_sint32(_current_received_number)
- msgout.put_bool(true)
- msgout.put_uint8(CLFECOMMON.SYSTEM_ACK_PROBE_CODE)
- msgout.put_sint32(_latest_probes.size())
- for data in _latest_probes:
- msgout.put_sint32(data)
- _latest_probes.clear()
- #_queue_message_system.append(msgout)
- var res = _socketUDP.put_packet(msgout.get_data())
- if ( res != OK):
- print("[net_low_level:send_system_quit] Error to send system quit : " + str(res))
- return
+func send_system_login(host, port, user_addr, user_key, user_id, lang):
+ _networkconnexion.send_system_login(host, port, user_addr, user_key, user_id, lang)
func send_system_quit():
- # TODO - check why we send quit_id
- var msgout = BitStream.new()
- _quit_id += 1
- msgout.put_sint32(_current_received_number)
- msgout.put_bool(true)
- msgout.put_uint8(CLFECOMMON.SYSTEM_QUIT_CODE)
- msgout.put_sint32(_quit_id)
- #_queue_message_system.append(msgout)
- _connection_state == TCONNECTIONSTATE.QUIT
- var res = _socketUDP.put_packet(msgout.get_data())
- if ( res != OK):
- print("[net_low_level:send_system_quit] Error to send system quit : " + str(res))
- return
+ _networkconnexion.send_system_quit()
func send_systemm_disconnect():
- var msgout = BitStream.new()
- msgout.put_sint32(_current_received_number)
- msgout.put_bool(true)
- msgout.put_uint8(CLFECOMMON.SYSTEM_DISCONNECTION_CODE)
- var res = _socketUDP.put_packet(msgout.get_data())
- _connection_state == TCONNECTIONSTATE.QUIT
- if ( res != OK):
- print("[net_low_level:send_systemm_disconnect] Error to send system disconnection : " + str(res))
- return
+ _networkconnexion.send_systemm_disconnect()
func disconnect_server():
- print("[net_low_level:disconnect_server] Disconnect")
- if typeof(_socketUDP) != TYPE_NIL:
- send_systemm_disconnect()
- print("[net_low_level:disconnect_server] Send disconnect to server")
- _socketUDP.close()
- _socketUDP = null
+ _networkconnexion.disconnect_server()
-func set_khaganat_server(host, port):
- _khaganat_host = host
- _khaganat_port = port
-
-func connect_to_server(user_addr, user_key, user_id):
- var connexion = load("res://assets/Scripts/Config/connexion.gd").connexion.new()
- var lang = connexion.get_language()
- print("[net_low_level:connect_to_server] prepare:" + str(_khaganat_host) + ":" + str(_khaganat_port))
- if typeof(_socketUDP) == TYPE_NIL:
- _socketUDP = PacketPeerUDP.new()
- _socketUDP.set_dest_address(_khaganat_host, _khaganat_port)
- send_system_login(user_addr, user_key, user_id, lang)
-
-func decode_system_message(msgin):
- var message = msgin.get_uint8()
- print("[net_low_level:analyze_message_received] Message type:" + str(message) )
- match message:
- CLFECOMMON.SYSTEM_LOGIN_CODE:
- pass
- CLFECOMMON.SYSTEM_SYNC_CODE:
- var hexa = preload("res://assets/Scripts/Tools/hexa.gd").new()
- var synchronize = msgin.get_uint32()
- var stime = msgin.get_sint64()
- _latest_sync = msgin.get_uint32()
- var msg_xml = msgin.get_array_uint8(16)
- var database_xml = msgin.get_array_uint8(16)
- print("[net_low_level:analyze_message_received] synchronize:" + str(synchronize) + " stime:" + str(stime) + " latest_sync:" + str(_latest_sync))
- var num = ""
- for item in msg_xml:
- num += str(item) + "."
- print(num)
- print(hexa.ArrayIntToStringHexa(msg_xml))
- num = ""
- for item in database_xml:
- num += str(item) + "."
- print(num)
- print(hexa.ArrayIntToStringHexa(database_xml))
- if not msg.is_correct_md5(hexa.ArrayIntToStringHexa(msg_xml)):
- print("[net_low_level:analyze_message_received] Wrong MD5 for msg.xml")
- # TODO - we need quit with message error and go to login
- return
- send_system_sync()
- CLFECOMMON.SYSTEM_STALLED_CODE:
- pass
- CLFECOMMON.SYSTEM_PROBE_CODE:
- _latest_probe_time = _update_time
- _latest_probe = msgin.get_sint32()
- _latest_probes.append(_latest_probe)
- send_system_ack_probe()
- CLFECOMMON.SYSTEM_SERVER_DOWN_CODE:
- pass
- _:
- print("[net_low_level:analyze_message_received] Message type unknown (" + str(message) + ")")
-
-func decode_normal_message(msgin):
- pass
-
-func analyze_message_received(msgbytes):
- # khanat-opennel-code/code/ryzom/server/src/frontend_service/fe_receive_sub.cpp:769 void CFeReceiveSub::handleReceivedMsg( CClientHost *clienthost )
- _update_time = OS.get_ticks_msec()
- var msgin = BitStream.new()
- msgin.put_data(msgbytes)
- _current_received_number = msgin.get_sint32()
- var system_mode = msgin.get_bool()
- if ProjectSettings.get_setting("khaganat/debug_mode"):
- print("[net_low_level:analyze_message_received] Tick:" + str(_current_received_number) + ", Mode:" + str(system_mode) + ", Size:" + str(msgin.size()))
- if system_mode:
- print("[net_low_level:analyze_message_received] System Mode")
- if _current_received_number > _last_received_number + 1:
- print("[net_low_level:analyze_message_received] lost message : " + str(_last_received_number + 1 - _current_received_number))
- elif _current_received_number == _last_received_number:
- print("[net_low_level:analyze_message_received] Server re-send last message")
- return
- elif _current_received_number < _last_received_number:
- print("[net_low_level:analyze_message_received] Server re-send old message")
- return
- var ackBool = false
- var ackBit = 0
- if not system_mode:
- match _connection_state:
- TCONNECTIONSTATE.CONNECTED:
- ackBool = true
- ackBit = 1
- TCONNECTIONSTATE.SYNCHRONIZE:
- ackBool = true
- ackBit = 1
- _:
- ackBool = false
- if _current_received_number - _last_received_number < 32:
- _ack_bit_mask <<= _current_received_number - _last_received_number
- _ack_bit_mask |= _last_ack_bit << (_current_received_number - _last_received_number - 1)
- elif (_current_received_number - _last_received_number) == 32 and _last_ack_bit != 0:
- _ack_bit_mask = 0x80000000
- else:
- _ack_bit_mask = 0x00000000
- _last_ack_bit = ackBit
- for i in range(_last_received_number + 1, _current_received_number):
- _long_ack_bit_field.clear_bit(i & (NUM_BITS_IN_LONG_ACK -1))
- _long_ack_bit_field.put(_current_received_number & (NUM_BITS_IN_LONG_ACK-1), ackBool)
- if _last_ack_in_long_ack <= (_last_received_number - NUM_BITS_IN_LONG_ACK):
- _last_ack_in_long_ack = _last_received_number - NUM_BITS_IN_LONG_ACK + 1
- _last_received_number = _current_received_number
-
- if system_mode:
- decode_system_message(msgin)
- else:
- decode_normal_message(msgin)
+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)
func _process(delta):
- if typeof(_socketUDP) == TYPE_NIL:
- return
- var max_read = 10
- if _connection_state == TCONNECTIONSTATE.NOTINITIALISED:
- return
- if _connection_state == TCONNECTIONSTATE.NOTCONNECTED:
- return
- if _connection_state == TCONNECTIONSTATE.QUIT:
- return
- if _queue_message_system.size() > 0:
- var msgout = _queue_message_system.pop_front()
- if ProjectSettings.get_setting("khaganat/debug_mode"):
- print("[net_low_level:_process] Send data system (" + str(msgout.size()) + ", " + msgout.show() + ")" )
- _socketUDP.put_packet(msgout.get_data())
-
- if _latest_probes.size() > 0:
- send_system_ack_probe()
-
- while _socketUDP.get_available_packet_count() > 0 and max_read > 0:
- var msgbytes = _socketUDP.get_packet()
- if msgbytes.size() > 0:
- analyze_message_received(msgbytes)
+ _networkconnexion.process(delta)
func _exit_tree():
print("[net_low_level] End")
diff --git a/gdnative/src/bitstream.cpp b/gdnative/src/bitstream.cpp
index 9aca249..18b401f 100644
--- a/gdnative/src/bitstream.cpp
+++ b/gdnative/src/bitstream.cpp
@@ -50,6 +50,7 @@ void BitStream::_register_methods()
register_method("show", &BitStream::show);
register_method("show_detail", &BitStream::show_detail);
+ register_method("show_counter", &BitStream::show_counter);
register_method("get_data", &BitStream::get_data);
register_method("put_data", &BitStream::put_data);
@@ -67,10 +68,15 @@ void BitStream::_register_methods()
register_method("get_array_uint8", &BitStream::get_array_uint8);
}
+void BitStream::clear()
+{
+ this->_pos = 0;
+ this->_read = 0;
+}
+
BitStream::BitStream()
{
- this->_pos = 0;
- this->_read = 0;
+ clear();
}
BitStream::~BitStream()
@@ -313,6 +319,13 @@ String BitStream::show_detail()
return "[size:" + strsize + ", pos:" + strpos + "]" + ret ;
}
+String BitStream::show_counter()
+{
+ String ret = "[" + String::num_int64(this->_read) + " / " + String::num_int64(this->_pos) + "]";
+
+ return ret;
+}
+
PoolByteArray BitStream::get_data()
{
return this->_data;
@@ -441,4 +454,4 @@ PoolByteArray BitStream::get_array_uint8(uint32_t length)
--length;
}
return ret;
-}
\ No newline at end of file
+}
diff --git a/gdnative/src/bitstream.h b/gdnative/src/bitstream.h
index 21036c7..25de312 100644
--- a/gdnative/src/bitstream.h
+++ b/gdnative/src/bitstream.h
@@ -34,6 +34,8 @@ private:
public:
static void _register_methods();
+ void clear();
+
BitStream();
~BitStream();
@@ -61,6 +63,7 @@ public:
String show();
String show_detail();
+ String show_counter();
PoolByteArray get_data();
void put_data(PoolByteArray value);
diff --git a/gdnative/src/clfecommon.h b/gdnative/src/clfecommon.h
new file mode 100644
index 0000000..c36a1ae
--- /dev/null
+++ b/gdnative/src/clfecommon.h
@@ -0,0 +1,42 @@
+/*
+ Header CLFECOMMON : message send by 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 .
+
+*/
+
+#ifndef CLFECOMMON_H
+#define CLFECOMMON_H
+
+namespace godot {
+
+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
+};
+
+}
+
+#endif // CLFECOMMON_H
diff --git a/gdnative/src/crypt.h b/gdnative/src/crypt.h
index eeef197..34d091b 100644
--- a/gdnative/src/crypt.h
+++ b/gdnative/src/crypt.h
@@ -6,8 +6,8 @@
namespace godot {
-class Crypt : public Reference {
- GODOT_CLASS(Crypt, Reference)
+class Crypt : public Object {
+ GODOT_CLASS(Crypt, Object)
public:
static void _register_methods();
diff --git a/gdnative/src/gdlibrary.cpp b/gdnative/src/gdlibrary.cpp
index 352fda1..0b05f8c 100644
--- a/gdnative/src/gdlibrary.cpp
+++ b/gdnative/src/gdlibrary.cpp
@@ -21,22 +21,25 @@
#include "bitstream.h"
#include "bitset.h"
#include "crypt.h"
+#include "network_connection.h"
/** GDNative Initialize **/
extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o) {
- godot::Godot::gdnative_init(o);
+ godot::Godot::gdnative_init(o);
}
/** GDNative Terminate **/
extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *o) {
- godot::Godot::gdnative_terminate(o);
+ terminate_network_connection();
+ godot::Godot::gdnative_terminate(o);
}
/** NativeScript Initialize **/
extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) {
- godot::Godot::nativescript_init(handle);
+ godot::Godot::nativescript_init(handle);
- godot::register_class();
- godot::register_class();
- godot::register_class();
+ godot::register_class();
+ godot::register_class();
+ godot::register_class();
+ godot::register_class();
}
diff --git a/gdnative/src/network_connection.cpp b/gdnative/src/network_connection.cpp
new file mode 100644
index 0000000..8decd60
--- /dev/null
+++ b/gdnative/src/network_connection.cpp
@@ -0,0 +1,93 @@
+/*
+ Library to present all functions of NetworkConnectionCore (network)
+
+ 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
+#include "network_connection.h"
+#include "bitstream.h"
+#include "network_connection_core.h"
+
+using namespace godot;
+
+NetworkConnectionCore *NetworkConnectionCore::singleton = NULL;
+
+void NetworkConnection::_register_methods()
+{
+ register_method("define_checksum_msg_xml", &NetworkConnection::define_checksum_msg_xml);
+ register_method("define_socket_udp", &NetworkConnection::define_socket_udp);
+ register_method("send_system_login", &NetworkConnection::send_system_login);
+ register_method("send_system_disconnect", &NetworkConnection::send_system_disconnect);
+ register_method("send_system_quit", &NetworkConnection::send_system_quit);
+ register_method("disconnect_server", &NetworkConnection::disconnect_server);
+ register_method("process", &NetworkConnection::process);
+ register_method("get_state", &NetworkConnection::get_state);
+}
+
+NetworkConnection::NetworkConnection()
+{
+}
+
+NetworkConnection::~NetworkConnection()
+{
+}
+
+int NetworkConnection::get_state()
+{
+ return NetworkConnectionCore::get_singleton()->get_state();
+}
+
+void NetworkConnection::define_checksum_msg_xml(Array checksum_msg_xml)
+{
+ NetworkConnectionCore::get_singleton()->define_checksum_msg_xml(checksum_msg_xml);
+}
+void NetworkConnection::define_socket_udp(PacketPeerUDP * socketUDP)
+{
+ NetworkConnectionCore::get_singleton()->define_socket_udp(socketUDP);
+}
+
+void NetworkConnection::send_system_login(String host, int64_t port, String user_addr, String user_key, String user_id, String lang)
+{
+ NetworkConnectionCore::get_singleton()->send_system_login(host, port, user_addr, user_key, user_id, lang);
+}
+
+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();
+}
+
+void NetworkConnection::process(int delta)
+{
+ NetworkConnectionCore::get_singleton()->process(delta);
+}
+
+void terminate_network_connection()
+{
+ NetworkConnectionCore::get_singleton()->terminate_connexion();
+}
diff --git a/gdnative/src/network_connection.h b/gdnative/src/network_connection.h
new file mode 100644
index 0000000..eb52c6b
--- /dev/null
+++ b/gdnative/src/network_connection.h
@@ -0,0 +1,62 @@
+/*
+ Header NetworkConnection
+
+ 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_CONNECTION_H
+#define NETWORK_CONNECTION_H
+
+#include
+#include
+#include
+#include "bitstream.h"
+#include "clfecommon.h"
+#include "store_message.h"
+#include "network_connection_core.h"
+
+namespace godot {
+
+class NetworkConnection : public Object {
+ GODOT_CLASS(NetworkConnection, Object)
+private:
+ static void _bind_methods();
+public:
+ NetworkConnection();
+ ~NetworkConnection();
+
+ static void _register_methods();
+
+ /* _init must exist as it is called by Godot */
+ void _init() {};
+
+ void define_checksum_msg_xml(Array checksum_msg_xml);
+ void define_socket_udp(PacketPeerUDP * socketUDP); // Not necessary, but you can define network directly on GdScript
+ void send_system_login(String host, int64_t port, String user_addr, String user_key, String user_id, String lang);
+ void send_system_disconnect();
+ void send_system_quit();
+ void disconnect_server();
+ void process(int delta);
+ int get_state();
+};
+
+}
+
+void terminate_network_connection();
+
+
+#endif // NETWORK_CONNECTION_H
diff --git a/gdnative/src/network_connection_core.cpp b/gdnative/src/network_connection_core.cpp
new file mode 100644
index 0000000..bd2540d
--- /dev/null
+++ b/gdnative/src/network_connection_core.cpp
@@ -0,0 +1,482 @@
+/*
+ Library to manage network
+
+ 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 .
+
+ */
+
+#define DEBUG_ENABLED
+
+#include
+#include
+#include
+
+#include "tools.h"
+#include "bitset.h"
+#include "bitstream.h"
+#include "network_connection_core.h"
+#include "state.h"
+
+using namespace godot;
+
+NetworkConnectionCore *NetworkConnectionCore::get_singleton()
+{
+ if ( NetworkConnectionCore::singleton == NULL )
+ NetworkConnectionCore::singleton = new NetworkConnectionCore();
+ return NetworkConnectionCore::singleton;
+}
+
+NetworkConnectionCore::NetworkConnectionCore()
+{
+ this->_socketUDP = NULL;
+ this->_state = STATE::NotInitialised ;
+}
+
+NetworkConnectionCore::~NetworkConnectionCore()
+{
+ NetworkConnectionCore::singleton = NULL;
+ this->_state = STATE::NotInitialised ;
+}
+
+int NetworkConnectionCore::get_state()
+{
+ return this->_state;
+}
+
+void NetworkConnectionCore::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()));
+}
+
+void NetworkConnectionCore::define_socket_udp(PacketPeerUDP * socketUDP)
+{
+ // Use if you define PacketPeerUDP on other script
+ if ( this->_socketUDP == NULL)
+ this->_socketUDP = socketUDP;
+}
+
+void NetworkConnectionCore::autodefine_socket_udp()
+{
+ // Create socket udp if not defined (If you don't use define_socket_udp)
+ if ( this->_socketUDP == NULL)
+ {
+ PacketPeerUDP::___init_method_bindings();
+ this->_socketUDP = PacketPeerUDP::_new();
+ if ( this->_socketUDP == NULL)
+ throw "Failed to open network";
+ }
+}
+
+void NetworkConnectionCore::send_system_login(String host, int64_t port, String user_addr, String user_key, String user_id, String lang)
+{
+ // Configure socket UDP
+ this->autodefine_socket_udp();
+ if ( this->_state != STATE::NotInitialised )
+ {
+ DEBUG_PRINT("Close old network socket");
+ this->_socketUDP->close();
+ }
+
+ INFO_PRINT("Connect to " + host + ":" + itos(port));
+ this->_socketUDP->set_dest_address(host, port);
+ // Open connection and send ID
+
+ BitStream msgout;
+ msgout.put_sint32(_current_received_number);
+ msgout.put_bool(true);
+ msgout.put_uint8(CLFECOMMON::SYSTEM_LOGIN_CODE);
+ msgout.put_string_hexa32(user_addr);
+ msgout.put_string_hexa32(user_key);
+ msgout.put_string_hexa32(user_id);
+ msgout.put_string(lang);
+ godot::Error ret;
+ ret = this->_socketUDP->put_packet(msgout.get_data());
+ 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;
+ }
+ INFO_PRINT("Connected to khganat");
+ this->_state = STATE::Connected;
+ // 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;
+}
+
+void NetworkConnectionCore::send_system_quit()
+{
+ // TODO - check why we send quit_id
+ if ( this->_state != STATE::Connected && this->_state != STATE::ForceSynchronize )
+ return;
+ DEBUG_PRINT("send quit to server");
+ BitStream msgout;
+ msgout.put_sint32(this->_current_received_number);
+ msgout.put_bool(true);
+ msgout.put_uint8(CLFECOMMON::SYSTEM_QUIT_CODE);
+ msgout.put_sint32(this->_quit_id);
+
+ if ( this->_socketUDP->put_packet(msgout.get_data()) != Error::OK )
+ {
+ ERR_PRINT("Error to send disconnect");
+ }
+ this->_state = STATE::Quit;
+}
+
+void NetworkConnectionCore::send_system_disconnect()
+{
+ if ( this->_state != STATE::Connected && this->_state != STATE::ForceSynchronize )
+ return;
+ DEBUG_PRINT("send disconnect to server");
+ BitStream msgout;
+ msgout.put_sint32(this->_current_received_number);
+ msgout.put_bool(true);
+ msgout.put_uint8(CLFECOMMON::SYSTEM_DISCONNECTION_CODE);
+
+ if ( this->_socketUDP->put_packet(msgout.get_data()) != Error::OK )
+ {
+ ERR_PRINT("Error to send disconnect");
+ }
+ this->_socketUDP->close();
+ this->_state = STATE::Disconnect;
+}
+
+void NetworkConnectionCore::send_system_ack_probe()
+{
+ // 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)
+ return;
+ int max = this->_latest_probes.size();
+ if (max == 0 )
+ return;
+ if (this->_state == STATE::ForceSynchronize && max < 5)
+ return;
+ DEBUG_PRINT("send system ACK PROBE to server");
+ BitStream msgout;
+ msgout.put_sint32(this->_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 )
+ {
+ //DEBUG_PRINT("i:" + itos(i));
+ int data = this->_latest_probes[i];
+ //DEBUG_PRINT("data:" + itos(data));
+ msgout.put_sint32(data);
+ //DEBUG_PRINT("updated");
+ }
+ if (this->_socketUDP->put_packet(msgout.get_data()) != Error::OK)
+ {
+ ERR_PRINT("Error to send disconnect");
+ return;
+ }
+ this->_latest_probes.clear();
+ 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->_state = STATE::Connected;
+ }
+}
+
+void NetworkConnectionCore::disconnect_server()
+{
+ if (this->_state != STATE::Connected && this->_state != STATE::ForceSynchronize)
+ return;
+ send_system_disconnect();
+}
+
+void NetworkConnectionCore::decode_system_message(BitStream *msgin)
+{
+ int message = msgin->get_uint8();
+ switch (message)
+ {
+ case CLFECOMMON::SYSTEM_LOGIN_CODE:
+ DEBUG_PRINT("SYSTEM_LOGIN_CODE");
+ break;
+ case CLFECOMMON::SYSTEM_SYNC_CODE:
+ this->receive_system_sync(msgin);
+ break;
+ case CLFECOMMON::SYSTEM_STALLED_CODE:
+ DEBUG_PRINT("SYSTEM_STALLED_CODE");
+ break;
+ case CLFECOMMON::SYSTEM_SERVER_DOWN_CODE:
+ DEBUG_PRINT("SYSTEM_SERVER_DOWN_CODE");
+ break;
+ case CLFECOMMON::SYSTEM_PROBE_CODE:
+ this->receive_system_probe(msgin);
+ break;
+ default:
+ ERR_PRINT("Received unknown message [" + itos(message) + "]");
+ break;
+ }
+}
+
+void NetworkConnectionCore::decode_normal_message(BitStream *msgin)
+{
+ DEBUG_PRINT("Decode normal message");
+}
+
+void NetworkConnectionCore::receive_system_sync(BitStream * msgin)
+{
+ int i;
+ bool valide = true;
+
+ DEBUG_PRINT("SYSTEM_SYNC_CODE");
+ 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);
+
+ if ( msg_xml.size() != this->_checksum_msg_xml.size() )
+ {
+ valide = false;
+ DEBUG_PRINT("MSG XML is incorrect (server:" + itos(msg_xml.size()) +", client:" + itos(this->_checksum_msg_xml.size()) + ")");
+ }
+ else
+ {
+ for(i=0; i_checksum_msg_xml[i] )
+ {
+ valide = false;
+ DEBUG_PRINT("MSG XML is incorrect (pos:" + itos(i) +")");
+ }
+ }
+ }
+
+ if ( valide == true )
+ DEBUG_PRINT("MSG XML is correct");
+ else
+ DEBUG_PRINT("MSG.XML is wrong");
+
+
+ /*
+ self._Synchronize = msg.readUint32('Synchronize')
+ stime = msg.readSint64('stime')
+ self._LatestSync = msg.readUint32('LatestSync')
+ logging.getLogger(LOGGER).debug("%d %d %d" %(self._Synchronize, stime, self._LatestSync))
+ # khanat-opennel-code/code/ryzom/client/src/network_connection.cpp : void CNetworkConnection::receiveSystemSync(CBitMemStream &msgin)
+ MsgData = msg.readArrayUint8(16, 'MsgData')
+ DatabaseData = msg.readArrayUint8(16, 'DatabaseData')
+ logging.getLogger(LOGGER).debug("MsgData:" + str(MsgData))
+ logging.getLogger(LOGGER).debug("DatabaseData:" + str(DatabaseData))
+ md5Msg = bytes(MsgData)
+ md5Database = bytes(DatabaseData)
+ if md5Msg == self._MsgXmlMD5:
+ logging.getLogger(LOGGER).info("Check MD5 msg.xml : OK")
+ else:
+ logging.getLogger(LOGGER).error("Check MD5 msg.xml : KO")
+ if md5Database == self._DatabaseXmlMD5:
+ logging.getLogger(LOGGER).info("Check MD5 database.xml : OK")
+ else:
+ logging.getLogger(LOGGER).error("Check MD5 database.xml : KO")
+ logging.getLogger(LOGGER).debug("Msg Received:" + msg.showAllData())
+ self._MsPerTick = 100
+ self._CurrentServerTick = self._Synchronize + self._CurrentReceivedNumber + 2
+ self._CurrentClientTick = self._CurrentServerTick - ( self._LCT + self._MsPerTick ) / self._MsPerTick
+ self._CurrentClientTime = self._UpdateTime - (self._LCT + self._MsPerTick)
+ */
+}
+
+void NetworkConnectionCore::receive_system_probe(BitStream * msgin)
+{
+ DEBUG_PRINT("SYSTEM_PROBE_CODE size:" + itos(this->_latest_probes.size()));
+ this->_latest_probes.append(msgin->get_sint32());
+}
+
+void NetworkConnectionCore::wait_resynchronize(int32_t current_received_number, BitStream * msgin)
+{
+ bool system_mode;
+ this->_current_received_number = current_received_number;
+ system_mode = msgin->get_bool();
+ if ( system_mode == true )
+ {
+ int message = msgin->get_uint8();
+ switch (message)
+ {
+ case CLFECOMMON::SYSTEM_LOGIN_CODE:
+ DEBUG_PRINT("SYSTEM_LOGIN_CODE");
+ break;
+ case CLFECOMMON::SYSTEM_SYNC_CODE:
+ DEBUG_PRINT("SYSTEM_SYNC_CODE");
+ break;
+ case CLFECOMMON::SYSTEM_STALLED_CODE:
+ DEBUG_PRINT("SYSTEM_STALLED_CODE");
+ break;
+ case CLFECOMMON::SYSTEM_SERVER_DOWN_CODE:
+ DEBUG_PRINT("SYSTEM_SERVER_DOWN_CODE");
+ break;
+ case CLFECOMMON::SYSTEM_PROBE_CODE:
+ this->receive_system_probe(msgin);
+ break;
+ default:
+ ERR_PRINT("Received unknown message [" + itos(message) + "]");
+ break;
+ }
+ }
+ this->_last_received_number = current_received_number;
+}
+
+void NetworkConnectionCore::analyze_message_receieved(int32_t current_received_number, BitStream * msgin)
+{
+ bool system_mode;
+ bool ackBool = false;
+ int ackBit = 0;
+ int i;
+
+ this->_current_received_number = current_received_number;
+ system_mode = msgin->get_bool();
+ if ( system_mode == true )
+ {
+ INFO_PRINT("Received system message");
+ if (this->_current_received_number == this->_last_received_number + 1)
+ {
+ INFO_PRINT("Received message");
+ }
+ else if (this->_current_received_number < this->_last_received_number + 1)
+ {
+ INFO_PRINT("Received old message");
+ return;
+ }
+ else if (this->_current_received_number > this->_last_received_number + 1)
+ {
+ INFO_PRINT("Received message in future (lost some message)");
+ }
+ }
+ else
+ {
+ INFO_PRINT("Received normal message");
+ }
+ if ( system_mode != true )
+ {
+ ackBool = true;
+ ackBit = 1;
+ }
+ if ( current_received_number - this->_last_received_number < 32 )
+ {
+ this->_ack_bit_mask <<= current_received_number - this->_last_received_number;
+ this->_ack_bit_mask |= this->_last_ack_bit << (current_received_number - this->_last_received_number - 1);
+ }
+ else if (((current_received_number - this->_last_received_number) == 32) && (this->_last_ack_bit != 0))
+ this->_ack_bit_mask = 0x80000000;
+ else
+ this->_ack_bit_mask = 0x00000000;
+ this->_last_ack_bit = ackBit;
+ for(i=this->_last_received_number + 1 ;i < _current_received_number; ++i)
+ this->_long_ack_bit_field.clear_bit(i & (NUM_BITS_IN_LONG_ACK -1) );
+
+ // TODO - what's action when we have rotate onthis number (max -> 0)
+ if( this->_last_received_number > 0x08000000 )
+ {
+ if(this->_last_ack_in_long_ack <= (this->_last_received_number - NUM_BITS_IN_LONG_ACK))
+ this->_last_ack_in_long_ack = this->_last_received_number - NUM_BITS_IN_LONG_ACK + 1;
+ this->_last_received_number = current_received_number;
+ }
+ else
+ {
+ if(this->_last_ack_in_long_ack - 0x80000000 <= (this->_last_received_number - NUM_BITS_IN_LONG_ACK - 0x80000000))
+ this->_last_ack_in_long_ack = this->_last_received_number - NUM_BITS_IN_LONG_ACK + 1;
+ this->_last_received_number = current_received_number;
+ }
+
+ if ( system_mode == true )
+ this->decode_system_message(msgin);
+ else
+ this->decode_normal_message(msgin);
+}
+
+void NetworkConnectionCore::store_message_received(PoolByteArray & msgbytes)
+{
+ int pos = this->queue.put_msgbytes(msgbytes);
+
+ BitStream * msgin = this->queue.get_msg(pos);
+ int32_t current_received_number = this->queue.get_received_number(pos);
+ /// 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);
+ }
+ else if ( current_received_number - this->_last_received_number <= 0 ) // Received old message
+ {
+ INFO_PRINT("current_received_number : " + itos(current_received_number) + " / queue size : " + itos(this->queue.length()));
+ this->queue.erase(pos);
+ return;
+ }
+ else if ( this->_last_received_number + 1 == current_received_number ) // Received next message
+ {
+ INFO_PRINT("current_received_number : " + itos(current_received_number) + " / queue size : " + itos(this->queue.length()));
+ analyze_message_receieved(current_received_number, msgin);
+ this->queue.erase(pos);
+ }
+ else // Received new message (but missing some message between) -> go to queue and cross finger to received the next message (for _last_received_number)
+ {
+ INFO_PRINT("current_received_number : " + itos(current_received_number) + " / queue size : " + itos(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();
+}
+
+void NetworkConnectionCore::process(int delta)
+{
+ if (this->_state != STATE::Connected && this->_state != STATE::ForceSynchronize)
+ return;
+ //INFO_PRINT( "Process - delta : " + itos(delta));
+ for(int i = 0; (this->_socketUDP->get_available_packet_count() > 0) && (i < MAX_LOOP_READ_BY_STEP) ; ++i)
+ {
+ PoolByteArray msgbytes ;
+ msgbytes = this->_socketUDP->get_packet();
+ DEBUG_PRINT("Size msg received : " + itos(msgbytes.size()) );
+ store_message_received(msgbytes);
+ }
+ send_message();
+}
+
+void NetworkConnectionCore::terminate_connexion()
+{
+ DEBUG_PRINT("Terminate network connexion");
+ if ( this->_socketUDP == NULL )
+ return;
+ delete this-> _socketUDP;
+ this->_socketUDP = NULL;
+}
diff --git a/gdnative/src/network_connection_core.h b/gdnative/src/network_connection_core.h
new file mode 100644
index 0000000..30cc950
--- /dev/null
+++ b/gdnative/src/network_connection_core.h
@@ -0,0 +1,88 @@
+/*
+ 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 NETWORK_CONNECTION_CORE_H
+#define NETWORK_CONNECTION_CORE_H
+
+#include
+#include
+#include "bitset.h"
+#include "bitstream.h"
+#include "clfecommon.h"
+#include "store_message.h"
+#include "state.h"
+
+#define MAX_LOOP_READ_BY_STEP 10
+#define NUM_BITS_IN_LONG_ACK 512
+
+namespace godot {
+
+class NetworkConnectionCore : public Object {
+ GODOT_CLASS(NetworkConnectionCore, Object)
+private:
+ static NetworkConnectionCore *singleton;
+
+ bool _force_resynchronize;
+ STATE _state;
+ PacketPeerUDP * _socketUDP;
+ int32_t _current_received_number;
+ int32_t _last_received_number;
+ int32_t _quit_id;
+ BitSet _long_ack_bit_field;
+ Array _latest_probes;
+ Array _checksum_msg_xml;
+ uint32_t _ack_bit_mask;
+ int32_t _last_ack_bit;
+ int32_t _last_ack_in_long_ack;
+ StoreMessage queue;
+
+public:
+ static NetworkConnectionCore * get_singleton();
+
+ NetworkConnectionCore();
+ ~NetworkConnectionCore();
+
+ int get_state();
+
+ void define_checksum_msg_xml(Array & checksum_msg_xml);
+
+ void define_socket_udp(PacketPeerUDP * socketUDP);
+ void autodefine_socket_udp();
+ void send_system_login(String host, int64_t port, String user_addr, String user_key, String user_id, String lang);
+ void send_system_disconnect();
+ void send_system_quit();
+ void disconnect_server();
+ void send_system_ack_probe();
+ void decode_system_message(BitStream *msgin);
+ void decode_normal_message(BitStream *msgin);
+ void receive_system_sync(BitStream * msgin);
+ void receive_system_probe(BitStream * msgin);
+ void wait_resynchronize(int32_t current_received_number, BitStream * msgin);
+ void analyze_message_receieved(int32_t, BitStream *msgin);
+ void store_message_received(PoolByteArray & msgbytes);
+ void send_message();
+ void process(int delta);
+ bool connected();
+ void terminate_connexion();
+};
+
+}
+
+#endif
diff --git a/gdnative/src/state.h b/gdnative/src/state.h
new file mode 100644
index 0000000..2d022f9
--- /dev/null
+++ b/gdnative/src/state.h
@@ -0,0 +1,38 @@
+/*
+ Header STATE : to know state of client
+
+ 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_H
+#define STATE_H
+
+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
+};
+
+#endif // STATE_H
diff --git a/gdnative/src/store_message.cpp b/gdnative/src/store_message.cpp
new file mode 100644
index 0000000..a3b999a
--- /dev/null
+++ b/gdnative/src/store_message.cpp
@@ -0,0 +1,127 @@
+/*
+
+ StoreMessage : class to manage packet received by khaganat
+ If we received message with bad order, with this class we can manage (with limit storage)
+
+ 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
+#include
+
+#include "bitstream.h"
+#include "tools.h"
+#include "store_message.h"
+
+using namespace godot;
+
+StoreMessage::StoreMessage()
+{
+ this->clear();
+}
+
+StoreMessage::~StoreMessage()
+{
+
+}
+
+void StoreMessage::clear()
+{
+ for(int i = 0 ; i < SIZE_QUEUE_MESSAGE ; ++i )
+ {
+ //this->_empty[i] = true;
+ this->_received_number[i] = 0;
+ this->_msgin[i].clear();
+ }
+ this->_size = 0;
+}
+
+int StoreMessage::length()
+{
+ return this->_size;
+}
+
+int StoreMessage::put_msgbytes(PoolByteArray & msgbytes)
+{
+ int i = 0;
+ int ii ;
+
+ //while((this->_empty[i] != true)&&(i < SIZE_QUEUE_MESSAGE))
+ while((i < SIZE_QUEUE_MESSAGE)&&(this->_msgin[i].size_data() != 0))
+ ++i;
+
+ if(i >= SIZE_QUEUE_MESSAGE) // Out of memory
+ {
+ ERR_PRINT("Network queue is full (" + itos(i) + " / " + itos(SIZE_QUEUE_MESSAGE) + ")");
+ throw "Out of memory";
+ }
+ //INFO_PRINT("-> i:" + itos(i) + "/" + itos(this->_size) + " State:" + itos(this->_msgin[i].size_data()) + " num:" + itos(this->_received_number[i]));
+ //INFO_PRINT("i:" + itos(i) + " / " + itos(SIZE_QUEUE_MESSAGE) );
+ this->_msgin[i].put_data(msgbytes);
+ int32_t current_received_number = this->_msgin[i].get_sint32();
+ this->_received_number[i] = current_received_number;
+
+ // Check we don't have other message with same _received_number (also remove it)
+ ii = i + 1;
+ while(ii < SIZE_QUEUE_MESSAGE)
+ {
+ if ( this->_received_number[ii] == current_received_number)
+ this->erase(ii);
+ ++ii;
+ }
+ this->_size ++;
+ /*
+ for(int ii = 0 ; ii < SIZE_QUEUE_MESSAGE ; ++ii)
+ {
+ INFO_PRINT(itos(ii) + ") i:" + itos(i) + "/" + itos(this->_size) + " State:" + itos(this->_msgin[ii].size_data()) + " num:" + itos(this->_received_number[ii]));
+ }
+ */
+ return i;
+}
+
+BitStream * StoreMessage::get_msg(int pos)
+{
+ if ( pos >= SIZE_QUEUE_MESSAGE )
+ {
+ ERR_PRINT("Try to get data out of memory");
+ throw "Out of memory";
+ }
+ return & this->_msgin[pos];
+}
+
+int32_t StoreMessage::get_received_number(int pos)
+{
+ if ( pos >= SIZE_QUEUE_MESSAGE )
+ {
+ ERR_PRINT("Try to get data out of memory");
+ throw "Out of memory";
+ }
+ return this->_received_number[pos];
+}
+
+void StoreMessage::erase(int pos)
+{
+ if ( pos >= SIZE_QUEUE_MESSAGE )
+ {
+ ERR_PRINT("Try to erase data out of memory");
+ return;
+ }
+ //this->_empty[pos] = true;
+ this->_received_number[pos] = 0;
+ this->_msgin[pos].clear();
+ this->_size -- ;
+}
diff --git a/gdnative/src/store_message.h b/gdnative/src/store_message.h
new file mode 100644
index 0000000..b85cda7
--- /dev/null
+++ b/gdnative/src/store_message.h
@@ -0,0 +1,47 @@
+/*
+ Header StoreMessage : message send by 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 .
+
+*/
+
+#ifndef STORE_MESSAGE_H
+#define STORE_MESSAGE_H
+
+#define SIZE_QUEUE_MESSAGE 6
+
+namespace godot {
+
+class StoreMessage
+{
+ // bool _empty[SIZE_QUEUE_MESSAGE];
+ int32_t _received_number[SIZE_QUEUE_MESSAGE];
+ BitStream _msgin[SIZE_QUEUE_MESSAGE];
+ int _size;
+public:
+ StoreMessage();
+ ~StoreMessage();
+ void clear();
+ int length();
+ int put_msgbytes(PoolByteArray & msgbytes);
+ BitStream * get_msg(int pos);
+ int32_t get_received_number(int pos);
+ void erase(int pos);
+};
+
+}
+
+#endif // STORE_MESSAGE_H
diff --git a/gdnative/src/tools.cpp b/gdnative/src/tools.cpp
new file mode 100644
index 0000000..4c4c2df
--- /dev/null
+++ b/gdnative/src/tools.cpp
@@ -0,0 +1,29 @@
+/*
+
+ 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
+#include
+#include "tools.h"
+
+using namespace godot;
+
+String godot::itos(int64_t p_val)
+{
+ return String::num_int64(p_val);
+}
diff --git a/gdnative/src/tools.h b/gdnative/src/tools.h
new file mode 100644
index 0000000..0f2e014
--- /dev/null
+++ b/gdnative/src/tools.h
@@ -0,0 +1,44 @@
+/*
+ Header Tools
+
+ 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 TOOLS_H
+#define TOOLS_H
+
+#include
+
+namespace godot {
+
+String itos(int64_t p_val);
+
+#define INFO_PRINT(msg) Godot::print( String(__FUNCTION__) + ":" + String(__FILE__) + ":" + itos( __LINE__) + " " + String(msg))
+
+#ifdef DEBUG_ENABLED
+
+#define DEBUG_PRINT(msg) Godot::print( String(__FUNCTION__) + ":" + String(__FILE__) + ":" + itos( __LINE__) + " " + String(msg))
+
+#else
+
+#define DEBUG_PRINT(msg)
+
+#endif
+
+}
+
+#endif // STORE_MESSAGE_H
diff --git a/gdnative/test/bitset.gd b/gdnative/test/bitset.gd
index 85d29b6..57f63a4 100644
--- a/gdnative/test/bitset.gd
+++ b/gdnative/test/bitset.gd
@@ -14,7 +14,7 @@ func _ready():
func test_resize():
var bitset = preload("res://bitset.gdns").new()
- print ("[bitset:test_init]")
+ print ("[bitset:test_resize]")
bitset.resize(1024)
func test_put():
@@ -33,9 +33,20 @@ func test_put():
#print ("[bitset:test_init] " + bitset.show())
assert( bitset.show() == "0000000000000000000000000000010000000000000000000000000000000000001000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
+func test_alloc():
+ var BitSet = preload("res://bitset.gdns")
+ print ("[bitset:test_alloc]")
+ var tab = {}
+ tab[1478] = BitSet.new()
+ assert( tab.size() == 1 )
+ tab[1479] = BitSet.new()
+ assert( tab.size() == 2 )
+ tab.erase(1478)
+ assert( tab.size() == 1 )
func test():
print("[bitset] Start check -> start")
test_resize()
test_put()
+ test_alloc()
print("[bitset] Start check -> end")
diff --git a/gui_scene/GUI/login/login_menu.gd b/gui_scene/GUI/login/login_menu.gd
index dbe7b65..54337a8 100644
--- a/gui_scene/GUI/login/login_menu.gd
+++ b/gui_scene/GUI/login/login_menu.gd
@@ -148,8 +148,10 @@ func _on_HTTPRequest_request_completed(result, response_code, headers, body):
print("[login_menu:_on_HTTPRequest_request_completed] state:" + state + ", cookie:" + cookie + ", fsaddr:" + fsaddr + ", ringmainurl:" + ringmainurl + ", fartp:" + fartp + ", stat:" + stat + ", r2serverversion:" + r2serverversion + ", r2backuppatchurl:" + r2backuppatchurl + ", r2patchurl:" + r2patchurl)
var server_info = server_info_script.nel_server_info.new(body.get_string_from_utf8());
- net_low_level.set_khaganat_server(khaganat_host, khaganat_port)
- net_low_level.connect_to_server(UserAddr, UserKey, UserId)
+ var connexion = load("res://assets/Scripts/Config/connexion.gd").connexion.new()
+ var lang = connexion.get_language()
+ print("[login_menu:_on_HTTPRequest_request_completed] khaganat_host:" + khaganat_host + ", khaganat_port:" + str(khaganat_port))
+ net_low_level.connect_to_server(khaganat_host, khaganat_port, UserAddr, UserKey, UserId, lang)
emit_signal( "login_button_pressed" )
diff --git a/networkconnexion.gdns b/networkconnexion.gdns
new file mode 100644
index 0000000..f3c3197
--- /dev/null
+++ b/networkconnexion.gdns
@@ -0,0 +1,7 @@
+[gd_resource type="NativeScript" load_steps=2 format=2]
+
+[ext_resource path="res://gdnative.gdnlib" type="GDNativeLibrary" id=1]
+
+[resource]
+class_name = "NetworkConnection"
+library = ExtResource( 1 )
diff --git a/project.godot b/project.godot
index 5bf0fde..6e8097d 100644
--- a/project.godot
+++ b/project.godot
@@ -27,6 +27,10 @@ character="*res://game_scene/Game/Character/Character.tscn"
net_low_level="*res://assets/Scripts/Network/net_low_level.gd"
msg="*res://assets/Scripts/Definition/msg.gd"
+[debug]
+
+settings/stdout/verbose_stdout=true
+
[display]
window/size/width=1280