- Lobbies: a name (default "Lobby <code>"), Unlisted or Public, and an optional password. The Multiplayer page scrolls: a Browser of public lobbies (name, count, padlock, code, little player previews, Join with a password field when locked), Join by code, Create, then Settings. Errors show under whatever caused them. Links take ?pass= (and --pass), and Copy Link includes it. Protocol 11. - Queue areas center on their host along the floor's flat stretch, squeezing their slots to fit, and move to a nearby surface when the host's is too short. - An airblast steals an enemy's flail ball onto its own chain for a while. Flail balls reel themselves back after 15 seconds. Doubler echoes of the Grimoire teleport move you too. - The Good Stuff: a new trinket, the inverse of Diazepam (more spread). Spread is now a multiplier, and it widens or narrows the Vacuum's cone. - Balance: Sword basic slash 25% smaller and charged slash half the size, Whip basic lash half the damage and reach, Recoil Coil recoil halved, Speedometer no longer speeds you up. - Fixes: fashions survive coming back from a game, Quit shows only in the sandbox menu, and the chat log keeps above the menu's tip.
121 lines
4.0 KiB
C++
121 lines
4.0 KiB
C++
#pragma once
|
|
|
|
#include "protocol.h"
|
|
#include <map>
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
struct Game;
|
|
|
|
enum NetState
|
|
{
|
|
NET_OFFLINE,
|
|
NET_CONNECTING,
|
|
NET_JOINING,
|
|
NET_LOBBY
|
|
};
|
|
|
|
// A line for the chat log from the server, and the member it's about (-1 for none), in whose color it shows.
|
|
struct NetNotice
|
|
{
|
|
std::string text;
|
|
int member = -1;
|
|
};
|
|
|
|
// A public lobby as the server lists it: its code and name, whether it needs a password, and each player's color
|
|
// (-1 while unassigned) and fashion, for little previews.
|
|
struct LobbyListing
|
|
{
|
|
std::string code;
|
|
std::string name;
|
|
std::vector<std::pair<int, int>> players;
|
|
bool isLocked = false;
|
|
};
|
|
|
|
// Whether the lobby list shows a lobby, or only its code or link finds it.
|
|
enum LobbyVisibility
|
|
{
|
|
LOBBY_UNLISTED,
|
|
LOBBY_PUBLIC
|
|
};
|
|
|
|
// What a new lobby is made with: its name (empty for "Lobby <code>"), its password (empty for none), and who can find
|
|
// it (see LobbyVisibility).
|
|
struct LobbyOptions
|
|
{
|
|
char name[LOBBY_NAME_MAX + 1] = {};
|
|
char password[LOBBY_PASSWORD_MAX + 1] = {};
|
|
int visibility = LOBBY_UNLISTED;
|
|
};
|
|
|
|
// Someone in the lobby (this screen's player too): their server id and name, and their connection's round trip to the
|
|
// server in milliseconds (-1 while it isn't known: this screen only measures its own).
|
|
struct NetMember
|
|
{
|
|
int id = -1;
|
|
std::string name;
|
|
float ping = -1;
|
|
};
|
|
|
|
// Online play: a WebSocket to the server (see protocol.h) to make or join a lobby, and through it a WebRTC connection
|
|
// to the server to play over, with two data channels: a reliable, ordered one for everything that mustn't go missing,
|
|
// and a lossy one for controls and frames, which are sent again until they're confirmed, so a lost one is never waited
|
|
// on. Until both are open (or where they never open, with UDP blocked), the game's messages go over the socket.
|
|
// The network calls back on its own threads (on desktop), so everything it reports is queued and handled in update,
|
|
// once a frame on the main thread. Members are in the order they joined, so the first hosts. Error holds why the last
|
|
// request failed or the connection was lost, until the next request.
|
|
class Net
|
|
{
|
|
public:
|
|
Net();
|
|
~Net();
|
|
|
|
void lobby_create(Game& game, LobbyOptions& options);
|
|
void lobbies_request(Game& game);
|
|
void lobby_join(Game& game, const std::string& code, const std::string& password);
|
|
void lobby_leave();
|
|
void update();
|
|
void shutdown();
|
|
void heartbeat();
|
|
void send(const std::string& bytes, Delivery delivery);
|
|
void kick_send(int member, const std::string& reason);
|
|
void host_send(int member);
|
|
bool is_linked();
|
|
|
|
NetState state = NET_OFFLINE;
|
|
std::string code;
|
|
std::string error;
|
|
// The lobby's name, and the password it was made or joined with (for its link).
|
|
std::string lobbyName;
|
|
std::string password;
|
|
// The public lobbies, as the server last listed them, and why the last listing failed (empty once one comes).
|
|
std::vector<LobbyListing> listings;
|
|
std::string listError;
|
|
int selfId = -1;
|
|
int hostId = -1;
|
|
std::vector<NetMember> members;
|
|
// Binary messages from the server, oldest first, for the session to take.
|
|
std::vector<std::string> packets;
|
|
// Lines for the chat log from the server (like this screen being kicked), oldest first, for the chat to take.
|
|
std::vector<NetNotice> notices;
|
|
// Members the server said were kicked, with the reason (empty for none given).
|
|
std::map<int, std::string> kicks;
|
|
|
|
private:
|
|
struct Impl;
|
|
std::unique_ptr<Impl> impl;
|
|
|
|
void request_send(Game& game, const std::string& request, NetState waiting);
|
|
void send_now(const std::string& bytes, Delivery delivery);
|
|
void ping_send();
|
|
void message_handle(const std::string& text);
|
|
void link_open();
|
|
void signal_handle(const std::string& payload);
|
|
NetMember* member_get(int id);
|
|
void host_announce(int previous);
|
|
std::string& failure_get();
|
|
|
|
// Whether the request in flight is only asking for the lobby list, so its failures go to listError.
|
|
bool isListing = false;
|
|
};
|