connect to XMPP

This commit is contained in:
AleaJactaEst 2023-12-17 01:03:48 +01:00
parent 40d8cc0318
commit 0ab321c3e1
8 changed files with 636 additions and 12 deletions

335
client/Stream/Stream.gd Normal file
View file

@ -0,0 +1,335 @@
extends Node
# Stream XMPP
# Author : AleaJactaEst
#
# https://xmpp.org/extensions/xep-0178.html
# https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml
# Boucle
# - non connecte
# - connecte en claire
# - connecte en TLS
# - lance l'authentification
# - step authentification
# - identifie
signal send_msg_debug(message:String)
signal send_msg_error(message:String)
signal new_stanza(stanza)
enum StreamState {
END, # Stream is over. Starting with this.
START, # Stream hass started.
TLS, # Connection has been made and the first header is send. Let's get ssl!
AUTHENTICATE, # We have negotiated whether to use TLS, let's authenticate.
STANZA # We have authenticated, account is now allowed to send stanzas
}
var stream_status = StreamState.END
@export var server_ip:String = "localhost":
set = set_server_ip, get = get_server_ip
func set_server_ip(value:String):
server_ip = value
func get_server_ip() -> String:
return server_ip
@export var port_number:int = 5222:
set = set_port_number, get = get_port_number
func set_port_number(value:int):
port_number = value
func get_port_number() -> int:
return port_number
@export var account_name:String = "undefined@localhost":
set = set_account_name, get = get_account_name
func set_account_name(value:String):
account_name = value
func get_account_name() -> String:
return account_name
@export var password:String = "undefined":
set = set_password, get = get_password
func set_password(value:String):
password = value
func get_password() -> String:
return password
@export var locale:String = "en":
set = set_locale, get = get_locale
func set_locale(value:String):
locale = value
func get_locale() -> String:
return locale
@export var xmppclient:bool = false:
get:
return xmppclient
set(value):
xmppclient = value
var try_connect:int = 0
var count_connecting_time:float = 0
var partial_stanza:String = ""
var tcp_peer:StreamPeerTCP = StreamPeerTCP.new()
var ssl_peer:StreamPeerTLS = StreamPeerTLS.new()
var tgt_peer = null
var status:StreamState = StreamState.END
func _init():
var language = OS.get_locale()
set_locale(language)
tgt_peer = tcp_peer
func _process(delta):
#Global.msg_info("TCP:%d", [tcp_peer.get_status()])
print(server_ip, ":", port_number, " / get_status:" , tcp_peer.get_status(), " / count_connecting_time:", count_connecting_time, " / stream_status:", stream_status)
# if tcp_peer.get_status() == StreamPeerTCP.STATUS_NONE and stream_status == self.StreamState.TLS:
# #negotiate_tls()
# print("negotiate_tls")
# pass
if (tgt_peer.get_status() == StreamPeerTCP.STATUS_CONNECTED) :
print("STATUS_CONNECTED:", delta)
if (tgt_peer.has_method("poll")):
tgt_peer.poll()
if tgt_peer.get_available_bytes()>0:
var response = tgt_peer.get_string(tgt_peer.get_available_bytes())
send_msg_debug.emit("Stream: response: " + response)
if stream_status == self.StreamState.STANZA:
#collect_stanza(remove_stream_header(response))
Global.msg_info("", [])
print("collect_stanza")
else:
print("stream_process")
stream_process(remove_stream_header(response))
# print(remove_stream_header(response))
elif stream_status == self.StreamState.END:
start_stream()
stream_status = self.StreamState.START
count_connecting_time = 0
if tgt_peer.get_status() == StreamPeerTCP.STATUS_CONNECTING:
print("STATUS_CONNECTING:", delta)
count_connecting_time += delta
if (tgt_peer.has_method("poll")):
tgt_peer.poll()
if count_connecting_time > 60: # (1 -> 1s) if it took more than 1s to connect, error
print("**** Stream: Stuck connecting, will now disconnect")
Global.msg_error("Stream: Stuck connecting, will now disconnect", [])
send_msg_debug.emit("Stream: Stuck connecting, will now disconnect")
tgt_peer.disconnect_from_host() #interrupts connection to nothing
set_process(false) # stop listening for packets
try_connect = 20
stream_status = self.StreamState.END
if tgt_peer.get_status() == StreamPeerTCP.STATUS_NONE and xmppclient:
print("connect_to_server:", xmppclient)
connect_to_server()
xmppclient = false
func connect_to_server():
""" Connect to the server ip and port, and start checking whether there's stream info yet. """
if tcp_peer.get_status() == StreamPeerTCP.STATUS_CONNECTED:
pass
if try_connect == 0 and tcp_peer.get_status() == StreamPeerTCP.STATUS_NONE:
#print("-> ", server_ip, ":", port_number, "/" , tcp_peer.get_status())
var res = tcp_peer.connect_to_host(server_ip, port_number)
if res == OK:
count_connecting_time = 0
stream_status = self.StreamState.END
set_process(true)
tgt_peer = tcp_peer
else:
try_connect = 20
else:
try_connect -= 1
func send_string(stanza:String) ->void:
""" Send a string in the appropriate encoding. """
send_msg_debug.emit("Sending data: '%'".format([stanza], "%"))
tgt_peer.put_data(stanza.to_utf8_buffer())
func conv_string_to_PackedByteArray(message:String) -> PackedByteArray:
return message.to_ascii_buffer()
#func send_PackedByteArray(message:PackedByteArray) -> void:
# """ Send a PackedByteArray """
# send_msg_debug.emit("Sending data: '" + message.get_string_from_utf8() + "'")
# tgt_peer.put_data(message)
func start_stream() -> void:
""" Send the stream header.
Needs to be done several times over stream negotiation.
"""
var server_name = account_name.split("@")[-1]
var message:String = "<?xml version='1.0'?>" + \
"<stream:stream" + \
" xmlns=\"jabber:client\"" + \
" version=\"1.0\"" + \
" xmlns:stream=\"http://etherx.jabber.org/streams\"" + \
" from=\"" + account_name + "\" " + \
" to=\"" + server_name + "\" " + \
" xml:lang=\"en\"" + \
" > "
# " from=\"" + account_name + "\" " + \
# + locale + "'" +
print(message)
send_string(message)
func remove_stream_header(text :String) -> String:
var index = 0
if text.begins_with("<?") :
# Strip xml header
index = text.find("?>")
text = text.substr(index+2).strip_edges()
# strip stream header
var rg = RegEx.new()
rg.compile("<\\s?(stream|stream:stream)\\s")
var result = rg.search(text)
if result:
send_msg_debug.emit("Stream: Response header received")
index = text.find(">", result.get_end())
text = text.substr(index+1)
return text
func stream_process(response :String = "") -> void:
""" Try to authenticate using SASL. We can currently only do plain.
For SCRAM based methods, we need HMAC at the very least.
"""
if (!response.length() == 0 and stream_status != self.StreamState.STANZA):
if response.begins_with("<stream:error"):
var stream_error = XMPPStreamError.new()
stream_error.parse_from_xml(response)
var error_name = stream_error.error_name_for_enum(stream_error.error_type)
var error = tr('A stream error of type "%" occured, or in other words: % \n\nStream errors cannot be recovered from, the connection will be closed.'.format([error_name, stream_error.human_friendly_error_message()], "%"))
error.emit(error)
elif response.begins_with("<stream:features"):
var stream_features = XMPPStreamFeatures.new()
stream_features.parse_from_xml(response)
if stream_features.parsedDictionary.has("starttls"):
send_msg_debug.emit("Stream: sending request for ssl")
var request_tls = "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
send_string(request_tls)
stream_status = self.StreamState.TLS
elif stream_features.parsedDictionary.has("mechanisms"):
print("response:", response)
var authentication_methods = stream_features.parsedDictionary["mechanisms"]
if (authentication_methods.size() > 0):
var tmp:String = ""
var sep:String = ""
for item in authentication_methods:
tmp += sep + item
sep = ", "
send_msg_debug.emit("Stream: authentication methods: " + tmp)
negotiate_sasl(authentication_methods)
stream_status = self.StreamState.AUTHENTICATE
else:
if stream_status == StreamState.TLS:
if response.begins_with("<proceed"):
send_msg_debug.emit("Stream: gotten go ahead for ssl")
negotiate_tls()
else:
send_msg_error.emit(tr("Tls negotiation failed."))
elif stream_status == StreamState.AUTHENTICATE:
if response.begins_with("<success"):
stream_status = self.StreamState.STANZA
# start_stream()
return
else:
var parser = XMLParser.new()
# parser.open_buffer(response.to_utf8())
var failure_text = []
while parser.read() == OK:
if parser.get_node_type() == XMLParser.NODE_TEXT:
failure_text.append(parser.get_node_data())
print(failure_text)
# failure_text = tr("Authentication failed! %".format([PoolStringArray(failure_text).join(" ")], "%"))
var msg:String = ""
for item in failure_text:
msg += item
send_msg_error.emit(msg)
elif stream_status == self.StreamState.START:
connect_to_server()
start_stream()
else:
print("Mystery stream status: "+str(stream_status))
func negotiate_tls() -> void:
#var ssl_peer = StreamPeerTLS.new()
# I am unsure how to validate the ssl certificate for an unknown host?
#var ssl_succes = FAILED
var options:TLSOptions = TLSOptions.client_unsafe()
print("accept_stream")
#var ssl_succes = ssl_peer.accept_stream(tcp_peer, options)
var ssl_succes = ssl_peer.connect_to_stream(tcp_peer, "localhost", options)
print("resultat:", ssl_succes)
if ssl_succes == OK:
send_msg_debug.emit("Stream: switched to SSL!")
print("get_status:", ssl_peer.get_status())
# Wait connection done
while ssl_peer.get_status() == StreamPeerTLS.STATUS_HANDSHAKING:
ssl_peer.poll()
print("get_status:", ssl_peer.get_status())
tgt_peer = ssl_peer
start_stream()
print("get_status:", ssl_peer.get_status())
print("-----")
#stream_status == StreamState.START
else:
send_msg_error.emit("SSL failed, error %".format([ssl_succes], "%"))
func negotiate_sasl(authentication_methods : Array) -> void:
if (!authentication_methods.has("PLAIN")):
end_stream()
send_msg_debug.emit("Stream: sending request for plain")
var msg:PackedByteArray = PackedByteArray()
msg.push_back(0)
var t = account_name.split("@")[0]
msg += t.to_ascii_buffer()
#msg += conv_string_to_PackedByteArray(account_name.split("@")[0])
msg.push_back(0)
msg += password.to_ascii_buffer()
print("7:", msg)
var auth_account:String = Marshalls.raw_to_base64(msg)
var request_sasl:String = "<auth" + \
" xmlns='urn:ietf:params:xml:ns:xmpp-sasl'" + \
" mechanism='PLAIN'" + \
" >" + auth_account + "</auth>"
send_string(request_sasl)
func end_stream() -> void:
""" End the stream """
send_msg_debug.emit("Stream: Ending stream")
send_string("</stream>")
if tcp_peer.has_method("disconnect_from_stream"):
tcp_peer.disconnect_from_stream()
else:
tcp_peer.disconnect_from_host()
set_process(false)
stream_status = StreamState.END

View file

@ -0,0 +1,147 @@
###
# This file is part of Godot XMPP Client
# SPDX-FileCopyrightText: 2020 Wolthera van Hovell tot Westerflier <griffinvalley@gmail.com>
#
# SPDX-License-Identifier: MIT
###
extends Resource
class_name XMPPStreamError
###
# This is a parser for stream errors, that keeps a list of human friendly error-explainations.
# Stream errors, unlike stanza errors, will always close the stream.
###
enum StreamErrorTypes{
bad_format,
bad_namespace_prefix,
conflict,
connection_timeout,
host_gone,
host_unknown,
improper_addressing,
internal_server_error,
invalid_from,
invalid_namespace,
invalid_xml,
not_authorized,
not_well_formed,
policy_violation,
remote_connection_failed,
reset,
resource_constraint,
restricted_xml,
see_other_host,
system_shutdown,
undefined_condition,
unsupported_encoding,
unsupported_feature,
unsupported_stanza_type,
unsupported_version
}
var humane_error_messages = {
StreamErrorTypes.bad_format:
tr("The sent message cannot be processed."),
StreamErrorTypes.bad_namespace_prefix:
tr("The namespace cannot be recognized"),
StreamErrorTypes.conflict:
tr("This connection conflicts with another connection coming from the same address, which makes it impossible to differentiate between the connections."),
StreamErrorTypes.connection_timeout:
tr("This client took too long to respond, and thus the server assumed the device had lost internet connection."),
StreamErrorTypes.host_gone:
tr("The address of the server has changed."),
StreamErrorTypes.host_unknown:
tr("The server does not know the address."),
StreamErrorTypes.improper_addressing:
tr("The address is missing from the sent message."),
StreamErrorTypes.internal_server_error:
tr("The server is experiencing issues, try again later."),
StreamErrorTypes.invalid_from:
tr("This connection is not allowed to sign it's messages with the given address."),
StreamErrorTypes.invalid_namespace:
tr("The message was formatted with an incorrect namespace."),
StreamErrorTypes.invalid_xml:
tr("The message was formatted with invalid xml."),
StreamErrorTypes.not_authorized:
tr("The client is not allowed to sent these messages because it is not authorized to do so."),
StreamErrorTypes.not_well_formed:
tr("The message was formatted with incorrectly formed xml."),
StreamErrorTypes.policy_violation:
tr("The server determined the message violated server policy in some technical manner."),
StreamErrorTypes.remote_connection_failed:
tr("The server is unable to deliver the message because it cannot connect to the other server."),
StreamErrorTypes.reset:
tr("The server closed the connection because it deemed to connection needed to be reset for either feature or security purposes."),
StreamErrorTypes.resource_constraint:
tr("The server is too busy to handle this stream."),
StreamErrorTypes.restricted_xml:
tr("The message contained restricted xml (such as comments, processing instructions, dtd subset, or an xml entity reference)"),
StreamErrorTypes.see_other_host:
tr("The server is redirecting the client to a different host."),
StreamErrorTypes.system_shutdown:
tr("The server is being shut down."),
StreamErrorTypes.undefined_condition:
tr("A special case error has occured. See included xml stream."),
StreamErrorTypes.unsupported_encoding:
tr("The message was encoded with an encoding other than UTF-8, or contained extra bytes that the server is not expecting (as possible with godot's tls functions)."),
StreamErrorTypes.unsupported_feature:
tr("The required stream features are not supported."),
StreamErrorTypes.unsupported_stanza_type:
tr("The sent message is of a stanza type that the server does not recognize."),
StreamErrorTypes.unsupported_version:
tr("This server does not support XMPP version 1.0")
}
var error_type = StreamErrorTypes.undefined_condition
var extra_data = ""
func parse_from_xml(xml:String):
var parser = XMLParser.new()
parser.open_buffer(xml.to_utf8_buffer())
parse_with_parser(parser)
func parse_with_parser(parser:XMLParser):
# Read the error element
if parser.read() == OK and parser.get_node_name() == "stream:error":
if parser.is_empty():
error_type = 0
# Read the error inside...
if parser.read() == OK:
var error_name = parser.get_node_name().replace("-", "_")
error_type = StreamErrorTypes[error_name]
if !parser.is_empty() and parser.read() == OK:
extra_data = parser.get_node_data()
return OK
func stanza() -> String:
var stanza = []
stanza.append("<stream:error>")
var error_name = error_name_for_enum(error_type)
if !error_type.empty():
stanza.append("<"+error_name)
stanza.append("xmlns='urn:ietf:params:xml:ns:xmpp-streams'")
if extra_data.empty():
stanza.append("/>")
else:
stanza.append(">"+extra_data+"</"+error_name+">")
stanza.append("</stream:error>")
return stanza.join(" ")
func error_name_for_enum(value :int) -> String:
var error_name:String = ""
for i in StreamErrorTypes.keys():
if StreamErrorTypes[i] == value:
error_name = str(i).replace("_", "-")
return error_name
func human_friendly_error_message() -> String:
""" Human friendly error messages for the error dialogue. """
return humane_error_messages[error_type]

View file

@ -0,0 +1,88 @@
###
# This file is part of Godot XMPP Client
# SPDX-FileCopyrightText: 2020 Wolthera van Hovell tot Westerflier <griffinvalley@gmail.com>
#
# SPDX-License-Identifier: MIT
###
extends Resource
class_name XMPPStreamFeatures
###
# Parser for stream features.
##
@export var xml_string:String = "":
set = parse_from_xml
@export var parsedDictionary:Dictionary = {}
enum FeatureReq{
NO_FEATURE,
NO_REQ,
OPTIONAL,
REQUIRED
}
func feature_done(feature:String):
""" Remove the entry as it's done. """
parsedDictionary.erase(feature)
func parse_from_xml(xml:String):
var parser = XMLParser.new()
parser.open_buffer(xml.to_utf8_buffer())
parser.read()
parse_children(parser, parser.get_node_name())
func parse_children(parser:XMLParser, _parent_name:String):
parsedDictionary = {}
while (parser.read() == OK):
if (parser.get_node_type()== XMLParser.NODE_ELEMENT):
var node_name = parser.get_node_name()
if !parser.is_empty():
match(node_name):
"mechanisms":
parsedDictionary[node_name] = parse_option_list(parser, node_name, "mechanism")
"compression":
parsedDictionary[node_name] = parse_option_list(parser, node_name, "method")
_:
parsedDictionary[node_name] = parse_requirement(parser, node_name)
else:
parsedDictionary[node_name] = FeatureReq.NO_REQ
# else:
# print("Unhandled xml node type: "+str(parser.get_node_type()))
func parse_requirement(parser:XMLParser, parent_name:String):
var required = self.FeatureReq.NO_REQ
while (parser.read() == OK):
if (parser.get_node_type()== XMLParser.NODE_ELEMENT):
var node_name = parser.get_node_name()
if parser.is_empty():
if node_name == "required":
return self.FeatureReq.REQUIRED
elif node_name == "optional":
return self.FeatureReq.OPTIONAL
elif(parser.get_node_type()== XMLParser.NODE_ELEMENT_END):
var node_name = parser.get_node_name()
if node_name == parent_name:
return required
func parse_option_list(parser:XMLParser, parent_name:String, option_name:String):
var options = []
while (parser.read() == OK):
var _result
if (parser.get_node_type()== XMLParser.NODE_ELEMENT):
if parser.get_node_name() == option_name:
_result =parser.read()
if (parser.get_node_type()== XMLParser.NODE_TEXT):
options.append(parser.get_node_data())
_result = parser.read()
elif(parser.get_node_type()== XMLParser.NODE_ELEMENT_END):
if parser.get_node_name() == parent_name:
return options

View file

@ -315,21 +315,21 @@ var pose_warping_instance = PoseWarping.new()
func _process(delta):
Global.msg_info("delta: %f", [delta])
Global.msg_debug("delta: %f", [delta])
calc_animation_data()
var orientation_warping_condition = rotation_mode != Global.ROTATION_MODE.VELOCITY_DIRECTION and \
movement_state == Global.MOVEMENT_STATE.GROUNDED and \
movement_action == Global.MOVEMENT_ACTION.NONE and \
gait != Global.GAIT.SPRINTING and \
input_is_moving
Global.msg_info("orientation_warping_condition:%s", [str(orientation_warping_condition)])
Global.msg_debug("orientation_warping_condition:%s", [str(orientation_warping_condition)])
pose_warping_instance.orientation_warping( orientation_warping_condition,camera_root.HObject,animation_velocity,skeleton_ref,"Hips",["Spine","Spine1","Spine2"],0.0,delta)
func _physics_process(delta):
#Debug()
#
Global.msg_info("delta: %f", [delta])
Global.msg_debug("delta: %f", [delta])
aim_rate_h = abs((camera_root.HObject.rotation.y - previous_aim_rate_h) / delta)
previous_aim_rate_h = camera_root.HObject.rotation.y
@ -382,15 +382,15 @@ func _physics_process(delta):
#------------------ Gravity ------------------#
if is_flying == false and character_node is CharacterBody3D:
character_node.velocity.y = lerp(character_node.velocity.y,vertical_velocity.y - character_node.get_floor_normal().y,delta * gravity)
Global.msg_info("ID:%d velocity:%s", [character_node.get_node("PlayerNetworkingComponent").id, str(character_node.velocity)])
Global.msg_debug("ID:%d velocity:%s", [character_node.get_node("PlayerNetworkingComponent").id, str(character_node.velocity)])
var collided = character_node.move_and_slide()
Global.msg_info("ID:%d velocity:%s collided:%s" , [character_node.get_node("PlayerNetworkingComponent").id, str(character_node.velocity), str(collided)])
Global.msg_debug("ID:%d velocity:%s collided:%s" , [character_node.get_node("PlayerNetworkingComponent").id, str(character_node.velocity), str(collided)])
if character_node.velocity.x * character_node.velocity.x + character_node.velocity.z * character_node.velocity.z > 0.5:
input_is_moving = true
Global.msg_info("ID:%d distance^2:%s true", [character_node.get_node("PlayerNetworkingComponent").id, str(character_node.velocity.x * character_node.velocity.x + character_node.velocity.z * character_node.velocity.z )])
Global.msg_debug("ID:%d distance^2:%s true", [character_node.get_node("PlayerNetworkingComponent").id, str(character_node.velocity.x * character_node.velocity.x + character_node.velocity.z * character_node.velocity.z )])
else:
input_is_moving = false
Global.msg_info("ID:%d distance^2:%s false", [character_node.get_node("PlayerNetworkingComponent").id, str(character_node.velocity.x * character_node.velocity.x + character_node.velocity.z * character_node.velocity.z )])
Global.msg_debug("ID:%d distance^2:%s false", [character_node.get_node("PlayerNetworkingComponent").id, str(character_node.velocity.x * character_node.velocity.x + character_node.velocity.z * character_node.velocity.z )])
if ground_check.is_colliding() and is_flying == false:
movement_state = Global.MOVEMENT_STATE.GROUNDED
@ -584,13 +584,13 @@ func add_movement_input(direction: Vector3 = Vector3.ZERO, Speed: float = 0, Acc
if is_flying == false:
character_node.velocity.x = lerp(character_node.velocity.x,(direction*max_speed).x,Acceleration/(max_speed if max_speed != 0 else (abs(character_node.velocity.x) if character_node.velocity.x != 0 else 1.0))*get_physics_process_delta_time())
character_node.velocity.z = lerp(character_node.velocity.z,(direction*max_speed).z,Acceleration/(max_speed if max_speed != 0 else (abs(character_node.velocity.z) if character_node.velocity.z != 0 else 1.0))*get_physics_process_delta_time())
Global.msg_info("ID:%d velocity:%s", [character_node.get_node("PlayerNetworkingComponent").id, str(character_node.velocity)])
Global.msg_debug("ID:%d velocity:%s", [character_node.get_node("PlayerNetworkingComponent").id, str(character_node.velocity)])
else:
character_node.velocity = character_node.velocity.lerp((direction*max_speed),Acceleration/(max_speed if max_speed != 0 else character_node.velocity.x if character_node.velocity.x != 0 else 1.0)*get_physics_process_delta_time())
var body_collided = character_node.move_and_slide()
Global.msg_info("ID:%d body_collided:%s", [character_node.get_node("PlayerNetworkingComponent").id, str(body_collided)])
Global.msg_debug("ID:%d body_collided:%s", [character_node.get_node("PlayerNetworkingComponent").id, str(body_collided)])
# Get the velocity from the character node
Global.msg_info("ID:%d velocity:%s", [character_node.get_node("PlayerNetworkingComponent").id, str(character_node.velocity)])
Global.msg_debug("ID:%d velocity:%s", [character_node.get_node("PlayerNetworkingComponent").id, str(character_node.velocity)])
var character_node_velocity = character_node.velocity if character_node is CharacterBody3D else character_node.linear_velocity
@ -598,7 +598,7 @@ func add_movement_input(direction: Vector3 = Vector3.ZERO, Speed: float = 0, Acc
movement_direction = atan2(input_velocity.x,input_velocity.z)
#input_is_moving = input_velocity.length() > 0.0
input_acceleration = Acceleration * direction * (1 if max_speed != 0 else -1)
Global.msg_info("ID:%d velocity:%s input_velocity:%s direction:%s input_acceleration:%s character_node_velocity:%s", [character_node.get_node("PlayerNetworkingComponent").id, str(character_node.velocity), str(input_velocity.length()), str(direction), str(input_acceleration), str(character_node_velocity)])
Global.msg_debug("ID:%d velocity:%s input_velocity:%s direction:%s input_acceleration:%s character_node_velocity:%s", [character_node.get_node("PlayerNetworkingComponent").id, str(character_node.velocity), str(input_velocity.length()), str(direction), str(input_acceleration), str(character_node_velocity)])
#
actual_acceleration = (character_node_velocity - PrevVelocity) / (get_physics_process_delta_time())
PrevVelocity = character_node_velocity

View file

@ -18,7 +18,8 @@ config/icon="res://icon.svg"
[autoload]
Multi="*res://scenes/multi.gd"
Global="*res://player/Global.gd"
Global="*res://scripts/Global.gd"
Stream="*res://Stream/Stream.gd"
[display]

View file

@ -35,8 +35,21 @@ func _ready():
Multi.update_my_position.connect(_on_update_me)
Multi.update_player_position.connect(_on_update_player)
Multi.remove_player.connect(_on_remove_player)
Stream.set_server_ip("localhost")
Stream.set_port_number(5222)
Stream.send_msg_debug.connect(show_stream_debug)
Stream.send_msg_error.connect(show_stream_error)
#$Window.world_2d = _MainWindow.world_2d
func show_stream_debug(msg:String):
print("DEBUG [Stream] ", msg)
func show_stream_error(msg:String):
print("ERROR [Stream] ", msg)
func create_view_window():
pass
# var new_window: Window = view_window.instantiate()
@ -77,6 +90,7 @@ func _on_connexion_updated(new_state:Multi.Connexion):
$PlayerSpawnLocation.get_child(0).set_activate()
$PlayerSpawnLocation.set_visible(true)
$CameraStarting.set_current(false)
Stream.xmppclient = true
else:
$CameraStarting.set_current(true)
$Panel/State.set_text("Unknown")

39
start-bazar-fake-xmpp-server.sh Executable file
View file

@ -0,0 +1,39 @@
#!/bin/bash
declare WORKDIR="$(dirname $(readlink -f $0))"
declare XMPPDIR="$WORKDIR/.xmpp"
echo "WORKDIR:$WORKDIR"
echo "XMPPDIR:$XMPPDIR"
docker pull ejabberd/ecs
#if [ ! -d $XMPPDIR ]
#then
# mkdir -p $XMPPDIR
# sudo chown 9000:9000 database
#fi
list=$( docker ps -q -a -f name="ejabberd")
if [ -z "$list" ]
then
docker run --name ejabberd \
--publish 5222:5222 \
--publish 5269:5269 \
--publish 5280:5280 \
--publish 5443:5443 \
--publish 1883:1883 \
ejabberd/ecs
else
docker start ejabberd
docker logs -f ejabberd
docker stop
fi
# https://localhost:5443/admin/
# docker exec -it ejabberd bin/ejabberdctl register admin localhost passw0rd
# docker exec -it ejabberd bin/ejabberdctl register toto localhost toto
# docker exec -it ejabberd bin/ejabberdctl status
# docker exec -it ejabberd bin/ejabberdctl stats registeredusers
# docker exec -it ejabberd bin/ejabberdctl register titi localhost titi
# docker exec -it ejabberd bin/ejabberdctl register undefined localhost undefined