How TetraForce runs Godot on AWS

Gameplay image captured from community live stream by Fornclake
AWS Diagram displaying which services are used within TetraForce’s cloud infrastructure

Dockerization

Godot being lightweight, is easy to Dockerize. For the TetraForce Docker image, it just installs dependencies, the Godot server runtime, and the TetraForce’s pckfile. It can easily be extended to add additional pck files in the future for mods or expansions.

FROM centos:centos8

RUN yum install -y wget unzip libXcursor openssl openssl-libs libXinerama libXrandr-devel libXi alsa-lib pulseaudio-libs mesa-libGL

ENV GODOT_VERSION "3.2.2"

# Install Godot Server
RUN wget -q https://downloads.tuxfamily.org/godotengine/${GODOT_VERSION}/Godot_v${GODOT_VERSION}-stable_linux_headless.64.zip \
&& unzip Godot_v${GODOT_VERSION}-stable_linux_headless.64.zip \
&& mv Godot_v${GODOT_VERSION}-stable_linux_headless.64 /usr/local/bin/godot \
&& chmod +x /usr/local/bin/godot

# Create Runtime User
RUN useradd -d /tetra tetra


# Add pck file
ADD build/TetraForce.pck /tetra/TetraForce.pck

CMD /usr/local/bin/godot --main-pack /tetra/TetraForce.pck --empty-server-timeout=300

Server Management

Each game room runs as a task in ECS. Amazon assigns those tasks a public IP. The client receives those IPs by interacting with TetraForce’s API.

The REST API

The client can get room information and create new rooms by making HTTPS requests to the REST API. The REST API uses API Gateway to route requests to a Lambda functions.

CloudWatch Events

Server cleanup is managed by an additional Lambda function that is triggered by a CloudWatch Event Rule:

{
"source": ["aws.ecs"],
"detail-type": [ "ECS Task State Change" ]
}

Client Integration

Using Godot’s HTTPRequest Node, the client can hit the REST API hosted on AWS to request server information or create a new lobby.

export(String) var api_endpoint = "api.tetraforce.io"

var _http_client : HTTPRequest
# Asynchronous coroutine.
# Requests API for data from a specific server
# Returns: {"message": [MESSAGE], "data" : [DATA] }
func get_server(lobby : String) -> Dictionary:
_http_client.request("https://" + api_endpoint + "/get_servers?server=" + str(lobby), [], true, HTTPClient.METHOD_GET)
var result = yield(_http_client, "request_completed")
if len(result) > 3 and result[1] == 200:
var json : JSONParseResult = JSON.parse(result[3].get_string_from_utf8())
if json.error:
return _build_error_message(json.error_string)
return json.result

return _build_error_message("Request failed!")

What’s next?

The team is currently moving forward towards building a full demo of TetraForce within the next few months. The demo will include a handful of zones, a dungeon, and an eventual boss battle.

Related Links

TetraForce Discord: https://discord.gg/cxTBVCZ

AWS Community Builder & Cloud Engineer