diff options
| -rw-r--r-- | README.md | 36 | ||||
| -rwxr-xr-x | contrib/deck.sh | 282 | ||||
| -rwxr-xr-x | contrib/pc.sh | 126 |
3 files changed, 437 insertions, 7 deletions
@@ -8,6 +8,8 @@  +Keep an eye on the [Wiki](https://deckbrew.xyz) for more information about Plugin Loader, documentation + tools for plugin development and more. + ## Installation 1. Go into the Steam Deck Settings 2. Under System -> System Settings toggle `Enable Developer Mode` @@ -17,10 +19,10 @@ 6. Open a terminal and paste the following command into it: - For users: - `curl -L https://github.com/SteamDeckHomebrew/PluginLoader/raw/main/dist/install_release.sh | sh` - - For developers: + - For plugin developers: ~~- `curl -L https://github.com/SteamDeckHomebrew/PluginLoader/raw/main/dist/install_nightly.sh | sh`~~ Nightly releases are currently broken. -8. Done! Reboot back into Gaming mode and enjoy your plugins! +7. Done! Reboot back into Gaming mode and enjoy your plugins! ### Install Plugins - Simply copy the plugin's folder into `~/homebrew/plugins` @@ -30,9 +32,6 @@ - For both users and developers: - `curl -L https://github.com/SteamDeckHomebrew/PluginLoader/raw/main/dist/uninstall.sh | sh` -### Developing plugins -- There is no complete plugin development documentation yet. However a good starting point is the [Plugin Template](https://github.com/SteamDeckHomebrew/Plugin-Template) repository - ## Features - Clean injecting and loading of one or more plugins - Persistent. It doesn't need to be reinstalled after every system update @@ -40,9 +39,32 @@ - Allows plugins to define python functions and run them from javascript. - Allows plugins to make fetch calls, bypassing cors completely. -## Caveats +## Developing plugins +- There is no complete plugin development documentation yet. However a good starting point is the [Plugin Template](https://github.com/SteamDeckHomebrew/decky-plugin-template) repository. + + + +## Contribution +- For Plugin Loader contributors (in possession of a Steam Deck): + - `curl -L https://github.com/SteamDeckHomebrew/PluginLoader/raw/react-frontend-plugins/contrib/deck.sh | sh` +- For PluginLoader contributors (without a Steam Deck): + - `curl -L https://github.com/SteamDeckHomebrew/PluginLoader/raw/react-frontend-plugins/contrib/pc.sh | sh` + - [Here's how to get the Steam Deck UI on your enviroment of choice.](https://youtu.be/1IAbZte8e7E?t=112) + - (The video shows Windows usage but unless you're using WSL/cygwin this script is unsupported on Windows.) + +To run your development version of Plugin Loader on Deck, run a command like this: +```bash +ssh deck@steamdeck 'export PLUGIN_PATH=/home/deck/loaderdev/plugins; export CHOWN_PLUGIN_PATH=0; echo 'password' | sudo -SE python3 /home/deck/loaderdev/pluginloader/backend/main.py' +``` + +Or on PC with the Deck UI enabled: +```bash +export PLUGIN_PATH=/home/user/installdirectory/plugins; +export CHOWN_PLUGIN_PATH=0; +sudo python3 /home/deck/loaderdev/pluginloader/backend/main.py +``` -- You can only interact with the Plugin Menu via touchscreen. +Source control and deploying plugins are left to each respective contributor for the cloned repos in order to keep depedencies up to date. ## Credit diff --git a/contrib/deck.sh b/contrib/deck.sh new file mode 100755 index 00000000..e67a05c5 --- /dev/null +++ b/contrib/deck.sh @@ -0,0 +1,282 @@ +#!/bin/sh + +## Before using this script, enable sshd on the deck and setup an sshd key between the deck and your dev in sshd_config. +## This script defaults to port 22 unless otherwise specified, and cannot run without a sudo password or LAN IP. +## You will need to specify the path to the ssh key if using key connection exclusively. + +## Pre-parse arugments for ease of use +CLONEFOLDER=${1:-""} +INSTALLFOLDER=${2:-""} +DECKIP=${3:-""} +SSHPORT=${4:-""} +PASSWORD=${5:-""} +SSHKEYLOC=${6:-""} + +## gather options into an array +OPTIONSARRAY=("$CLONEFOLDER" $INSTALLFOLDER "$DECKIP" "$SSHPORT" "$PASSWORD" "$SSHKEYLOC") + +## iterate through options array to check their presence +count=0 +for OPTION in ${OPTIONSARRAY[@]}; do + ! [[ "$OPTION" == "" ]] && count=$(($count+1)) + # printf "OPTION=$OPTION\n" +done + +setfolder() { + if [[ "$2" == "clone" ]]; then + local ACTION="clone" + local DEFAULT="git" + elif [[ "$2" == "install" ]]; then + local ACTION="install" + local DEFAULT="loaderdev" + fi + + printf "Enter the directory in /home/user to ${ACTION} to.\n" + printf "Example: if your home directory is /home/user you would type: ${DEFAULT}\n" + printf "The ${ACTION} directory would be: ${HOME}/${DEFAULT}\n" + if [[ "$ACTION" == "clone" ]]; then + read -p "Enter your ${ACTION} directory: " CLONEFOLDER + if ! [[ "$CLONEFOLDER" =~ ^[[:alnum:]]+$ ]]; then + printf "Folder name not provided. Using default, '${DEFAULT}'.\n" + CLONEFOLDER="${DEFAULT}" + fi + elif [[ "$ACTION" == "install" ]]; then + read -p "Enter your ${ACTION} directory: " INSTALLFOLDER + if ! [[ "$INSTALLFOLDER" =~ ^[[:alnum:]]+$ ]]; then + printf "Folder name not provided. Using default, '${DEFAULT}'.\n" + INSTALLFOLDER="${DEFAULT}" + fi + else + printf "Folder type could not be determined, exiting\n" + exit 1 + fi +} + +checkdeckip() { + ### check that ip is provided + if [[ "$1" == "" ]]; then + printf "An ip address must be provided, exiting.\n" + exit 1 + fi + + ### check to make sure it's a potentially valid ipv4 address + if ! [[ $1 =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then + printf "A valid ip address must be provided, exiting.\n" + exit 1 + fi +} + +checksshport() { + ### check to make sure a port was specified + if [[ "$1" == "" ]]; then + printf "ssh port not provided. Using default, '22'.\n" + SSHPORT="22" + fi + + ### check for valid ssh port + if [[ $1 -le 0 ]]; then + printf "A valid ssh port must be provided, exiting.\n" + exit 1 + fi +} + +checkpassword() { + ### check to make sure a password was specified + if [[ "$1" == "" ]] || ! [[ "$1" =~ ^[[:alnum:]]+$ ]]; then + printf "Password was not provided, exiting.\n" + exit 1 + fi +} + +checksshkey() { + ### check if ssh key is present at location provided + if [[ "$1" == "" ]]; then + SSHKEYLOC="$HOME/.ssh/id_rsa" + printf "ssh key was not provided. Defaulting to $SSHKEYLOC if it exists.\n" + fi + + ### check if sshkey is present at location + if ! [[ -e "$1" ]]; then + SSHKEYLOC="" + printf "ssh key does not exist. This script will use password authentication.\n" + fi +} + +clonefromto() { + # printf "repo=$1\n" + # printf "outdir=$2\n" + # printf "branch=$3\n" + if [[ -z $3 ]]; then + BRANCH="" + else + BRANCH="-b $3" + fi + git clone $1 $2 $BRANCH &> '/dev/null' + CODE=$? + if [[ $CODE -eq 128 ]]; then + cd $2 + git fetch &> '/dev/null' + fi +} + +npmtransbundle() { + cd $1 + if [[ "$2" == "library" ]]; then + npm install --quiet &> '/dev/null' + npm run build --quiet &> '/dev/null' + sudo npm link --quiet &> '/dev/null' + elif [[ "$2" == "frontend" ]] || [[ "$2" == "template" ]]; then + npm install --quiet &> '/dev/null' + npm link decky-frontend-lib --quiet &> '/dev/null' + npm run build --quiet &> '/dev/null' + fi +} + +printf "Installing Steam Deck Plugin Loader contributor (for Steam Deck)...\n" + +printf "THIS SCRIPT ASSUMES YOU ARE RUNNING IT ON A PC, NOT THE DECK! +Not planning to contribute to PluginLoader? +If so, you should not be using this script.\n +If you have a release/nightly installed this script will disable it.\n" + +printf "This script requires you to have nodejs installed. (If nodejs doesn't bundle npm on your OS/distro, then npm is required as well).\n" + +# [[ $count -gt 0 ]] || read -p "Press any key to continue" + +if ! [[ $count -gt 0 ]] ; then + read -p "Press any key to continue" +fi + +## User chooses preffered clone & install directories + +if [[ "$CLONEFOLDER" == "" ]]; then + setfolder "$CLONEFOLDER" "clone" +fi + +if [[ "$INSTALLFOLDER" == "" ]]; then + setfolder "$INSTALLFOLDER" "install" +fi + +CLONEDIR="$HOME/$CLONEFOLDER" +INSTALLDIR="/home/deck/$INSTALLFOLDER" + +## Input ip address, port, password and sshkey + +### DECKIP already been parsed? +if [[ "$DECKIP" == "" ]]; then + ### get ip address of deck from user + read -p "Enter the ip address of your Steam Deck: " DECKIP +fi + +### validate DECKIP +checkdeckip "$DECKIP" + +### SSHPORT already been parsed? +if [[ "$SSHPORT" == "" ]]; then + ### get ssh port from user + read -p "Enter the ssh port of your Steam Deck: " SSHPORT +fi + +### validate SSHPORT +checksshport "$SSHPORT" + +### PASSWORD already been parsed? +if [[ "$PASSWORD" == "" ]]; then + ### prompt the user for their deck's password + printf "Enter the password for the Steam Deck user 'deck' : " + read -s PASSWORD + printf "\n" +fi + +### validate PASSWORD +checkpassword "$PASSWORD" + +### SSHKEYLOC already been parsed? +if [[ "$SSHKEYLOC" == "" ]]; then + ### prompt the user for their ssh key + read -p "Enter the directory for your ssh key, for ease of connection : " SSHKEYLOC +fi + +### validate SSHKEYLOC +checksshkey "$SSHKEYLOC" + +if [[ "$SSHKEYLOC" == "" ]]; then + IDENINVOC="" +else + IDENINVOC="-i ${SSHKEYLOC}" +fi + +## Create folder structure + +printf "\nCloning git repositories.\n" + +mkdir -p ${CLONEDIR} &> '/dev/null' + +### remove folders just in case +# rm -r ${CLONEDIR}/pluginloader +# rm -r ${CLONEDIR}/pluginlibrary +# rm -r ${CLONEDIR}/plugintemplate + +clonefromto "https://github.com/SteamDeckHomebrew/PluginLoader" ${CLONEDIR}/pluginloader react-frontend-plugins + +clonefromto "https://github.com/SteamDeckHomebrew/decky-frontend-lib" ${CLONEDIR}/pluginlibrary + +clonefromto "https://github.com/SteamDeckHomebrew/decky-plugin-template" ${CLONEDIR}/plugintemplate + +## Transpile and bundle typescript + +type npm &> '/dev/null' + +NPMLIVES=$? + +if ! [[ "$NPMLIVES" -eq 0 ]]; then + printf "npm does not to be installed, exiting.\n" + exit 1 +fi + +[ "$UID" -eq 0 ] || printf "Input password to install typscript compilier.\n" + +## TODO: add a way of verifying if tsc is installed and to skip this step if it is +sudo npm install --quiet -g tsc &> '/dev/null' + +printf "Transpiling and bundling typescript.\n" + +npmtransbundle ${CLONEDIR}/pluginlibrary/ "library" + +npmtransbundle ${CLONEDIR}/pluginloader/frontend "frontend" + +npmtransbundle ${CLONEDIR}/plugintemplate "template" + +## Transfer relevant files to deck + +printf "Copying relevant files to install directory\n\n" + +### copy files for PluginLoader +rsync -avzp --mkpath --rsh="ssh -p ${SSHPORT} ${IDENINVOC}" --exclude='.git/' --exclude='node_modules' --exclude="package-lock.json" --exclude=='frontend' --exclude="*dist*" --exclude="*contrib*" --delete ${CLONEDIR}/pluginloader/* deck@${DECKIP}:${INSTALLDIR}/pluginloader/ &> '/dev/null' +if ! [[ $? -eq 0 ]]; then + printf "Error occurred when copying ${CLONEDIR}/pluginloader/ to ${INSTALLDIR}/pluginloader/\n" + exit 1 +fi + +### copy files for PluginLoader template +rsync -avzp --mkpath --rsh="ssh -p ${SSHPORT} ${IDENINVOC}" --exclude='.git/' --exclude='node_modules' --exclude="package-lock.json" --delete ${CLONEDIR}/plugintemplate deck@${DECKIP}:${INSTALLDIR}/plugins &> '/dev/null' +if ! [[ $? -eq 0 ]]; then + printf "Error occurred when copying ${CLONEDIR}/plugintemplate to ${INSTALLDIR}/plugins\n" + exit 1 +fi + +## TODO: direct contributors to wiki for this info? + +printf "Run these commands to deploy your local changes to the deck:\n" +printf "'rsync -avzp --mkpath --rsh=""\"ssh -p ${SSHPORT} ${IDENINVOC}\""" --exclude='.git/' --exclude='node_modules' --exclude='package-lock.json' --delete ${CLONEDIR}/pluginname deck@${DECKIP}:${INSTALLDIR}/plugins'\n" +printf "'rsync -avzp --mkpath --rsh=""\"ssh -p ${SSHPORT} ${IDENINVOC}\""" --exclude='.git/' --exclude='node_modules' --exclude='package-lock.json' --exclude=='frontend' --exclude='*dist*' --exclude='*contrib*' --delete ${CLONEDIR}/pluginloader/* deck@${DECKIP}:${INSTALLDIR}/pluginloader/'\n" + +printf "Run in console or in a script this command to run your development version:\n'ssh deck@${DECKIP} -p 22 ${IDENINVOC} 'export PLUGIN_PATH=${INSTALLDIR}/plugins; export CHOWN_PLUGIN_PATH=0; echo 'steam' | sudo -SE python3 ${INSTALLDIR}/pluginloader/backend/main.py'\n" + +## Disable Releases versions if they exist + +### ssh into deck and disable PluginLoader release/nightly service +printf "Connecting via ssh to disable any PluginLoader release versions.\n" +printf "Script will exit after this. All done!\n" + +ssh deck@$DECKIP -p $SSHPORT $IDENINVOC "printf ${PASSWORD} | sudo -S systemctl disable --now plugin_loader; echo $?"
\ No newline at end of file diff --git a/contrib/pc.sh b/contrib/pc.sh new file mode 100755 index 00000000..1c4b3ede --- /dev/null +++ b/contrib/pc.sh @@ -0,0 +1,126 @@ +#!/bin/sh + +## Pre-parse arugments for ease of use +CLONEFOLDER=${1:-""} + +setfolder() { + if [[ "$2" == "clone" ]]; then + local ACTION="clone" + local DEFAULT="git" + elif [[ "$2" == "install" ]]; then + local ACTION="install" + local DEFAULT="loaderdev" + fi + + printf "Enter the directory in /home/user to ${ACTION} to.\n" + printf "Example: if your home directory is /home/user you would type: ${DEFAULT}\n" + printf "The ${ACTION} directory would be: ${HOME}/${DEFAULT}\n" + if [[ "$ACTION" == "clone" ]]; then + read -p "Enter your ${ACTION} directory: " CLONEFOLDER + if ! [[ "$CLONEFOLDER" =~ ^[[:alnum:]]+$ ]]; then + printf "Folder name not provided. Using default, '${DEFAULT}'.\n" + CLONEFOLDER="${DEFAULT}" + fi + elif [[ "$ACTION" == "install" ]]; then + read -p "Enter your ${ACTION} directory: " INSTALLFOLDER + if ! [[ "$INSTALLFOLDER" =~ ^[[:alnum:]]+$ ]]; then + printf "Folder name not provided. Using default, '${DEFAULT}'.\n" + INSTALLFOLDER="${DEFAULT}" + fi + else + printf "Folder type could not be determined, exiting\n" + exit 1 + fi +} + +clonefromto() { + # printf "repo=$1\n" + # printf "outdir=$2\n" + # printf "branch=$3\n" + if [[ -z $3 ]]; then + BRANCH="" + else + BRANCH="-b $3" + fi + git clone $1 $2 $BRANCH &> '/dev/null' + CODE=$? + if [[ $CODE -eq 128 ]]; then + cd $2 + git fetch &> '/dev/null' + fi +} + +npmtransbundle() { + cd $1 + if [[ "$2" == "library" ]]; then + npm install --quiet &> '/dev/null' + npm run build --quiet &> '/dev/null' + sudo npm link --quiet &> '/dev/null' + elif [[ "$2" == "frontend" ]] || [[ "$2" == "template" ]]; then + npm install --quiet &> '/dev/null' + npm link decky-frontend-lib --quiet &> '/dev/null' + npm run build --quiet &> '/dev/null' + fi +} + +printf "Installing Steam Deck Plugin Loader contributor (no Steam Deck)..." + +printf "\nTHIS SCRIPT ASSUMES YOU ARE RUNNING IT ON A PC, NOT THE DECK! +If you are not planning to contribute to PluginLoader then you should not be using this script.\n" + +printf "\nThis script requires you to have nodejs installed. (If nodejs doesn't bundle npm on your OS/distro, then npm is required as well).\n" + +if [[ -z $1 ]]; then + read -p "Press any key to continue" +fi + +if [[ "$CLONEFOLDER" == "" ]]; then + setfolder "$CLONEFOLDER" "clone" +fi + +CLONEDIR="$HOME/$CLONEFOLDER" + +## Create folder structure + +printf "\nCloning git repositories.\n" + +mkdir -p ${CLONEDIR} &> '/dev/null' + +### remove folders just in case +# rm -r ${CLONEDIR}/pluginloader +# rm -r ${CLONEDIR}/pluginlibrary +# rm -r ${CLONEDIR}/plugintemplate + +clonefromto "https://github.com/SteamDeckHomebrew/PluginLoader" ${CLONEDIR}/pluginloader react-frontend-plugins + +clonefromto "https://github.com/SteamDeckHomebrew/decky-frontend-lib" ${CLONEDIR}/pluginlibrary + +clonefromto "https://github.com/SteamDeckHomebrew/decky-plugin-template" ${CLONEDIR}/plugintemplate + +## Transpile and bundle typescript +type npm &> '/dev/null' + +NPMLIVES=$? + +if ! [[ "$NPMLIVES" -eq 0 ]]; then + printf "npm needs to be installed, exiting.\n" + exit 1 +fi + +[ "$UID" -eq 0 ] || printf "Input password to install typscript compilier.\n" + +sudo npm install --quiet -g tsc &> '/dev/null' + +printf "Transpiling and bundling typescript.\n" + +npmtransbundle ${CLONEDIR}/pluginlibrary/ "library" + +npmtransbundle ${CLONEDIR}/pluginloader/frontend "frontend" + +npmtransbundle ${CLONEDIR}/plugintemplate "template" + +printf "Plugin Loader is located at '${CLONEDIR}/pluginloader/'.\n" + +printf "Run in console or in a script these commands to run your development version:\n'export PLUGIN_PATH=${CLONEDIR}/plugins; export CHOWN_PLUGIN_PATH=0; sudo python3 ${CLONEDIR}/pluginloader/backend/main.py'\n" + +printf "All done!\n"
\ No newline at end of file |
