JSHint is now a fair bit stricter, and is now correctly checking
files in `mods/`.
The code has been fixed to match the new stricter standards.
JSHint has now caught its second actual bug: Gen 5 Pinap Berry
was Ice instead of Grass.
I used a hack to make the multiple declaration errors go away,
so all that remained in jsHint were actual errors, which I've
now mostly fixed.
All this linting ended up uncovering one actual bug: Uproar's
message not showing. It's a very minor bug in a move no one uses,
so I'm going to fold it into this commit.
The main process no longer does any JSON parsing/stringifying of
teams. The communication protocol with validator processes has
been changed from JSON to a string protocol delimited by pipes.
A variety of more minor optimizations have also been done.
This doesn't yet handle modded formats that don't validate ability
selection in the ordinary manner. Those formats will continue to work
essentially in the same manner as before, rather than with the correct
mechanics.
Previously, Simulator.prototype.resendRequest() called user.sendTo()
with an invalid room specified, causing the server to send the
message to all rooms, leading to problems on the live server.
In certain laggy situations, the following sequence of events
was previously possible in a battle:
1) Server makes request R_1 and R_2.
2) User 1 selects decision D_1 for request R_1
3) User 2 selects decision D_2 for request R_2
4) Server receives D_1 and D_2 and runs the turn
5) Server makes request R_3 and R_4.
4) Due to lag, User 1 does not realise that the server has
already run the turn. User 1 wants to change his or her move
for request R_1, so User 1 cancels decision D_1 and sends in
decision D_3, intending it to be for request R_1.
5) User 2 selects decision D_4 for R_4.
6) Server receives D_3 and considers it to be the response to R_3,
rather than the response to R_1 (which was what User 1 intended).
7) Server receives D_4 and considers it to be the response to R_4.
8) Server runs the turn.
The result of this sequence of events is that a move that User 1
intended to be for request R_1 is instead used for R_3, which has
the effect of depriving the user of the ability to make a reasoned
choice of which move to use for R_3.
This commit attempts to solve this problem by requiring the client
to acknowledge having received a request before the server will
accept a decision for that request.
Unfortunately, there is no seamless way to implement this in a
backward-compatible way. In other words, if the client were updated
to always send acks, it would no longer be able to work with old
versions of the server. For example, if the ack were added to the
choice string, old servers would no longer be able to handle choice
strings sent from the client. Similarly, if the ack were added
in the form of a new command (say, /ackrequest), old servers would
emit an unrecognised command error on receiving the command.
This commit maintains backward-compatibility by introducing a version
field to the init data structure sent to the client when joining a
battle room. This version should be incremented for any future
backward-incompatible changes as well.
The implementation of the ack request system is that the client must
send in "/ackrequest rqid" for each request, where rqid is the ID of
the request. If the server has not received an ack for request 'rqid'
when it receives a decision for request 'rqid', it discards the
decision and asks the client for another decision.
The corresponding client commit is Zarel/Pokemon-Showdown-Client@ccf0a97733
Battles now occur in a separate process.
Hopefully, this results in a substantial increase in network stability.
WARNING: Battle crashes are now practically unrecoverable.