Compare commits

..
7 Commits
12 changed files with 512 additions and 819 deletions

No files matched your search

+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
java-version: '17'
# Build plugin
- name: Build with Maven
+2 -9
View File
@@ -22,7 +22,7 @@ jobs:
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
java-version: '17'
# Build plugin
- name: Build with Maven
@@ -33,14 +33,7 @@ jobs:
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: |
${{
startsWith(matrix.version, '1.16') && '11' ||
startsWith(matrix.version, '1.17') && '16' ||
startsWith(matrix.version, '1.18') && '17' ||
startsWith(matrix.version, '1.19') && '17' ||
'21'
}}
java-version: ${{ startsWith(matrix.version, '1.16') && '11' || (startsWith(matrix.version, '1.17') && '16' || '17') }}
# Setup Node.js
- name: Setup Node.js
+193 -158
View File
@@ -6,43 +6,43 @@
"": {
"name": "@yamipa/automata",
"dependencies": {
"mineflayer": "^4.20.1",
"rcon-client": "^4.2.4"
"mineflayer": "^4.14.0",
"rcon-client": "^4.2.3"
}
},
"node_modules/@azure/msal-common": {
"version": "14.10.0",
"resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.10.0.tgz",
"integrity": "sha512-Zk6DPDz7e1wPgLoLgAp0349Yay9RvcjPM5We/ehuenDNsz/t9QEFI7tRoHpp/e47I4p20XE3FiDlhKwAo3utDA==",
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.1.0.tgz",
"integrity": "sha512-xphmhcfl5VL+uq5//VKMwQn+wfEZLMKNpFCcMi8Ur8ej5UT166g6chBsxgMzc9xo9Y24R9FB3m/tjDiV03xMIA==",
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/@azure/msal-node": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.8.1.tgz",
"integrity": "sha512-VcZZM+5VvCWRBTOF7SxMKaxrz+EXjntx2u5AQe7QE06e6FuPJElGBrImgNgCh5QmFaNCfVFO+3qNR7UoFD/Gfw==",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.2.0.tgz",
"integrity": "sha512-aZZ1m7OATOR9kz7+/Kl+/LZrNEj+HYaEH84XZfnBtN/9JPRazngk1XTjvAkh7W1u/O/yQrlYiiSwSAKHnNBc8A==",
"dependencies": {
"@azure/msal-common": "14.10.0",
"@azure/msal-common": "14.1.0",
"jsonwebtoken": "^9.0.0",
"uuid": "^8.3.0"
},
"engines": {
"node": ">=16"
"node": "18 || 20"
}
},
"node_modules/@types/node": {
"version": "20.12.12",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz",
"integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==",
"version": "20.8.6",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz",
"integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==",
"dependencies": {
"undici-types": "~5.26.4"
"undici-types": "~5.25.1"
}
},
"node_modules/@types/readable-stream": {
"version": "4.0.14",
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.14.tgz",
"integrity": "sha512-xZn/AuUbCMShGsqH/ehZtGDwQtbx00M9rZ2ENLe4tOjFZ/JFeWMhEZkk2fEe1jAUqqEAURIkFJ7Az/go8mM1/w==",
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.3.tgz",
"integrity": "sha512-Z8BOzyIj3UPpn3j5DmDNKIw4wPN9N8a1d1oyteiprWq+wxdgQNC0UfFAQwWjmjyA7uoj7mvoWgxWWH66zYtm4Q==",
"dependencies": {
"@types/node": "*",
"safe-buffer": "~5.1.1"
@@ -230,9 +230,9 @@
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
},
"node_modules/follow-redirects": {
"version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
"version": "1.15.3",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
"integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==",
"funding": [
{
"type": "individual",
@@ -273,9 +273,9 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/jose": {
"version": "4.15.5",
"resolved": "https://registry.npmjs.org/jose/-/jose-4.15.5.tgz",
"integrity": "sha512-jc7BFxgKPKi94uOvEmzlSWFFe2+vASyXaKUpdQKatWAESU2MWjDfFf0fdfc83CDKcA5QecabZeNLyfhe3yKNkg==",
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/jose/-/jose-4.15.3.tgz",
"integrity": "sha512-RZJdL9Qjd1sqNdyiVteRGV/bnWtik/+PJh1JP4kT6+x1QQMn+7ryueRys5BEueuayvSVY8CWGCisCDazeRLTuw==",
"funding": {
"url": "https://github.com/sponsors/panva"
}
@@ -375,15 +375,26 @@
"resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz",
"integrity": "sha512-6raRe2vxCYBhpBu+B+TtNGUzah+hQjVdu3E17wfusjyrXBka2nBS8OH/gjVZ5PvHOhWmIZTYri09Z6n/QfnNMw=="
},
"node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/macaddress": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.5.3.tgz",
"integrity": "sha512-vGBKTA+jwM4KgjGZ+S/8/Mkj9rWzePyGY6jManXPGhiWu63RYwW8dKPyk5koP+8qNVhPhHgFa1y/MJ4wrjsNrg=="
},
"node_modules/minecraft-data": {
"version": "3.65.0",
"resolved": "https://registry.npmjs.org/minecraft-data/-/minecraft-data-3.65.0.tgz",
"integrity": "sha512-9K8dOrdrcpUklTdqKBtRcKur0gLZnguTvhM/1Xv52qzh8Unkto4290RJc4ueRIYo1VqN4zzQrRxO8lnqtkERDQ=="
"version": "3.46.2",
"resolved": "https://registry.npmjs.org/minecraft-data/-/minecraft-data-3.46.2.tgz",
"integrity": "sha512-vunI/l5mqjU7FisB5iFxcNl6BkKLzELUvsP5P4gpUOAUtTWXEUYTnVg9jdIFOl7Y2zw3TxG2RHDa0h0ScnRCEA=="
},
"node_modules/minecraft-folder-path": {
"version": "1.2.0",
@@ -391,9 +402,9 @@
"integrity": "sha512-qaUSbKWoOsH9brn0JQuBhxNAzTDMwrOXorwuRxdJKKKDYvZhtml+6GVCUrY5HRiEsieBEjCUnhVpDuQiKsiFaw=="
},
"node_modules/minecraft-protocol": {
"version": "1.47.0",
"resolved": "https://registry.npmjs.org/minecraft-protocol/-/minecraft-protocol-1.47.0.tgz",
"integrity": "sha512-IHL8faXLLIWv1O+2v2NgyKlooilu/OiSL9orI8Kqed/rZvVOrFPzs2PwMAYjpQX9gxLPhiSU19KqZ8CjfNuqhg==",
"version": "1.44.0",
"resolved": "https://registry.npmjs.org/minecraft-protocol/-/minecraft-protocol-1.44.0.tgz",
"integrity": "sha512-sYu4fFzUKt3spPG5tAdkaB9sNQPT0sV6fyS0sS7/nxdzFfjmLhF6BLNC+32ieK4/MhgNyHtH6xusD0Bi0Roq9w==",
"dependencies": {
"@types/readable-stream": "^4.0.0",
"aes-js": "^3.1.2",
@@ -402,13 +413,12 @@
"endian-toggle": "^0.0.0",
"lodash.get": "^4.1.2",
"lodash.merge": "^4.3.0",
"minecraft-data": "^3.55.0",
"minecraft-data": "^3.37.0",
"minecraft-folder-path": "^1.2.0",
"node-fetch": "^2.6.1",
"node-rsa": "^0.4.2",
"prismarine-auth": "^2.2.0",
"prismarine-chat": "^1.10.0",
"prismarine-nbt": "^2.5.0",
"prismarine-nbt": "^2.0.0",
"prismarine-realms": "^1.2.0",
"protodef": "^1.8.0",
"readable-stream": "^4.1.0",
@@ -420,12 +430,12 @@
}
},
"node_modules/mineflayer": {
"version": "4.20.1",
"resolved": "https://registry.npmjs.org/mineflayer/-/mineflayer-4.20.1.tgz",
"integrity": "sha512-QMMNPx4IyZE7ydAzjvGLQLCnQNUOfkk1qVZKxTTS9q3qPTAewz4GhsVUBtbQ8LSbHthe5RcQ1Sgxs4wlIma/Qw==",
"version": "4.14.0",
"resolved": "https://registry.npmjs.org/mineflayer/-/mineflayer-4.14.0.tgz",
"integrity": "sha512-4EYzUmZNxH3Gpz3GkgO2eaR90ANb50nVhMCU2y6Rl1Ru8M6HqxID1Eg7tRgsodfAOD+AKh5SPwmPnISLcxvnOA==",
"dependencies": {
"minecraft-data": "^3.56.0",
"minecraft-protocol": "^1.47.0",
"minecraft-data": "^3.44.0",
"minecraft-protocol": "^1.44.0",
"prismarine-biome": "^1.1.1",
"prismarine-block": "^1.17.0",
"prismarine-chat": "^1.7.1",
@@ -436,14 +446,14 @@
"prismarine-physics": "^1.8.0",
"prismarine-recipe": "^1.3.0",
"prismarine-registry": "^1.5.0",
"prismarine-windows": "^2.9.0",
"prismarine-windows": "^2.8.0",
"prismarine-world": "^3.6.0",
"protodef": "^1.14.0",
"typed-emitter": "^1.0.0",
"vec3": "^0.1.7"
},
"engines": {
"node": ">=18"
"node": ">=14"
}
},
"node_modules/mojangson": {
@@ -513,9 +523,9 @@
}
},
"node_modules/prismarine-auth": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/prismarine-auth/-/prismarine-auth-2.4.2.tgz",
"integrity": "sha512-Cq4woGobnFYYfMBDh1WITW+Vs98toN91qAFBvBitwV7IwJaiSAh2Nl+WPUEGeg5eLBoSPpSyCVT8P2oi7Cav8g==",
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/prismarine-auth/-/prismarine-auth-2.3.0.tgz",
"integrity": "sha512-giKZiHwuQdpMJ7KX94UncOJqM3u+yqKIR2UI/rqmdmFUuQilV9vhlz/zehpVkvo7FE8gmZsuUMCUPhI+gtgd3A==",
"dependencies": {
"@azure/msal-node": "^2.0.2",
"@xboxreplay/xboxlive-auth": "^3.3.3",
@@ -536,9 +546,9 @@
}
},
"node_modules/prismarine-block": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/prismarine-block/-/prismarine-block-1.17.1.tgz",
"integrity": "sha512-r1TIn/b5v77BX4a+qd+Yv+4/vZpsC/Jp5ElYxd6++2wpCnqiuxVG7BlS2Eo14vez1M2gt3qoNEl54Hr8qox/rQ==",
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/prismarine-block/-/prismarine-block-1.17.0.tgz",
"integrity": "sha512-GawzWU91pH4sLTtMvrRe2wiEbO8hgTRwViCBYoFmmqeJYLiblq4GfXOvclj3rEAEdAAVzRKCQxQHpLJhhLWssg==",
"dependencies": {
"minecraft-data": "^3.38.0",
"prismarine-biome": "^1.1.0",
@@ -549,19 +559,20 @@
}
},
"node_modules/prismarine-chat": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/prismarine-chat/-/prismarine-chat-1.10.1.tgz",
"integrity": "sha512-XukYcuueuhDxzEXG7r8BZyt6jOObrPPB4JESCgb+/XenB9nExoSHF8eTQWWj8faKPLqm1dRQaYwFJlNBlJZJUw==",
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/prismarine-chat/-/prismarine-chat-1.8.0.tgz",
"integrity": "sha512-hEz47GESIEP0W1KSHrK7ZSy0PqbQW7khYWenv8d5wvyAYnBs1E4KXDBJSWqyGIYinKGN9aes8v3xpQhgURK/Fg==",
"dependencies": {
"mojangson": "^2.0.1",
"prismarine-item": "^1.10.0",
"prismarine-nbt": "^2.0.0",
"prismarine-registry": "^1.4.0"
}
},
"node_modules/prismarine-chunk": {
"version": "1.35.0",
"resolved": "https://registry.npmjs.org/prismarine-chunk/-/prismarine-chunk-1.35.0.tgz",
"integrity": "sha512-Q1lElMUle7wWxWdQjbZo3j2/dLNG325j90IcbbMmBTnHdQSWIjWFe792XOz3RVBlvrhRJEiZk38S6/eQTQ9esw==",
"version": "1.34.0",
"resolved": "https://registry.npmjs.org/prismarine-chunk/-/prismarine-chunk-1.34.0.tgz",
"integrity": "sha512-5RuQk8w9Ot550G5mmUFZvjpHugEXozgEFXiAhynrBCHOKJ3mMQ7VvhWF2irtjx+d2t29yDAiSEiSS34vxAmODQ==",
"dependencies": {
"prismarine-biome": "^1.2.0",
"prismarine-block": "^1.14.1",
@@ -577,9 +588,9 @@
}
},
"node_modules/prismarine-entity": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/prismarine-entity/-/prismarine-entity-2.4.0.tgz",
"integrity": "sha512-DBwjmoCX1IYAhN99KwYkk2rMArn65JHTzuuGXchr4GLWQs7UN4Pf9tELqBwNOu4r57x3RaW0+9+0sI3FvJQWzQ==",
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/prismarine-entity/-/prismarine-entity-2.3.1.tgz",
"integrity": "sha512-HOv8l7IetHNf4hwZ7V/W4vM3GNl+e6VCtKDkH9h02TRq7jWngsggKtJV+VanCce/sNwtJUhJDjORGs728ep4MA==",
"dependencies": {
"prismarine-chat": "^1.4.1",
"prismarine-item": "^1.11.2",
@@ -597,9 +608,9 @@
}
},
"node_modules/prismarine-nbt": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/prismarine-nbt/-/prismarine-nbt-2.5.0.tgz",
"integrity": "sha512-F0/8UAa9SDDnAGrBYqZc4nG8h2zj5cE2eAJU5xlDR/IsQQ3moVxkOjE3h3nMv6SbvZrvAcgX7waA/nd9LLHYdA==",
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/prismarine-nbt/-/prismarine-nbt-2.2.1.tgz",
"integrity": "sha512-Mb50c58CPnuZ+qvM31DBa08tf9UumlTq1LkvpMoUpKfCuN05GZHTqCUwER3lxTSHLL0GZKghIPbYR/JQkINijQ==",
"dependencies": {
"protodef": "^1.9.0"
}
@@ -641,9 +652,9 @@
}
},
"node_modules/prismarine-windows": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/prismarine-windows/-/prismarine-windows-2.9.0.tgz",
"integrity": "sha512-fm4kOLjGFPov7TEJRmXHoiPabxIQrG36r2mDjlNxfkcLfMHFb3/1ML6mp4iRQa7wL0GK4DIAyiBqCWoeWDxARg==",
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/prismarine-windows/-/prismarine-windows-2.8.0.tgz",
"integrity": "sha512-9HVhJ8tfCeRubYwQzgz8oiHNAebMJ5hDdjm45PZwrOgewaislnR2HDsbPMWiCcyWkYL7J8bVLVoSzEzv5pH98g==",
"dependencies": {
"prismarine-item": "^1.12.2",
"prismarine-registry": "^1.7.0",
@@ -662,9 +673,9 @@
}
},
"node_modules/prismarine-world": {
"version": "3.6.3",
"resolved": "https://registry.npmjs.org/prismarine-world/-/prismarine-world-3.6.3.tgz",
"integrity": "sha512-zqdqPEYCDHzqi6hglJldEO63bOROXpbZeIdxBmoQq7o04Lf81t016LU6stFHo3E+bmp5+xU74eDFdOvzYNABkA==",
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/prismarine-world/-/prismarine-world-3.6.2.tgz",
"integrity": "sha512-xNNo3bd8EnCMjiPbVrh3jYa1Upa8Krkb13BgO7FOOfD5ZYf+iYDZewBtDbHYWzZZB2N0JlTtimMOHRhZhDJirw==",
"dependencies": {
"vec3": "^0.1.7"
},
@@ -719,9 +730,9 @@
}
},
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
"engines": {
"node": ">=6"
}
@@ -744,9 +755,9 @@
}
},
"node_modules/rcon-client": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/rcon-client/-/rcon-client-4.2.4.tgz",
"integrity": "sha512-sTHYLbcu2qrrOX4TOD3rvcLZNs7xiAhTsnZZIvxviSpa0yeV63sPAVI0PeScn5IvhKOCMURGt1NmnQ8h/GxjtA==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/rcon-client/-/rcon-client-4.2.3.tgz",
"integrity": "sha512-g+DEzI3O0Nl4Y3mPp6DHhSpYeiv+wTq8iKxCumFGO0/SMCsdNfx9bpT5RyHa7phR5dvspKfQK0ZYJp1YCtXNng==",
"dependencies": {
"typed-emitter": "^0.1.0"
}
@@ -757,9 +768,9 @@
"integrity": "sha512-Tfay0l6gJMP5rkil8CzGbLthukn+9BN/VXWcABVFPjOoelJ+koW8BuPZYk+h/L+lEeIp1fSzVRiWRPIjKVjPdg=="
},
"node_modules/readable-stream": {
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz",
"integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==",
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz",
"integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==",
"dependencies": {
"abort-controller": "^3.0.0",
"buffer": "^6.0.3",
@@ -794,9 +805,12 @@
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"node_modules/semver": {
"version": "7.6.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
"integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
@@ -862,9 +876,9 @@
"integrity": "sha512-lhEx78gdTwFWG+mt6cWAZD/R6qrIj0TTBeH5xwyuDJyswLNlGe+KVlUPQ6+mx5Ld332pS0AMUTo9hIly7YsWxQ=="
},
"node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
"version": "5.25.3",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz",
"integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA=="
},
"node_modules/uri-js": {
"version": "4.4.1",
@@ -896,9 +910,9 @@
}
},
"node_modules/vec3": {
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/vec3/-/vec3-0.1.10.tgz",
"integrity": "sha512-Sr1U3mYtMqCOonGd3LAN9iqy0qF6C+Gjil92awyK/i2OwiUo9bm7PnLgFpafymun50mOjnDcg4ToTgRssrlTcw=="
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/vec3/-/vec3-0.1.8.tgz",
"integrity": "sha512-LfKrP625Bsg/Tj52YdYPsHmpsJuo+tc6fLxZxXjEo9k2xSspKlPvoYTHehykKhp1FvV9nm+XU3Ehej5/9tpDCg=="
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
@@ -919,6 +933,11 @@
"resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-0.4.2.tgz",
"integrity": "sha512-/eyHVRJQCirEkSZ1agRSCwriMhwlyUcFkXD5TPVSLP+IPzjsqMVzZwdoczLp1SoQU0R3dxz1RpIK+4YNQbCVOA=="
},
"node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/yggdrasil": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/yggdrasil/-/yggdrasil-1.7.0.tgz",
@@ -931,32 +950,32 @@
},
"dependencies": {
"@azure/msal-common": {
"version": "14.10.0",
"resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.10.0.tgz",
"integrity": "sha512-Zk6DPDz7e1wPgLoLgAp0349Yay9RvcjPM5We/ehuenDNsz/t9QEFI7tRoHpp/e47I4p20XE3FiDlhKwAo3utDA=="
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.1.0.tgz",
"integrity": "sha512-xphmhcfl5VL+uq5//VKMwQn+wfEZLMKNpFCcMi8Ur8ej5UT166g6chBsxgMzc9xo9Y24R9FB3m/tjDiV03xMIA=="
},
"@azure/msal-node": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.8.1.tgz",
"integrity": "sha512-VcZZM+5VvCWRBTOF7SxMKaxrz+EXjntx2u5AQe7QE06e6FuPJElGBrImgNgCh5QmFaNCfVFO+3qNR7UoFD/Gfw==",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.2.0.tgz",
"integrity": "sha512-aZZ1m7OATOR9kz7+/Kl+/LZrNEj+HYaEH84XZfnBtN/9JPRazngk1XTjvAkh7W1u/O/yQrlYiiSwSAKHnNBc8A==",
"requires": {
"@azure/msal-common": "14.10.0",
"@azure/msal-common": "14.1.0",
"jsonwebtoken": "^9.0.0",
"uuid": "^8.3.0"
}
},
"@types/node": {
"version": "20.12.12",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz",
"integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==",
"version": "20.8.6",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz",
"integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==",
"requires": {
"undici-types": "~5.26.4"
"undici-types": "~5.25.1"
}
},
"@types/readable-stream": {
"version": "4.0.14",
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.14.tgz",
"integrity": "sha512-xZn/AuUbCMShGsqH/ehZtGDwQtbx00M9rZ2ENLe4tOjFZ/JFeWMhEZkk2fEe1jAUqqEAURIkFJ7Az/go8mM1/w==",
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.3.tgz",
"integrity": "sha512-Z8BOzyIj3UPpn3j5DmDNKIw4wPN9N8a1d1oyteiprWq+wxdgQNC0UfFAQwWjmjyA7uoj7mvoWgxWWH66zYtm4Q==",
"requires": {
"@types/node": "*",
"safe-buffer": "~5.1.1"
@@ -1089,9 +1108,9 @@
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
},
"follow-redirects": {
"version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA=="
"version": "1.15.3",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
"integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q=="
},
"ieee754": {
"version": "1.2.1",
@@ -1104,9 +1123,9 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"jose": {
"version": "4.15.5",
"resolved": "https://registry.npmjs.org/jose/-/jose-4.15.5.tgz",
"integrity": "sha512-jc7BFxgKPKi94uOvEmzlSWFFe2+vASyXaKUpdQKatWAESU2MWjDfFf0fdfc83CDKcA5QecabZeNLyfhe3yKNkg=="
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/jose/-/jose-4.15.3.tgz",
"integrity": "sha512-RZJdL9Qjd1sqNdyiVteRGV/bnWtik/+PJh1JP4kT6+x1QQMn+7ryueRys5BEueuayvSVY8CWGCisCDazeRLTuw=="
},
"json-schema-traverse": {
"version": "0.4.1",
@@ -1199,15 +1218,23 @@
"resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz",
"integrity": "sha512-6raRe2vxCYBhpBu+B+TtNGUzah+hQjVdu3E17wfusjyrXBka2nBS8OH/gjVZ5PvHOhWmIZTYri09Z6n/QfnNMw=="
},
"lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"requires": {
"yallist": "^4.0.0"
}
},
"macaddress": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.5.3.tgz",
"integrity": "sha512-vGBKTA+jwM4KgjGZ+S/8/Mkj9rWzePyGY6jManXPGhiWu63RYwW8dKPyk5koP+8qNVhPhHgFa1y/MJ4wrjsNrg=="
},
"minecraft-data": {
"version": "3.65.0",
"resolved": "https://registry.npmjs.org/minecraft-data/-/minecraft-data-3.65.0.tgz",
"integrity": "sha512-9K8dOrdrcpUklTdqKBtRcKur0gLZnguTvhM/1Xv52qzh8Unkto4290RJc4ueRIYo1VqN4zzQrRxO8lnqtkERDQ=="
"version": "3.46.2",
"resolved": "https://registry.npmjs.org/minecraft-data/-/minecraft-data-3.46.2.tgz",
"integrity": "sha512-vunI/l5mqjU7FisB5iFxcNl6BkKLzELUvsP5P4gpUOAUtTWXEUYTnVg9jdIFOl7Y2zw3TxG2RHDa0h0ScnRCEA=="
},
"minecraft-folder-path": {
"version": "1.2.0",
@@ -1215,9 +1242,9 @@
"integrity": "sha512-qaUSbKWoOsH9brn0JQuBhxNAzTDMwrOXorwuRxdJKKKDYvZhtml+6GVCUrY5HRiEsieBEjCUnhVpDuQiKsiFaw=="
},
"minecraft-protocol": {
"version": "1.47.0",
"resolved": "https://registry.npmjs.org/minecraft-protocol/-/minecraft-protocol-1.47.0.tgz",
"integrity": "sha512-IHL8faXLLIWv1O+2v2NgyKlooilu/OiSL9orI8Kqed/rZvVOrFPzs2PwMAYjpQX9gxLPhiSU19KqZ8CjfNuqhg==",
"version": "1.44.0",
"resolved": "https://registry.npmjs.org/minecraft-protocol/-/minecraft-protocol-1.44.0.tgz",
"integrity": "sha512-sYu4fFzUKt3spPG5tAdkaB9sNQPT0sV6fyS0sS7/nxdzFfjmLhF6BLNC+32ieK4/MhgNyHtH6xusD0Bi0Roq9w==",
"requires": {
"@types/readable-stream": "^4.0.0",
"aes-js": "^3.1.2",
@@ -1226,13 +1253,12 @@
"endian-toggle": "^0.0.0",
"lodash.get": "^4.1.2",
"lodash.merge": "^4.3.0",
"minecraft-data": "^3.55.0",
"minecraft-data": "^3.37.0",
"minecraft-folder-path": "^1.2.0",
"node-fetch": "^2.6.1",
"node-rsa": "^0.4.2",
"prismarine-auth": "^2.2.0",
"prismarine-chat": "^1.10.0",
"prismarine-nbt": "^2.5.0",
"prismarine-nbt": "^2.0.0",
"prismarine-realms": "^1.2.0",
"protodef": "^1.8.0",
"readable-stream": "^4.1.0",
@@ -1241,12 +1267,12 @@
}
},
"mineflayer": {
"version": "4.20.1",
"resolved": "https://registry.npmjs.org/mineflayer/-/mineflayer-4.20.1.tgz",
"integrity": "sha512-QMMNPx4IyZE7ydAzjvGLQLCnQNUOfkk1qVZKxTTS9q3qPTAewz4GhsVUBtbQ8LSbHthe5RcQ1Sgxs4wlIma/Qw==",
"version": "4.14.0",
"resolved": "https://registry.npmjs.org/mineflayer/-/mineflayer-4.14.0.tgz",
"integrity": "sha512-4EYzUmZNxH3Gpz3GkgO2eaR90ANb50nVhMCU2y6Rl1Ru8M6HqxID1Eg7tRgsodfAOD+AKh5SPwmPnISLcxvnOA==",
"requires": {
"minecraft-data": "^3.56.0",
"minecraft-protocol": "^1.47.0",
"minecraft-data": "^3.44.0",
"minecraft-protocol": "^1.44.0",
"prismarine-biome": "^1.1.1",
"prismarine-block": "^1.17.0",
"prismarine-chat": "^1.7.1",
@@ -1257,7 +1283,7 @@
"prismarine-physics": "^1.8.0",
"prismarine-recipe": "^1.3.0",
"prismarine-registry": "^1.5.0",
"prismarine-windows": "^2.9.0",
"prismarine-windows": "^2.8.0",
"prismarine-world": "^3.6.0",
"protodef": "^1.14.0",
"typed-emitter": "^1.0.0",
@@ -1310,9 +1336,9 @@
}
},
"prismarine-auth": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/prismarine-auth/-/prismarine-auth-2.4.2.tgz",
"integrity": "sha512-Cq4woGobnFYYfMBDh1WITW+Vs98toN91qAFBvBitwV7IwJaiSAh2Nl+WPUEGeg5eLBoSPpSyCVT8P2oi7Cav8g==",
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/prismarine-auth/-/prismarine-auth-2.3.0.tgz",
"integrity": "sha512-giKZiHwuQdpMJ7KX94UncOJqM3u+yqKIR2UI/rqmdmFUuQilV9vhlz/zehpVkvo7FE8gmZsuUMCUPhI+gtgd3A==",
"requires": {
"@azure/msal-node": "^2.0.2",
"@xboxreplay/xboxlive-auth": "^3.3.3",
@@ -1330,9 +1356,9 @@
"requires": {}
},
"prismarine-block": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/prismarine-block/-/prismarine-block-1.17.1.tgz",
"integrity": "sha512-r1TIn/b5v77BX4a+qd+Yv+4/vZpsC/Jp5ElYxd6++2wpCnqiuxVG7BlS2Eo14vez1M2gt3qoNEl54Hr8qox/rQ==",
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/prismarine-block/-/prismarine-block-1.17.0.tgz",
"integrity": "sha512-GawzWU91pH4sLTtMvrRe2wiEbO8hgTRwViCBYoFmmqeJYLiblq4GfXOvclj3rEAEdAAVzRKCQxQHpLJhhLWssg==",
"requires": {
"minecraft-data": "^3.38.0",
"prismarine-biome": "^1.1.0",
@@ -1343,19 +1369,20 @@
}
},
"prismarine-chat": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/prismarine-chat/-/prismarine-chat-1.10.1.tgz",
"integrity": "sha512-XukYcuueuhDxzEXG7r8BZyt6jOObrPPB4JESCgb+/XenB9nExoSHF8eTQWWj8faKPLqm1dRQaYwFJlNBlJZJUw==",
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/prismarine-chat/-/prismarine-chat-1.8.0.tgz",
"integrity": "sha512-hEz47GESIEP0W1KSHrK7ZSy0PqbQW7khYWenv8d5wvyAYnBs1E4KXDBJSWqyGIYinKGN9aes8v3xpQhgURK/Fg==",
"requires": {
"mojangson": "^2.0.1",
"prismarine-item": "^1.10.0",
"prismarine-nbt": "^2.0.0",
"prismarine-registry": "^1.4.0"
}
},
"prismarine-chunk": {
"version": "1.35.0",
"resolved": "https://registry.npmjs.org/prismarine-chunk/-/prismarine-chunk-1.35.0.tgz",
"integrity": "sha512-Q1lElMUle7wWxWdQjbZo3j2/dLNG325j90IcbbMmBTnHdQSWIjWFe792XOz3RVBlvrhRJEiZk38S6/eQTQ9esw==",
"version": "1.34.0",
"resolved": "https://registry.npmjs.org/prismarine-chunk/-/prismarine-chunk-1.34.0.tgz",
"integrity": "sha512-5RuQk8w9Ot550G5mmUFZvjpHugEXozgEFXiAhynrBCHOKJ3mMQ7VvhWF2irtjx+d2t29yDAiSEiSS34vxAmODQ==",
"requires": {
"prismarine-biome": "^1.2.0",
"prismarine-block": "^1.14.1",
@@ -1368,9 +1395,9 @@
}
},
"prismarine-entity": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/prismarine-entity/-/prismarine-entity-2.4.0.tgz",
"integrity": "sha512-DBwjmoCX1IYAhN99KwYkk2rMArn65JHTzuuGXchr4GLWQs7UN4Pf9tELqBwNOu4r57x3RaW0+9+0sI3FvJQWzQ==",
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/prismarine-entity/-/prismarine-entity-2.3.1.tgz",
"integrity": "sha512-HOv8l7IetHNf4hwZ7V/W4vM3GNl+e6VCtKDkH9h02TRq7jWngsggKtJV+VanCce/sNwtJUhJDjORGs728ep4MA==",
"requires": {
"prismarine-chat": "^1.4.1",
"prismarine-item": "^1.11.2",
@@ -1388,9 +1415,9 @@
}
},
"prismarine-nbt": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/prismarine-nbt/-/prismarine-nbt-2.5.0.tgz",
"integrity": "sha512-F0/8UAa9SDDnAGrBYqZc4nG8h2zj5cE2eAJU5xlDR/IsQQ3moVxkOjE3h3nMv6SbvZrvAcgX7waA/nd9LLHYdA==",
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/prismarine-nbt/-/prismarine-nbt-2.2.1.tgz",
"integrity": "sha512-Mb50c58CPnuZ+qvM31DBa08tf9UumlTq1LkvpMoUpKfCuN05GZHTqCUwER3lxTSHLL0GZKghIPbYR/JQkINijQ==",
"requires": {
"protodef": "^1.9.0"
}
@@ -1430,9 +1457,9 @@
}
},
"prismarine-windows": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/prismarine-windows/-/prismarine-windows-2.9.0.tgz",
"integrity": "sha512-fm4kOLjGFPov7TEJRmXHoiPabxIQrG36r2mDjlNxfkcLfMHFb3/1ML6mp4iRQa7wL0GK4DIAyiBqCWoeWDxARg==",
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/prismarine-windows/-/prismarine-windows-2.8.0.tgz",
"integrity": "sha512-9HVhJ8tfCeRubYwQzgz8oiHNAebMJ5hDdjm45PZwrOgewaislnR2HDsbPMWiCcyWkYL7J8bVLVoSzEzv5pH98g==",
"requires": {
"prismarine-item": "^1.12.2",
"prismarine-registry": "^1.7.0",
@@ -1450,9 +1477,9 @@
}
},
"prismarine-world": {
"version": "3.6.3",
"resolved": "https://registry.npmjs.org/prismarine-world/-/prismarine-world-3.6.3.tgz",
"integrity": "sha512-zqdqPEYCDHzqi6hglJldEO63bOROXpbZeIdxBmoQq7o04Lf81t016LU6stFHo3E+bmp5+xU74eDFdOvzYNABkA==",
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/prismarine-world/-/prismarine-world-3.6.2.tgz",
"integrity": "sha512-xNNo3bd8EnCMjiPbVrh3jYa1Upa8Krkb13BgO7FOOfD5ZYf+iYDZewBtDbHYWzZZB2N0JlTtimMOHRhZhDJirw==",
"requires": {
"vec3": "^0.1.7"
}
@@ -1494,9 +1521,9 @@
}
},
"punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA=="
},
"railroad-diagrams": {
"version": "1.0.0",
@@ -1513,9 +1540,9 @@
}
},
"rcon-client": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/rcon-client/-/rcon-client-4.2.4.tgz",
"integrity": "sha512-sTHYLbcu2qrrOX4TOD3rvcLZNs7xiAhTsnZZIvxviSpa0yeV63sPAVI0PeScn5IvhKOCMURGt1NmnQ8h/GxjtA==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/rcon-client/-/rcon-client-4.2.3.tgz",
"integrity": "sha512-g+DEzI3O0Nl4Y3mPp6DHhSpYeiv+wTq8iKxCumFGO0/SMCsdNfx9bpT5RyHa7phR5dvspKfQK0ZYJp1YCtXNng==",
"requires": {
"typed-emitter": "^0.1.0"
},
@@ -1528,9 +1555,9 @@
}
},
"readable-stream": {
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz",
"integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==",
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz",
"integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==",
"requires": {
"abort-controller": "^3.0.0",
"buffer": "^6.0.3",
@@ -1559,9 +1586,12 @@
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"semver": {
"version": "7.6.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
"integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w=="
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"requires": {
"lru-cache": "^6.0.0"
}
},
"smart-buffer": {
"version": "4.2.0",
@@ -1605,9 +1635,9 @@
"integrity": "sha512-lhEx78gdTwFWG+mt6cWAZD/R6qrIj0TTBeH5xwyuDJyswLNlGe+KVlUPQ6+mx5Ld332pS0AMUTo9hIly7YsWxQ=="
},
"undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
"version": "5.25.3",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz",
"integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA=="
},
"uri-js": {
"version": "4.4.1",
@@ -1636,9 +1666,9 @@
}
},
"vec3": {
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/vec3/-/vec3-0.1.10.tgz",
"integrity": "sha512-Sr1U3mYtMqCOonGd3LAN9iqy0qF6C+Gjil92awyK/i2OwiUo9bm7PnLgFpafymun50mOjnDcg4ToTgRssrlTcw=="
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/vec3/-/vec3-0.1.8.tgz",
"integrity": "sha512-LfKrP625Bsg/Tj52YdYPsHmpsJuo+tc6fLxZxXjEo9k2xSspKlPvoYTHehykKhp1FvV9nm+XU3Ehej5/9tpDCg=="
},
"webidl-conversions": {
"version": "3.0.1",
@@ -1659,6 +1689,11 @@
"resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-0.4.2.tgz",
"integrity": "sha512-/eyHVRJQCirEkSZ1agRSCwriMhwlyUcFkXD5TPVSLP+IPzjsqMVzZwdoczLp1SoQU0R3dxz1RpIK+4YNQbCVOA=="
},
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"yggdrasil": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/yggdrasil/-/yggdrasil-1.7.0.tgz",
+2 -2
View File
@@ -6,7 +6,7 @@
"start": "node index.js"
},
"dependencies": {
"mineflayer": "^4.20.1",
"rcon-client": "^4.2.4"
"mineflayer": "^4.14.0",
"rcon-client": "^4.2.3"
}
}
+5 -5
View File
@@ -6,7 +6,7 @@
<groupId>io.josemmo.bukkit.plugin</groupId>
<artifactId>YamipaPlugin</artifactId>
<version>1.3.2-SNAPSHOT-b2</version>
<version>1.3.0</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
@@ -42,7 +42,7 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.20.6-R0.1-SNAPSHOT</version>
<version>1.20.4-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
@@ -97,7 +97,7 @@
<dependency>
<groupId>com.github.TechFortress</groupId>
<artifactId>GriefPrevention</artifactId>
<version>16.18.3</version>
<version>16.18.1</version>
<scope>provided</scope>
</dependency>
@@ -105,7 +105,7 @@
<dependency>
<groupId>com.github.TownyAdvanced</groupId>
<artifactId>towny</artifactId>
<version>0.100.2.11</version>
<version>0.100.0.9</version>
<scope>provided</scope>
</dependency>
@@ -113,7 +113,7 @@
<dependency>
<groupId>com.github.angeschossen</groupId>
<artifactId>LandsAPI</artifactId>
<version>7.1.12</version>
<version>6.42.0</version>
<scope>provided</scope>
</dependency>
@@ -76,127 +76,16 @@ public class WorldAreaId {
return distance / 4;
});
// Size 0 (1+1+1=3)
// ·|·
// XOX
// ·|·
if (size == 0) {
neighborhood = new WorldAreaId[]{
new WorldAreaId(world, x, z-1),
new WorldAreaId(world, x-1, z),
this,
new WorldAreaId(world, x+1, z),
new WorldAreaId(world, x, z+1),
};
return neighborhood;
}
// Size 1 (2+1+2=5)
// ·X|X·
// XX|XX
// XXOXX
// XX|XX
// ·X|X·
if (size == 1) {
neighborhood = new WorldAreaId[]{
new WorldAreaId(world, x-1, z-2),
new WorldAreaId(world, x, z-2),
new WorldAreaId(world, x+1, z-2),
new WorldAreaId(world, x-2, z-1),
new WorldAreaId(world, x-1, z-1),
new WorldAreaId(world, x, z-1),
new WorldAreaId(world, x+1, z-1),
new WorldAreaId(world, x+2, z-1),
new WorldAreaId(world, x-2, z),
new WorldAreaId(world, x-1, z),
this,
new WorldAreaId(world, x+1, z),
new WorldAreaId(world, x+2, z),
new WorldAreaId(world, x-2, z+1),
new WorldAreaId(world, x-1, z+1),
new WorldAreaId(world, x, z+1),
new WorldAreaId(world, x+1, z+1),
new WorldAreaId(world, x+2, z+1),
new WorldAreaId(world, x-1, z+2),
new WorldAreaId(world, x, z+2),
new WorldAreaId(world, x+1, z+2),
};
return neighborhood;
}
// Size 2 (3+1+3=7)
// ··X|X··
// ·XX|XX·
// XXX|XXX
// XXXOXXX
// XXX|XXX
// ·XX|XX·
// ··X|X··
if (size == 2) {
neighborhood = new WorldAreaId[]{
new WorldAreaId(world, x-1, z-3),
new WorldAreaId(world, x, z-3),
new WorldAreaId(world, x+1, z-3),
new WorldAreaId(world, x-2, z-2),
new WorldAreaId(world, x-1, z-2),
new WorldAreaId(world, x, z-2),
new WorldAreaId(world, x+1, z-2),
new WorldAreaId(world, x+2, z-2),
new WorldAreaId(world, x-3, z-1),
new WorldAreaId(world, x-2, z-1),
new WorldAreaId(world, x-1, z-1),
new WorldAreaId(world, x, z-1),
new WorldAreaId(world, x+1, z-1),
new WorldAreaId(world, x+2, z-1),
new WorldAreaId(world, x+3, z-1),
new WorldAreaId(world, x-3, z),
new WorldAreaId(world, x-2, z),
new WorldAreaId(world, x-1, z),
this,
new WorldAreaId(world, x+1, z),
new WorldAreaId(world, x+2, z),
new WorldAreaId(world, x+3, z),
new WorldAreaId(world, x-3, z+1),
new WorldAreaId(world, x-2, z+1),
new WorldAreaId(world, x-1, z+1),
new WorldAreaId(world, x, z+1),
new WorldAreaId(world, x+1, z+1),
new WorldAreaId(world, x+2, z+1),
new WorldAreaId(world, x+3, z+1),
new WorldAreaId(world, x-2, z+2),
new WorldAreaId(world, x-1, z+2),
new WorldAreaId(world, x, z+2),
new WorldAreaId(world, x+1, z+2),
new WorldAreaId(world, x+2, z+2),
new WorldAreaId(world, x-1, z+3),
new WorldAreaId(world, x, z+3),
new WorldAreaId(world, x+1, z+3),
};
return neighborhood;
}
// Size 3 (4+1+4=9)
// ···X|X···
// ·XXX|XXX·
// ·XXX|XXX·
// XXXX|XXXX
// Size 3 (16-chunks radius)
// ···XXX···
// ·XXXXXXX·
// ·XXXXXXX·
// XXXXXXXXX
// XXXXOXXXX
// XXXX|XXXX
// ·XXX|XXX·
// ·XXX|XXX·
// ···X|X···
// XXXXXXXXX
// ·XXXXXXX·
// ·XXXXXXX·
// ···XXX···
if (size == 3) {
neighborhood = new WorldAreaId[]{
new WorldAreaId(world, x-1, z-4),
@@ -272,126 +161,112 @@ public class WorldAreaId {
return neighborhood;
}
// Size ≥4 (5+1+5=11)
// ···XX|XX···
// ··XXX|XXX··
// ·XXXX|XXXX·
// XXXXX|XXXXX
// XXXXX|XXXXX
// XXXXXOXXXXX
// XXXXX|XXXXX
// XXXXX|XXXXX
// ·XXXX|XXXX·
// ··XXX|XXX··
// ···XX|XX···
// Size 2 (12-chunks radius)
// ··XXX··
// ·XXXXX·
// XXXXXXX
// XXXOXXX
// XXXXXXX
// ·XXXXX·
// ··XXX··
if (size == 2) {
neighborhood = new WorldAreaId[]{
new WorldAreaId(world, x-1, z-3),
new WorldAreaId(world, x, z-3),
new WorldAreaId(world, x+1, z-3),
new WorldAreaId(world, x-2, z-2),
new WorldAreaId(world, x-1, z-2),
new WorldAreaId(world, x, z-2),
new WorldAreaId(world, x+1, z-2),
new WorldAreaId(world, x+2, z-2),
new WorldAreaId(world, x-3, z-1),
new WorldAreaId(world, x-2, z-1),
new WorldAreaId(world, x-1, z-1),
new WorldAreaId(world, x, z-1),
new WorldAreaId(world, x+1, z-1),
new WorldAreaId(world, x+2, z-1),
new WorldAreaId(world, x+3, z-1),
new WorldAreaId(world, x-3, z),
new WorldAreaId(world, x-2, z),
new WorldAreaId(world, x-1, z),
this,
new WorldAreaId(world, x+1, z),
new WorldAreaId(world, x+2, z),
new WorldAreaId(world, x+3, z),
new WorldAreaId(world, x-3, z+1),
new WorldAreaId(world, x-2, z+1),
new WorldAreaId(world, x-1, z+1),
new WorldAreaId(world, x, z+1),
new WorldAreaId(world, x+1, z+1),
new WorldAreaId(world, x+2, z+1),
new WorldAreaId(world, x+3, z+1),
new WorldAreaId(world, x-2, z+2),
new WorldAreaId(world, x-1, z+2),
new WorldAreaId(world, x, z+2),
new WorldAreaId(world, x+1, z+2),
new WorldAreaId(world, x+2, z+2),
new WorldAreaId(world, x-1, z+3),
new WorldAreaId(world, x, z+3),
new WorldAreaId(world, x+1, z+3),
};
return neighborhood;
}
//// Size 1 (8-chunks radius)
// ·XXX·
// XXXXX
// XXOXX
// XXXXX
// ·XXX·
if (size == 1) {
neighborhood = new WorldAreaId[]{
new WorldAreaId(world, x-1, z-2),
new WorldAreaId(world, x, z-2),
new WorldAreaId(world, x+1, z-2),
new WorldAreaId(world, x-2, z-1),
new WorldAreaId(world, x-1, z-1),
new WorldAreaId(world, x, z-1),
new WorldAreaId(world, x+1, z-1),
new WorldAreaId(world, x+2, z-1),
new WorldAreaId(world, x-2, z),
new WorldAreaId(world, x-1, z),
this,
new WorldAreaId(world, x+1, z),
new WorldAreaId(world, x+2, z),
new WorldAreaId(world, x-2, z+1),
new WorldAreaId(world, x-1, z+1),
new WorldAreaId(world, x, z+1),
new WorldAreaId(world, x+1, z+1),
new WorldAreaId(world, x+2, z+1),
new WorldAreaId(world, x-1, z+2),
new WorldAreaId(world, x, z+2),
new WorldAreaId(world, x+1, z+2),
};
return neighborhood;
}
//// Size 0 (4x4 chunks)
// ·X·
// XOX
// ·X·
neighborhood = new WorldAreaId[]{
new WorldAreaId(world, x-2, z-5),
new WorldAreaId(world, x-1, z-5),
new WorldAreaId(world, x, z-5),
new WorldAreaId(world, x+1, z-5),
new WorldAreaId(world, x+2, z-5),
new WorldAreaId(world, x-3, z-4),
new WorldAreaId(world, x-2, z-4),
new WorldAreaId(world, x-1, z-4),
new WorldAreaId(world, x, z-4),
new WorldAreaId(world, x+1, z-4),
new WorldAreaId(world, x+2, z-4),
new WorldAreaId(world, x+3, z-4),
new WorldAreaId(world, x-4, z-3),
new WorldAreaId(world, x-3, z-3),
new WorldAreaId(world, x-2, z-3),
new WorldAreaId(world, x-1, z-3),
new WorldAreaId(world, x, z-3),
new WorldAreaId(world, x+1, z-3),
new WorldAreaId(world, x+2, z-3),
new WorldAreaId(world, x+3, z-3),
new WorldAreaId(world, x+4, z-3),
new WorldAreaId(world, x-5, z-2),
new WorldAreaId(world, x-4, z-2),
new WorldAreaId(world, x-3, z-2),
new WorldAreaId(world, x-2, z-2),
new WorldAreaId(world, x-1, z-2),
new WorldAreaId(world, x, z-2),
new WorldAreaId(world, x+1, z-2),
new WorldAreaId(world, x+2, z-2),
new WorldAreaId(world, x+3, z-2),
new WorldAreaId(world, x+4, z-2),
new WorldAreaId(world, x+5, z-2),
new WorldAreaId(world, x-5, z-1),
new WorldAreaId(world, x-4, z-1),
new WorldAreaId(world, x-3, z-1),
new WorldAreaId(world, x-2, z-1),
new WorldAreaId(world, x-1, z-1),
new WorldAreaId(world, x, z-1),
new WorldAreaId(world, x+1, z-1),
new WorldAreaId(world, x+2, z-1),
new WorldAreaId(world, x+3, z-1),
new WorldAreaId(world, x+4, z-1),
new WorldAreaId(world, x+5, z-1),
new WorldAreaId(world, x-5, z),
new WorldAreaId(world, x-4, z),
new WorldAreaId(world, x-3, z),
new WorldAreaId(world, x-2, z),
new WorldAreaId(world, x-1, z),
this,
new WorldAreaId(world, x+1, z),
new WorldAreaId(world, x+2, z),
new WorldAreaId(world, x+3, z),
new WorldAreaId(world, x+4, z),
new WorldAreaId(world, x+5, z),
new WorldAreaId(world, x-5, z+1),
new WorldAreaId(world, x-4, z+1),
new WorldAreaId(world, x-3, z+1),
new WorldAreaId(world, x-2, z+1),
new WorldAreaId(world, x-1, z+1),
new WorldAreaId(world, x, z+1),
new WorldAreaId(world, x+1, z+1),
new WorldAreaId(world, x+2, z+1),
new WorldAreaId(world, x+3, z+1),
new WorldAreaId(world, x+4, z+1),
new WorldAreaId(world, x+5, z+1),
new WorldAreaId(world, x-5, z+2),
new WorldAreaId(world, x-4, z+2),
new WorldAreaId(world, x-3, z+2),
new WorldAreaId(world, x-2, z+2),
new WorldAreaId(world, x-1, z+2),
new WorldAreaId(world, x, z+2),
new WorldAreaId(world, x+1, z+2),
new WorldAreaId(world, x+2, z+2),
new WorldAreaId(world, x+3, z+2),
new WorldAreaId(world, x+4, z+2),
new WorldAreaId(world, x+5, z+2),
new WorldAreaId(world, x-4, z+3),
new WorldAreaId(world, x-3, z+3),
new WorldAreaId(world, x-2, z+3),
new WorldAreaId(world, x-1, z+3),
new WorldAreaId(world, x, z+3),
new WorldAreaId(world, x+1, z+3),
new WorldAreaId(world, x+2, z+3),
new WorldAreaId(world, x+3, z+3),
new WorldAreaId(world, x+4, z+3),
new WorldAreaId(world, x-3, z+4),
new WorldAreaId(world, x-2, z+4),
new WorldAreaId(world, x-1, z+4),
new WorldAreaId(world, x, z+4),
new WorldAreaId(world, x+1, z+4),
new WorldAreaId(world, x+2, z+4),
new WorldAreaId(world, x+3, z+4),
new WorldAreaId(world, x-2, z+5),
new WorldAreaId(world, x-1, z+5),
new WorldAreaId(world, x, z+5),
new WorldAreaId(world, x+1, z+5),
new WorldAreaId(world, x+2, z+5),
};
return neighborhood;
}
@@ -114,7 +114,6 @@ public class CachedMapsFile extends SynchronizedFile {
private void load() {
// Try to load maps from disk
if (exists() && getLastModified() > imageFile.getLastModified()) {
LOGGER.fine("Found warm cache file \"" + path + "\"");
try {
loadFromDisk();
return;
@@ -126,7 +125,6 @@ public class CachedMapsFile extends SynchronizedFile {
}
// Generate maps from image file
LOGGER.fine("Missed cache file \"" + path + "\"");
try {
generateFromImage();
tryToWriteToDisk();
@@ -1,326 +0,0 @@
package io.josemmo.bukkit.plugin.storage;
import com.sun.nio.file.ExtendedWatchEventModifier;
import io.josemmo.bukkit.plugin.utils.Logger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;
import java.util.stream.Collectors;
/**
* Service for detecting file events inside a given directory.
* <p>
* It supports recursive storage (<i>e.g.,</i> nested directories) and watches for file system changes in realtime
* when supported by the OS.
*/
public abstract class FileSystemWatcher {
private static final int MAX_DEPTH = 32;
private static final int POLLING_INTERVAL = 4000;
private static final String PROBE_FILENAME = ".inotify_test";
private static final Logger LOGGER = Logger.getLogger("FileSystemWatcher");
protected final Path basePath;
/** Map of existing directories with the files they contain and their last modification timestamps */
private final SortedMap<Path, Map<Path, Long>> fileTree = new TreeMap<>();
private @Nullable Thread watcherThread;
/**
* Class constructor
* @param basePath Base path
*/
public FileSystemWatcher(@NotNull Path basePath) {
this.basePath = basePath;
}
/**
* Start watcher
* @throws RuntimeException if failed to start
*/
protected void start() throws RuntimeException {
// Prevent initializing more than once
if (watcherThread != null) {
throw new RuntimeException("File system watcher is already running");
}
// Perform initial scan
scan();
// Start watching files
watcherThread = new WatcherThread();
watcherThread.start();
}
/**
* Stop watcher
*/
protected void stop() {
if (watcherThread != null) {
watcherThread.interrupt();
watcherThread = null;
}
}
/**
* On file created
* @param path File path
*/
protected abstract void onFileCreated(@NotNull Path path);
/**
* On file modified
* @param path File path
*/
protected abstract void onFileModified(@NotNull Path path);
/**
* On file deleted
* @param path File path
*/
protected abstract void onFileDeleted(@NotNull Path path);
/**
* Scan base directory recursively
*/
private void scan() {
synchronized (fileTree) {
// Assume all directories and files have been deleted, will discard existing items afterward
Set<Path> deletedDirectories = new HashSet<>(fileTree.keySet());
Set<Path> deletedFiles = fileTree.values().stream()
.map(Map::keySet)
.flatMap(Set::stream)
.collect(Collectors.toSet());
// Traverse file tree
Set<FileVisitOption> options = EnumSet.noneOf(FileVisitOption.class);
try {
Files.walkFileTree(basePath, options, MAX_DEPTH, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes attrs) {
fileTree.putIfAbsent(path, new HashMap<>());
deletedDirectories.remove(path);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) {
Map<Path, Long> subtree = fileTree.get(path.getParent());
Long oldModifiedAt = subtree.get(path);
long newModifiedAt = attrs.lastModifiedTime().toMillis();
if (oldModifiedAt == null) {
subtree.put(path, newModifiedAt);
onFileCreated(path);
} else if (newModifiedAt > oldModifiedAt) {
subtree.put(path, newModifiedAt);
onFileModified(path);
}
deletedFiles.remove(path);
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
LOGGER.severe("Failed to list files in directory", e);
}
// Process deleted files and directories
for (Path path : deletedFiles) {
fileTree.get(path.getParent()).remove(path);
onFileDeleted(path);
}
for (Path path : deletedDirectories) {
fileTree.remove(path);
}
}
}
private class WatcherThread extends Thread {
private final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("win");
@Override
public void run() {
if (isInotifySupported()) {
runWithFileSystemEvents();
} else {
LOGGER.warning("Device does not support inotify, detection of file changes will be slower");
runWithPolling();
}
}
/**
* Is inotify supported
* @return Whether inotify is supported
*/
@SuppressWarnings("ResultOfMethodCallIgnored")
private boolean isInotifySupported() {
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
// Start listening for events
basePath.register(
watchService,
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY
);
// Create and delete probe directory
File testFile = basePath.resolve(PROBE_FILENAME).toFile();
testFile.mkdir();
testFile.delete();
// Check that at least one event was emitted
WatchKey watchKey = watchService.poll();
return (watchKey != null && !watchKey.pollEvents().isEmpty());
} catch (IOException __) {
return false;
}
}
/**
* Run with polling
*/
@SuppressWarnings({"InfiniteLoopStatement", "BusyWait"})
private void runWithPolling() {
try {
while (true) {
Thread.sleep(POLLING_INTERVAL);
scan();
}
} catch (InterruptedException __) {
// Silently ignore exception, this is expected when service shuts down
}
}
/**
* Run with file system events
*/
private void runWithFileSystemEvents() {
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
// Register initial directories
synchronized (fileTree) {
for (Path path : fileTree.keySet()) {
registerDirectory(watchService, path);
}
}
// Listen for events
WatchKey key;
try {
while ((key = watchService.take()) != null) {
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
Path keyPath = (Path) key.watchable();
Path path = keyPath.resolve((Path) event.context());
handleWatchEvent(watchService, path, kind);
}
key.reset();
}
} catch (ClosedWatchServiceException | InterruptedException __) {
// Silently ignore exception, this is expected when service shuts down
}
} catch (IOException e) {
LOGGER.severe("Unexpected error at watch service", e);
}
}
/**
* Handle watch event
* @param watchService Watch service
* @param path File or directory path
* @param kind Event kind
*/
private void handleWatchEvent(@NotNull WatchService watchService, @NotNull Path path, @NotNull WatchEvent.Kind<?> kind) {
synchronized (fileTree) {
Map<Path, Long> subtree = fileTree.computeIfAbsent(path.getParent(), k -> new HashMap<>());
// Handle deletion of files and directories
if (kind == StandardWatchEventKinds.ENTRY_DELETE) {
if (subtree.containsKey(path)) {
subtree.remove(path);
onFileDeleted(path);
} else {
unregisterDirectory(path);
}
return;
}
// Handle creation of directories
if (path.toFile().isDirectory()) {
if (kind == StandardWatchEventKinds.ENTRY_CREATE) {
registerDirectory(watchService, path);
}
return;
}
// Handle creation and modification of files
// NOTE: in Windows, some file creation events are reported as modifications
Long oldModifiedAt = subtree.get(path);
long newModifiedAt = path.toFile().lastModified();
if (oldModifiedAt == null) {
subtree.put(path, newModifiedAt);
onFileCreated(path);
} else if (newModifiedAt > oldModifiedAt) {
subtree.put(path, newModifiedAt);
onFileModified(path);
}
}
}
/**
* Register directory
* @param watchService Watch service
* @param path Directory path
*/
private void registerDirectory(@NotNull WatchService watchService, @NotNull Path path) {
// Windows supports listing to events in the entire file tree,
// in that case only allow registering the listener on the base path
if (IS_WINDOWS && !path.equals(basePath)) {
return;
}
// Start watching directory for events
try {
WatchEvent.Kind<?>[] events = new WatchEvent.Kind[]{
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY
};
WatchEvent.Modifier[] modifiers = IS_WINDOWS ?
new WatchEvent.Modifier[]{ExtendedWatchEventModifier.FILE_TREE} :
new WatchEvent.Modifier[0];
path.register(watchService, events, modifiers);
LOGGER.fine("Started watching directory at \"" + path + "\"");
} catch (IOException e) {
LOGGER.severe("Failed to register directory", e);
}
}
/**
* Unregister directory
* @param path Directory path
*/
private void unregisterDirectory(@NotNull Path path) {
synchronized (fileTree) {
if (!fileTree.containsKey(path)) {
// Already unregistered, can skip work
return;
}
boolean foundFirst = false;
Iterator<Map.Entry<Path, Map<Path, Long>>> iter = fileTree.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<Path, Map<Path, Long>> entry = iter.next();
if (entry.getKey().startsWith(path)) {
for (Path childPath : entry.getValue().keySet()) {
onFileDeleted(childPath);
}
foundFirst = true;
iter.remove();
} else if (foundFirst) {
// We can break early because set is alphabetically sorted by key
break;
}
}
}
}
}
}
@@ -1,11 +1,14 @@
package io.josemmo.bukkit.plugin.storage;
import com.sun.nio.file.ExtendedWatchEventModifier;
import io.josemmo.bukkit.plugin.utils.Logger;
import io.josemmo.bukkit.plugin.utils.Permissions;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.util.*;
import java.util.regex.Matcher;
@@ -13,18 +16,23 @@ import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
/**
* Service for keeping track of image images.
* A service whose purpose is to keep track of all available image files in a given directory.
* It supports recursive storage (<i>e.g.</i>, nested directories) and watches for file system changes in realtime.
* <p>
* All files are indexed based on their <b>filename</b>.
* Due to recursion, filenames can contain forward slashes (<i>i.e.,</i> "/") and act as relative paths to the base
* Due to recursion, filenames can contain forward slashes (<i>i.e.</i>, "/") and act as relative paths to the base
* directory.
*/
public class ImageStorage extends FileSystemWatcher {
public class ImageStorage {
private static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("win");
private static final Logger LOGGER = Logger.getLogger("ImageStorage");
/** Map of registered files indexed by filename */
private final SortedMap<String, ImageFile> files = new TreeMap<>();
private final Path basePath;
private final Path cachePath;
private final String allowedPaths;
private @Nullable WatchService watchService;
private @Nullable Thread watchServiceThread;
/**
* Class constructor
@@ -33,7 +41,7 @@ public class ImageStorage extends FileSystemWatcher {
* @param allowedPaths Allowed paths pattern
*/
public ImageStorage(@NotNull Path basePath, @NotNull Path cachePath, @NotNull String allowedPaths) {
super(basePath);
this.basePath = basePath;
this.cachePath = cachePath;
this.allowedPaths = allowedPaths;
}
@@ -56,10 +64,15 @@ public class ImageStorage extends FileSystemWatcher {
/**
* Start service
* @throws RuntimeException if failed to start watch service
* @throws IOException if failed to start watch service
* @throws RuntimeException if already running
*/
@Override
public void start() throws RuntimeException {
public void start() throws IOException, RuntimeException {
// Prevent initializing more than once
if (watchService != null || watchServiceThread != null) {
throw new RuntimeException("Service is already running");
}
// Create base directories if necessary
if (basePath.toFile().mkdirs()) {
LOGGER.info("Created images directory as it did not exist");
@@ -68,17 +81,33 @@ public class ImageStorage extends FileSystemWatcher {
LOGGER.info("Created cache directory as it did not exist");
}
// Start file system watcher
super.start();
// Start watching files
watchService = FileSystems.getDefault().newWatchService();
watchServiceThread = new WatcherThread();
watchServiceThread.start();
registerDirectory(basePath, true);
LOGGER.fine("Found " + files.size() + " file(s) in images directory");
}
/**
* Stop service
*/
@Override
public void stop() {
super.stop();
// Interrupt watch service thread
if (watchServiceThread != null) {
watchServiceThread.interrupt();
watchServiceThread = null;
}
// Close watch service
if (watchService != null) {
try {
watchService.close();
} catch (IOException e) {
LOGGER.warning("Failed to close watch service", e);
}
watchService = null;
}
}
/**
@@ -111,7 +140,7 @@ public class ImageStorage extends FileSystemWatcher {
* @return Whether sender is allowed to access path
*/
public boolean isPathAllowed(@NotNull Path path, @NotNull CommandSender sender) {
return isPathAllowed(pathToFilename(path), sender);
return isPathAllowed(getFilename(path), sender);
}
/**
@@ -162,20 +191,58 @@ public class ImageStorage extends FileSystemWatcher {
}
/**
* Convert path to filename
* @param path File path
* @return Relative path used for indexing
* Register directory
* @param path Path to directory
* @param isBase Whether is base directory or not
*/
private @NotNull String pathToFilename(@NotNull Path path) {
return basePath.relativize(path).toString().replaceAll("\\\\", "/");
private synchronized void registerDirectory(@NotNull Path path, boolean isBase) {
// Validate path
if (!Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS)) {
LOGGER.warning("Cannot list files in \"" + path + "\" as it is not a valid directory");
return;
}
// Do initial directory listing
for (File child : Objects.requireNonNull(path.toFile().listFiles())) {
if (child.isDirectory()) {
registerDirectory(child.toPath(), false);
} else {
registerFile(child.toPath());
}
}
// Start watching for files changes
if (!IS_WINDOWS || isBase) {
try {
WatchEvent.Kind<?>[] events = new WatchEvent.Kind[]{
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY
};
WatchEvent.Modifier[] modifiers = IS_WINDOWS ?
new WatchEvent.Modifier[]{ExtendedWatchEventModifier.FILE_TREE} :
new WatchEvent.Modifier[0];
path.register(Objects.requireNonNull(watchService), events, modifiers);
LOGGER.fine("Started watching directory at \"" + path + "\"");
} catch (IOException | NullPointerException e) {
LOGGER.severe("Failed to register directory", e);
}
}
}
/**
* On file created
* @param path File path
* Register file
* @param path Path to file
*/
protected synchronized void onFileCreated(@NotNull Path path) {
String filename = pathToFilename(path);
private synchronized void registerFile(@NotNull Path path) {
// Validate path
if (!Files.isRegularFile(path, LinkOption.NOFOLLOW_LINKS)) {
LOGGER.warning("Cannot register \"" + path + "\" as it is not a valid file");
return;
}
// Add file to map
String filename = getFilename(path);
ImageFile imageFile = new ImageFile(filename, path);
if (files.putIfAbsent(filename, imageFile) == null) {
LOGGER.fine("Registered file \"" + filename + "\"");
@@ -183,28 +250,113 @@ public class ImageStorage extends FileSystemWatcher {
}
/**
* On file modified
* @param path File path
* Unregister directory
* @param filename Filename to directory
*/
protected synchronized void onFileModified(@NotNull Path path) {
String filename = pathToFilename(path);
ImageFile imageFile = files.get(filename);
if (imageFile != null) {
imageFile.invalidate();
LOGGER.fine("Invalidated file \"" + filename + "\"");
private synchronized void unregisterDirectory(@NotNull String filename) {
boolean foundFirst = false;
Iterator<Map.Entry<String, ImageFile>> iter = files.entrySet().iterator();
while (iter.hasNext()) {
String entryKey = iter.next().getKey();
if (entryKey.startsWith(filename+"/")) {
foundFirst = true;
iter.remove();
LOGGER.fine("Unregistered file \"" + entryKey + "\"");
} else if (foundFirst) {
// We can break early because set is alphabetically sorted by key
break;
}
}
}
/**
* On file deleted
* @param path File path
* Unregister file
* @param filename Filename to file
*/
protected synchronized void onFileDeleted(@NotNull Path path) {
String filename = pathToFilename(path);
private synchronized void unregisterFile(@NotNull String filename) {
ImageFile imageFile = files.remove(filename);
if (imageFile != null) {
imageFile.invalidate();
LOGGER.fine("Unregistered file \"" + filename + "\"");
}
}
/**
* Invalidate file
* @param filename Filename to file
*/
private synchronized void invalidateFile(@NotNull String filename) {
ImageFile imageFile = files.get(filename);
if (imageFile != null) {
imageFile.invalidate();
}
}
/**
* Handle watch event
* @param path Path to file or directory
* @param kind Event kind
*/
private synchronized void handleWatchEvent(@NotNull Path path, WatchEvent.Kind<?> kind) {
// Check whether file currently exists in file system (for CREATE and UPDATE events)
// or is registered in the file list (for DELETE event)
String filename = getFilename(path);
boolean isFile = path.toFile().isFile() || files.containsKey(filename);
// Handle creation event
if (kind == StandardWatchEventKinds.ENTRY_CREATE) {
if (isFile) {
registerFile(path);
} else {
registerDirectory(path, false);
}
return;
}
// Handle deletion event
if (kind == StandardWatchEventKinds.ENTRY_DELETE) {
if (isFile) {
unregisterFile(filename);
} else {
unregisterDirectory(filename);
}
return;
}
// Handle modification event
if (kind == StandardWatchEventKinds.ENTRY_MODIFY && isFile) {
invalidateFile(filename);
}
}
/**
* Get filename from path
* @param path Path to file
* @return Relative path used for indexing
*/
private @NotNull String getFilename(@NotNull Path path) {
return basePath.relativize(path).toString().replaceAll("\\\\", "/");
}
private class WatcherThread extends Thread {
@Override
public void run() {
try {
WatchKey key;
while ((key = Objects.requireNonNull(watchService).take()) != null) {
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
Path keyPath = (Path) key.watchable();
Path path = keyPath.resolve((Path) event.context());
handleWatchEvent(path, kind);
}
key.reset();
}
} catch (ClosedWatchServiceException | InterruptedException __) {
// Silently ignore exception, this is expected when service shuts down
} catch (NullPointerException e) {
LOGGER.severe("Watch service was stopped before watcher thread", e);
}
}
}
}
@@ -4,9 +4,6 @@ import org.jetbrains.annotations.Blocking;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.OverlappingFileLockException;
import java.nio.file.Path;
/**
@@ -20,29 +17,10 @@ public class SynchronizedFileStream extends RandomAccessFile {
* @param readOnly Whether to open stream in read-only mode
* @throws IOException if failed to acquire lock
*/
@Blocking
public SynchronizedFileStream(@NotNull Path path, boolean readOnly) throws IOException {
super(path.toFile(), readOnly ? "r" : "rw");
waitForLock(readOnly);
}
/**
* Wait for lock to be released
* @param readOnly Whether to acquire read-only (shared) lock
*/
@Blocking
private void waitForLock(boolean readOnly) throws IOException {
FileChannel channel = getChannel();
FileLock lock = null;
while (lock == null) {
try {
lock = channel.lock(0L, Long.MAX_VALUE, readOnly);
} catch (OverlappingFileLockException e) {
try {
Thread.sleep(20);
} catch (InterruptedException __) {
throw e;
}
}
}
//noinspection ResultOfMethodCallIgnored
getChannel().lock(0L, Long.MAX_VALUE, readOnly);
}
}
@@ -6,7 +6,6 @@ import org.bukkit.Server;
import org.bukkit.command.CommandMap;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -14,7 +13,7 @@ public class Internals {
public static final float MINECRAFT_VERSION;
private static final CommandDispatcher<?> DISPATCHER;
private static final CommandMap COMMAND_MAP;
private static @Nullable Method GET_BUKKIT_SENDER_METHOD = null;
private static final Method GET_BUKKIT_SENDER_METHOD;
static {
try {
@@ -31,30 +30,24 @@ public class Internals {
Object nmsInstance = obcClass.getDeclaredMethod("getServer").invoke(obcInstance);
Class<?> nmsClass = nmsInstance.getClass().getSuperclass();
if (MINECRAFT_VERSION >= 20.6) {
// Get "net.minecraft.commands.Commands" references
Object nmsCommandsInstance = nmsClass.getDeclaredMethod("getCommands").invoke(nmsInstance);
Class<?> nmsCommandsClass = nmsCommandsInstance.getClass();
// Get "net.minecraft.server.CommandDispatcher" references
Object nmsDispatcherInstance = nmsClass.getDeclaredField("vanillaCommandDispatcher").get(nmsInstance);
Class<?> nmsDispatcherClass = nmsDispatcherInstance.getClass();
// Get "com.mojang.brigadier.CommandDispatcher" instance
Field nmsDispatcherField = nmsCommandsClass.getDeclaredField("dispatcher");
nmsDispatcherField.setAccessible(true);
DISPATCHER = (CommandDispatcher<?>) nmsDispatcherField.get(nmsCommandsInstance);
} else {
// Get "net.minecraft.server.CommandDispatcher" references
Object nmsDispatcherInstance = nmsClass.getDeclaredField("vanillaCommandDispatcher").get(nmsInstance);
Class<?> nmsDispatcherClass = nmsDispatcherInstance.getClass();
// Get "com.mojang.brigadier.CommandDispatcher" instance
Method getDispatcherMethod = nmsDispatcherClass.getDeclaredMethod("a");
getDispatcherMethod.setAccessible(true);
DISPATCHER = (CommandDispatcher<?>) getDispatcherMethod.invoke(nmsDispatcherInstance);
}
// Get Brigadier dispatcher instance
Method getDispatcherMethod = nmsDispatcherClass.getDeclaredMethod("a");
getDispatcherMethod.setAccessible(true);
DISPATCHER = (CommandDispatcher<?>) getDispatcherMethod.invoke(nmsDispatcherInstance);
// Get command map instance
Field commandMapField = obcClass.getDeclaredField("commandMap");
commandMapField.setAccessible(true);
COMMAND_MAP = (CommandMap) commandMapField.get(obcInstance);
// Get CommandListenerWrapper.getBukkitSender() method
Class<?> clwClass = Class.forName(nmsDispatcherClass.getPackage().getName() + ".CommandListenerWrapper");
GET_BUKKIT_SENDER_METHOD = clwClass.getDeclaredMethod("getBukkitSender");
GET_BUKKIT_SENDER_METHOD.setAccessible(true);
} catch (Exception e) {
throw new RuntimeException("Failed to get internal classes due to incompatible Minecraft server", e);
}
@@ -83,12 +76,9 @@ public class Internals {
*/
public static @NotNull CommandSender getBukkitSender(@NotNull Object source) {
try {
if (GET_BUKKIT_SENDER_METHOD == null) {
GET_BUKKIT_SENDER_METHOD = source.getClass().getDeclaredMethod("getBukkitSender");
}
return (CommandSender) GET_BUKKIT_SENDER_METHOD.invoke(source);
} catch (Exception e) {
throw new RuntimeException("Failed to extract Bukkit sender from source", e);
throw new RuntimeException("Failed to extract bukkit sender from source", e);
}
}
}
-2
View File
@@ -4,14 +4,12 @@ main: io.josemmo.bukkit.plugin.YamipaPlugin
api-version: 1.16
depend: [ProtocolLib]
softdepend:
- BentoBox
- GriefPrevention
- GroupManager
- Hyperverse
- LuckPerms
- Multiverse-Core
- My_Worlds
- PhantomWorlds
- Towny
- WorldGuard