-
Notifications
You must be signed in to change notification settings - Fork 0
/
cloud-gaming.sh
executable file
·419 lines (338 loc) · 12.6 KB
/
cloud-gaming.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
#!/bin/bash
source ~/.bashrc
source aws-tools.sh
source logger.sh
source utils.sh
source stream-tools.sh
cloudGamingLogFile=/tmp/cloud-gaming.log
rm "$cloudGamingLogFile" > /dev/null 2>&1 &
export KERNEL=$(uname -s)
if [[ -z $AWS_CLOUD_GAMING_SSH_KEY ]]; then
printError "The AWS_CLOUD_GAMING_SSH_KEY must be defined in order to use this script." true
exit 1
fi
if [[ $KERNEL == "Darwin" ]]; then
if ! (hash brew 2>/dev/null); then
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
fi
if ! (hash whiptail 2>/dev/null); then
printWarn "whiptail is not installed. Installing now..." true
if [[ $KERNEL == "Linux" ]]; then
sudo apt-get -y install whiptail
elif [[ $KERNEL == "Darwin" ]]; then
yes | brew install whiptail
fi
fi
createPrerequisitesMap() {
declare mapName="prerequisites"
declare linuxName="Linux"
declare darwinName="Darwin"
put $mapName "flatpak" $linuxName
put $mapName "xvfb-run" $linuxName
put $mapName "xdotool" $linuxName
put $mapName "dialog" $linuxName
put $mapName "pulsemixer" $linuxName
put $mapName "nc" $linuxName
put $mapName "mas" $darwinName
put $mapName "python" $darwinName
put $mapName "pulseaudio" $darwinName
put $mapName "xdotool" $darwinName
put $mapName "dialog" $darwinName
put $mapName "pulsemixer" $darwinName
put $mapName "nc" $darwinName
}
verifyPrerequisites() {
printInfo "Verifying prerequisites"
declare -a prerequisites
createPrerequisitesMap
prerequisites=($(ls $map/prerequisites/ | xargs -i basename {}))
printInfo "Detected kernel: $KERNEL"
for application in "${prerequisites[@]}"; do
declare value
value=$(get prerequisites "$application")
if [[ ${value[*]} =~ $KERNEL ]] && ! (hash $application 2>/dev/null); then
printWarn "$application is not installed. Installing now..." true
if [[ $KERNEL == "Linux" ]]; then
checkSudoPass "Installing $application requires sudo permissions."
if [[ $application == "xvfb-run" ]]; then
echo "$SUDO_PASSWORD" | sudo -k -S apt-get -y install xvfb
elif [[ $application == "nc" ]]; then
echo "$SUDO_PASSWORD" | sudo -k -S apt-get -y install netcat
else
echo "$SUDO_PASSWORD" | sudo -k -S apt-get -y install $application
fi
elif [[ $KERNEL == "Darwin" ]]; then
if [[ $application == "pulsemixer" ]]; then
pip install pulsemixer
elif [[ $application == "nc" ]]; then
yes | brew install netcat
else
yes | brew install $application
fi
fi
fi
done
if [[ $KERNEL == "Linux" ]]; then
if ! (flatpak info com.valvesoftware.SteamLink > /dev/null 2>&1); then
printWarn "SteamLink is not installed. Installing now..." true
checkSudoPass "Installing SteamLink requires sudo permissions."
printWarn "Installing the FlatHub repo for Flatpak if it doesn't already exist..."
echo "$SUDO_PASSWORD" | sudo -k -S flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
printWarn "Installing SteamLink from FlatHub..."
echo "$SUDO_PASSWORD" | sudo -k -S flatpak install -y flathub com.valvesoftware.SteamLink
fi
# elif [[ $KERNEL == "Darwin" ]]; then
# TODO check if SteamLink is installed, and if not, install it via mas-cli
fi
if ! (hash aws 2> /dev/null); then
printError "The AWS CLI must be installed to use this script. Please install the applicable AWS CLI from AWS and try again" true
exit 1
fi
if ! (hash npm 2> /dev/null); then
printError "NodeJS and NPM must be installed to use this script. Please install NodeJS and NPM and try again." true
exit 1
fi
if [[ ! -f ~/.ssh/"$AWS_CLOUD_GAMING_SSH_KEY".pem ]]; then
printError "In order to use this script, you need to have the ~/.ssh/$AWS_CLOUD_GAMING_SSH_KEY key. Reach out to one of the team members to acquire it via Snappass and then try again." true
exit 1
fi
if ! (hash cdk 2> /dev/null); then
printWarn "CDK is not installed. Installing now..." true
echo "$SUDO_PASSWORD" | sudo -k -S npm -g install aws-cdk@latest
fi
checkAwsProfile
}
verifyPrerequisites
checkInstanceStatus() {
declare state
state=$(getInstanceState)
msgBox "Current instance state: $state"
printInfo "Checking instance state. Received state: $state"
}
guideHostThroughSharedStreamSetup() {
printInfo "Guiding user through host shared stream setup"
msgBox "$(cat <<-EOF
This will guide you through getting the other players connected to your personal EC2 instance.
Hit 'OK' to start a desktop connection to your instance
EOF
)"
msgBox "$(cat <<-EOF
We now need to add your user's PINs to your steam client so they can connect to your instance.
Hit 'OK' to start a desktop connection to your steam instance.
EOF
)"
connectToInstanceViaDcvViewer
printInfo "Directing user to enter PIN acquired from user's local SteamLinks"
msgBox "$(cat <<-EOF
On your EC2 Instance, in Steam, navigate to Steam -> Settings -> Remote Play.
Click the 'Pair Steam Link' button and when prompted.
Your users should have this connection PIN ready to give to you, so for each player, provide the PIN you received from them.
Click 'OK' to exit the Steam settings menu when you've entered everyone's PINs and everyone confirms that they see your EC2 instance ready.
Tell your users they can hit 'OK'.
You're now ready to play!
Hit 'OK' to finish the shared instance hosting setup and to start your stream!
EOF
)"
stopStream
startStream
}
guideClientThroughSharedStreamSetup() {
printInfo "Guiding user through client shared stream setup"
printInfo "Starting shared stream for client"
printInfo "Starting SteamLink"
flatpak run com.valvesoftware.SteamLink > /dev/null 2>&1 &
printInfo "Prompting user to fetch the connection PIN from local SteamLink"
msgBox "$(cat <<-EOF
We need to get a unique PIN from SteamLink that will identify this machine for connection to the host's EC2 Instance.
In SteamLink, do the following:
1. Click on the gear icon in the top right hand corner.
2. Then click on 'Computer'
3. Click 'Other Computer'
This will give you a PIN to enter into Steam on the host's EC2 instance.
Give the host this PIN when prompted.
Hit 'OK' when the host says to do so.
EOF
)"
msgBox "$(cat <<-EOF
You should see that EC2 instance highlighted as a streaming option with a big 'Start Playing' button. You're now ready to play!
Finished setting up the shared stream. Have fun!
EOF
)"
}
startSharedStream() {
if (whiptail --fb --title "Shared Stream Setup" --yesno "Are you hosting this shared stream?" --defaultno "$BOX_HEIGHT" "$BOX_WIDTH"); then
printInfo "User is the HOST of the shared stream"
guideHostThroughSharedStreamSetup
else
printInfo "User is a CLIENT of the shared stream"
guideClientThroughSharedStreamSetup
fi
}
streamSettings() {
declare choice
choice=$(whiptail --fb --title "Stream Settings" --menu "Select an option" "$BOX_HEIGHT" "$BOX_WIDTH" 4 \
"P" "Start stream to (p)ersonal instance" \
"S" "Start (S)hared stream" \
"K" "(K)ill the stream" \
"B" "(B)ack" 3>&2 2>&1 1>&3
)
case $choice in
"P")
startStream
streamSettings
;;
"S")
startSharedStream
streamSettings
;;
"K")
stopStream
streamSettings
;;
"B")
mainMenu
;;
esac
}
guideThroughSteamLink() {
printInfo "Guiding user through SteamLink setup"
msgBox "$(cat <<-EOF
Now we need to set up SteamLink.
First, we're going to connect to your instance via the fancy new NICE DCV viewer.
Hit 'OK' when you're ready to log into your instance.
EOF
)"
printInfo "Starting DCV Viewer connection to instance using cloud_gaming_dcv_profile.dcv profile"
waitForInstanceToBecomeAvailable
dcvviewer cloud_gaming_dcv_profile.dcv --certificate-validation-policy=accept-untrusted > /dev/null 2>&1 &
printInfo "Directing user to log into Steam on the instance"
msgBox "$(cat <<-EOF
Next, we need to log into Steam. So start Steam and log into your account.
For ease of use, check the 'Remember my password' box so you don't have to log in manually every time your instance starts.
Hit 'OK' once you're logged in.
EOF
)"
msgBox "$(cat <<-EOF
Next, we need to connect your local SteamLink to this box.
Hit 'OK' to start SteamLink
EOF
)"
printInfo "Starting SteamLink"
flatpak run com.valvesoftware.SteamLink > /dev/null 2>&1 &
printInfo "Prompting user to fetch the connection PIN from local SteamLink"
msgBox "$(cat <<-EOF
Now, we need to get a unique PIN from SteamLink that will identify this machine for connection to your EC2 Instance.
In SteamLink, do the following:
1. Click on the gear icon in the top right hand corner.
2. Then click on 'Computer'
3. Click 'Other Computer'
This will give you a PIN to enter into Steam on your EC2 instance. Hit 'OK' when you're ready to continue.
EOF
)"
printInfo "Directing user to enter PIN acquired from local SteamLink"
msgBox "$(cat <<-EOF
On your EC2 Instance, in Steam, navigate to Steam -> Settings -> Remote Play.
Click the 'Pair Steam Link' button and when prompted, provide the PIN you received from SteamLink in the last step.
Click 'OK' to exit the Steam settings menu.
Once you're done, your SteamLink should have the EC2 instance highlighted. Click on it and it should return you to the main menu.
You should see that EC2 instance highlighted as a streaming option with a big 'Start Playing' button. You're now ready to play!
Hit 'OK' to finish the one-time setup and return to the main menu.
EOF
)"
printInfo "Killing dcvviewer, xvfb (if running, which it shouldn't be), and steamlink"
pkill -9 -f dcvviewer > /dev/null 2>&1 &
pkill -9 -f xvfb > /dev/null 2>&1 &
pkill -9 -f steamlink > /dev/null 2>&1 &
}
deployInstance() {
if (whiptail --fb --title "Deploy CDK" --yesno "This will now deploy the CDK for your cloud gaming instance. Do you wish to continue?" --defaultno "$BOX_HEIGHT" "$BOX_WIDTH"); then
deployCdk
fi
if (whiptail --fb --title "Setup" --yesno "We'll now go through the first time setup. Do you wish to continue?" "$BOX_HEIGHT" "$BOX_WIDTH"); then
msgBox "For first time setups, ensure your terminal is full screen so you don't miss any instructions. If it's not, exit this application, enter full screen, then start again"
if (whiptail --fb --title "First Time Setup" --yesno "This will now perform first time setup for your cloud gaming instance. Is your terminal full screen?" "$BOX_HEIGHT" "$BOX_WIDTH"); then
printInfo "Running first time setup"
msgBox "For the first run, some manual, one-time setup steps are required. When ready, hit 'OK' to continue and start the connection to your instance's desktop."
prepareStream
guideThroughSteamLink
msgBox "Finished setting up your instance. Have fun!"
else
printInfo "User selected 'No' to running the first time setup. Nothing was done"
msgBox "Nothing was done."
fi
fi
}
managePersonalInstance() {
declare choice
choice=$(whiptail --fb --title "Manage personal instance" --menu "Select an option" "$BOX_HEIGHT" "$BOX_WIDTH" 7 \
"T" "Check instance s(t)atus" \
"C" "(C)onnect to personal instance desktop via DCV Viewer" \
"I" "D(i)sconnect from personal instance desktop" \
"D" "(D)eploy a personal gaming instance" \
"S" "(S)tart instance" \
"K" "Stop instance" \
"B" "(B)ack" 3>&2 2>&1 1>&3
)
case $choice in
"T")
checkInstanceStatus
managePersonalInstance
;;
"C")
connectToInstanceViaDcvViewer
managePersonalInstance
;;
"I")
printInfo "Killing connection to instance desktop via DCV Viewer"
pkill -9 -f dcvviewer > /dev/null 2>&1 &
managePersonalInstance
;;
"D")
deployInstance
managePersonalInstance
;;
"S")
startInstance
managePersonalInstance
;;
"K")
stopInstance
managePersonalInstance
;;
"B")
mainMenu
;;
esac
}
mainMenu() {
declare choice
choice=$(whiptail --fb --title "Team Building Cloud Gaming" --menu "Select an option" "$BOX_HEIGHT" "$BOX_WIDTH" 3 \
"M" "(M)anage your personal instance" \
"S" "(S)tream settings" \
"X" "E(x)it" 3>&2 2>&1 1>&3
)
case $choice in
"M")
managePersonalInstance
;;
"S")
streamSettings
;;
"X")
clear
printInfo "Killing dcvviewer, xvfb, and steamlink"
pkill -9 -f dcvviewer > /dev/null 2>&1 &
pkill -9 -f xvfb > /dev/null 2>&1 &
pkill -9 -f steamlink > /dev/null 2>&1 &
if (whiptail --fb --title "Stop instance" --yesno "Do you wish to stop your instance before exiting?" "$BOX_HEIGHT" "$BOX_WIDTH"); then
stopInstance
fi
printInfo "Exiting"
exit 0
;;
esac
}
while :; do
mainMenu
done