diff --git a/README.md b/README.md index c772593..cda065b 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ dedicated game servers, utilising both Google Cloud's products and open source g If you’re using this demo, please **★Star** this repository to show your interest! **Note to Googlers**: Please fill out the form at [go/global-scale-game-form](http://go/global-scale-game-form). -Details of the program can be found at [go/global-scale-game](http://go/global-scale-game). +Details of the program can be found at [go/global-scale-game]. Projects and products utilised include: @@ -287,6 +287,69 @@ the file and `unzip` it locally. Run `launcher` to run the Game Launcher, and see [Playing The Game](#playing-the-game) for details on how to play the game once the launcher is up and running. +### Enable Remote Cloud Game Client VM + +Since not everyone has a Linux machine with a graphics card - we've supplied one for you in the Cloud, which can run +our automated Linux build of the game launcher and client! + +To enable the VM for the Game Client, make sure to set `enable_game_client_vm = true` in the `terraform.tfvars`, +and `terraform apply` those changes. + +Once Terraform has run and the VM has successfully rebooted after all the software has installed, SSH into the VM +using gcloud (or the [Cloud Console](https://console.cloud.google.com/compute/instances)) for first time setup with +[Chrome Remote Desktop](https://remotedesktop.google.com/). + +```shell +gcloud compute ssh game-client-vm +``` + +To determine if the setup scripts are complete, running +[`nvidia-smi`](https://developer.nvidia.com/nvidia-system-management-interface) will complete successfully. + +The first time you use the service, you will need to configure the Game Client VM +by [Setting up via SSH](https://remotedesktop.google.com/headless). + +**Note to Googlers**: Check [go/global-scale-game] for special instructions on setting up Chrome Remote Desktop for +the Game Client VM. + +Click through the buttons Begin -> Next -> Authorize (skip installing the deb, we already did that) to get to +the screen where you can then copy the commands for `Debian Linux`. + +Paste these commands into the SSH terminal you have open to the Game Client VM. After the commands have been +successfully run, you can return to [Chrome Remote Desktop](https://remotedesktop.google.com/access) and click on the +Game Client VM that should now be displayed. + +If Chrome Remote Desktop is an issue for you, we have also installed several other (but less tested) remoting solutions +into the VM, including: + +* [TightVNC](https://www.tightvnc.com/) +* [Xpra](https://xpra.org/) +* [Sunshine](https://app.lizardbyte.dev/Sunshine/) +* [xrdp](https://www.xrdp.org/) + +#### Downloading the latest client + +On first connection to the remote machine, you will need to download the latest client. To do so, open a terminal and +run: + +```shell +/opt/game-client/update-client.sh +``` + +Which will download the latest DroidShooter Client to the Desktop of this machine. + +If you ever want to update the client to the latest build, run the same command again. + +#### Running the Launcher + +After remoting into the Game Cloud Game Client VM, open the `Client` folder on the Desktop, and double-click the +`launcher` to run the game launcher. + +**Note:** When using Chrome Remote Desktop, you may want to enable "Relative Mouse Mode" via the sidebar, when playing +the game for better mouse interaction with the game client (hit `Esc` to exit Relative Mouse Mode). + +See [Playing The Game](#playing-the-game) for details on how to play the game once the launcher is up and running. + ### Editing or Building the Game Locally To build the Game Client for your host machine, you will need to @@ -297,7 +360,7 @@ This project currently uses **Unreal Engine 5.2.0**. > Installing Unreal Engine from source can take several hours, and use all your CPU. You have been warned! -Open [`game/Droidshooter.uproject`](./game) in the Unreal Engine Editor. +Open [`game/Droidshooter.uproject`](./game) in the Unreal Engine Editor. To package the project: @@ -317,30 +380,7 @@ gcloud compute addresses list --filter=name=frontend-service --format="value(add JWT token can be obtained by accessing frontend api's ip address with '/login' path, such as "http://[IP_ADDRESS].sslip.io/login" and extracting it from the URL. -### Enable Cloud Linux VM for Game Client - -You have the option to enable a GCP Linux VM for the Game Client. To have Terraform setup the VM, edit `terraform.tfvars` and set: - -`enable_game_client_vm = true` - -Then you will need to run Terraform to apply the changes to your environment: - -```shell -terraform apply -``` - -Once Terraform has run and a few minutes have passed for all of the software packages to install, you can then connect to the VM using gcloud: - -```shell -gcloud compute ssh game-client-vm -``` - -You can also connect to an X display using [Chrome Remote Desktop](https://remotedesktop.google.com/). -The first time you use the service, you will need to configure the Game Client VM by [Setting up via SSH](https://remotedesktop.google.com/headless) - -You can click through the buttons Begin -> Next -> Authorize to get to the screen where you can then copy the commands for `Debian Linux`. Then you can paste these commands into the SSH terminal you have open to the Game Client VM. After the commands have been succesfully run, you can return to [Chrome Remote Desktop](https://remotedesktop.google.com/access) and click on the Game Client VM that should now be displayed. - -### Run the Game Launcher +#### Run the Game Launcher from source To run the game launcher, you will need to have [Go](https://go.dev/dl/) installed to run it, as well as the [prerequisites for the Fyne Go Cross Platform UI library](https://developer.fyne.io/started/). @@ -389,3 +429,5 @@ The project should open as normal now. Apache 2.0 This is not an officially supported Google product + +[go/global-scale-game]: http://go/global-scale-game \ No newline at end of file diff --git a/game/unreal-engine/cloudbuild.yaml b/game/unreal-engine/cloudbuild.yaml index 3e3ef45..865356b 100644 --- a/game/unreal-engine/cloudbuild.yaml +++ b/game/unreal-engine/cloudbuild.yaml @@ -18,9 +18,9 @@ steps: - name: gcr.io/cloud-builders/git id: clone-unreal-engine script: | - df -h - git clone --depth=1 --single-branch --branch "$_UNREAL_VERSION-release" https://$GITHUB_AUTH@github.com/EpicGames/UnrealEngine.git - cd UnrealEngine + df -h && \ + git clone --depth=1 --single-branch --branch "$_UNREAL_VERSION-release" https://$GITHUB_AUTH@github.com/EpicGames/UnrealEngine.git && \ + cd UnrealEngine && \ ls -l secretEnv: - GITHUB_AUTH diff --git a/infrastructure/client.tf b/infrastructure/client.tf index 18d28b9..a2e8ea9 100644 --- a/infrastructure/client.tf +++ b/infrastructure/client.tf @@ -16,3 +16,9 @@ resource "google_storage_bucket" "release-artifacts" { location = "US" name = "${var.project}-release-artifacts" } + +resource "google_storage_bucket_object" "update-client" { + name = "update-client.sh" + bucket = google_storage_bucket.release-artifacts.name + source = "./files/update-client.sh" +} diff --git a/infrastructure/files/game-client-startup.sh b/infrastructure/files/game-client-startup.sh new file mode 100644 index 0000000..135be20 --- /dev/null +++ b/infrastructure/files/game-client-startup.sh @@ -0,0 +1,101 @@ +#!/bin/bash + +# +# Copyright 2024 Google LLC All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Script to install applications for the Game Client VM + +# Credits +# https://cloud.google.com/architecture/chrome-desktop-remote-on-compute-engine +# https://cloud.google.com/compute/docs/gpus/install-grid-drivers#debianubuntu + +set -euxo pipefail + +export DEBIAN_FRONTEND=noninteractive + +# if we've already run this script, exit successfully +if [ -f /opt/game-client/init.lock ]; then + echo "Remote Game Client VM startup script already ran - exiting" + exit 0 +fi + +# Latest version of Xpra +sudo wget -O "/usr/share/keyrings/xpra.asc" https://xpra.org/xpra.asc +cd /etc/apt/sources.list.d +sudo wget https://raw.githubusercontent.com/Xpra-org/xpra/master/packaging/repos/bookworm/xpra.sources +sudo apt-get update --assume-yes +cd - + +# Installs: +# * xfce4 desktop environment +# * remoting libraries +# * graphics support and utilities +# * general handy utilities +sudo apt-get install --assume-yes \ + xfce4 desktop-base dbus-x11 xscreensaver \ + tightvncserver xrdp xpra \ + build-essential "linux-headers-$(uname -r)" mesa-utils \ + less bzip2 zip unzip tasksel wget + +# Chrome Remote Desktop session +sudo bash -c 'echo "exec /etc/X11/Xsession /usr/bin/xfce4-session" > /etc/chrome-remote-desktop-session' + +# Install Nvidia Virtual Workstation Drivers +curl -O https://storage.googleapis.com/nvidia-drivers-us-public/GRID/vGPU16.4/NVIDIA-Linux-x86_64-535.161.07-grid.run +sudo bash NVIDIA-Linux-x86_64-535.161.07-grid.run --silent + +# Disable GSP Firmware +echo "options nvidia NVreg_EnableGpuFirmware=0" | sudo tee /etc/modprobe.d/nvidia.conf + +function download_and_install { # args URL FILENAME + curl -L -o "$2" "$1" + sudo apt-get install --assume-yes --fix-broken "$2" +} + +function is_installed { # args PACKAGE_NAME + dpkg-query --list "$1" | grep -q "^ii" 2>/dev/null + return $? +} + +! is_installed sunshine && \ + download_and_install \ + https://github.com/LizardByte/Sunshine/releases/download/v0.21.0/sunshine-debian-bookworm-amd64.deb \ + /tmp/sunshine-debian-bookworm-amd64.deb + +! is_installed chrome-remote-desktop && \ + download_and_install \ + https://dl.google.com/linux/direct/chrome-remote-desktop_current_amd64.deb \ + /tmp/chrome-remote-desktop_current_amd64.deb + +! is_installed google-chrome-stable && \ + download_and_install \ + https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb \ + /tmp/google-chrome-stable_current_amd64.deb + +# Write lock file, to stop this file rerunning, and Terraform recreating the VM if the script gets deleted. +sudo mkdir /opt/game-client +sudo touch /opt/game-client/init.lock + +# Grab the script that will pull down the latest Client. +project=$(curl http://metadata.google.internal/computeMetadata/v1/project/project-id -H Metadata-Flavor:Google) +storage_bucket="gs://$project-release-artifacts" + +sudo gsutil cp "$storage_bucket/update-client.sh" /opt/game-client/update-client.sh +sudo chmod o+x /opt/game-client/update-client.sh + +# Rebooting to disable GSP Firmware because Nvidia says so. +echo "Remote Game Client VM startup script completed - rebooting" +sudo reboot diff --git a/infrastructure/files/update-client.sh b/infrastructure/files/update-client.sh new file mode 100644 index 0000000..88b8a12 --- /dev/null +++ b/infrastructure/files/update-client.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# +# Copyright 2024 Google LLC All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Script to download and update the Game Client for Google Cloud Storage + +set -euxo pipefail + +project=$(curl http://metadata.google.internal/computeMetadata/v1/project/project-id -H Metadata-Flavor:Google) +storage_bucket="gs://$project-release-artifacts" +latest_client=$(gsutil ls -l "$storage_bucket/*.zip" | sort -k 2 -r | head -n 2 | tail -n 1 | awk '{print $3}') + +mkdir -p ~/Desktop/Client || true + +gsutil cp "$latest_client" ~/Desktop/Client/Client.zip +cd ~/Desktop/Client/ +unzip Client.zip diff --git a/infrastructure/game-client-startup.sh b/infrastructure/game-client-startup.sh deleted file mode 100644 index 48dbc3e..0000000 --- a/infrastructure/game-client-startup.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/bash - -# Script to install applications for the Game Client VM - -export DEBIAN_FRONTEND=noninteractive - -wget -O "/usr/share/keyrings/xpra.asc" https://xpra.org/xpra.asc -cd /etc/apt/sources.list.d -wget https://raw.githubusercontent.com/Xpra-org/xpra/master/packaging/repos/bookworm/xpra.sources -sudo apt update -y -cd - - -curl -OL https://github.com/LizardByte/Sunshine/releases/download/v0.21.0/sunshine-debian-bookworm-amd64.deb -sudo apt install -f ./sunshine-debian-bookworm-amd64.deb -y -sudo apt install xfce4 xfce4-goodies tightvncserver dbus-x11 gcc make linux-headers-$(uname -r) software-properties-common mesa-utils golang libgl1-mesa-dev xorg-dev xpra -y - -wget https://developer.download.nvidia.com/compute/cuda/12.3.1/local_installers/cuda_12.3.1_545.23.08_linux.run -sudo sh cuda_12.3.1_545.23.08_linux.run --silent - -sudo apt update -y - -######### -# -# Startup script to install Chrome remote desktop and a desktop environment. -# -# See environmental variables at then end of the script for configuration -# - -function install_desktop_env { - PACKAGES="desktop-base xscreensaver dbus-x11" - - if [[ "$INSTALL_XFCE" != "yes" && "$INSTALL_CINNAMON" != "yes" ]] ; then - # neither XFCE nor cinnamon specified; install both - INSTALL_XFCE=yes - INSTALL_CINNAMON=yes - fi - - if [[ "$INSTALL_XFCE" = "yes" ]] ; then - PACKAGES="$PACKAGES xfce4" - echo "exec xfce4-session" > /etc/chrome-remote-desktop-session - [[ "$INSTALL_FULL_DESKTOP" = "yes" ]] && \ - PACKAGES="$PACKAGES task-xfce-desktop" - fi - - if [[ "$INSTALL_CINNAMON" = "yes" ]] ; then - PACKAGES="$PACKAGES cinnamon-core" - echo "exec cinnamon-session-cinnamon2d" > /etc/chrome-remote-desktop-session - [[ "$INSTALL_FULL_DESKTOP" = "yes" ]] && \ - PACKAGES="$PACKAGES task-cinnamon-desktop" - fi - - DEBIAN_FRONTEND=noninteractive \ - apt-get install --assume-yes $PACKAGES $EXTRA_PACKAGES - - systemctl disable lightdm.service -} - -function download_and_install { # args URL FILENAME - curl -L -o "$2" "$1" - apt-get install --assume-yes --fix-broken "$2" -} - -function is_installed { # args PACKAGE_NAME - dpkg-query --list "$1" | grep -q "^ii" 2>/dev/null - return $? -} - -# Configure the following environmental variables as required: -INSTALL_XFCE=yes -INSTALL_CINNAMON=yes -INSTALL_CHROME=yes -INSTALL_FULL_DESKTOP=yes - -# Any additional packages that should be installed on startup can be added here -EXTRA_PACKAGES="less bzip2 zip unzip tasksel wget" - -apt-get update - -! is_installed chrome-remote-desktop && \ - download_and_install \ - https://dl.google.com/linux/direct/chrome-remote-desktop_current_amd64.deb \ - /tmp/chrome-remote-desktop_current_amd64.deb - -install_desktop_env - -[[ "$INSTALL_CHROME" = "yes" ]] && \ - ! is_installed google-chrome-stable && \ - download_and_install \ - https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb \ - /tmp/google-chrome-stable_current_amd64.deb - -echo "Chrome remote desktop installation completed" - -# Delete instance startup script do it does not re-run after a boot -gcloud compute instances remove-metadata --keys startup-script --zone us-central1-a game-client-vm diff --git a/infrastructure/game-client.tf b/infrastructure/game-client.tf index 425ea56..bfb3a30 100644 --- a/infrastructure/game-client.tf +++ b/infrastructure/game-client.tf @@ -38,6 +38,15 @@ resource "google_project_iam_member" "game_client_vm_compute_is_sa" { member = "serviceAccount:${google_service_account.game_client_vm[0].email}" } +# GCS storage, so we can pull down the Client build. +resource "google_project_iam_member" "game_client_vm_compute_storage_viewer" { + count = var.enable_game_client_vm ? 1 : 0 + + project = var.project + role = "roles/storage.objectViewer" + member = "serviceAccount:${google_service_account.game_client_vm[0].email}" +} + resource "google_compute_address" "game_client_vm_static_ip" { count = var.enable_game_client_vm ? 1 : 0 @@ -62,6 +71,10 @@ resource "google_compute_instance" "game_client_vm" { machine_type = var.game_client_vm_machine_type zone = "${var.game_client_vm_region}-a" + guest_accelerator { + type = "nvidia-l4-vws" + count = 1 + } tags = ["game-client-vm-ssh", "game-client-vm-vnc"] scheduling { @@ -94,7 +107,7 @@ resource "google_compute_instance" "game_client_vm" { serial-port-logging-enable = "TRUE" } - metadata_startup_script = file("${path.root}/game-client-startup.sh") + metadata_startup_script = file("${path.root}/files/game-client-startup.sh") service_account { # Google recommends custom service accounts that have cloud-platform scope and permissions granted via IAM Roles. diff --git a/infrastructure/terraform.tfvars.sample b/infrastructure/terraform.tfvars.sample index f6fa21e..c0588da 100644 --- a/infrastructure/terraform.tfvars.sample +++ b/infrastructure/terraform.tfvars.sample @@ -18,9 +18,9 @@ project = "PROJECT_ID" resource_env_label = "demo-global-game" -# Game Client Configuration +# Remote Game Client VM - enable if you need a Linux machine with a GPU to run the game client! enable_game_client_vm = false -game_client_vm_machine_type = "g2-standard-4" +game_client_vm_machine_type = "g2-standard-8" game_client_vm_region = "us-central1" # MUST MATCH one of the below VPC regions game_client_vm_storage = 300 game_client_vm_os_family = "debian-12"