-
-
Notifications
You must be signed in to change notification settings - Fork 239
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add dynamic cross-protocol support #331
Conversation
createClient doesn't create an "all ready" client: people will want to wait for the login packet for example. |
Err probably not login, that's server side, but there are many "ready" events in mineflayer (spawn, received inventory,...), so people wait for one of these before writing anything to the client. |
I'd definitely like to maintain API compatibility with createClient, will have to investigate more to try to do this. The problem I was running into is that the client created by createClient would continue the protocol handshake even before I received the ping. Maybe need some way to "pause" the client object? Also to dynamically change the version and hostname after object construction. |
I think to do it cleanly you'd have to change createClient so it would On Tue, Jan 26, 2016, 03:33 deathcap [email protected] wrote:
|
I think that's problematic for other reasons, imho the 0xfe01 ping #332 is superior, as it does not require a status handshake, nor a protocol version (and works on all 1.4.4+)
Notes for testing this scenario: edit src/createServer.js to comment out
client should hang (hits #329 Missing ping timeout callback when server is running but not responding to pings) or timeout:
then edit src/createClientAuto.js (from this PR), move the now, the client will despite not receiving a ping (callback not executed), it will still begin to connect:
Now that the client is more modular, it's easier to see what's going on, need to test to confirm but I think this is where it is unexpectedly (or undesirably) executing from: // src/client/setProtocol.js
ar states = require("../states");
module.exports = function(client, options) {
client.on('connect', onConnect);
function onConnect() {
client.write('set_protocol', {
protocolVersion: options.protocolVersion,
serverHost: options.host,
serverPort: options.port,
nextState: 2
}); setProtocol sends the set_protocol packet as soon as the socket connects. (and src/client/caseCorrect.js calls client options.connect(), which is set from src/client/tcp_dns.js to call client.setSocket()) |
caseCorrecting and tcp_dns (SRV lookup and TCP initiation) can occur beforehand, but sending set_protocol should be delayed until the client knows (via ping) the protocolVersion. |
Listen for another event in setProtocol before sending the packet? 'connect' is going to be received when the TCP socket it connected, whether we are ready for it or not. Additionally block on another event (optionally), something like 'connect_allowed'? |
…c/client/setProtocol proceeds Intended to allow clients to configure the client object before any data is sent, specifically, before src/client/setProtocol sends the set_protocol packet.
The server immediately closes the socket after sending the ping response, so unfortunately I don't think reusing it is possible. |
This allows client plugins to change the options on the client object, and have it reflected in other plugins. Previously, had to rely on the options being the same object, and hold a reference to it. Now it is always accessible as `client.options`.
Converted to use "sync" API ok, started to move into createClient() via a src/client/autoVersion.js plugin. Having some difficulty re-versioning the client object after it is instantiated. The constructor calls setHandshake() and sets .version to the major version, so I do this too in autoVersion.js after the version is ready, and then emit connect_allowed to uncork setProtocol, it sends the set_protocol packet but then the program just exits:
|
Looks like the ping connection is somehow interfering with the subsequent normal connection. The logged
Problem with the serializer? Packet capture shows the handshaking.set_protocol packet is never sent on the 2nd connection, only the login.login_start packet:
even though it was logged as being written in:
|
…re properly piped
Updating the client state using (why I was confused: the src/client.js constructor calls this.setSerializer, not this.state=..., tried to mimic that behavior to re-initialize the version, but |
Failing tests in requiring minecraft-data: PrismarineJS/node-minecraft-data#16 Attempted to use latest node-minecraft-data from git, but still fails, I think CircleCI is caching the node_modules. Will try a clean CircleCI setup. |
PrismarineJS/node-minecraft-protocol#331 Add dynamic cross-protocol support
20564a4
to
80fe58f
Compare
@@ -1,7 +1,8 @@ | |||
var yggdrasil = require('yggdrasil')({}); | |||
var UUID = require('uuid-1345'); | |||
|
|||
module.exports = function(client, options) { | |||
module.exports = function(client) { | |||
var options = client.options; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why client.options ? The client, options
pattern is consistent with what mineflayer is doing, and it seems to makes sense. (It also allows destructuring : for example https://github.com/PrismarineJS/flying-squid/blob/master/src/lib/plugins/world.js#L10 )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I saw your commit message "This allows client plugins to change the options on the client object,
and have it reflected in other plugins. Previously, had to rely on the
options being the same object, and hold a reference to it. Now it is
always accessible as client.options
."
It sounds like it assume some order of execution between plugins. Which plugins is accessing the modified property ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah that kind of thing https://github.com/PrismarineJS/node-minecraft-protocol/pull/331/files#diff-9053b72ce1984293dcb954a0ccc89097R9.
Couldn't it be put in a client.wait_connect ?
But the problem of relying on the order of execution of plugins remains.
I made some comments
(I guess it's probably necessary for some plugins to depend on other, but let's probably keep it implicit for now) |
I am very, very, very much against the
What plugin needs modifying the options ? I believe that if any plugin requires this, it should instead wrap the original plugin in some way. |
Updated to data 0.19.1, removing need for git clone post-action Plugins currently modifying options:
I suppose these 'options' could be moved onto the client object, since they're not really options but data passed between plugins (which can initially come from options, but only as a default). tagHost could use the system described in #336 (comment) |
|
||
// Get the minecraft-data version string for a protocol version | ||
// TODO: add to node-minecraft-data index (protocol to newest release, if multiple) | ||
function protocolVersion2MinecraftVersion(n) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can now be implemented using https://github.com/PrismarineJS/node-minecraft-data/blob/master/example.js#L19 I think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, missed that, will use postNettyVersionsByProtocolVersion
Alright I've restored the |
Moved |
Add dynamic cross-protocol support
Implements the dynamic part of #234 Cross version support
Ported from https://github.com/deathcap/node-minecraft-protocol-auto (which I can deprecate if this is merged)
To do: