From 83d0e3e9c89d33e3d20a105766547c80e341769d Mon Sep 17 00:00:00 2001 From: mutoo Date: Tue, 22 Oct 2024 00:12:15 +1100 Subject: [PATCH 1/4] improve docs --- README.md | 41 +++++- dont-starve-airdrop-client/README.md | 7 + dont-starve-airdrop-client/package.json | 3 +- dont-starve-airdrop-mod/README.md | 1 + dont-starve-airdrop-mod/package.json | 2 +- dont-starve-airdrop-mod/src/modinfo.lua | 11 +- dont-starve-airdrop-mod/src/modmain.lua | 11 +- dont-starve-airdrop-mod/tools/install.js | 26 ++++ dont-starve-airdrop-server/package.json | 4 +- dont-starve-airdrop-server/src/index.js | 9 +- dont-starve-airdrop-server/yarn.lock | 175 ++++++++++++----------- dont-starve-assets-extractor/README.md | 7 + 12 files changed, 199 insertions(+), 98 deletions(-) create mode 100644 dont-starve-airdrop-mod/tools/install.js diff --git a/README.md b/README.md index 895e483..30f9a7b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,41 @@ # Don't Starve AirDrop Mod Server -This is a mod for Don't Starve that allows players to send items to game via web app. +This is a mod for Don't Starve (and DST) that allows players to send items to game via a web app. + +![Arch](./docs/arch.png) + +## Features + +- Mod: a slim mod which is polling supplies from airdrop server every 10 seconds. +- Server: a self host server running on the same machine to communicate with the mode. +- Client: a web interface to communicate with local airdrop server, allow collecting items ready for next airdrop. + +## Usage + +### Install mod + +First, you will need to install the mod either from the workshop or directly download it from github release page. + +Ensure the mod is installed in your Don't Starve (or DST) game folder: + +* Windows: `C:\Program Files (x86)\Steam\steamapps\common\Don't Starve Together\mods` +* MacOS: `~/Library/Application Support/Steam/steamapps/common/Don't Starve Together/dontstarve_steam.app/Contents/mods` + +Enable the mod when you start a new game. + +### Install server + +The airdop server is required to communicate with the mod. The mod will keep polling the items from the server every 10 seconds (by default). + +Please install the latest server from the github release page. + +The server is a standalone executable file, once started, it runs at http://localhost:9987. + +### The Web Client + +You don't need to host the web interface by your own. Once the airdrop server is running, open https://airdrop-mod.mutoo.im in the browser windows on the same computer and it should works. + +Now you can select any items in the list, and then drop it in the game. Enjoy the adventure! ## Project Structure @@ -8,7 +43,3 @@ This is a mod for Don't Starve that allows players to send items to game via web - `dont-starve-airdrop-server/` - The node.js server for holding the items to airdrop and communicating with the don't starve game - `dont-starve-airdrop-client/` - The React web app for sending items to the server - `dont-starve-assets-extractor/` - The handy tool for extracting inventory assets from the don't starve game - -## Diagram - -[Arch](./docs/arch.png) diff --git a/dont-starve-airdrop-client/README.md b/dont-starve-airdrop-client/README.md index b4ec8a0..52fc3f6 100644 --- a/dont-starve-airdrop-client/README.md +++ b/dont-starve-airdrop-client/README.md @@ -1,2 +1,9 @@ # Don't Starve AirDrop Client +This is the web client of Don't Starve (or DST) Airdrop mod. + +## Usage + +The latest client is deployed at https://airdrop-mod.mutoo.im + +Once your Airdrop Server is started, open above link and you should see the interface. diff --git a/dont-starve-airdrop-client/package.json b/dont-starve-airdrop-client/package.json index 350d2dc..f67d6cc 100644 --- a/dont-starve-airdrop-client/package.json +++ b/dont-starve-airdrop-client/package.json @@ -1,6 +1,7 @@ { - "name": "dont-starve-airdrop-server", + "name": "dont-starve-airdrop-client", "version": "0.1.0", + "description": "Don't Starve (Together) Airdrop Client.", "author": "mutoo ", "license": "MIT", "dependencies": { diff --git a/dont-starve-airdrop-mod/README.md b/dont-starve-airdrop-mod/README.md index 8020af8..34ee35b 100644 --- a/dont-starve-airdrop-mod/README.md +++ b/dont-starve-airdrop-mod/README.md @@ -1,2 +1,3 @@ # Don't Starve AirDrop Mod +This is the source of the mod, you may directly install it from the steam workshop. Or manually install it by copying this `dont-starve-airdop-mod/src` folder to don't starve or dst's mods folder. diff --git a/dont-starve-airdrop-mod/package.json b/dont-starve-airdrop-mod/package.json index 6641bb9..2d2d0a6 100644 --- a/dont-starve-airdrop-mod/package.json +++ b/dont-starve-airdrop-mod/package.json @@ -5,7 +5,7 @@ "author": "mutoo ", "license": "MIT", "scripts": { - "mod:install": "rsync -avz --delete ./src/ ~/Library/Application\\ Support/Steam/steamapps/common/Don\\'t\\ Starve\\ Together/dontstarve_steam.app/Contents/mods/dont-starve-airdrop-mod/", + "mod:install": "node tools/install", "mod:watch": "nodemon -e lua --watch ./src --exec \"npm run mod:install\"" }, "devDependencies": { diff --git a/dont-starve-airdrop-mod/src/modinfo.lua b/dont-starve-airdrop-mod/src/modinfo.lua index 6cfb8e3..a1210c2 100644 --- a/dont-starve-airdrop-mod/src/modinfo.lua +++ b/dont-starve-airdrop-mod/src/modinfo.lua @@ -33,7 +33,7 @@ configuration_options = { label = "Server address:", options = { - {description = "http://localhost:9978", data = "http://localhost:9978"}, + {description = "localhost:9978", data = "http://localhost:9978"}, }, default = "http://localhost:9978", }, @@ -48,5 +48,14 @@ configuration_options = { {description = "20", data = 20}, }, default = 10 + }, + { + name = "ENABLE_DEBUG", + label = "Enable Debug", + options = { + {description = "No", data = false}, + {description = "Yes", data = true}, + }, + default = false } } diff --git a/dont-starve-airdrop-mod/src/modmain.lua b/dont-starve-airdrop-mod/src/modmain.lua index 867296e..05cf246 100644 --- a/dont-starve-airdrop-mod/src/modmain.lua +++ b/dont-starve-airdrop-mod/src/modmain.lua @@ -5,10 +5,12 @@ local ExecuteConsoleCommand = GLOBAL.ExecuteConsoleCommand local ConsoleRemote = GLOBAL.ConsoleRemote local QUERY_INTERVAL = GetModConfigData("QUERY_INTERVAL") or 10 +local ENABLE_DEBUG = GetModConfigData("ENABLE_DEBUG") or false function airdrop_sync() local players = {} for _, v in ipairs(GLOBAL.AllPlayers) do + -- collect information of all nearby players table.insert(players, {userid = v.userid, name = v.name, prefab = tostring(v.prefab)}) end TheSim:QueryServer( @@ -22,10 +24,15 @@ function airdrop_sync() end ) if status and data then - print("[AIRDROP] INFO", "- number of airdrops arrived:", #data.commands) + if ENABLE_DEBUG then + print("[AIRDROP] INFO", "- number of airdrops arrived:", #data.commands) + end for _, command in ipairs(data.commands) do - print("[AIRDROP] INFO", "- cmd: ", command) + if ENABLE_DEBUG then + print("[AIRDROP] INFO", "- cmd: ", command) + end + if GLOBAL.TheWorld.ismastersim then ExecuteConsoleCommand(command) else diff --git a/dont-starve-airdrop-mod/tools/install.js b/dont-starve-airdrop-mod/tools/install.js new file mode 100644 index 0000000..9c63b43 --- /dev/null +++ b/dont-starve-airdrop-mod/tools/install.js @@ -0,0 +1,26 @@ +const { exec } = require('child_process'); +const path = require('path'); + +// Define source and destination paths +const srcPath = path.join(__dirname, '../src'); +const destPath = process.platform === 'win32' + ? 'C:\\Program Files\\ (x86)\\Steam\\steamapps\\common\\Don\'t\\ Starve\\ Together\\mods\\dont-starve-airdrop-mod\\' // Updated Windows path + : '~/Library/Application Support/Steam/steamapps/common/Don\'t Starve Together/dontstarve_steam.app/Contents/mods/dont-starve-airdrop-mod/'; + +// Construct the command based on the platform +const command = process.platform === 'win32' + ? `mklink /D "${destPath}" "${srcPath}"` // Create a soft link on Windows + : `rsync -avz --delete "${srcPath}" "${destPath}"`; // Keep rsync for other platforms + +// Execute the command +exec(command, (error, stdout, stderr) => { + if (error) { + console.error(`Error: ${error.message}`); + return; + } + if (stderr) { + console.error(`Stderr: ${stderr}`); + return; + } + console.log(`Output: ${stdout}`); +}); diff --git a/dont-starve-airdrop-server/package.json b/dont-starve-airdrop-server/package.json index 18cf6cc..a122886 100644 --- a/dont-starve-airdrop-server/package.json +++ b/dont-starve-airdrop-server/package.json @@ -1,7 +1,7 @@ { "name": "dont-starve-airdrop-server", - "version": "1.0.0", - "description": "Don't Starve Together Airdrop Server.", + "version": "0.1.0", + "description": "Don't Starve (Together) Airdrop Server.", "author": "mutoo ", "license": "MIT", "main": "src/index.js", diff --git a/dont-starve-airdrop-server/src/index.js b/dont-starve-airdrop-server/src/index.js index 14c2bd2..282893a 100644 --- a/dont-starve-airdrop-server/src/index.js +++ b/dont-starve-airdrop-server/src/index.js @@ -3,7 +3,7 @@ const express = require("express"); const expressWs = require("express-ws"); -const port = 9978; +const port = process.env.AIRDROP_PORT || 9978; const app = express(); expressWs(app); @@ -20,7 +20,12 @@ app.use("/api", airdrop); if (process.env.NODE_ENV === "development") { // serve the static files from the React app app.use(express.static("../dont-starve-airdrop-client/build")); +} else { + // otherwise redirect all other request to https://airdrop-mod.mutoo.im + app.get('*', (req, res) => { + res.redirect('https://airdrop-mod.mutoo.im'); + }); } // start the server listening for requests -app.listen(port, () => console.log(`Server is running on port ${port}!`)); +app.listen(port, () => console.log(`Airdrop Server is running on port ${port}! Please launch your game with airdrop-mod enabled now, and start from https://airdrop-mod.mutoo.im to airdrop your suppliment!`)); diff --git a/dont-starve-airdrop-server/yarn.lock b/dont-starve-airdrop-server/yarn.lock index 931ac4a..92973db 100644 --- a/dont-starve-airdrop-server/yarn.lock +++ b/dont-starve-airdrop-server/yarn.lock @@ -11,15 +11,15 @@ "@jridgewell/gen-mapping" "^0.3.0" jsesc "^2.5.1" -"@babel/helper-string-parser@^7.18.10", "@babel/helper-string-parser@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" - integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== +"@babel/helper-string-parser@^7.18.10", "@babel/helper-string-parser@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz#d50e8d37b1176207b4fe9acedec386c565a44a54" + integrity sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g== -"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" - integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== +"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz#77b7f60c40b15c97df735b38a66ba1d7c3e93da5" + integrity sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg== "@babel/parser@7.18.4": version "7.18.4" @@ -36,42 +36,42 @@ to-fast-properties "^2.0.0" "@babel/types@^7.18.2": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb" - integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg== + version "7.25.8" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.8.tgz#5cf6037258e8a9bcad533f4979025140cb9993e1" + integrity sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg== dependencies: - "@babel/helper-string-parser" "^7.22.5" - "@babel/helper-validator-identifier" "^7.22.20" + "@babel/helper-string-parser" "^7.25.7" + "@babel/helper-validator-identifier" "^7.25.7" to-fast-properties "^2.0.0" "@jridgewell/gen-mapping@^0.3.0": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" - integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== dependencies: - "@jridgewell/set-array" "^1.0.1" + "@jridgewell/set-array" "^1.2.1" "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/trace-mapping" "^0.3.24" "@jridgewell/resolve-uri@^3.1.0": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" - integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== -"@jridgewell/trace-mapping@^0.3.9": - version "0.3.20" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" - integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== +"@jridgewell/trace-mapping@^0.3.24": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== dependencies: "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" @@ -202,7 +202,14 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.2, braces@~3.0.2: +braces@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -319,11 +326,11 @@ debug@2.6.9: ms "2.0.0" debug@4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== dependencies: - ms "2.1.2" + ms "^2.1.3" debug@^3.2.7: version "3.2.7" @@ -355,9 +362,9 @@ destroy@1.2.0: integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== detect-libc@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.2.tgz#8ccf2ba9315350e1241b88d0ac3b0e1fbd99605d" - integrity sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw== + version "2.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700" + integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== dir-glob@^3.0.1: version "3.0.1" @@ -389,9 +396,9 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1: once "^1.4.0" escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== escape-html@~1.0.3: version "1.0.3" @@ -453,9 +460,9 @@ express@^4.18.2: vary "~1.1.2" fast-glob@^3.2.9: - version "3.3.1" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" - integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -464,16 +471,16 @@ fast-glob@^3.2.9: micromatch "^4.0.4" fastq@^1.6.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" - integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + version "1.17.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== dependencies: reusify "^1.0.4" -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +fill-range@^7.0.1, fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" @@ -602,10 +609,10 @@ has@^1.0.3: resolved "https://registry.yarnpkg.com/has/-/has-1.0.4.tgz#2eb2860e000011dae4f1406a86fe80e530fb2ec6" integrity sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ== -hasown@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" - integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== dependencies: function-bind "^1.1.2" @@ -646,9 +653,9 @@ ignore-by-default@^1.0.1: integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== ignore@^5.2.0: - version "5.2.4" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" - integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: version "2.0.4" @@ -688,11 +695,11 @@ is-core-module@2.9.0: has "^1.0.3" is-core-module@^2.13.0: - version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + version "2.15.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.1.tgz#a7363a25bee942fefab0de13bf6aa372c82dcc37" + integrity sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ== dependencies: - hasown "^2.0.0" + hasown "^2.0.2" is-extglob@^2.1.1: version "2.1.1" @@ -763,11 +770,11 @@ methods@~1.1.2: integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== dependencies: - braces "^3.0.2" + braces "^3.0.3" picomatch "^2.3.1" mime-db@1.52.0: @@ -814,12 +821,7 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3, ms@^2.1.1: +ms@2.1.3, ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -843,9 +845,9 @@ negotiator@0.6.3: integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== node-abi@^3.3.0: - version "3.51.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.51.0.tgz#970bf595ef5a26a271307f8a4befa02823d4e87d" - integrity sha512-SQkEP4hmNWjlniS5zdnfIXTk1x7Ome85RDzHlTbBtzE97Gfwz/Ipw4v/Ryk20DWIy3yCNVLVlGKApCnmvYoJbA== + version "3.71.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.71.0.tgz#52d84bbcd8575efb71468fbaa1f9a49b2c242038" + integrity sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw== dependencies: semver "^7.3.5" @@ -1009,9 +1011,9 @@ pstree.remy@^1.1.8: integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + version "3.0.2" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.2.tgz#836f3edd6bc2ee599256c924ffe0d88573ddcbf8" + integrity sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw== dependencies: end-of-stream "^1.1.0" once "^1.3.1" @@ -1123,7 +1125,12 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -semver@^7.3.5, semver@^7.5.3: +semver@^7.3.5: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + +semver@^7.5.3: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== @@ -1336,9 +1343,9 @@ undefsafe@^2.0.5: integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" diff --git a/dont-starve-assets-extractor/README.md b/dont-starve-assets-extractor/README.md index c637edd..16fb902 100644 --- a/dont-starve-assets-extractor/README.md +++ b/dont-starve-assets-extractor/README.md @@ -6,3 +6,10 @@ For the Don't Starve AirDrop app, we only needs the inventoy images. Which can b The default `inventoryimages.tex` can be found at `dontstarve_steam.app/Contents/data/images/inventoryimages.tex`. While it's atlas xml file can be found at `dontstarve_steam.app/Contents/data/databundles/images/inventoryimages.xml`, which comes from `dontstarve_steam.app/Contents/data/databundles/images.zip`. +### Usage + +Ensure you have node environment installed. + +To extract or update the Don't Starve assets, we firstly copy all the inventory images from above zip to the `dont-starve-assets-extractor/assets` folder. Then run `yarn run extract` command. + +All the assets will be extracted to the `dont-starve-assets-client/public/inventory` folder. From b0ab670dea9845d01c0c5f987003c90eddc4779a Mon Sep 17 00:00:00 2001 From: mutoo Date: Tue, 22 Oct 2024 23:03:03 +1100 Subject: [PATCH 2/4] improve comments --- dont-starve-airdrop-client/public/bmc_qr.png | Bin 0 -> 53690 bytes dont-starve-airdrop-client/src/App.js | 7 ++++++- .../src/components/BuyMeCoffee.js | 16 ++++++++++++++++ .../src/components/Draft.js | 5 ++++- dont-starve-airdrop-server/src/airdrop.js | 6 +++--- 5 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 dont-starve-airdrop-client/public/bmc_qr.png create mode 100644 dont-starve-airdrop-client/src/components/BuyMeCoffee.js diff --git a/dont-starve-airdrop-client/public/bmc_qr.png b/dont-starve-airdrop-client/public/bmc_qr.png new file mode 100644 index 0000000000000000000000000000000000000000..32feece6756da314fda5133afe4c86219bbaa792 GIT binary patch literal 53690 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 DKkB~} literal 0 HcmV?d00001 diff --git a/dont-starve-airdrop-client/src/App.js b/dont-starve-airdrop-client/src/App.js index cd68fdb..236809e 100644 --- a/dont-starve-airdrop-client/src/App.js +++ b/dont-starve-airdrop-client/src/App.js @@ -9,6 +9,7 @@ import History from "./components/History"; import { inventory } from "./config"; import { getInventoryImage } from "./utils/image"; import styles from "./App.module.css"; +import BuyMeCoffee from "./components/BuyMeCoffee"; function App() { const [ws, error] = useWebsocket(); @@ -52,7 +53,7 @@ function App() { ); })} -

## Filter: {categoryType}

+

## {categoryType}

{fav.items.map((item) => { return ( @@ -67,12 +68,16 @@ function App() { ); })}
+
+ Tip: hold "shift" key to add 5x items on each click. +

# Airdrop History


Disclaimer: All game-related images and trademarks are property of klei.
+ ); } diff --git a/dont-starve-airdrop-client/src/components/BuyMeCoffee.js b/dont-starve-airdrop-client/src/components/BuyMeCoffee.js new file mode 100644 index 0000000..620c8df --- /dev/null +++ b/dont-starve-airdrop-client/src/components/BuyMeCoffee.js @@ -0,0 +1,16 @@ +export default function BuyMeCoffee() { + return ( +
+ ); +} diff --git a/dont-starve-airdrop-client/src/components/Draft.js b/dont-starve-airdrop-client/src/components/Draft.js index e1915bf..28b0d97 100644 --- a/dont-starve-airdrop-client/src/components/Draft.js +++ b/dont-starve-airdrop-client/src/components/Draft.js @@ -51,7 +51,10 @@ export default observer(function Draft({ ws }) {
{!draft.entries.length ? (
- Please add some inventory items to drop. + + Please add some inventory items from the listing, and the click + the button on the right to airdrop. +
) : (
diff --git a/dont-starve-airdrop-server/src/airdrop.js b/dont-starve-airdrop-server/src/airdrop.js index 2c947a1..3d76571 100644 --- a/dont-starve-airdrop-server/src/airdrop.js +++ b/dont-starve-airdrop-server/src/airdrop.js @@ -54,11 +54,11 @@ function generateCommands(package) { } const player = package.receiver - ? `UserToPlayer("${package.receiver}")` + ? // when a player is not in range of host, it may return nil, + // in this case we just fallback to the host. + `UserToPlayer("${package.receiver}") or ThePlayer` : "ThePlayer"; - // TODO: handle drop to everone - for (const entry of package.entries) { if (entry.type === "item") { const count = entry.count || 1; From 776352210ccf42a83efe8d4ab7a09899bd17e864 Mon Sep 17 00:00:00 2001 From: mutoo Date: Sat, 26 Oct 2024 23:37:35 +1100 Subject: [PATCH 3/4] improve docs --- dont-starve-airdrop-client/README.md | 4 +- dont-starve-airdrop-client/src/App.js | 2 +- .../src/components/Draft.js | 3 +- .../src/components/ReloadDialog.js | 4 + dont-starve-airdrop-client/src/config.yml | 120 ++++++++++++++++++ dont-starve-airdrop-mod/src/modinfo.lua | 2 +- dont-starve-airdrop-server/README.md | 7 + dont-starve-airdrop-server/src/index.js | 2 +- 8 files changed, 137 insertions(+), 7 deletions(-) create mode 100644 dont-starve-airdrop-client/src/config.yml diff --git a/dont-starve-airdrop-client/README.md b/dont-starve-airdrop-client/README.md index 52fc3f6..234a9a6 100644 --- a/dont-starve-airdrop-client/README.md +++ b/dont-starve-airdrop-client/README.md @@ -1,9 +1,9 @@ # Don't Starve AirDrop Client -This is the web client of Don't Starve (or DST) Airdrop mod. +This is the web client for Don't Starve (or DST) Airdrop mod. ## Usage The latest client is deployed at https://airdrop-mod.mutoo.im -Once your Airdrop Server is started, open above link and you should see the interface. +Once your Airdrop Server is started locally, open above link and you should see the interface. diff --git a/dont-starve-airdrop-client/src/App.js b/dont-starve-airdrop-client/src/App.js index 236809e..90e871a 100644 --- a/dont-starve-airdrop-client/src/App.js +++ b/dont-starve-airdrop-client/src/App.js @@ -69,7 +69,7 @@ function App() { })}
- Tip: hold "shift" key to add 5x items on each click. + Tip: Press and hold the "Shift" key to add five items with each click.

# Airdrop History

diff --git a/dont-starve-airdrop-client/src/components/Draft.js b/dont-starve-airdrop-client/src/components/Draft.js index 28b0d97..117cc9b 100644 --- a/dont-starve-airdrop-client/src/components/Draft.js +++ b/dont-starve-airdrop-client/src/components/Draft.js @@ -52,8 +52,7 @@ export default observer(function Draft({ ws }) { {!draft.entries.length ? (
- Please add some inventory items from the listing, and the click - the button on the right to airdrop. + Please select some inventory items from the list, and then click the button on the right to initiate the airdrop.
) : ( diff --git a/dont-starve-airdrop-client/src/components/ReloadDialog.js b/dont-starve-airdrop-client/src/components/ReloadDialog.js index e7e2a44..c0d51f4 100644 --- a/dont-starve-airdrop-client/src/components/ReloadDialog.js +++ b/dont-starve-airdrop-client/src/components/ReloadDialog.js @@ -8,6 +8,10 @@ export default function ReloadDialog({ message }) { className={classnames(styles.reloadDialog, "max-w-xl mx-auto")} >
+
+ To use the Airdrop Mod Client, please make sure you have the Airdrop Mod Server running on your local machine. For more details, visit this github link. +
+
Could not connect to server: {message}
diff --git a/dont-starve-airdrop-client/src/config.yml b/dont-starve-airdrop-client/src/config.yml new file mode 100644 index 0000000..1c9aaea --- /dev/null +++ b/dont-starve-airdrop-client/src/config.yml @@ -0,0 +1,120 @@ +inventory: + categories: + - type: "favorites" + icon: "favorites" + items: + - name: "twigs" + - name: "cutgrass" + - name: "flint" + - name: "rocks" + - name: "log" + - name: "petals" + - name: "goldnugget" + - name: "honey" + - name: "silk" + - name: "spidergland" + - name: "ash" + - name: "charcoal" + - name: "carrot" + - name: "cutreeds" + - name: "fireflies" + - name: "lightbulb" + - type: "survival" + icon: "science" + items: + - name: "twigs" + - name: "cutgrass" + - name: "flint" + - name: "rocks" + - name: "nitre" + - name: "ice" + - name: "log" + - name: "ash" + - name: "charcoal" + - name: "gears" + - name: "pigskin" + - name: "poop" + - name: "boneshard" + - name: "houndstooth" + - name: "mosquitosack" + - name: "manrabbit_tail" + - name: "beefalowool" + - name: "horn" + - type: "food" + icon: "cooking" + items: + - name: "carrot" + - name: "honey" + - name: "berries" + - name: "smallmeat" + - name: "meat" + - name: "monstermeat" + - name: "fish" + - name: "seeds" + - name: "acorn" + - name: "perogies" + - name: "taffy" + - type: "light" + icon: "fire" + items: + - name: "torch" + - name: "lantern" + - name: "fireflies" + - name: "lightbulb" + - type: "tools" + icon: "tool" + items: + - name: "axe" + - name: "pickaxe" + - name: "shovel" + - name: "hammer" + - name: "fishingrod" + - name: "bugnet" + - name: "pitchfork" + - name: "trap" + - name: "heatrock" + - name: "compass" + - name: "farm_hoe" + - name: "razor" + - name: "umbrella" + - type: "weapons" + icon: "weapon" + items: + - name: "spear" + - name: "tentaclespike" + - name: "batbat" + - name: "boomerang" + - name: "hambat" + - name: "ruins_bat" + - type: "armour" + icon: "armour" + items: + - name: "armorgrass" + - name: "armorwood" + - name: "footballhat" + - name: "armorruins" + - name: "ruinshat" + - type: "magic" + icon: "skull" + items: + - name: "nightmarefuel" + - name: "livinglog" + - name: "reviver" + - name: "beardhair" + - name: "lifeinjector" + - type: "dress" + icon: "warable" + items: + - name: "strawhat" + - name: "tophat" + - name: "winterhat" + - name: "earmuffshat" + - name: "trunkvest_winter" + - name: "minerhat" + - type: "other" + icon: "modded" + items: + - name: "spidereggsack" + - name: "honeycomb" + - name: "beemine" + - name: "trap_teeth" diff --git a/dont-starve-airdrop-mod/src/modinfo.lua b/dont-starve-airdrop-mod/src/modinfo.lua index a1210c2..f078597 100644 --- a/dont-starve-airdrop-mod/src/modinfo.lua +++ b/dont-starve-airdrop-mod/src/modinfo.lua @@ -1,6 +1,6 @@ name = "Airdrop" description = - "Get a surprise without the sky-high wait! Connect to the DontStarveAirdropServer and watch items magically appear on your screen. No real drops, just instant fun! Note: Requires a connection to the standalone DontStarveAirdropServer for item delivery. Checkout more on https://airdrop-mod.mutoo.im/." + "Get a surprise without the sky-high wait! Connect to the DontStarveAirdropServer and watch items magically appear on your screen. No real drops, just instant fun! Note: Requires a connection to the standalone DontStarveAirdropServer for item delivery. Checkout more on https://github.com/mutoo/dont-starve-airdrop-mod" author = "mutoo" version = "0.1.0" diff --git a/dont-starve-airdrop-server/README.md b/dont-starve-airdrop-server/README.md index 3f5ab8a..28e8b28 100644 --- a/dont-starve-airdrop-server/README.md +++ b/dont-starve-airdrop-server/README.md @@ -1,2 +1,9 @@ # Don't Starve AirDrop Server +This is the web server for Don't Starve (or DST) Airdrop mod. + +## Usage + +The latest service binary files are release at https://github.com/mutoo/dont-starve-airdrop-mod/releases + +Download one for your platform and run it with Airdrop mod enable, then you may start airdropping item from the [Airdrop Client](https://airdrop-mod.mutoo.im). diff --git a/dont-starve-airdrop-server/src/index.js b/dont-starve-airdrop-server/src/index.js index 282893a..468b518 100644 --- a/dont-starve-airdrop-server/src/index.js +++ b/dont-starve-airdrop-server/src/index.js @@ -28,4 +28,4 @@ if (process.env.NODE_ENV === "development") { } // start the server listening for requests -app.listen(port, () => console.log(`Airdrop Server is running on port ${port}! Please launch your game with airdrop-mod enabled now, and start from https://airdrop-mod.mutoo.im to airdrop your suppliment!`)); +app.listen(port, () => console.log(`The Airdrop Server is now active on port ${port}! Please launch your game with the airdrop-mod enabled, and begin your airdrop journey at https://airdrop-mod.mutoo.im to distribute your supplies!`)); From f234d03364d1c232550800573570511c3c87c6f1 Mon Sep 17 00:00:00 2001 From: mutoo Date: Sun, 27 Oct 2024 00:06:11 +1100 Subject: [PATCH 4/4] convert config to yml --- dont-starve-airdrop-client/craco.config.js | 36 +++ dont-starve-airdrop-client/package.json | 16 +- dont-starve-airdrop-client/src/App.js | 6 +- dont-starve-airdrop-client/src/config.js | 229 ------------------- dont-starve-airdrop-client/src/config.yml | 216 +++++++++--------- dont-starve-airdrop-client/yarn.lock | 247 ++++++++++++++++++++- 6 files changed, 400 insertions(+), 350 deletions(-) create mode 100644 dont-starve-airdrop-client/craco.config.js delete mode 100644 dont-starve-airdrop-client/src/config.js diff --git a/dont-starve-airdrop-client/craco.config.js b/dont-starve-airdrop-client/craco.config.js new file mode 100644 index 0000000..f9b96e7 --- /dev/null +++ b/dont-starve-airdrop-client/craco.config.js @@ -0,0 +1,36 @@ +const { getLoader } = require("@craco/craco"); + +module.exports = { + plugins: [ + { + plugin: { + overrideWebpackConfig: ({ context, webpackConfig }) => { + console.log( + webpackConfig.module.rules.find((rule) => + rule.hasOwnProperty("oneOf") + ) + ); + const { isFound, match: fileLoaderMatch } = getLoader( + webpackConfig, + (rule) => rule.type === "asset/resource" + ); + + if (!isFound) { + throw new Error( + `Can't find resource loader in the ${context.env} webpack config!` + ); + } + + fileLoaderMatch.loader.exclude.push(/\.ya?ml$/); + + const yamlLoader = { + use: "yaml-loader", + test: /\.(ya?ml)$/, + }; + webpackConfig.module.rules.push(yamlLoader); + return webpackConfig; + }, + }, + }, + ], +}; diff --git a/dont-starve-airdrop-client/package.json b/dont-starve-airdrop-client/package.json index f67d6cc..9a3c1da 100644 --- a/dont-starve-airdrop-client/package.json +++ b/dont-starve-airdrop-client/package.json @@ -5,6 +5,7 @@ "author": "mutoo ", "license": "MIT", "dependencies": { + "@craco/craco": "^7.1.0", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", @@ -14,14 +15,16 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1", + "tailwindcss": "^3.3.3", "uuid": "^9.0.1", - "web-vitals": "^2.1.4" + "web-vitals": "^2.1.4", + "yaml-loader": "^0.8.1" }, "scripts": { - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test", - "eject": "react-scripts eject" + "start": "craco start", + "build": "craco build", + "test": "craco test", + "eject": "craco eject" }, "eslintConfig": { "extends": [ @@ -40,8 +43,5 @@ "last 1 firefox version", "last 1 safari version" ] - }, - "devDependencies": { - "tailwindcss": "^3.3.3" } } diff --git a/dont-starve-airdrop-client/src/App.js b/dont-starve-airdrop-client/src/App.js index 90e871a..4e68077 100644 --- a/dont-starve-airdrop-client/src/App.js +++ b/dont-starve-airdrop-client/src/App.js @@ -6,7 +6,7 @@ import useWebsocket from "./hooks/ws"; import airdropState from "./state"; import Draft from "./components/Draft"; import History from "./components/History"; -import { inventory } from "./config"; +import config from "./config.yml"; import { getInventoryImage } from "./utils/image"; import styles from "./App.module.css"; import BuyMeCoffee from "./components/BuyMeCoffee"; @@ -23,7 +23,7 @@ function App() { ); } - const fav = inventory.categories.filter( + const fav = config.inventory.categories.filter( (category) => category.type === categoryType )[0]; @@ -33,7 +33,7 @@ function App() {

# Categories

- {inventory.categories.map((category) => { + {config.inventory.categories.map((category) => { return (