mirror of
https://port.numenaute.org/aleajactaest/bazar_alea.git
synced 2024-11-09 08:49:03 +00:00
connect to XMPP
This commit is contained in:
parent
40d8cc0318
commit
0ab321c3e1
8 changed files with 636 additions and 12 deletions
335
client/Stream/Stream.gd
Normal file
335
client/Stream/Stream.gd
Normal 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
|
147
client/Stream/xmpp_stream_errors.gd
Normal file
147
client/Stream/xmpp_stream_errors.gd
Normal 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]
|
88
client/Stream/xmpp_stream_features.gd
Normal file
88
client/Stream/xmpp_stream_features.gd
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
||||
|
|
|
@ -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
39
start-bazar-fake-xmpp-server.sh
Executable 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
|
||||
|
Loading…
Reference in a new issue