From c7cb295628f79fe5585d3225b7dbf498d2000bee Mon Sep 17 00:00:00 2001 From: Wanjohi <71614375+wanjohiryan@users.noreply.github.com> Date: Mon, 22 Apr 2024 12:53:46 +0300 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(server):=20Add=20keyboard=20an?= =?UTF-8?q?d=20mouse=20input=20(#27)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description **What(what issue does this code solve/what feature does it add):** We need to support feedback for mouse and keyboard. **How(how does it solve it):** ## Required Checklist: - [ ] I have added any necessary documentation and comments in my code (where appropriate) - [ ] I have added tests to make sure my code runs in all contexts ## Further comments --- .scripts/entrypoint.sh | 98 +++++++++++++++++++++++++++++---------- .scripts/proton | 2 +- .scripts/supervisord.conf | 4 +- .vscode/settings.json | 3 ++ server.Dockerfile | 42 +++++++++++++---- 5 files changed, 113 insertions(+), 36 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.scripts/entrypoint.sh b/.scripts/entrypoint.sh index 6e4d41a0..b1daf265 100644 --- a/.scripts/entrypoint.sh +++ b/.scripts/entrypoint.sh @@ -2,16 +2,56 @@ trap "echo TRAPed signal" HUP INT QUIT TERM # Create and modify permissions of XDG_RUNTIME_DIR -sudo -u ubuntu mkdir -pm700 /tmp/runtime-ubuntu -sudo chown ubuntu:ubuntu /tmp/runtime-ubuntu -sudo -u ubuntu chmod 700 /tmp/runtime-ubuntu +sudo -u netris mkdir -pm700 /tmp/runtime-1000 +sudo chown netris:netris /tmp/runtime-1000 +sudo -u netris chmod 700 /tmp/runtime-1000 # Make user directory owned by the user in case it is not -sudo chown ubuntu:ubuntu /home/ubuntu || sudo chown ubuntu:ubuntu /home/ubuntu/* || { echo "Failed to change user directory permissions. There may be permission issues."; } +sudo chown netris:netris /home/netris || sudo chown netris:netris /home/netris/* || { echo "$(date +"[%Y-%m-%d %H:%M:%S]") Failed to change user directory permissions. There may be permission issues."; } + +#Input devices ownable by our default user +export REQUIRED_DEVICES=${REQUIRED_DEVICES:-/dev/uinput /dev/input/event*} + +declare -A group_map + +for dev in $REQUIRED_DEVICES; do + if [ -e "$dev" ]; then + dev_group=$(stat -c "%G" "$dev") + dev_gid=$(stat -c "%g" "$dev") + + if [ "$dev_group" = "UNKNOWN" ]; then + new_name="netris-gid-$dev_gid" + # We only have a GID for this group; create a named group for it + # this isn't 100% necessary but it prevents some useless noise in the console + sudo groupadd -g "$dev_gid" "$new_name" + group_map[$new_name]=1 + else + # the group already exists; just add it to the list + group_map[$dev_group]=1 + fi + + # is this device read/writable by the group? if not, make it so + if [ "$(stat -c "%a" "$dev" | cut -c2)" -lt 6 ]; then + sudo chmod g+rw "$dev" + fi + else + echo "$(date +"[%Y-%m-%d %H:%M:%S]") Path '$dev' is not present." + fi +done + +join_by() { local IFS="$1"; shift; echo "$*"; } + +groups=$(join_by "," "${!group_map[@]}") +if [ "$groups" != "" ]; then + echo "$(date +"[%Y-%m-%d %H:%M:%S]") Adding user '${USER}' to groups: $groups" + sudo usermod -a -G "$groups" "${USER}" +else + echo "$(date +"[%Y-%m-%d %H:%M:%S]") Not modifying user groups ($groups)" +fi # Remove directories to make sure the desktop environment starts sudo rm -rf /tmp/.X* ~/.cache # Change time zone from environment variable -sudo ln -snf "/usr/share/zoneinfo/$TZ" /etc/localtime && echo "$TZ" | sudo tee /etc/timezone > /dev/null +sudo ln -snf "/usr/share/zoneinfo/$TZ" /etc/localtime && echo "$TZ" | sudo tee /etc/timezone >/dev/null # Add gamescope directories to path export PATH="${PATH:+${PATH}:}/usr/local/games:/usr/games" @@ -21,7 +61,7 @@ sudo ln -snf /dev/ptmx /dev/tty7 sudo /etc/init.d/dbus start # Install NVIDIA userspace driver components including X graphic libraries -if ! command -v nvidia-xconfig &> /dev/null; then +if ! command -v nvidia-xconfig &>/dev/null; then # Driver version is provided by the kernel through the container toolkit export DRIVER_ARCH="$(dpkg --print-architecture | sed -e 's/arm64/aarch64/' -e 's/armhf/32bit-ARM/' -e 's/i.*86/x86/' -e 's/amd64/x86_64/' -e 's/unknown/x86_64/')" export DRIVER_VERSION="$(head -n1 /dev/null; then # If version is different, new installer will overwrite the existing components if [ ! -f "/tmp/NVIDIA-Linux-${DRIVER_ARCH}-${DRIVER_VERSION}.run" ]; then # Check multiple sources in order to probe both consumer and datacenter driver versions - curl -fsSL -O "https://international.download.nvidia.com/XFree86/Linux-${DRIVER_ARCH}/${DRIVER_VERSION}/NVIDIA-Linux-${DRIVER_ARCH}-${DRIVER_VERSION}.run" || curl -fsSL -O "https://international.download.nvidia.com/tesla/${DRIVER_VERSION}/NVIDIA-Linux-${DRIVER_ARCH}-${DRIVER_VERSION}.run" || { echo "Failed NVIDIA GPU driver download. Exiting."; exit 1; } + curl -fsSL -O "https://international.download.nvidia.com/XFree86/Linux-${DRIVER_ARCH}/${DRIVER_VERSION}/NVIDIA-Linux-${DRIVER_ARCH}-${DRIVER_VERSION}.run" || curl -fsSL -O "https://international.download.nvidia.com/tesla/${DRIVER_VERSION}/NVIDIA-Linux-${DRIVER_ARCH}-${DRIVER_VERSION}.run" || { + echo "$(date +"[%Y-%m-%d %H:%M:%S]") Failed NVIDIA GPU driver download. Exiting." + exit 1 + } fi # Extract installer before installing sudo sh "NVIDIA-Linux-${DRIVER_ARCH}-${DRIVER_VERSION}.run" -x cd "NVIDIA-Linux-${DRIVER_ARCH}-${DRIVER_VERSION}" # Run installation without the kernel modules and host components sudo ./nvidia-installer --silent \ - --no-kernel-module \ - --install-compat32-libs \ - --no-nouveau-check \ - --no-nvidia-modprobe \ - --no-rpms \ - --no-backup \ - --no-check-for-alternate-installs + --no-kernel-module \ + --install-compat32-libs \ + --no-nouveau-check \ + --no-nvidia-modprobe \ + --no-rpms \ + --no-backup \ + --no-check-for-alternate-installs sudo rm -rf /tmp/NVIDIA* && cd ~ fi # Allow starting Xorg from a pseudoterminal instead of strictly on a tty console if [ ! -f /etc/X11/Xwrapper.config ]; then - echo -e "allowed_users=anybody\nneeds_root_rights=yes" | sudo tee /etc/X11/Xwrapper.config > /dev/null + echo -e "allowed_users=anybody\nneeds_root_rights=yes" | sudo tee /etc/X11/Xwrapper.config >/dev/null fi if grep -Fxq "allowed_users=console" /etc/X11/Xwrapper.config; then sudo sed -i "s/allowed_users=console/allowed_users=anybody/;$ a needs_root_rights=yes" /etc/X11/Xwrapper.config @@ -71,7 +114,7 @@ else fi if [ -z "$GPU_SELECT" ]; then - echo "No NVIDIA GPUs detected or nvidia-container-toolkit not configured. Exiting." + echo "$(date +"[%Y-%m-%d %H:%M:%S]") No NVIDIA GPUs detected or nvidia-container-toolkit not configured. Exiting." exit 1 fi @@ -97,7 +140,7 @@ sudo sed -i '/Driver\s\+"nvidia"/a\ Option "ModeValidation" "NoMaxPCl # Add custom generated modeline to the configuration sudo sed -i '/Section\s\+"Monitor"/a\ '"$MODELINE" /etc/X11/xorg.conf # Prevent interference between GPUs, add this to the host or other containers running Xorg as well -echo -e "Section \"ServerFlags\"\n Option \"AutoAddGPU\" \"false\"\nEndSection" | sudo tee -a /etc/X11/xorg.conf > /dev/null +echo -e "Section \"ServerFlags\"\n Option \"AutoAddGPU\" \"false\"\nEndSection" | sudo tee -a /etc/X11/xorg.conf >/dev/null # Default display is :0 across the container export DISPLAY=":0" @@ -105,17 +148,22 @@ export DISPLAY=":0" /usr/bin/Xorg vt7 -noreset -novtswitch -sharevts -dpi "${DPI}" +extension "COMPOSITE" +extension "DAMAGE" +extension "GLX" +extension "RANDR" +extension "RENDER" +extension "MIT-SHM" +extension "XFIXES" +extension "XTEST" "${DISPLAY}" & # Wait for X11 to start -echo "Waiting for X socket" +echo "$(date +"[%Y-%m-%d %H:%M:%S]") Waiting for X socket" until [ -S "/tmp/.X11-unix/X${DISPLAY/:/}" ]; do sleep 1; done -echo "X socket is ready" +echo "$(date +"[%Y-%m-%d %H:%M:%S]") X socket is ready" if [[ -z "${NAME}" ]]; then - echo "No stream name was found, did you forget to set the env variable NAME?" && exit 1 -else - /usr/bin/gpu-screen-recorder -w screen -c flv -f 60 -a "$(pactl get-default-sink).monitor" | ffmpeg -i pipe:0 -c copy -f mp4 -movflags empty_moov+frag_every_frame+separate_moof+omit_tfhd_offset - | /usr/bin/warp --name "${NAME}" https://fst.so:4443 & + echo "$(date +"[%Y-%m-%d %H:%M:%S]") No stream name was found, did you forget to set the env variable NAME?" && exit 1 +else + /usr/bin/gpu-screen-recorder -w screen -c flv -f 60 -a "$(pactl get-default-sink).monitor" | ffmpeg -hide_banner -v quiet -i pipe:0 -c copy -f mp4 -movflags empty_moov+frag_every_frame+separate_moof+omit_tfhd_offset - | /usr/bin/warp --name "${NAME}" https://fst.so:4443 & fi -# /usr/bin/gpu-screen-recorder -w screen -c flv -f 60 -a "$(pactl get-default-sink).monitor" | ffmpeg -i pipe:0 -c copy -f mp4 -movflags empty_moov+frag_every_frame+separate_moof+omit_tfhd_offset - | /usr/bin/warp --name "bbb" https://fst.so -/usr/games/g amescope -h 720 -H 1080 -F fsr -f -- mangohud glxgears > /dev/null & -echo "Session Running. Press [Return] to exit." +openbox-session & + +#Now we can safely run our input server without permission errors +/inputtino/input-server & + +/usr/games/gamescope -- mangohud glxgears > /dev/null & + +echo "$(date +"[%Y-%m-%d %H:%M:%S]") Session Running. Press [Return] to exit." read diff --git a/.scripts/proton b/.scripts/proton index f21f9424..fc5d7cf2 100644 --- a/.scripts/proton +++ b/.scripts/proton @@ -68,7 +68,7 @@ xpge() { fi fi if [[ -n "$chse" ]]; then - wget "$(curl -s https://api.github.com/repos/GloriousEggroll/proton-ge-custom/releases/latest | grep browser_download_url | cut -d\" -f4 | grep .tar.gz)" -P "$temp"/ + wget --progress=dot:giga "$(curl -s https://api.github.com/repos/GloriousEggroll/proton-ge-custom/releases/latest | grep browser_download_url | cut -d\" -f4 | grep .tar.gz)" -P "$temp"/ rm -rf "$pnpge/protonge" tar -xf "$temp/$gedl".tar.gz -C "$pnpge/" diff --git a/.scripts/supervisord.conf b/.scripts/supervisord.conf index a7571015..35eb8828 100644 --- a/.scripts/supervisord.conf +++ b/.scripts/supervisord.conf @@ -1,5 +1,5 @@ [supervisord] -user=ubuntu +user=netris nodaemon=true loglevel=info logfile=/tmp/supervisord.log @@ -16,7 +16,7 @@ redirect_stderr=true priority=1 [program:pulseaudio] -user=ubuntu +user=netris command=bash -c "until [ -S \"/tmp/.X11-unix/X${DISPLAY/:/}\" ]; do sleep 1; done; sudo /usr/bin/pulseaudio -k >/dev/null 2>&1 || sudo /usr/bin/pulseaudio --system --verbose --log-target=stderr --realtime=true --disallow-exit -L 'module-native-protocol-tcp auth-ip-acl=127.0.0.0/8 port=4713 auth-anonymous=1'" environment=DISPLAY=":0" logfile=/tmp/pulseaudio.log diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..37441bee --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "files.eol": "\n" +} \ No newline at end of file diff --git a/server.Dockerfile b/server.Dockerfile index 0835ea7f..c2f8e251 100644 --- a/server.Dockerfile +++ b/server.Dockerfile @@ -1,7 +1,5 @@ #This contains all the necessary libs for the server to work. #NOTE: KEEP THIS IMAGE AS LEAN AS POSSIBLE. -FROM ghcr.io/wanjohiryan/netris/warp:nightly as warp - FROM ghcr.io/wanjohiryan/netris/base:nightly ENV TZ=UTC \ @@ -12,13 +10,15 @@ ENV TZ=UTC \ CDEPTH=24 \ VIDEO_PORT=DFP -#Install Mangohud and gamescope +#Install Mangohud, openbox and gamescope RUN apt-get update -y \ && add-apt-repository -y multiverse \ && apt-get install -y --no-install-recommends \ libxnvctrl0 \ + libevdev2 \ mangohud \ gamescope \ + openbox \ && setcap cap_sys_nice+ep /usr/games/gamescope \ && rm -rf /var/lib/apt/lists/* @@ -33,18 +33,40 @@ COPY .scripts/proton /usr/bin/netris/ RUN chmod +x /usr/bin/netris/proton \ && /usr/bin/netris/proton -i -ARG USERNAME=ubuntu +ARG USERNAME=netris \ + PUID=1000 \ + PGID=1000 \ + UMASK=000 \ + HOME="/home/netris" + +ENV XDG_RUNTIME_DIR=/tmp/runtime-1000 + # Create user and assign adequate groups RUN apt-get update && apt-get install --no-install-recommends -y \ sudo \ tzdata \ - && rm -rf /var/lib/apt/lists/* \ - && usermod -a -G adm,audio,cdrom,dialout,dip,fax,floppy,input,lp,lpadmin,plugdev,pulse-access,render,scanner,ssl-cert,sudo,tape,tty,video,voice $USERNAME \ + && rm -rf /var/lib/apt/lists/* \ + # Delete default user + && if id -u "${PUID}" &>/dev/null; then \ + oldname=$(id -nu "${PUID}"); \ + if [ -z "${oldname}" ]; then \ + echo "User with UID ${PUID} exists but username could not be determined."; \ + exit 1; \ + else \ + userdel -r "${oldname}"; \ + fi \ + fi \ + # Now create ours + && groupadd -f -g "${PGID}" ${USERNAME} \ + && useradd -m -d ${HOME} -u "${PUID}" -g "${PGID}" -s /bin/bash ${USERNAME} \ + && umask "${UMASK}" \ + && chown "${PUID}:${PGID}" "${HOME}" \ + && usermod -a -G adm,audio,cdrom,dialout,dip,fax,floppy,input,lp,lpadmin,plugdev,pulse-access,render,ssl-cert,sudo,tape,tty,video,voice $USERNAME \ && echo "${USERNAME} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers \ - && chown $USERNAME:$USERNAME /home/$USERNAME \ && ln -snf "/usr/share/zoneinfo/$TZ" /etc/localtime && echo "$TZ" > /etc/timezone -COPY --from=warp /usr/bin/warp /usr/bin/ +COPY --from=ghcr.io/wanjohiryan/netris/warp:nightly /usr/bin/warp /usr/bin/ +COPY --from=ghcr.io/games-on-whales/inputtino:stable /inputtino/input-server /inputtino/input-server RUN chmod +x /usr/bin/warp COPY .scripts/entrypoint.sh .scripts/supervisord.conf /etc/ RUN chmod 755 /etc/supervisord.conf /etc/entrypoint.sh @@ -52,6 +74,10 @@ RUN chmod 755 /etc/supervisord.conf /etc/entrypoint.sh USER 1000 ENV SHELL=/bin/bash \ USER=${USERNAME} +#For mounting the game into the container +VOLUME [ "/game" ] +#For inputtino server +EXPOSE 8080 WORKDIR /home/${USERNAME}