npx skills add smithery/pluginagentmarketplace --skill communication-protocols
pluginagentmarketplace/custom-plugin-server-side-game-dev · Archived
communication-protocols
Game server communication protocols including gRPC, REST, and custom binary protocols
Installation
npx skills add pluginagentmarketplace/custom-plugin-server-side-game-dev --skill communication-protocols
Stronger alternatives
This repository is archived — consider an actively maintained alternative.
Game state synchronization, snapshot systems, and conflict resolution for consistent multiplaye…
3 installsGame server design patterns including ECS, command pattern, and event sourcing
3 installsEfficient data serialization for game networking including Protobuf, FlatBuffers, and custom bi…
3 installsMultithreading and concurrency patterns for game servers including synchronization primitives
2 installsSimilar popular skills
Related neighbors and high-traction skills in the same topics — useful to compare before installing.
Helps users discover and install agent skills when they ask questions like "how do I do X", "fi…
3.3M installsBrowser automation CLI for AI agents. Use when the user needs to interact with websites, includ…
810.4K installsReview UI code for Web Interface Guidelines compliance. Use when asked to "review my UI", "chec…
617.3K installsBuild, deploy, evaluate, optimize, fine-tune, and manage Microsoft Foundry agents, models, and …
576.5K installsPrepare azd-based Azure projects for deployment: generates azure.yaml, infrastructure (Bicep/Te…
568.3K installsAlso in this package
Other skills from pluginagentmarketplace/custom-plugin-server-side-game-dev.
npx skills add pluginagentmarketplace/custom-plugin-server-side-game-dev
Browse all from pluginagentmarketplace/custom-plugin-server-side-game-dev
More details
Agent compatibility
Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.
Also listed on
Alternate registries and mirrors of this skill.
Repository health
main
Skill metadata
Parsed from SKILL.md frontmatter.
Package contents
Files included with this skill beyond the listing page.
-
skill md
SKILL.md10,566 B -
docs
SUMMARY.md116 B
History
- First seen on skills.sh
- First recorded snapshot · 2 installs
SKILL.md
Communication Protocols for Game Servers
Implement efficient communication protocols between game services and clients.
Protocol Selection Guide
| Protocol | Latency | Throughput | Use Case |
|---|---|---|---|
| Custom Binary | Lowest | Highest | Real-time gameplay |
| gRPC | Low | High | Service-to-service |
| WebSocket | Low | Medium | Browser clients |
| REST | Medium | Medium | Admin APIs, lobbies |
| QUIC | Low | High | Mobile, unreliable networks |
gRPC for Game Services
// matchmaking.proto
syntax = "proto3";
package game.matchmaking;
service Matchmaking {
rpc FindMatch(MatchRequest) returns (MatchResponse);
rpc JoinQueue(QueueRequest) returns (stream QueueUpdate);
rpc CancelQueue(CancelRequest) returns (CancelResponse);
}
message MatchRequest {
string player_id = 1;
string game_mode = 2;
int32 skill_rating = 3;
repeated string preferred_regions = 4;
}
message MatchResponse {
string match_id = 1;
string server_address = 2;
int32 server_port = 3;
repeated TeamAssignment teams = 4;
string connection_token = 5;
}
message QueueUpdate {
enum Status {
SEARCHING = 0;
MATCH_FOUND = 1;
CANCELLED = 2;
}
Status status = 1;
int32 estimated_wait_seconds = 2;
int32 players_in_queue = 3;
}
Go gRPC Server
type matchmakingServer struct {
pb.UnimplementedMatchmakingServer
matchmaker *Matchmaker
}
func (s *matchmakingServer) FindMatch(
ctx context.Context,
req *pb.MatchRequest,
) (*pb.MatchResponse, error) {
match, err := s.matchmaker.FindMatch(ctx, req.PlayerId, req.GameMode, req.SkillRating)
if err != nil {
return nil, status.Errorf(codes.Internal, "matchmaking failed: %v", err)
}
return &pb.MatchResponse{
MatchId: match.ID,
ServerAddress: match.ServerAddr,
ServerPort: int32(match.ServerPort),
ConnectionToken: match.Token,
}, nil
}
func (s *matchmakingServer) JoinQueue(
req *pb.QueueRequest,
stream pb.Matchmaking_JoinQueueServer,
) error {
updates := s.matchmaker.Subscribe(req.PlayerId)
defer s.matchmaker.Unsubscribe(req.PlayerId)
for update := range updates {
if err := stream.Send(update); err != nil {
return err
}
if update.Status == pb.QueueUpdate_MATCH_FOUND {
return nil
}
}
return nil
}
Custom Binary Protocol
// Packet header (8 bytes)
struct PacketHeader {
uint8_t type; // Message type
uint8_t flags; // Compression, reliability flags
uint16_t length; // Payload length
uint32_t sequence; // Packet sequence for ordering/ack
};
enum PacketType : uint8_t {
PLAYER_INPUT = 0x01,
STATE_UPDATE = 0x02,
PLAYER_JOIN = 0x03,
PLAYER_LEAVE = 0x04,
CHAT_MESSAGE = 0x10,
PING = 0xFE,
PONG = 0xFF
};
enum PacketFlags : uint8_t {
FLAG_RELIABLE = 0x01,
FLAG_COMPRESSED = 0x02,
FLAG_ENCRYPTED = 0x04
};
// Zero-copy packet builder
class PacketBuilder {
uint8_t buffer[MAX_PACKET_SIZE];
size_t offset = sizeof(PacketHeader);
public:
PacketBuilder& writeU8(uint8_t v) {
buffer[offset++] = v;
return *this;
}
PacketBuilder& writeU16(uint16_t v) {
*reinterpret_cast<uint16_t*>(&buffer[offset]) = htons(v);
offset += 2;
return *this;
}
PacketBuilder& writeFloat(float v) {
*reinterpret_cast<float*>(&buffer[offset]) = v;
offset += 4;
return *this;
}
std::span<uint8_t> build(PacketType type, uint8_t flags = 0) {
auto* header = reinterpret_cast<PacketHeader*>(buffer);
header->type = static_cast<uint8_t>(type);
header->flags = flags;
header->length = htons(offset - sizeof(PacketHeader));
header->sequence = htonl(nextSequence++);
return {buffer, offset};
}
};
// Player input packet (compact)
struct PlayerInputPacket {
uint32_t tick; // 4 bytes
uint8_t keys; // 1 byte: WASD + jump + fire (bitfield)
int16_t aim_x; // 2 bytes: quantized aim [-32768, 32767]
int16_t aim_y; // 2 bytes: quantized aim
}; // Total: 9 bytes
WebSocket for Browser Games
// Server (Node.js with ws)
const WebSocket = require('ws');
const wss = new WebSocket.Server({
port: 8080,
perMessageDeflate: true, // Compression
maxPayload: 64 * 1024 // 64KB limit
});
wss.on('connection', (ws, req) => {
const playerId = authenticate(req);
ws.on('message', (data, isBinary) => {
if (isBinary) {
// Binary protocol for gameplay
const view = new DataView(data.buffer);
const type = view.getUint8(0);
handleBinaryMessage(playerId, type, view);
} else {
// JSON for lobby/chat
const msg = JSON.parse(data);
handleJsonMessage(playerId, msg);
}
});
ws.on('close', () => {
onPlayerDisconnect(playerId);
});
// Send binary state updates at 60Hz
const tickInterval = setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
const state = serializeGameState(playerId);
ws.send(state, { binary: true });
}
}, 16);
ws.on('close', () => clearInterval(tickInterval));
});
// Client
class GameClient {
constructor(url) {
this.ws = new WebSocket(url);
this.ws.binaryType = 'arraybuffer';
this.ws.onmessage = (event) => {
if (event.data instanceof ArrayBuffer) {
this.handleStateUpdate(new DataView(event.data));
} else {
this.handleJsonMessage(JSON.parse(event.data));
}
};
}
sendInput(keys, aimX, aimY) {
const buffer = new ArrayBuffer(9);
const view = new DataView(buffer);
view.setUint32(0, this.currentTick);
view.setUint8(4, keys);
view.setInt16(5, aimX);
view.setInt16(7, aimY);
this.ws.send(buffer);
}
}
REST API for Game Services
// Lobby API with proper error handling
type LobbyHandler struct {
lobbyService *LobbyService
}
func (h *LobbyHandler) CreateLobby(w http.ResponseWriter, r *http.Request) {
var req CreateLobbyRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
respondError(w, http.StatusBadRequest, "invalid request body")
return
}
lobby, err := h.lobbyService.Create(r.Context(), req)
if err != nil {
switch {
case errors.Is(err, ErrPlayerAlreadyInLobby):
respondError(w, http.StatusConflict, err.Error())
case errors.Is(err, ErrMaxLobbiesReached):
respondError(w, http.StatusTooManyRequests, err.Error())
default:
respondError(w, http.StatusInternalServerError, "internal error")
}
return
}
respondJSON(w, http.StatusCreated, lobby)
}
func respondJSON(w http.ResponseWriter, status int, data interface{}) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
json.NewEncoder(w).Encode(data)
}
Protocol Selection Matrix
| Scenario | Protocol | Reason |
|---|---|---|
| Real-time gameplay | Custom UDP binary | Lowest latency |
| Microservices | gRPC | Type safety, streaming |
| Web/mobile lobby | WebSocket JSON | Browser compatibility |
| Admin dashboard | REST | Standard tooling |
| Streaming updates | gRPC streaming | Backpressure handling |
Troubleshooting
Common Failure Modes
| Error | Root Cause | Solution |
|---|---|---|
| Connection reset | Message too large | Chunk large messages |
| Timeout | Slow processing | Async handlers |
| Parse error | Version mismatch | Protocol versioning |
| High latency | No compression | Enable compression |
Debug Checklist
# gRPC debugging
GRPC_VERBOSITY=DEBUG GRPC_TRACE=all ./game-server
# WebSocket inspection
wscat -c ws://localhost:8080
# Protocol buffer decoding
protoc --decode=game.StateUpdate game.proto < message.bin
# Network trace
tcpdump -i any port 8080 -w capture.pcap
Unit Test Template
func TestMatchmakingRPC(t *testing.T) {
server := setupTestServer()
defer server.Stop()
conn, err := grpc.Dial(server.Addr, grpc.WithInsecure())
require.NoError(t, err)
defer conn.Close()
client := pb.NewMatchmakingClient(conn)
resp, err := client.FindMatch(context.Background(), &pb.MatchRequest{
PlayerId: "player123",
GameMode: "ranked",
SkillRating: 1500,
})
require.NoError(t, err)
assert.NotEmpty(t, resp.MatchId)
assert.NotEmpty(t, resp.ServerAddress)
}
func TestBinaryProtocol(t *testing.T) {
builder := NewPacketBuilder()
packet := builder.
WriteU32(12345). // tick
WriteU8(0x0F). // keys
WriteI16(1000). // aim_x
WriteI16(-500). // aim_y
Build(PLAYER_INPUT)
parsed := ParsePlayerInput(packet)
assert.Equal(t, uint32(12345), parsed.Tick)
assert.Equal(t, uint8(0x0F), parsed.Keys)
}
Resources
assets/- Protocol templatesreferences/- Performance benchmarks