Brandling Safari: LAN safari-zone creature catching on the HD-2D engine
- Authoritative 30 Hz server (ENet, SQLite): accounts, characters, wild AI, tall grass / water / wandering spawns, fishing, captures, follower chains, clock + weather, LAN beacon - Client: title / join / character creator / play screens, prediction + reconciliation, interpolated players and parties, HD-2D UI (dialogue with Professor Henry, HUD, collection) - Shared deterministic zone generator, movement, protocol, roster, appearance - Paper-doll character art pipeline (PixelLab base walk + per-item animation edits) - Brandling roster from the company list (logo colors, jev types), Blender safari props - Headless test bot
This commit is contained in:
81
shared/Net.h
Normal file
81
shared/Net.h
Normal file
@@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
// Thin ENet wrapper (reliable channel + unreliable channel) and a UDP
|
||||
// broadcast beacon for finding servers on the LAN.
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
struct _ENetHost;
|
||||
struct _ENetPeer;
|
||||
|
||||
namespace bs::net {
|
||||
|
||||
enum Channel : uint8_t { Reliable = 0, Unreliable = 1, kChannelCount = 2 };
|
||||
|
||||
struct Event {
|
||||
enum Type { None, Connect, Disconnect, Receive } type = None;
|
||||
uint32_t peer = 0;
|
||||
std::vector<uint8_t> data;
|
||||
};
|
||||
|
||||
bool initialize(); // once per process (enet_initialize); safe to call repeatedly
|
||||
void shutdown();
|
||||
|
||||
class Host {
|
||||
public:
|
||||
Host() = default;
|
||||
Host(const Host&) = delete;
|
||||
Host& operator=(const Host&) = delete;
|
||||
~Host();
|
||||
|
||||
bool listen(uint16_t port, size_t maxPeers);
|
||||
// Starts connecting; a Connect (or Disconnect on failure) event follows.
|
||||
bool connect(const std::string& address, uint16_t port);
|
||||
// Next event; waits up to timeoutMs for the first one.
|
||||
bool poll(Event& ev, uint32_t timeoutMs = 0);
|
||||
void send(uint32_t peer, Channel ch, const std::vector<uint8_t>& data);
|
||||
void disconnect(uint32_t peer);
|
||||
void flush();
|
||||
std::string address(uint32_t peer) const;
|
||||
uint32_t roundTripMs(uint32_t peer) const;
|
||||
bool valid() const { return host_ != nullptr; }
|
||||
|
||||
private:
|
||||
_ENetHost* host_ = nullptr;
|
||||
uint32_t nextId_ = 1;
|
||||
std::unordered_map<uint32_t, _ENetPeer*> peers_;
|
||||
};
|
||||
|
||||
struct ServerInfo {
|
||||
std::string address; // ip the reply came from
|
||||
uint16_t port = 0;
|
||||
std::string name;
|
||||
int players = 0;
|
||||
};
|
||||
|
||||
// Server side: answers "BSAFARI?" broadcasts on kDiscoveryPort.
|
||||
class Beacon {
|
||||
public:
|
||||
~Beacon();
|
||||
bool open(uint16_t discoveryPort);
|
||||
void poll(uint16_t gamePort, const std::string& serverName, int players);
|
||||
|
||||
private:
|
||||
intptr_t sock_ = -1;
|
||||
};
|
||||
|
||||
// Client side: broadcasts a query and collects replies.
|
||||
class Scanner {
|
||||
public:
|
||||
~Scanner();
|
||||
bool open();
|
||||
void ping(uint16_t discoveryPort);
|
||||
void poll(std::vector<ServerInfo>& found);
|
||||
|
||||
private:
|
||||
intptr_t sock_ = -1;
|
||||
};
|
||||
|
||||
} // namespace bs::net
|
||||
Reference in New Issue
Block a user