Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

EVOID

EVOID

Godot game integration for EVOID — WebSocket, EventBus, WebGL hosting

Godot License GitHub Docs


Connect your Godot games (desktop or web) to an EVOID server. Zero boilerplate, zero coupling.

Features

  • EventBus pattern — subscribe/emit like native Godot signals
  • State Machine — BOOT → IDLE → CONNECTING → ONLINE → RECOVERING → ERROR
  • Auto-reconnect — exponential backoff, hands-free recovery
  • Intent System (IOP) — send game actions as Intents, not raw HTTP
  • Dual transport — WebSocket (broad compatibility) + UDP (low-latency)
  • WebGL support — play in browser with instant loading
  • Embed mode — seamless integration in parent websites
  • Export optimizations — auto SW injection, manifest generation
  • Zero dependencies — pure GDScript, no native builds

Quick Start

1. Install

Copy evoid_godot/ into your project's addons/ folder:

your-game/
  addons/
    evoid_godot/
      core/
        app.gd
        client.gd
        udp_client.gd
        event_bus.gd
        config.gd
        topics.gd
        web_loader.gd
      export_plugin.gd
      plugin.cfg
      plugin.gd
      icon.png

2. Enable

Project → Project Settings → Plugins → EVOID → Enable

3. Connect

func _ready():
    EvoidApp.connect_to_server("wss://your-server.com", "game-id")

4. Send Actions

EvoidApp.send_intent("player_move", {"x": 10, "y": 20})
EvoidApp.send_intent("player_shot", {"origin": global_position, "direction": aim_direction})

5. Receive Events

func _ready():
    EvoidBus.subscribe(EvoidTopics.GAME_EVENT, _on_game_event)

func _on_game_event(payload: Dictionary):
    match payload.get("type"):
        "player_moved": update_player(payload)
        "shot_fired": play_shot_animation(payload)

Architecture

Godot Game
    ↓
EvoidApp (State Machine)
    ↓
EvoidClient (WebSocket) or EvoidUDP (UDP)
    ↓
EVOID Server
    ↓
Message Bus (in-process, 0ms)
    ↓
Intent Handlers / Auth / Analytics

Components

Component Purpose
EvoidApp State machine + orchestration layer
EvoidClient WebSocket connection
EvoidUDP Low-latency UDP transport (binary protocol)
EvoidBus Pub/sub event bus (zero-coupling)
EvoidConfig Configuration resource (Inspector-friendly)
EvoidTopics Topic constants (mirrors Python server)
EvoidWebLoader WebGL auto-detection + chunk prefetching + embed API
EvoidExportPlugin Export-time optimizations (SW, manifest)

Setup Scenarios

Scenario 1: Desktop Game (Client + Server)

func _ready():
    var config = EvoidConfig.new()
    config.server_url = "wss://your-server.com"
    config.game_id = "my-game"
    EvoidApp.config = config
    EvoidApp.connect_to_server()

Prerequisites: Godot 4.4+, EVOID server (Python 3.12+)

Scenario 2: Web Game (Standalone)

func _ready():
    var config = EvoidConfig.new()
    config.game_id = "my-game"
    EvoidApp.config = config
    EvoidApp.auto_connect()  # auto-detects WebGL, resolves same-origin URL

Prerequisites: Godot 4.4+ with HTML5 export template, EVOID server with GameHost

Scenario 3: Embed in Website (Seamless)

<!-- Parent website -->
<iframe src="/game/tic-tac-toe/" width="400" height="600" frameborder="0"></iframe>
<script>
iframe.addEventListener("message", (e) => {
    if (e.data.type === "evoid:player_joined") {
        showPlayerCount(e.data.player_id);
    }
});
// Send intent to game
iframe.contentWindow.postMessage({type: "evoid:send_intent", name: "pause", metadata: {}}, "*");
</script>
# Game side — receive from parent
func _ready():
    EvoidWebLoader.embed_message.connect(_on_embed_message)

func _on_embed_message(message: Dictionary):
    match message.get("type"):
        "evoid:focus": grab_focus()
        "evoid:resize": resize_canvas(message.get("width"), message.get("height"))

Prerequisites: Server with GameHost(embed_mode=True), parent page supports postMessage

Scenario 4: UDP Transport (Low-Latency)

func _ready():
    var config = EvoidConfig.new()
    config.udp_address = "your-server.com"
    config.udp_port = 9000
    EvoidApp.config = config
    EvoidApp.connect_udp(config.udp_address, config.udp_port, "Player1")

Prerequisites: evoid-transport plugin on server, UDP port open

Scenario 5: Binary Intents (Bandwidth Optimization)

# ~60% smaller than JSON
EvoidClient.send_intent_binary("player_move", {"x": 10, "y": 20})

Scenario 6: Auto-Reconnect

Built-in. If connection drops:

  • State: ONLINE → RECOVERING
  • Exponential backoff: 1s, 2s, 4s, 8s, 16s, 20s (cap)
  • Auto-retry up to max_reconnect_attempts

WebGL / Browser Games

func _ready():
    EvoidApp.auto_connect()  # auto-detects WebGL, connects to same-origin

Features:

  • Instant splash screen (no loading)
  • Service Worker caching (instant repeat visits)
  • Chunked PCK streaming (256KB chunks)
  • Manifest-aware prefetch (uses server manifest for correct chunk count)
  • Parent website communication (postMessage API)

Configuration

var config = EvoidConfig.new()
config.server_url = "wss://your-server.com"
config.game_id = "my-game"
config.auto_connect = true
config.tick_rate = 60

# UDP
config.udp_address = "your-server.com"
config.udp_port = 9000

# Embed mode
config.embed_mode = true

# Export optimizations
config.optimize_web = true
config.binary_intents = false

EvoidApp.config = config
EvoidApp.connect_to_server()

Or via Inspector:

@export var evoid_config: EvoidConfig

Game Types

Shooter

func _on_shot_pressed():
    EvoidApp.send_intent("player_shot", {
        "origin": global_position,
        "direction": aim_direction
    })

Card Game

func play_card(card_id: String):
    EvoidApp.send_intent("card_played", {"card": card_id})

MMO

func _on_player_moved(payload):
    var position = Vector2(payload.x, payload.y)
    update_remote_player(payload.player_id, position)

Cluster Compatibility

EVOID cluster is transparent to the Godot client. The game connects to one node via EvoidApp.connect_to_server(). The server-side cluster plugin handles routing between nodes. The client doesn't know or care how many nodes exist.

Prerequisites (server-side only):

  • evoid-cluster plugin installed
  • WebSocket ports open between nodes
  • evoid-di for service discovery

Dependency Injection

This plugin uses Godot's native autoload singleton pattern — the equivalent of DI in GDScript. All components (EvoidApp, EvoidClient, EvoidUDP, EvoidBus, EvoidWebLoader) are globally accessible singletons.

On the server side, the Python evoid-godot plugin registers with evoid-di:

di.register("godot", create_game_handler, scope="singleton")

Comparison

Feature Godot Dedicated Server EVOID
Complexity High Simple
Setup Manual Automatic
Reconnect Manual Auto
EventBus None Built-in
State Machine None Built-in
Web Support Limited Full
Embed in Website Manual postMessage API
Export Optimizations None Auto SW + manifest
Latency 10-50ms < 1ms (UDP)

Server Side

This is the client plugin (GDScript). For the server, see:

# Server setup
uv add evoid evoid-godot

# Or with evo CLI
evo plug install godot

Requirements

  • Godot 4.4+
  • EVOID server (Python 3.12+)

Links

License

MIT

About

Godot game integration for EVOID — WebSocket, EventBus, WebGL hosting

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages