diff --git a/.examples/extend/simple-proxy/go.mod b/.examples/extend/simple-proxy/go.mod index 629cfeeb..91208918 100644 --- a/.examples/extend/simple-proxy/go.mod +++ b/.examples/extend/simple-proxy/go.mod @@ -1,6 +1,6 @@ module simple-proxy -go 1.22.2 +go 1.23.2 replace go.minekube.com/gate => ../../../ @@ -12,7 +12,7 @@ require ( ) require ( - buf.build/gen/go/minekube/connect/protocolbuffers/go v1.34.2-20240220124425-904ce30425c9.2 // indirect + buf.build/gen/go/minekube/connect/protocolbuffers/go v1.35.2-20240220124425-904ce30425c9.1 // indirect github.com/Tnze/go-mc v1.20.2 // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/coder/websocket v1.8.12 // indirect @@ -21,8 +21,8 @@ require ( github.com/edwingeng/deque/v2 v2.1.1 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/francoispqt/gojay v1.2.13 // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/gammazero/deque v0.2.1 // indirect + github.com/fsnotify/fsnotify v1.8.0 // indirect + github.com/gammazero/deque v1.0.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -35,7 +35,7 @@ require ( github.com/magiconair/properties v1.8.7 // indirect github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect - github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/pires/go-proxyproto v0.8.0 // indirect github.com/rs/xid v1.6.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect @@ -55,14 +55,14 @@ require ( go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect + golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect golang.org/x/sync v0.9.0 // indirect - golang.org/x/sys v0.24.0 // indirect - golang.org/x/text v0.19.0 // indirect - golang.org/x/time v0.7.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect - google.golang.org/grpc v1.67.1 // indirect - google.golang.org/protobuf v1.34.2 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect + golang.org/x/time v0.8.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f // indirect + google.golang.org/grpc v1.68.0 // indirect + google.golang.org/protobuf v1.35.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/.examples/extend/simple-proxy/go.sum b/.examples/extend/simple-proxy/go.sum index 07d4777a..3ee31afe 100644 --- a/.examples/extend/simple-proxy/go.sum +++ b/.examples/extend/simple-proxy/go.sum @@ -4,6 +4,7 @@ buf.build/gen/go/minekube/connect/protocolbuffers/go v1.34.1-20240220124425-904c buf.build/gen/go/minekube/connect/protocolbuffers/go v1.34.1-20240220124425-904ce30425c9.1/go.mod h1:6hSa70osNsHkE8luMasPFGzmsajsvzcBXHilLjBOWUw= buf.build/gen/go/minekube/connect/protocolbuffers/go v1.34.2-20240220124425-904ce30425c9.2 h1:P9rrKBfkybGwL8Rb5UmzCnOa/mkcJtrUrRVEX5An9k8= buf.build/gen/go/minekube/connect/protocolbuffers/go v1.34.2-20240220124425-904ce30425c9.2/go.mod h1:D/wczfxm9oSmKysNIdtRRiwwkOnJUw8xWj8hgDMBko0= +buf.build/gen/go/minekube/connect/protocolbuffers/go v1.35.2-20240220124425-904ce30425c9.1/go.mod h1:96yQVJkVjg/fSbxhL7wpEEz59WDdYZ4M9f7MIcGeMQY= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= @@ -54,8 +55,10 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0= github.com/gammazero/deque v0.2.1/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZDV34tuU= +github.com/gammazero/deque v1.0.0/go.mod h1:iflpYvtGfM3U8S8j+sZEKIak3SAKYpA5/SQewgfXDKo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= @@ -149,6 +152,7 @@ github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOS github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs= github.com/pires/go-proxyproto v0.7.0/go.mod h1:Vz/1JPY/OACxWGQNIRY2BeyDmpoaWmEP40O9LbuiFR4= github.com/pires/go-proxyproto v0.7.1-0.20231012122632-e5b291b295b4 h1:VM7Tse0I0kTEaO/Rk7BPjmDqfiUcpv+RWtiwIY04pgI= @@ -294,6 +298,7 @@ golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDT golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= +golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -341,6 +346,8 @@ golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= @@ -355,6 +362,7 @@ golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= @@ -363,6 +371,7 @@ golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -394,6 +403,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240808171019-573a1156607a h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20240808171019-573a1156607a/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs= google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -415,6 +426,7 @@ google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw= google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= @@ -424,6 +436,8 @@ google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFW google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/.gitignore b/.gitignore index 82f18fed..3a6f9739 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ - +.idea +.yarn /.web/docs/.vitepress/cache diff --git a/.web/.gitignore b/.web/.gitignore index 6a814c3e..94a5e3f5 100644 --- a/.web/.gitignore +++ b/.web/.gitignore @@ -1,2 +1,5 @@ /docs/.vitepress/dist/ +/docs/.vitepress/cache /node_modules/ +.pnp.* +.yarn \ No newline at end of file diff --git a/.web/docs/.vitepress/config.ts b/.web/docs/.vitepress/config.ts index 8bc028bb..71970a60 100644 --- a/.web/docs/.vitepress/config.ts +++ b/.web/docs/.vitepress/config.ts @@ -1,220 +1,286 @@ -import {defineConfig} from 'vitepress' +import { defineConfig } from 'vitepress'; -import {additionalTitle, commitRef, discordLink, editLink, gitHubLink} from '../shared/' +import { + additionalTitle, + commitRef, + discordLink, + editLink, + gitHubLink, +} from '../shared/'; -const ogUrl = 'https://gate.minekube.com' -const ogImage = `${ogUrl}/og-image.png` -const ogTitle = 'Gate Proxy' -const ogDescription = 'Next Generation Minecraft Proxy' +const ogUrl = 'https://gate.minekube.com'; +const ogImage = `${ogUrl}/og-image.png`; +const ogTitle = 'Gate Proxy'; +const ogDescription = 'Next Generation Minecraft Proxy'; export default defineConfig({ - title: `Gate Proxy${additionalTitle}`, - description: ogDescription, - appearance: 'dark', + title: `Gate Proxy${additionalTitle}`, + description: ogDescription, + appearance: 'dark', - sitemap: { - hostname: ogUrl, - }, + sitemap: { + hostname: ogUrl, + }, - head: [ - ['link', {rel: 'icon', type: 'image/png', href: '/favicon.png'}], - ['meta', {property: 'og:type', content: 'website'}], - ['meta', {property: 'og:title', content: ogTitle}], - ['meta', {property: 'og:image', content: ogImage}], - ['meta', {property: 'og:url', content: ogUrl}], - ['meta', {property: 'og:description', content: ogDescription}], - ['meta', {name: 'theme-color', content: '#646cff'}], - // [ - // 'script', - // { - // src: 'https://cdn.usefathom.com/script.js', - // 'data-site': 'CBDFBSLI', - // 'data-spa': 'auto', - // defer: '' - // } - // ] - [ - 'script', - {}, - `!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.async=!0,p.src=s.api_host+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="capture identify alias people.set people.set_once set_config register register_once unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset isFeatureEnabled onFeatureFlags getFeatureFlag getFeatureFlagPayload reloadFeatureFlags group updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures getActiveMatchingSurveys getSurveys onSessionId".split(" "),n=0;n + +
+
+
+

+ Powerful Extensibility +

+

+ Build with your favorite language +

+

+ Gate provides official SDKs for multiple languages. Create plugins and + integrations using modern APIs and tools you love. +

+
+ + + + + + +
+
+ + +
+
+
+

+ Get Started in Minutes +

+

+ The next generation Minecraft proxy +

+

+ Choose your preferred installation method and start scaling your + Minecraft network with Gate's powerful features. +

+
+ + +
+ + + +
+ +
+ + +
+ + +
+
+
+
+
+ + {{ + showWindowsCommand + ? 'powershell -c "irm https://gate.minekube.com/install.ps1 | iex"' + : 'curl -sSL https://gate.minekube.com/install.sh | sh' + }} + +
+
+ +
+
+
+
+
+
+ + +
+
+
+

+ Ultra-Lightweight Mode +

+

+ Host-based routing made simple +

+

+ Gate Lite acts as an ultra-thin reverse proxy, efficiently routing + connections based on hostnames. Protect multiple backend servers + behind a single port with minimal overhead. +

+
+ + +
+
+ Lite Mode Diagram +
+
+ + +
+ + + +
+
+
+
+
+ config.yml + +
+
config:
+  lite:
+    enabled: true
+    routes:
+      - host: '*.example.com'
+        backend: 10.0.0.1:25567
+      - host: [ example.com, localhost ]
+        backend: [ 10.0.0.2:25566 ]
+        cachePingTTL: 3m
+
+
+
+ + + +
+
+
+ + +
+
+
+

+ Live Configuration +

+

+ Configure without restarts +

+

+ Gate watches your config file for changes and applies them instantly + without disconnecting players. Switch modes, add servers, or update + settings - all while staying live. +

+
+ +
+ + + +
+
+
+
+
+ config.yml + +
+
bind: 0.0.0.0:25565
+servers:
+  lobby:
+    addr: 127.0.0.1:25566
+  minigames:
+    addr: 127.0.0.1:25567
+try:
+  - lobby
+  - minigames
+
+
+
+ + + +
+
+
+ + +
+
+
+

+ Scale your Minecraft network today +

+

+ Start using Gate in under 5 minutes. Join hundreds of server owners + building better networks with Minekube technology. +

+ + +
+
+
+ 650+ +
+
+ Discord Members +
+
+
+
+
+ 650+ +
+
+ GitHub Stars +
+
+
+ + + + + + +
+
+
+ + + + + diff --git a/.web/docs/.vitepress/theme/components/Layout.vue b/.web/docs/.vitepress/theme/components/Layout.vue index daa653ef..7e4a0c74 100644 --- a/.web/docs/.vitepress/theme/components/Layout.vue +++ b/.web/docs/.vitepress/theme/components/Layout.vue @@ -3,6 +3,7 @@ import DefaultTheme from 'vitepress/theme' import {useRouter} from 'vitepress'; import {watch} from 'vue'; import HomeHeroImage from "./HomeHeroImage.vue"; +import LandingAfter from './LandingAfter.vue'; const {Layout} = DefaultTheme @@ -22,5 +23,8 @@ if (typeof window !== 'undefined' && window.posthog) { + \ No newline at end of file diff --git a/.web/docs/developers/api/definition.md b/.web/docs/developers/api/definition.md new file mode 100644 index 00000000..c46350c7 --- /dev/null +++ b/.web/docs/developers/api/definition.md @@ -0,0 +1,15 @@ +# API Definition + + + +::: details `gate_service.proto` + +```protobuf + +``` + +::: + +--- + + diff --git a/.web/docs/developers/api/gen/definition.gen.md b/.web/docs/developers/api/gen/definition.gen.md new file mode 100644 index 00000000..e315a601 --- /dev/null +++ b/.web/docs/developers/api/gen/definition.gen.md @@ -0,0 +1,314 @@ +# Protocol Documentation + + +## Table of Contents + +- [minekube/gate/v1/gate_service.proto](#minekube_gate_v1_gate_service-proto) + - [ConnectPlayerRequest](#minekube-gate-v1-ConnectPlayerRequest) + - [ConnectPlayerResponse](#minekube-gate-v1-ConnectPlayerResponse) + - [DisconnectPlayerRequest](#minekube-gate-v1-DisconnectPlayerRequest) + - [DisconnectPlayerResponse](#minekube-gate-v1-DisconnectPlayerResponse) + - [GetPlayerRequest](#minekube-gate-v1-GetPlayerRequest) + - [GetPlayerResponse](#minekube-gate-v1-GetPlayerResponse) + - [ListPlayersRequest](#minekube-gate-v1-ListPlayersRequest) + - [ListPlayersResponse](#minekube-gate-v1-ListPlayersResponse) + - [ListServersRequest](#minekube-gate-v1-ListServersRequest) + - [ListServersResponse](#minekube-gate-v1-ListServersResponse) + - [Player](#minekube-gate-v1-Player) + - [RegisterServerRequest](#minekube-gate-v1-RegisterServerRequest) + - [RegisterServerResponse](#minekube-gate-v1-RegisterServerResponse) + - [Server](#minekube-gate-v1-Server) + - [UnregisterServerRequest](#minekube-gate-v1-UnregisterServerRequest) + - [UnregisterServerResponse](#minekube-gate-v1-UnregisterServerResponse) + + - [GateService](#minekube-gate-v1-GateService) + +- [Scalar Value Types](#scalar-value-types) + + + + +

Top

+ +## minekube/gate/v1/gate_service.proto + + + + + +### ConnectPlayerRequest +ConnectPlayerRequest is the request for ConnectPlayer method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| player | [string](#string) | | The player's username or ID to connect | +| server | [string](#string) | | The target server name to connect the player to | + + + + + + + + +### ConnectPlayerResponse +ConnectPlayerResponse is the response for ConnectPlayer method. + + + + + + + + +### DisconnectPlayerRequest +DisconnectPlayerRequest is the request for DisconnectPlayer method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| player | [string](#string) | | The player's username or ID to disconnect | +| reason | [string](#string) | | The reason displayed to the player when they are disconnected. + +Formats: + +- `{"text":"Hello, world!"}` - JSON text component. See https://wiki.vg/Text_formatting for details. + +- `§aHello,\n§bworld!` - Simple color codes. See https://wiki.vg/Text_formatting#Colors + +Optional, if empty no reason will be shown. | + + + + + + + + +### DisconnectPlayerResponse +DisconnectPlayerResponse is the response for DisconnectPlayer method. + + + + + + + + +### GetPlayerRequest +GetPlayerRequest is the request for GetPlayer method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| id | [string](#string) | | Gets the player by their Minecraft UUID. Optional, if not set the username will be used. If both id and username are set, the id will be used. Must be a valid Minecraft UUID format (e.g. "550e8400-e29b-41d4-a716-446655440000") | +| username | [string](#string) | | Gets the player by their username. Optional, if not set the id will be used. Case-sensitive. | + + + + + + + + +### GetPlayerResponse +GetPlayerResponse is the response for GetPlayer method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| player | [Player](#minekube-gate-v1-Player) | | The player matching the request criteria | + + + + + + + + +### ListPlayersRequest +ListPlayersRequest is the request for ListPlayers method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| servers | [string](#string) | repeated | Filter players by server names. Optional, if empty all online players are returned. If specified, only returns players on the listed servers. | + + + + + + + + +### ListPlayersResponse +ListPlayersResponse is the response for ListPlayers method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| players | [Player](#minekube-gate-v1-Player) | repeated | | + + + + + + + + +### ListServersRequest +ListServersRequest is the request for ListServers method. + + + + + + + + +### ListServersResponse +ListServersResponse is the response for ListServers method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| servers | [Server](#minekube-gate-v1-Server) | repeated | | + + + + + + + + +### Player +Player represents an online player on the proxy. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| id | [string](#string) | | The player's Minecraft UUID | +| username | [string](#string) | | The player's username | + + + + + + + + +### RegisterServerRequest +RegisterServerRequest is the request for RegisterServer method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| name | [string](#string) | | The unique name of the server | +| address | [string](#string) | | The network address of the server (e.g. "localhost:25565") | + + + + + + + + +### RegisterServerResponse +RegisterServerResponse is the response for RegisterServer method. + + + + + + + + +### Server +Server represents a backend server where Gate can connect players to. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| name | [string](#string) | | The unique name of the server. | +| address | [string](#string) | | The network address of the server. | +| players | [int32](#int32) | | The number of players currently on the server. | + + + + + + + + +### UnregisterServerRequest +UnregisterServerRequest is the request for UnregisterServer method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| name | [string](#string) | | The name of the server. Optional, if not set, the address will be used to match servers. | +| address | [string](#string) | | The address of the server. Optional, if not set, the name will be used to match servers. If both name and address are set, only the server that matches both properties exactly will be unregistered. If only the address is set, the first server matching that address will be unregistered. | + + + + + + + + +### UnregisterServerResponse +UnregisterServerResponse is the response for UnregisterServer method. + + + + + + + + + + + + + + +### GateService +GateService is the service API for managing a Gate proxy instance. +It provides methods for managing players and servers. +All methods follow standard gRPC error codes and include detailed error messages. + +| Method Name | Request Type | Response Type | Description | +| ----------- | ------------ | ------------- | ------------| +| GetPlayer | [GetPlayerRequest](#minekube-gate-v1-GetPlayerRequest) | [GetPlayerResponse](#minekube-gate-v1-GetPlayerResponse) | GetPlayer returns the player by the given id or username. Returns NOT_FOUND if the player is not online. Returns INVALID_ARGUMENT if neither id nor username is provided, or if the id format is invalid. | +| ListPlayers | [ListPlayersRequest](#minekube-gate-v1-ListPlayersRequest) | [ListPlayersResponse](#minekube-gate-v1-ListPlayersResponse) | ListPlayers returns all online players. If servers are specified in the request, only returns players on those servers. | +| ListServers | [ListServersRequest](#minekube-gate-v1-ListServersRequest) | [ListServersResponse](#minekube-gate-v1-ListServersResponse) | ListServers returns all registered servers. | +| RegisterServer | [RegisterServerRequest](#minekube-gate-v1-RegisterServerRequest) | [RegisterServerResponse](#minekube-gate-v1-RegisterServerResponse) | RegisterServer adds a server to the proxy. Returns ALREADY_EXISTS if a server with the same name is already registered. Returns INVALID_ARGUMENT if the server name or address is invalid. | +| UnregisterServer | [UnregisterServerRequest](#minekube-gate-v1-UnregisterServerRequest) | [UnregisterServerResponse](#minekube-gate-v1-UnregisterServerResponse) | UnregisterServer removes a server from the proxy. Returns NOT_FOUND if no matching server is found. Returns INVALID_ARGUMENT if neither name nor address is provided. | +| ConnectPlayer | [ConnectPlayerRequest](#minekube-gate-v1-ConnectPlayerRequest) | [ConnectPlayerResponse](#minekube-gate-v1-ConnectPlayerResponse) | ConnectPlayer connects a player to a specified server. Returns NOT_FOUND if either the player or target server doesn't exist. Returns FAILED_PRECONDITION if the connection attempt fails. | +| DisconnectPlayer | [DisconnectPlayerRequest](#minekube-gate-v1-DisconnectPlayerRequest) | [DisconnectPlayerResponse](#minekube-gate-v1-DisconnectPlayerResponse) | DisconnectPlayer disconnects a player from the proxy. Returns NOT_FOUND if the player doesn't exist. Returns INVALID_ARGUMENT if the reason text is malformed. | + + + + + +## Scalar Value Types + +| .proto Type | Notes | C++ | Java | Python | Go | C# | PHP | Ruby | +| ----------- | ----- | --- | ---- | ------ | -- | -- | --- | ---- | +| double | | double | double | float | float64 | double | float | Float | +| float | | float | float | float | float32 | float | float | Float | +| int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) | +| int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long | int64 | long | integer/string | Bignum | +| uint32 | Uses variable-length encoding. | uint32 | int | int/long | uint32 | uint | integer | Bignum or Fixnum (as required) | +| uint64 | Uses variable-length encoding. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum or Fixnum (as required) | +| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) | +| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long | int64 | long | integer/string | Bignum | +| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int | uint32 | uint | integer | Bignum or Fixnum (as required) | +| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum | +| sfixed32 | Always four bytes. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) | +| sfixed64 | Always eight bytes. | int64 | long | int/long | int64 | long | integer/string | Bignum | +| bool | | bool | boolean | boolean | bool | bool | boolean | TrueClass/FalseClass | +| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode | string | string | string | String (UTF-8) | +| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str | []byte | ByteString | string | String (ASCII-8BIT) | + diff --git a/.web/docs/developers/api/glossary.md b/.web/docs/developers/api/glossary.md new file mode 100644 index 00000000..7b4d3aad --- /dev/null +++ b/.web/docs/developers/api/glossary.md @@ -0,0 +1,31 @@ +# API Technology Glossary + +This glossary provides a brief overview of the key technologies used in Gate's API. + +## Protocol Buffers (Protobuf) + +Protocol Buffers is Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data. It provides a more efficient and type-safe alternative to formats like JSON, with built-in schema validation and backwards compatibility support. + +## gRPC + +gRPC is a modern, open-source remote procedure call (RPC) framework that runs over HTTP/2. It enables client and server applications to communicate transparently and makes it easier to build connected systems. gRPC uses Protocol Buffers as its interface definition language and leverages HTTP/2's features like multiplexing and header compression for efficient communication. + +## ConnectRPC + +ConnectRPC is a slim RPC framework that supports both gRPC and HTTP/1.1 JSON, making it ideal for web browsers and HTTP API clients. It provides a more lightweight alternative to full gRPC implementations while maintaining compatibility with gRPC services. + +## buf.build + +buf.build is a modern Protocol Buffers ecosystem that provides tools for managing, versioning, and sharing Protocol Buffer schemas. It includes features like linting, breaking change detection, and a schema registry. Gate uses buf.build to maintain its API definitions and automatically generate client libraries in multiple programming languages. + +## HTTP/1.1 + +HTTP/1.1 is the most widely used version of the HTTP protocol that enables client-server communication on the web. Gate's API supports HTTP/1.1 through ConnectRPC, allowing for broad compatibility with web browsers and standard HTTP clients. + +## JSON (JavaScript Object Notation) + +JSON is a lightweight, text-based data interchange format that is easy for humans to read and write and easy for machines to parse and generate. While Gate primarily uses Protocol Buffers for efficiency, it also supports JSON encoding through ConnectRPC for better web compatibility. + +## SDK (Software Development Kit) + +An SDK is a collection of tools, libraries, documentation, and examples that developers use to create applications for specific platforms or programming languages. Gate provides official SDKs for multiple languages including TypeScript, Python, Go, Rust, Kotlin, and Java through buf.build. See https://buf.build/minekube/gate/sdks for more information and available SDKs. \ No newline at end of file diff --git a/.web/docs/developers/api/go/go.mod b/.web/docs/developers/api/go/go.mod new file mode 100644 index 00000000..dbffa1b0 --- /dev/null +++ b/.web/docs/developers/api/go/go.mod @@ -0,0 +1,11 @@ +module example + +go 1.23.2 + +require ( + buf.build/gen/go/minekube/gate/connectrpc/go v1.17.0-20241118150055-50fffb007499.1 + buf.build/gen/go/minekube/gate/protocolbuffers/go v1.35.2-20241118150055-50fffb007499.1 + connectrpc.com/connect v1.17.0 +) + +require google.golang.org/protobuf v1.35.2 // indirect diff --git a/.web/docs/developers/api/go/go.sum b/.web/docs/developers/api/go/go.sum new file mode 100644 index 00000000..27f9a811 --- /dev/null +++ b/.web/docs/developers/api/go/go.sum @@ -0,0 +1,14 @@ +buf.build/gen/go/minekube/gate/connectrpc/go v1.17.0-20241118150055-50fffb007499.1 h1:PuMlOYaWQWlaFIbEHYQf3/BDSP9t9sr4vIPbg6pLBSI= +buf.build/gen/go/minekube/gate/connectrpc/go v1.17.0-20241118150055-50fffb007499.1/go.mod h1:4dsv7Pyg90q6BS9Axo0HpbmoIUaFpI3jCOivdcA+luM= +buf.build/gen/go/minekube/gate/protocolbuffers/go v1.35.2-20241118150055-50fffb007499.1 h1:8PC1CKMQ003wd5wErIm76IsKcXXHbjlXt/MQ81e3P08= +buf.build/gen/go/minekube/gate/protocolbuffers/go v1.35.2-20241118150055-50fffb007499.1/go.mod h1:K6y2JBJAi5uHKdVriZl83y65fmpymf6utjiVR03NA2w= +connectrpc.com/connect v1.17.0 h1:W0ZqMhtVzn9Zhn2yATuUokDLO5N+gIuBWMOnsQrfmZk= +connectrpc.com/connect v1.17.0/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= diff --git a/.web/docs/developers/api/go/index.md b/.web/docs/developers/api/go/index.md new file mode 100644 index 00000000..37840271 --- /dev/null +++ b/.web/docs/developers/api/go/index.md @@ -0,0 +1,66 @@ +# Go Go Client + +Gate offers two powerful approaches to integrate with Go applications: + + + +If you choose to use the HTTP API Client, follow along below. + +## HTTP API Client + +1. Install the required packages: + +```bash +go get buf.build/gen/go/minekube/gate/connectrpc/go@latest +go get buf.build/gen/go/minekube/gate/protocolbuffers/go@latest +``` + +2. Example usage: + +```go + +``` + +3. Run the example: + +```bash +go run . +{ + "servers": [ + { + "name": "server2", + "address": "localhost:25567" + }, + { + "name": "server3", + "address": "localhost:25568" + }, + { + "name": "server4", + "address": "localhost:25569" + }, + { + "name": "server1", + "address": "localhost:25566" + } + ] +} +``` + +This example project is located in the [`docs/developers/api/go`](https://github.com/minekube/gate/tree/main/.web/docs/developers/api/go) directory. + +::: info Learn More +For more details on using ConnectRPC with Go, check out the [ConnectRPC Documentation](https://connectrpc.com/docs/go/getting-started#make-requests). +::: + + diff --git a/.web/docs/developers/api/go/integration-options.md b/.web/docs/developers/api/go/integration-options.md new file mode 100644 index 00000000..e9b752ef --- /dev/null +++ b/.web/docs/developers/api/go/integration-options.md @@ -0,0 +1,119 @@ +
+ +
+

🔌 Native Go Plugin

+
    +
  • Create your own Go module and import Gate APIs
  • +
  • Compile like a normal Go program
  • +
  • Full access to Gate's core functionality
  • +
  • Maximum performance with in-process execution
  • +
  • Perfect for extending Gate's functionality
  • +
+ +
+
+ + +
+

🌐 HTTP API Client

+
    +
  • Language-agnostic interface
  • +
  • Perfect for out-of-process execution
  • +
  • Independent deployment cycles
  • +
  • Cross-version compatibility
  • +
  • Ideal for external integrations
  • +
+ +
+
+
+ + diff --git a/.web/docs/developers/api/go/main.go b/.web/docs/developers/api/go/main.go new file mode 100644 index 00000000..e5466081 --- /dev/null +++ b/.web/docs/developers/api/go/main.go @@ -0,0 +1,31 @@ +package main + +import ( + "context" + "encoding/json" + "log" + "net/http" + + "buf.build/gen/go/minekube/gate/connectrpc/go/minekube/gate/v1/gatev1connect" + gatev1 "buf.build/gen/go/minekube/gate/protocolbuffers/go/minekube/gate/v1" + "connectrpc.com/connect" +) + +// main is an example of how to use the ListServers method. +func main() { + ctx := context.Background() + + client := gatev1connect.NewGateServiceClient( + http.DefaultClient, + "http://localhost:8080", + ) + + req := connect.NewRequest(&gatev1.ListServersRequest{}) + res, err := client.ListServers(ctx, req) + if err != nil { + log.Fatalln("make sure Gate is running with the API enabled", err) + } + + j, _ := json.MarshalIndent(res.Msg, "", " ") + println(string(j)) +} diff --git a/.web/docs/developers/api/index.md b/.web/docs/developers/api/index.md new file mode 100644 index 00000000..4668d77c --- /dev/null +++ b/.web/docs/developers/api/index.md @@ -0,0 +1,92 @@ +# Gate HTTP API + +Gate provides a powerful API that exposes its functionality to a wide ecosystem of languages and tools. Using modern technologies like Protocol Buffers, gRPC, and ConnectRPC with schemas managed through buf.build. + +## Quick Start + +Simply enable the API in Gate's configuration, choose your preferred language's client library, and start building! + +::: code-group + +```yaml [config.yml] +api: + enabled: true + bind: localhost:8080 +``` + +::: + + + +## Features + +::: info Why Gate API? +The HTTP API enables you to build and deploy functionality independently from your proxy - perfect for rapid iteration without disrupting your players. +::: + +
+
+
🚀 Independent Updates
+
Ship updates without restarting Gate or disconnecting players
+
+
+
🌐 Cross-Language Support
+
Access Gate's core functionality from any programming language
+
+
+
🔌 Plugin Development
+
Build extensions and plugins in your preferred language
+
+
+
🤖 Automation
+
Automate server registration and management tasks
+
+
+
🎮 Custom Tools
+
Create administrative interfaces and management tools
+
+
+
🔄 Integration
+
Connect Gate with external systems and services
+
+
+ +::: tip Learn More +To understand the key technologies used in Gate's API, check out the [Glossary](/developers/api/glossary). +::: + + diff --git a/.web/docs/developers/api/java/index.md b/.web/docs/developers/api/java/index.md new file mode 100644 index 00000000..06f24bd3 --- /dev/null +++ b/.web/docs/developers/api/java/index.md @@ -0,0 +1,144 @@ +# Java Java + +Gate provides a Java API for integrating with your Java applications using gRPC. You can use the API to interact with Gate programmatically. + +## Installation + +First, configure your package manager to add the Buf registry. You only need to do this once: + +::: code-group + +```xml [Maven] + + + + Buf Maven Repository + buf + https://buf.build/gen/maven + + true + + + false + + + +``` + +```kotlin [Gradle (Kotlin)] +// build.gradle.kts +repositories { + mavenCentral() + maven { + name = "buf" + url = uri("https://buf.build/gen/maven") + } +} +``` + +```groovy [Gradle (Groovy)] +// build.gradle +repositories { + mavenCentral() + maven { + name = 'buf' + url 'https://buf.build/gen/maven' + } +} +``` + +::: + +Then add the dependencies: + +::: warning Latest Version Check +Make sure to check [buf.build/minekube/gate/sdks](https://buf.build/minekube/gate/sdks) for the latest versions of the dependencies. +::: + +::: code-group + +```xml [Maven] + + + + build.buf.gen + minekube_gate_protocolbuffers_java + 28.3.0.2.20241118150055.50fffb007499 + + + build.buf.gen + minekube_gate_grpc_java + 1.68.1.1.20241118150055.50fffb007499 + + +``` + +```kotlin [Gradle (Kotlin)] +dependencies { + // Check latest version at https://buf.build/minekube/gate/sdks + implementation("build.buf.gen:minekube_gate_protocolbuffers_java:28.3.0.2.20241118150055.50fffb007499") + implementation("build.buf.gen:minekube_gate_grpc_java:1.68.1.1.20241118150055.50fffb007499") +} +``` + +```groovy [Gradle (Groovy)] +dependencies { + // Check latest version at https://buf.build/minekube/gate/sdks + implementation 'build.buf.gen:minekube_gate_protocolbuffers_java:28.3.0.2.20241118150055.50fffb007499' + implementation 'build.buf.gen:minekube_gate_grpc_java:1.68.1.1.20241118150055.50fffb007499' +} +``` + +::: + +## Usage Example + +Here's a basic example of using the Gate Java API to connect to Gate and list servers: + +```java + +``` + +## Running the Example + +1. Run Gate with the API enabled +2. Navigate to the [docs/developers/api/java](https://github.com/minekube/gate/tree/main/.web/docs/developers/api/java) directory +3. Run the following commands: + +```bash +mvn compile +mvn exec:java -Dexec.mainClass="com.example.Main" + +servers { + name: "server3" + address: "localhost:25568" +} +servers { + name: "server4" + address: "localhost:25569" +} +servers { + name: "server1" + address: "localhost:25566" +} +servers { + name: "server2" + address: "localhost:25567" +} +``` + +::: info Learn More +For more details on using gRPC with Java, check out the [gRPC Java Documentation](https://grpc.io/docs/languages/java/basics/). +::: + + diff --git a/.web/docs/developers/api/java/pom.xml b/.web/docs/developers/api/java/pom.xml new file mode 100644 index 00000000..4b94d635 --- /dev/null +++ b/.web/docs/developers/api/java/pom.xml @@ -0,0 +1,66 @@ + + + 4.0.0 + + com.example + gate-example + 1.0-SNAPSHOT + + + 11 + 11 + UTF-8 + + + + + Buf Maven Repository + buf + https://buf.build/gen/maven + + true + + + false + + + + + + + + build.buf.gen + minekube_gate_protocolbuffers_java + 28.3.0.2.20241118150055.50fffb007499 + + + build.buf.gen + minekube_gate_grpc_java + 1.68.1.1.20241118150055.50fffb007499 + + + + io.grpc + grpc-netty-shaded + 1.68.1 + + + io.grpc + grpc-protobuf + 1.68.1 + + + io.grpc + grpc-stub + 1.68.1 + + + + com.google.protobuf + protobuf-java + 4.28.3 + + + \ No newline at end of file diff --git a/.web/docs/developers/api/java/src/main/java/com/example/Main.java b/.web/docs/developers/api/java/src/main/java/com/example/Main.java new file mode 100644 index 00000000..99b8d174 --- /dev/null +++ b/.web/docs/developers/api/java/src/main/java/com/example/Main.java @@ -0,0 +1,32 @@ +package com.example; + +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import build.buf.gen.minekube.gate.v1.*; + +public class Main { + public static void main(String[] args) { + try { + // Create a gRPC channel + ManagedChannel channel = ManagedChannelBuilder + .forAddress("localhost", 8080) + .usePlaintext() + .build(); + + // Create a blocking stub + GateServiceGrpc.GateServiceBlockingStub stub = GateServiceGrpc.newBlockingStub(channel); + + // List all servers + ListServersResponse response = stub.listServers(ListServersRequest.getDefaultInstance()); + + // Print protobuf response + System.out.println(response); + + // Shutdown the channel + channel.shutdown(); + } catch (Exception e) { + System.err.println("Make sure Gate is running with the API enabled"); + e.printStackTrace(); + } + } +} diff --git a/.web/docs/developers/api/kotlin/build.gradle.kts b/.web/docs/developers/api/kotlin/build.gradle.kts new file mode 100644 index 00000000..bf10bc3b --- /dev/null +++ b/.web/docs/developers/api/kotlin/build.gradle.kts @@ -0,0 +1,51 @@ +plugins { + kotlin("jvm") version "1.9.21" + application +} + +repositories { + mavenCentral() + maven { + name = "buf" + url = uri("https://buf.build/gen/maven") + } +} + +val grpcVersion = "1.68.1" +val grpcKotlinVersion = "1.4.1" +val connectVersion = "0.7.1" +val protobufVersion = "4.28.3" + +dependencies { + // Kotlin + implementation(kotlin("stdlib")) + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") + + // Connect-RPC + implementation("build.buf.gen:minekube_gate_connectrpc_kotlin:${connectVersion}.1.20241118150055.50fffb007499") + + // gRPC + implementation("build.buf.gen:minekube_gate_grpc_kotlin:${grpcKotlinVersion}.1.20241118150055.50fffb007499") + implementation("io.grpc:grpc-kotlin-stub:$grpcKotlinVersion") + implementation("io.grpc:grpc-protobuf:$grpcVersion") + implementation("io.grpc:grpc-netty-shaded:$grpcVersion") + + // Protobuf + implementation("com.google.protobuf:protobuf-java:$protobufVersion") +} + +// Configure multiple main classes +application { + mainClass.set("com.example.ConnectExampleKt") // Default main class +} + +// Create tasks for running each example +tasks.register("runConnect") { + classpath = sourceSets["main"].runtimeClasspath + mainClass.set("com.example.connect.ConnectExampleKt") +} + +tasks.register("runGrpc") { + classpath = sourceSets["main"].runtimeClasspath + mainClass.set("com.example.grpc.GrpcExampleKt") +} diff --git a/.web/docs/developers/api/kotlin/index.md b/.web/docs/developers/api/kotlin/index.md new file mode 100644 index 00000000..e57335b5 --- /dev/null +++ b/.web/docs/developers/api/kotlin/index.md @@ -0,0 +1,207 @@ +# Kotlin Kotlin + +Gate provides a Kotlin API for integrating with your Kotlin applications using either Connect-RPC or gRPC. You can use the API to interact with Gate programmatically. + +## Installation + +First, configure your package manager to add the Buf registry. You only need to do this once: + +::: code-group + +```kotlin [Gradle (Kotlin)] +// build.gradle.kts +repositories { + mavenCentral() + maven { + name = "buf" + url = uri("https://buf.build/gen/maven") + } +} +``` + +```groovy [Gradle (Groovy)] +// build.gradle +repositories { + mavenCentral() + maven { + name = 'buf' + url 'https://buf.build/gen/maven' + } +} +``` + +```xml [Maven] + + + + Buf Maven Repository + buf + https://buf.build/gen/maven + + true + + + false + + + +``` + +::: + +Then add the dependencies. You can choose between Connect-RPC (recommended) or gRPC: + +::: warning Latest Version Check +Make sure to check [buf.build/minekube/gate/sdks](https://buf.build/minekube/gate/sdks) for the latest versions of the dependencies. +::: + +::: code-group + +```kotlin [Gradle (Kotlin) - Connect] +dependencies { + // Connect-RPC for Kotlin (Recommended) + implementation("build.buf.gen:minekube_gate_connectrpc_kotlin:0.7.1.1.20241118150055.50fffb007499") + implementation("com.connectrpc:connect-kotlin:0.7.1") +} +``` + +```groovy [Gradle (Groovy) - Connect] +dependencies { + // Connect-RPC for Kotlin (Recommended) + implementation 'build.buf.gen:minekube_gate_connectrpc_kotlin:0.7.1.1.20241118150055.50fffb007499' + implementation 'com.connectrpc:connect-kotlin:0.7.1' +} +``` + +```xml [Maven - Connect] + + + + build.buf.gen + minekube_gate_connectrpc_kotlin + 0.7.1.1.20241118150055.50fffb007499 + + + com.connectrpc + connect-kotlin + 0.7.1 + + +``` + +```kotlin [Gradle (Kotlin) - gRPC] +dependencies { + // gRPC for Kotlin + implementation("build.buf.gen:minekube_gate_grpc_kotlin:1.4.1.1.20241118150055.50fffb007499") + implementation("io.grpc:grpc-kotlin-stub:1.4.1") + implementation("io.grpc:grpc-protobuf:1.68.1") + implementation("io.grpc:grpc-netty-shaded:1.68.1") +} +``` + +```groovy [Gradle (Groovy) - gRPC] +dependencies { + // gRPC for Kotlin + implementation 'build.buf.gen:minekube_gate_grpc_kotlin:1.4.1.1.20241118150055.50fffb007499' + implementation 'io.grpc:grpc-kotlin-stub:1.4.1' + implementation 'io.grpc:grpc-protobuf:1.68.1' + implementation 'io.grpc:grpc-netty-shaded:1.68.1' +} +``` + +```xml [Maven - gRPC] + + + + build.buf.gen + minekube_gate_grpc_kotlin + 1.4.1.1.20241118150055.50fffb007499 + + + io.grpc + grpc-kotlin-stub + 1.4.1 + + + io.grpc + grpc-protobuf + 1.68.1 + + + io.grpc + grpc-netty-shaded + 1.68.1 + + +``` + +::: + +## Usage Example + +Here's a basic example of using the Gate Kotlin API to connect to Gate and list servers: + +::: code-group + +```kotlin [Connect] + +``` + +```kotlin [gRPC] + +``` + +::: + +## Running the Example + +1. Run Gate with the API enabled +2. Navigate to the [docs/developers/api/kotlin](https://github.com/minekube/gate/tree/main/.web/docs/developers/api/kotlin) directory +3. Initialize the Gradle wrapper (only needed once): +```bash +gradle wrapper +``` + +4. Run one of the following commands: +```bash +# For Connect example (recommended) +./gradlew runConnect + +# For gRPC example +./gradlew runGrpc + +# Example output: +servers { + name: "server3" + address: "localhost:25568" +} +servers { + name: "server4" + address: "localhost:25569" +} +servers { + name: "server1" + address: "localhost:25566" +} +servers { + name: "server2" + address: "localhost:25567" +} +``` + +::: info Learn More +For more details on using ConnectRPC with Kotlin, check out the [ConnectRPC Documentation](https://connectrpc.com/docs/kotlin/using-clients). +::: + + + diff --git a/.web/docs/developers/api/kotlin/settings.gradle.kts b/.web/docs/developers/api/kotlin/settings.gradle.kts new file mode 100644 index 00000000..7ac6dce1 --- /dev/null +++ b/.web/docs/developers/api/kotlin/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "gate-example" \ No newline at end of file diff --git a/.web/docs/developers/api/kotlin/src/main/kotlin/com/example/connect/ConnectExample.kt b/.web/docs/developers/api/kotlin/src/main/kotlin/com/example/connect/ConnectExample.kt new file mode 100644 index 00000000..a767297b --- /dev/null +++ b/.web/docs/developers/api/kotlin/src/main/kotlin/com/example/connect/ConnectExample.kt @@ -0,0 +1,38 @@ +package com.example.connect + +import build.buf.gen.minekube.gate.v1.GateServiceClient +import build.buf.gen.minekube.gate.v1.ListServersRequest +import com.connectrpc.ConnectException +import com.connectrpc.ProtocolClientConfig +import com.connectrpc.extensions.GoogleJavaProtobufStrategy +import com.connectrpc.impl.ProtocolClient +import com.connectrpc.okhttp.ConnectOkHttpClient +import com.connectrpc.protocols.NetworkProtocol +import kotlinx.coroutines.runBlocking +import okhttp3.OkHttpClient + +fun main() = runBlocking { + try { + // Create a Connect client + val client = ProtocolClient( + httpClient = ConnectOkHttpClient(OkHttpClient()), + ProtocolClientConfig( + host = "http://localhost:8080", + serializationStrategy = GoogleJavaProtobufStrategy(), + networkProtocol = NetworkProtocol.CONNECT, + ), + ) + + // Create the service client + val gateService = GateServiceClient(client) + + // List all servers + val request = ListServersRequest.newBuilder().build() + val response = gateService.listServers(request) + println(response.toString()) + + } catch (e: ConnectException) { + System.err.println("Make sure Gate is running with the API enabled") + e.printStackTrace() + } +} diff --git a/.web/docs/developers/api/kotlin/src/main/kotlin/com/example/grpc/GrpcExample.kt b/.web/docs/developers/api/kotlin/src/main/kotlin/com/example/grpc/GrpcExample.kt new file mode 100644 index 00000000..a54f0576 --- /dev/null +++ b/.web/docs/developers/api/kotlin/src/main/kotlin/com/example/grpc/GrpcExample.kt @@ -0,0 +1,30 @@ +package com.example.grpc + +import io.grpc.ManagedChannelBuilder +import build.buf.gen.minekube.gate.v1.GateServiceGrpcKt +import build.buf.gen.minekube.gate.v1.ListServersRequest +import kotlinx.coroutines.runBlocking + +fun main(): Unit = runBlocking { + try { + // Create a gRPC channel + val channel = ManagedChannelBuilder + .forAddress("localhost", 8080) + .usePlaintext() + .build() + + // Create the service client + val stub = GateServiceGrpcKt.GateServiceCoroutineStub(channel) + + // List all servers + val response = stub.listServers(ListServersRequest.getDefaultInstance()) + println(response) + + // Shutdown the channel + channel.shutdown() + + } catch (e: Exception) { + System.err.println("Make sure Gate is running with the API enabled") + e.printStackTrace() + } +} diff --git a/.web/docs/developers/api/python/index.md b/.web/docs/developers/api/python/index.md new file mode 100644 index 00000000..6eff1ae7 --- /dev/null +++ b/.web/docs/developers/api/python/index.md @@ -0,0 +1,148 @@ +# Python Python Client + +Gate provides a Python API for integrating with your Python applications. You can use the API to interact with Gate programmatically using either gRPC or HTTP protocols. + +## Environment Setup + +::: tip Best DX +We recommend using [uv](https://github.com/astral-sh/uv) for beginners and experienced developers alike! +::: + +::: code-group + +```bash [uv (Recommended)] +# Install uv (on macOS/Linux) +curl -LsSf https://astral.sh/uv/install.sh | sh + +# Create a new virtual environment +uv init +``` + +```bash [venv] +# Create a new virtual environment +python3 -m venv .venv + +# Activate the environment (Unix) +source .venv/bin/activate + +# Activate the environment (Windows) +.venv\Scripts\activate +``` + +```bash [poetry] +# Install poetry +curl -sSL https://install.python-poetry.org | python3 - + +# Create new project +poetry init +poetry shell +``` + +```bash [pipenv] +# Install pipenv +pip install pipenv + +# Create environment and activate shell +pipenv install +pipenv shell +``` + +::: + +## Installation + +::: code-group + +```bash [uv (Recommended)] +uv add minekube-gate-grpc-python minekube-gate-protocolbuffers-python --index https://buf.build/gen/python +``` + +```bash [pip] +python3 -m pip install minekube-gate-grpc-python minekube-gate-protocolbuffers-python --extra-index-url https://buf.build/gen/python +``` + +```bash [poetry] +poetry add minekube-gate-grpc-python minekube-gate-protocolbuffers-python --source buf.build/gen/python +``` + +```bash [pipenv] +pipenv install minekube-gate-grpc-python minekube-gate-protocolbuffers-python --extra-index-url https://buf.build/gen/python +``` + +::: + +## Usage Example + +Here's a basic example of using the Gate Python API to connect to Gate and list servers: + +::: code-group + +```python [main.py] + +``` + +::: + +## Running the Example + +1. Make sure Gate is running with the API enabled +2. Save one of the example scripts above to `main.py` +3. Run the script: + +::: code-group + +```bash [uv (Recommended)] +uv run main.py +{ + "servers": [ + { + "name": "server3", + "address": "localhost:25568" + }, + { + "name": "server4", + "address": "localhost:25569" + }, + { + "name": "server1", + "address": "localhost:25566" + }, + { + "name": "server2", + "address": "localhost:25567" + } + ] +} +``` + +```bash [python] +python3 main.py +``` + +```bash [poetry] +poetry run python main.py +``` + +```bash [pipenv] +pipenv run python main.py +``` + +::: + +::: info Learn More + +- [uv Documentation](https://github.com/astral-sh/uv) - Learn more about the recommended Python package manager +- [gRPC Python Documentation](https://grpc.io/docs/languages/python/basics/) - Learn more about using gRPC with Python + ::: + + diff --git a/.web/docs/developers/api/python/main.py b/.web/docs/developers/api/python/main.py new file mode 100644 index 00000000..83e2968a --- /dev/null +++ b/.web/docs/developers/api/python/main.py @@ -0,0 +1,30 @@ +import grpc +import json +from google.protobuf import json_format +from minekube.gate.v1 import gate_service_pb2 as gatepb +from minekube.gate.v1 import gate_service_pb2_grpc as gateapi + + +def main(): + # Create a gRPC channel + channel = grpc.insecure_channel('localhost:8080') + + # Create a stub (client) + stub = gateapi.GateServiceStub(channel) + + try: + # List servers + response = stub.ListServers(gatepb.ListServersRequest()) + # Convert to JSON and print + json_response = json_format.MessageToDict(response) + print(json.dumps(json_response, indent=2)) + + except grpc.RpcError as e: + print(f"RPC failed: {e}") + + finally: + channel.close() + + +if __name__ == '__main__': + main() diff --git a/.web/docs/developers/api/python/pyproject.toml b/.web/docs/developers/api/python/pyproject.toml new file mode 100644 index 00000000..03e5dac3 --- /dev/null +++ b/.web/docs/developers/api/python/pyproject.toml @@ -0,0 +1,13 @@ +[project] +name = "python" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.13" +dependencies = [ + "minekube-gate-grpc-python>=1.68.0.1.20241118150055", + "minekube-gate-protocolbuffers-python>=28.3.0.2.20241118150055", +] + +[[tool.uv.index]] +url = "https://buf.build/gen/python" diff --git a/.web/docs/developers/api/python/uv.lock b/.web/docs/developers/api/python/uv.lock new file mode 100644 index 00000000..c729673e --- /dev/null +++ b/.web/docs/developers/api/python/uv.lock @@ -0,0 +1,93 @@ +version = 1 +requires-python = ">=3.13" + +[[package]] +name = "grpcio" +version = "1.68.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d5/da/132615afbfc722df4bba963844843a205aa298fd5f9a03fa2995e8dddf11/grpcio-1.68.0.tar.gz", hash = "sha256:7e7483d39b4a4fddb9906671e9ea21aaad4f031cdfc349fec76bdfa1e404543a", size = 12682655 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/2d/d9cbdb75dc99141705f08474e97b181034c2e53a345d94b58e3c55f4dd92/grpcio-1.68.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:fc05759ffbd7875e0ff2bd877be1438dfe97c9312bbc558c8284a9afa1d0f40e", size = 5149697 }, + { url = "https://files.pythonhosted.org/packages/6f/37/a848871a5adba8cd571fa89e8aabc40ca0c475bd78b2e645e1649b20e095/grpcio-1.68.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:15fa1fe25d365a13bc6d52fcac0e3ee1f9baebdde2c9b3b2425f8a4979fccea1", size = 11084394 }, + { url = "https://files.pythonhosted.org/packages/1f/52/b09374aab9c9c2f66627ce7de39eef41d73670aa0f75286d91dcc22a2dd8/grpcio-1.68.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:32a9cb4686eb2e89d97022ecb9e1606d132f85c444354c17a7dbde4a455e4a3b", size = 5645417 }, + { url = "https://files.pythonhosted.org/packages/01/78/ec5ad7c44d7adaf0b932fd41ce8c59a95177a8c79c947c77204600b652db/grpcio-1.68.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dba037ff8d284c8e7ea9a510c8ae0f5b016004f13c3648f72411c464b67ff2fb", size = 6291062 }, + { url = "https://files.pythonhosted.org/packages/f7/7f/7f5a1a8dc63a42b78ca930d195eb0c97aa7a09e8553bb3a07b7cf37f6bc1/grpcio-1.68.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0efbbd849867e0e569af09e165363ade75cf84f5229b2698d53cf22c7a4f9e21", size = 5906505 }, + { url = "https://files.pythonhosted.org/packages/41/7b/0b048b8ad1a09fab5f4567fba2a569fb9106c4c1bb473c009c25659542cb/grpcio-1.68.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:4e300e6978df0b65cc2d100c54e097c10dfc7018b9bd890bbbf08022d47f766d", size = 6635069 }, + { url = "https://files.pythonhosted.org/packages/5e/c5/9f0ebc9cfba8309a15a9786c953ce99eaf4e1ca2df402b3c5ecf42493bd4/grpcio-1.68.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:6f9c7ad1a23e1047f827385f4713b5b8c6c7d325705be1dd3e31fb00dcb2f665", size = 6200683 }, + { url = "https://files.pythonhosted.org/packages/ce/e1/d3eba05299d5acdae6c11d056308b885f1d1be0b328baa8233d5d139ec1d/grpcio-1.68.0-cp313-cp313-win32.whl", hash = "sha256:3ac7f10850fd0487fcce169c3c55509101c3bde2a3b454869639df2176b60a03", size = 3637301 }, + { url = "https://files.pythonhosted.org/packages/3c/c1/decb2b368a54c00a6ee815c3f610903f36432e3cb591d43369319826b05e/grpcio-1.68.0-cp313-cp313-win_amd64.whl", hash = "sha256:afbf45a62ba85a720491bfe9b2642f8761ff348006f5ef67e4622621f116b04a", size = 4390939 }, +] + +[[package]] +name = "minekube-gate-grpc-python" +version = "1.68.0.1.20241118150055+50fffb007499" +source = { registry = "https://buf.build/gen/python" } +dependencies = [ + { name = "grpcio" }, + { name = "minekube-gate-protocolbuffers-python" }, +] +wheels = [ + { url = "https://buf.build/gen/python/minekube-gate-grpc-python/minekube_gate_grpc_python-1.68.0.1.20241118150055+50fffb007499-py3-none-any.whl" }, +] + +[[package]] +name = "minekube-gate-protocolbuffers-pyi" +version = "28.3.0.2.20241118150055+50fffb007499" +source = { registry = "https://buf.build/gen/python" } +dependencies = [ + { name = "protobuf" }, + { name = "types-protobuf" }, +] +wheels = [ + { url = "https://buf.build/gen/python/minekube-gate-protocolbuffers-pyi/minekube_gate_protocolbuffers_pyi-28.3.0.2.20241118150055+50fffb007499-py3-none-any.whl" }, +] + +[[package]] +name = "minekube-gate-protocolbuffers-python" +version = "28.3.0.2.20241118150055+50fffb007499" +source = { registry = "https://buf.build/gen/python" } +dependencies = [ + { name = "minekube-gate-protocolbuffers-pyi" }, + { name = "protobuf" }, +] +wheels = [ + { url = "https://buf.build/gen/python/minekube-gate-protocolbuffers-python/minekube_gate_protocolbuffers_python-28.3.0.2.20241118150055+50fffb007499-py3-none-any.whl" }, +] + +[[package]] +name = "protobuf" +version = "5.28.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/74/6e/e69eb906fddcb38f8530a12f4b410699972ab7ced4e21524ece9d546ac27/protobuf-5.28.3.tar.gz", hash = "sha256:64badbc49180a5e401f373f9ce7ab1d18b63f7dd4a9cdc43c92b9f0b481cef7b", size = 422479 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/c5/05163fad52d7c43e124a545f1372d18266db36036377ad29de4271134a6a/protobuf-5.28.3-cp310-abi3-win32.whl", hash = "sha256:0c4eec6f987338617072592b97943fdbe30d019c56126493111cf24344c1cc24", size = 419624 }, + { url = "https://files.pythonhosted.org/packages/9c/4c/4563ebe001ff30dca9d7ed12e471fa098d9759712980cde1fd03a3a44fb7/protobuf-5.28.3-cp310-abi3-win_amd64.whl", hash = "sha256:91fba8f445723fcf400fdbe9ca796b19d3b1242cd873907979b9ed71e4afe868", size = 431464 }, + { url = "https://files.pythonhosted.org/packages/1c/f2/baf397f3dd1d3e4af7e3f5a0382b868d25ac068eefe1ebde05132333436c/protobuf-5.28.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a3f6857551e53ce35e60b403b8a27b0295f7d6eb63d10484f12bc6879c715687", size = 414743 }, + { url = "https://files.pythonhosted.org/packages/85/50/cd61a358ba1601f40e7d38bcfba22e053f40ef2c50d55b55926aecc8fec7/protobuf-5.28.3-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:3fa2de6b8b29d12c61911505d893afe7320ce7ccba4df913e2971461fa36d584", size = 316511 }, + { url = "https://files.pythonhosted.org/packages/5d/ae/3257b09328c0b4e59535e497b0c7537d4954038bdd53a2f0d2f49d15a7c4/protobuf-5.28.3-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:712319fbdddb46f21abb66cd33cb9e491a5763b2febd8f228251add221981135", size = 316624 }, + { url = "https://files.pythonhosted.org/packages/ad/c3/2377c159e28ea89a91cf1ca223f827ae8deccb2c9c401e5ca233cd73002f/protobuf-5.28.3-py3-none-any.whl", hash = "sha256:cee1757663fa32a1ee673434fcf3bf24dd54763c79690201208bafec62f19eed", size = 169511 }, +] + +[[package]] +name = "python" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "minekube-gate-grpc-python" }, + { name = "minekube-gate-protocolbuffers-python" }, +] + +[package.metadata] +requires-dist = [ + { name = "minekube-gate-grpc-python", specifier = ">=1.68.0.1.20241118150055" }, + { name = "minekube-gate-protocolbuffers-python", specifier = ">=28.3.0.2.20241118150055" }, +] + +[[package]] +name = "types-protobuf" +version = "5.28.3.20241030" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c8/d4/d186e43cfb38ecefc91315ee9193d5722a88d7a3c8eac34a3ed603377407/types-protobuf-5.28.3.20241030.tar.gz", hash = "sha256:f7e6b45845d75393fb41c0b3ce82c46d775f9771fae2097414a1dbfe5b51a988", size = 54665 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/72/da/c261bb44799d3f4455fc881ca342c14f5b5b23878bef568a1cdcd324e62f/types_protobuf-5.28.3.20241030-py3-none-any.whl", hash = "sha256:f3dae16adf342d4fb5bb3673cabb22549a6252e5dd66fc52d8310b1a39c64ba9", size = 68781 }, +] diff --git a/.web/docs/developers/api/rust/Cargo.lock b/.web/docs/developers/api/rust/Cargo.lock new file mode 100644 index 00000000..3a7c8323 --- /dev/null +++ b/.web/docs/developers/api/rust/Cargo.lock @@ -0,0 +1,976 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "anyhow" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "axum" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" +dependencies = [ + "async-trait", + "axum-core", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper 1.0.1", + "tower 0.5.1", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper 1.0.1", + "tower-layer", + "tower-service", +] + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap 2.6.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.1", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "libc" +version = "0.2.164" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" + +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "minekube_gate_community_neoeinstein-prost" +version = "0.4.0-20241118150055-50fffb007499.1" +source = "sparse+https://buf.build/gen/cargo/" +checksum = "d4687c4eff9beb46b13fb1f408d83e0734d9f6e7d6a19a536f5bc1633df66ec0" +dependencies = [ + "prost", + "prost-types", +] + +[[package]] +name = "minekube_gate_community_neoeinstein-tonic" +version = "0.4.1-20241118150055-50fffb007499.1" +source = "sparse+https://buf.build/gen/cargo/" +checksum = "890525679f6fcadaf589068d49c904143df9820c7dd7cf0bef666bcea82b6555" +dependencies = [ + "minekube_gate_community_neoeinstein-prost", + "tonic", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys", +] + +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" +dependencies = [ + "prost", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rust" +version = "0.1.0" +dependencies = [ + "minekube_gate_community_neoeinstein-prost", + "minekube_gate_community_neoeinstein-tonic", + "tokio", + "tonic", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[package]] +name = "serde" +version = "1.0.215" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.215" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "syn" +version = "2.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + +[[package]] +name = "tokio" +version = "1.41.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-stream" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tonic" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64", + "bytes", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "prost", + "socket2", + "tokio", + "tokio-stream", + "tower 0.4.13", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap 1.9.3", + "pin-project", + "pin-project-lite", + "rand", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/.web/docs/developers/api/rust/Cargo.toml b/.web/docs/developers/api/rust/Cargo.toml new file mode 100644 index 00000000..876bcc1d --- /dev/null +++ b/.web/docs/developers/api/rust/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "rust" +version = "0.1.0" +edition = "2021" + +[dependencies] +minekube_gate_community_neoeinstein-prost = { version = "0.4.0-20241118150055-50fffb007499.1", registry = "buf" } +minekube_gate_community_neoeinstein-tonic = { version = "0.4.1-20241118150055-50fffb007499.1", registry = "buf" } +tokio = { version = "1.41.1", features = ["macros", "rt-multi-thread"] } +tonic = "0.12.3" diff --git a/.web/docs/developers/api/rust/index.md b/.web/docs/developers/api/rust/index.md new file mode 100644 index 00000000..f932f5b5 --- /dev/null +++ b/.web/docs/developers/api/rust/index.md @@ -0,0 +1,106 @@ +# Rust Rust Client + +Gate provides a Rust API for integrating with your Rust applications. You can use the API to interact with Gate programmatically using gRPC. + +## Environment Setup + +First, make sure you have Rust and Cargo installed. If not, install them using [rustup](https://rustup.rs/): + +```bash +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +``` + +## Registry Configuration + +1. Configure Cargo to use the Buf registry. Add the following to your `~/.cargo/config.toml`: + +```toml +[registries.buf] +index = "sparse+https://buf.build/gen/cargo/" +credential-provider = "cargo:token" +``` + +2. Configure authentication (required even for public repositories): + 1. Go to [Gate SDKs on Buf](https://buf.build/minekube/gate/sdks) + 2. Select the Rust SDK + 3. Scroll down to generate a token + 4. Use the token to authenticate: + ```bash + cargo login --registry buf "Bearer YOUR_TOKEN" + ``` + +## Installation + +Add the Gate SDK to your project: + +```bash +cargo add --registry buf minekube_gate_community_neoeinstein-prost +cargo add --registry buf minekube_gate_community_neoeinstein-tonic +cargo add tonic --features tls-roots # Enable the features we need +cargo add tokio --features macros,rt-multi-thread # Async runtime +``` + +This is the sample `Cargo.toml` file from the [`docs/developers/api/rust`](https://github.com/minekube/gate/tree/main/.web/docs/developers/api/rust) directory: + +```toml + +``` + +## Usage Example + +Here's a basic example of using the Gate Rust API to connect to Gate and list servers: + +::: code-group + +```rust [src/main.rs] + +``` + +::: + +## Running the Example + +1. Make sure Gate is running with the API enabled +2. Run the example: + +```bash +cargo run +[ + Server { + name: "server1", + address: "localhost:25566", + players: 0, + }, + Server { + name: "server2", + address: "localhost:25567", + players: 0, + }, + Server { + name: "server3", + address: "localhost:25568", + players: 0, + }, + Server { + name: "server4", + address: "localhost:25569", + players: 0, + }, +] +``` + +::: info Learn More +Refer to the [Buf Blog](https://buf.build/blog/bsr-generated-sdks-for-rust) for more information about using the generated Rust SDKs. +::: + + diff --git a/.web/docs/developers/api/rust/src/main.rs b/.web/docs/developers/api/rust/src/main.rs new file mode 100644 index 00000000..d5a63b94 --- /dev/null +++ b/.web/docs/developers/api/rust/src/main.rs @@ -0,0 +1,25 @@ +use minekube_gate_community_neoeinstein_prost::minekube::gate::v1::ListServersRequest; +use minekube_gate_community_neoeinstein_tonic::minekube::gate::v1::tonic::gate_service_client::GateServiceClient; + +fn main() -> Result<(), Box> { + // Create a runtime for async operations + let rt = tokio::runtime::Runtime::new()?; + rt.block_on(async { + // Create a gRPC channel + let channel = tonic::transport::Channel::from_static("http://localhost:8080") + .connect() + .await?; + + // Create the client + let mut client = GateServiceClient::new(channel); + + // Make the request + let request = tonic::Request::new(ListServersRequest {}); + let response = client.list_servers(request).await?; + + // Print the response + println!("{:#?}", response.get_ref().servers); + + Ok(()) + }) +} diff --git a/.web/docs/developers/api/sdks.md b/.web/docs/developers/api/sdks.md new file mode 100644 index 00000000..dcdb38ab --- /dev/null +++ b/.web/docs/developers/api/sdks.md @@ -0,0 +1,106 @@ +## Official SDKs + +Gate's API definitions are hosted on [buf.build/minekube/gate](https://buf.build/minekube/gate/sdks), where you can directly pull client libraries using your preferred language's package manager: + + + + diff --git a/.web/docs/developers/api/typescript/README.md b/.web/docs/developers/api/typescript/README.md new file mode 100644 index 00000000..58a6e275 --- /dev/null +++ b/.web/docs/developers/api/typescript/README.md @@ -0,0 +1,15 @@ +# bun + +To install dependencies: + +```bash +bun install +``` + +To run: + +```bash +bun run index.ts +``` + +This project was created using `bun init` in bun v1.1.26. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime. diff --git a/.web/docs/developers/api/typescript/bun/.gitignore b/.web/docs/developers/api/typescript/bun/.gitignore new file mode 100644 index 00000000..9b1ee42e --- /dev/null +++ b/.web/docs/developers/api/typescript/bun/.gitignore @@ -0,0 +1,175 @@ +# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore + +# Logs + +logs +_.log +npm-debug.log_ +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Caches + +.cache + +# Diagnostic reports (https://nodejs.org/api/report.html) + +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# Runtime data + +pids +_.pid +_.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover + +lib-cov + +# Coverage directory used by tools like istanbul + +coverage +*.lcov + +# nyc test coverage + +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) + +.grunt + +# Bower dependency directory (https://bower.io/) + +bower_components + +# node-waf configuration + +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) + +build/Release + +# Dependency directories + +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) + +web_modules/ + +# TypeScript cache + +*.tsbuildinfo + +# Optional npm cache directory + +.npm + +# Optional eslint cache + +.eslintcache + +# Optional stylelint cache + +.stylelintcache + +# Microbundle cache + +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history + +.node_repl_history + +# Output of 'npm pack' + +*.tgz + +# Yarn Integrity file + +.yarn-integrity + +# dotenv environment variable files + +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) + +.parcel-cache + +# Next.js build output + +.next +out + +# Nuxt.js build / generate output + +.nuxt +dist + +# Gatsby files + +# Comment in the public line in if your project uses Gatsby and not Next.js + +# https://nextjs.org/blog/next-9-1#public-directory-support + +# public + +# vuepress build output + +.vuepress/dist + +# vuepress v2.x temp and cache directory + +.temp + +# Docusaurus cache and generated files + +.docusaurus + +# Serverless directories + +.serverless/ + +# FuseBox cache + +.fusebox/ + +# DynamoDB Local files + +.dynamodb/ + +# TernJS port file + +.tern-port + +# Stores VSCode versions used for testing VSCode extensions + +.vscode-test + +# yarn v2 + +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# IntelliJ based IDEs +.idea + +# Finder (MacOS) folder config +.DS_Store diff --git a/.web/docs/developers/api/typescript/bun/bun.lockb b/.web/docs/developers/api/typescript/bun/bun.lockb new file mode 100755 index 00000000..f6fbe449 Binary files /dev/null and b/.web/docs/developers/api/typescript/bun/bun.lockb differ diff --git a/.web/docs/developers/api/typescript/bun/bunfig.toml b/.web/docs/developers/api/typescript/bun/bunfig.toml new file mode 100644 index 00000000..ab7b9d5d --- /dev/null +++ b/.web/docs/developers/api/typescript/bun/bunfig.toml @@ -0,0 +1,2 @@ +[install.scopes] +"@buf" = "https://buf.build/gen/npm/v1/" diff --git a/.web/docs/developers/api/typescript/bun/index.md b/.web/docs/developers/api/typescript/bun/index.md new file mode 100644 index 00000000..00ac3f8b --- /dev/null +++ b/.web/docs/developers/api/typescript/bun/index.md @@ -0,0 +1,101 @@ +# Bun Bun + +You can use the following `bunfig.toml` to install the dependencies from the `buf.build` registry. + +::: code-group + +```toml [bunfig.toml] + +``` + +::: + +To install dependencies: + +::: code-group + +```bash [bun] +bun add @buf/minekube_gate.connectrpc_es@latest +``` + +```bash [pnpm] +pnpm add @buf/minekube_gate.connectrpc_es@latest +``` + +```bash [npm] +npm install @buf/minekube_gate.connectrpc_es@latest +``` + +```bash [yarn] +yarn add @buf/minekube_gate.connectrpc_es@latest +``` + +::: + +Refer to the [ConnectRPC](https://connectrpc.com/docs/node/using-clients) documentation for more information on how to use ConnectRPC with TypeScript on server side. + +::: tip Browser support + +To use the Gate API in the browser, check out the [Web](/developers/api/typescript/web/) documentation. + +::: + +::: code-group + +```ts [index.ts] + +``` + +::: + +## Sample project + +This sample project is located in the [`docs/developers/api/typescript/bun`](https://github.com/minekube/gate/tree/main/.web/docs/developers/api/typescript/bun) directory. + +To install dependencies: + +```bash +bun install +``` + +To run: + +```bash +bun run index.ts +[ + { + "name": "server1", + "address": "localhost:25566", + "players": 0 + }, + { + "name": "server2", + "address": "localhost:25567", + "players": 0 + }, + { + "name": "server3", + "address": "localhost:25568", + "players": 0 + }, + { + "name": "server4", + "address": "localhost:25569", + "players": 0 + } +] +``` + +This project was created using `bun init` in bun v1.1.26. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime. + + diff --git a/.web/docs/developers/api/typescript/bun/index.ts b/.web/docs/developers/api/typescript/bun/index.ts new file mode 100644 index 00000000..25df2dbe --- /dev/null +++ b/.web/docs/developers/api/typescript/bun/index.ts @@ -0,0 +1,15 @@ +import { createClient } from '@connectrpc/connect'; +import { createConnectTransport } from '@connectrpc/connect-node'; +import { GateService } from '@buf/minekube_gate.connectrpc_es/minekube/gate/v1/gate_service_connect'; + +const transport = createConnectTransport({ + httpVersion: '1.1', + baseUrl: 'http://localhost:8080', +}); + +async function main() { + const client = createClient(GateService, transport); + const res = await client.listServers({}); + console.log(JSON.stringify(res.servers, null, 2)); +} +void main(); diff --git a/.web/docs/developers/api/typescript/bun/package.json b/.web/docs/developers/api/typescript/bun/package.json new file mode 100644 index 00000000..a0d676bc --- /dev/null +++ b/.web/docs/developers/api/typescript/bun/package.json @@ -0,0 +1,12 @@ +{ + "name": "bun", + "module": "index.ts", + "type": "module", + "devDependencies": { + "@types/bun": "latest" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "dependencies": { "@buf/minekube_gate.connectrpc_es": "^1.6.1-20241118150055-50fffb007499.1", "@bufbuild/buf": "^1.47.2", "@bufbuild/protobuf": "^1.0.0", "@connectrpc/connect": "^1.0.0", "@connectrpc/connect-node": "^1.6.1" } +} diff --git a/.web/docs/developers/api/typescript/bun/tsconfig.json b/.web/docs/developers/api/typescript/bun/tsconfig.json new file mode 100644 index 00000000..238655f2 --- /dev/null +++ b/.web/docs/developers/api/typescript/bun/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + // Enable latest features + "lib": ["ESNext", "DOM"], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, + + // Bundler mode + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, + + // Best practices + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false + } +} diff --git a/.web/docs/developers/api/typescript/index.md b/.web/docs/developers/api/typescript/index.md new file mode 100644 index 00000000..d2e99ca4 --- /dev/null +++ b/.web/docs/developers/api/typescript/index.md @@ -0,0 +1,108 @@ +# TypeScript TypeScript Guide + +Gate's TypeScript/JavaScript client libraries allow you to interact with Gate's API using your preferred runtime environment. This guide covers installation and usage across different JavaScript runtimes. + +## Installation + +Choose your preferred runtime environment: + + + +## Features + +- **Type Safety**: Full TypeScript support with generated types +- **Modern APIs**: Promise-based async/await API +- **Cross-Platform**: Works in Node.js, Bun, and web browsers +- **Efficient**: Uses Protocol Buffers for efficient data transfer +- **Secure**: HTTPS support with customizable transport options + +## Common Use Cases + +- Building admin panels and dashboards +- Creating Discord bots +- Automating server management +- Developing custom monitoring tools +- Integration with existing TypeScript/JavaScript applications + + diff --git a/.web/docs/developers/api/typescript/node/.npmrc b/.web/docs/developers/api/typescript/node/.npmrc new file mode 100644 index 00000000..c599297d --- /dev/null +++ b/.web/docs/developers/api/typescript/node/.npmrc @@ -0,0 +1 @@ +@buf:registry=https://buf.build/gen/npm/v1/ diff --git a/.web/docs/developers/api/typescript/node/index.md b/.web/docs/developers/api/typescript/node/index.md new file mode 100644 index 00000000..3d1d10e3 --- /dev/null +++ b/.web/docs/developers/api/typescript/node/index.md @@ -0,0 +1,105 @@ +# Node.js Node.js + +You can use the following `.npmrc` to install the dependencies from the `buf.build` registry. + +::: code-group + +```toml [.npmrc] + +``` + +::: + +or using `pnpm`: + +```bash +pnpm config set @buf:registry https://buf.build/gen/npm/v1/ +``` + +To install dependencies: + +::: code-group + +```bash [pnpm] +pnpm add @buf/minekube_gate.connectrpc_es@latest +``` + +```bash [bun] +bun add @buf/minekube_gate.connectrpc_es@latest +``` + +```bash [npm] +npm install @buf/minekube_gate.connectrpc_es@latest +``` + +```bash [yarn] +yarn add @buf/minekube_gate.connectrpc_es@latest +``` + +::: + +Refer to the [ConnectRPC](https://connectrpc.com/docs/node/using-clients) documentation for more information on how to use ConnectRPC with TypeScript on server side. + +::: tip Browser support + +To use the Gate API in the browser, check out the [Web](/developers/api/typescript/web/) documentation. + +::: + +::: code-group + +```ts [index.js] + +``` + +::: + +::: warning + +Note that we had to append `.js` to the import path in line 3 due Node.js requiring `.js` for CommonJS modules, other than in [Bun](/developers/api/typescript/bun/). + +```ts +import { GateService } from '@buf/minekube_gate.connectrpc_es/minekube/gate/v1/gate_service_connect.js'; +``` + +::: + +## Sample project + +This sample project is located in the [`docs/developers/api/typescript/node`](https://github.com/minekube/gate/tree/main/.web/docs/developers/api/typescript/node) directory. + +To install dependencies: + +```bash +pnpm install +``` + +To run: + +```bash +node --experimental-strip-types index.ts +[ + { + "name": "server1", + "address": "localhost:25566", + "players": 0 + }, + { + "name": "server2", + "address": "localhost:25567", + "players": 0 + }, + { + "name": "server3", + "address": "localhost:25568", + "players": 0 + }, + { + "name": "server4", + "address": "localhost:25569", + "players": 0 + } +] +``` + +This project was created using `pnpm init` in pnpm v9.5.0. [pnpm](https://pnpm.io) is a fast, disk space efficient package manager. diff --git a/.web/docs/developers/api/typescript/node/index.ts b/.web/docs/developers/api/typescript/node/index.ts new file mode 100644 index 00000000..9a210e90 --- /dev/null +++ b/.web/docs/developers/api/typescript/node/index.ts @@ -0,0 +1,15 @@ +import { createClient } from '@connectrpc/connect'; +import { createConnectTransport } from '@connectrpc/connect-node'; +import { GateService } from '@buf/minekube_gate.connectrpc_es/minekube/gate/v1/gate_service_connect.js'; + +const transport = createConnectTransport({ + httpVersion: '1.1', + baseUrl: 'http://localhost:8080', +}); + +async function main() { + const client = createClient(GateService, transport); + const res = await client.listServers({}); + console.log(JSON.stringify(res.servers, null, 2)); +} +void main(); diff --git a/.web/docs/developers/api/typescript/node/package.json b/.web/docs/developers/api/typescript/node/package.json new file mode 100644 index 00000000..a3f69863 --- /dev/null +++ b/.web/docs/developers/api/typescript/node/package.json @@ -0,0 +1,16 @@ +{ + "name": "node", + "module": "index.ts", + "type": "module", + "devDependencies": {}, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "dependencies": { + "@buf/minekube_gate.connectrpc_es": "^1.6.1-20241118150055-50fffb007499.1", + "@bufbuild/buf": "^1.47.2", + "@bufbuild/protobuf": "^1.0.0", + "@connectrpc/connect": "^1.0.0", + "@connectrpc/connect-node": "^1.6.1" + } +} diff --git a/.web/docs/developers/api/typescript/node/pnpm-lock.yaml b/.web/docs/developers/api/typescript/node/pnpm-lock.yaml new file mode 100644 index 00000000..35a63ec8 --- /dev/null +++ b/.web/docs/developers/api/typescript/node/pnpm-lock.yaml @@ -0,0 +1,179 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@buf/minekube_gate.connectrpc_es': + specifier: ^1.6.1-20241118150055-50fffb007499.1 + version: 1.6.1-20241118150055-50fffb007499.1(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0)) + '@bufbuild/buf': + specifier: ^1.47.2 + version: 1.47.2 + '@bufbuild/protobuf': + specifier: ^1.0.0 + version: 1.10.0 + '@connectrpc/connect': + specifier: ^1.0.0 + version: 1.6.1(@bufbuild/protobuf@1.10.0) + '@connectrpc/connect-node': + specifier: ^1.6.1 + version: 1.6.1(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0)) + typescript: + specifier: ^5.0.0 + version: 5.6.3 + +packages: + + '@buf/minekube_gate.bufbuild_es@1.10.0-20241118150055-50fffb007499.1': + resolution: {tarball: https://buf.build/gen/npm/v1/@buf/minekube_gate.bufbuild_es/-/minekube_gate.bufbuild_es-1.10.0-20241118150055-50fffb007499.1.tgz} + peerDependencies: + '@bufbuild/protobuf': ^1.10.0 + + '@buf/minekube_gate.connectrpc_es@1.6.1-20241118150055-50fffb007499.1': + resolution: {tarball: https://buf.build/gen/npm/v1/@buf/minekube_gate.connectrpc_es/-/minekube_gate.connectrpc_es-1.6.1-20241118150055-50fffb007499.1.tgz} + peerDependencies: + '@connectrpc/connect': ^1.6.1 + + '@bufbuild/buf-darwin-arm64@1.47.2': + resolution: {integrity: sha512-74WerFn06y+azgVfsnzhfbI5wla/OLPDnIvaNJBWHaqya/3bfascJkDylW2GVNHmwG1K/cscpmcc/RJPaO7ntQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@bufbuild/buf-darwin-x64@1.47.2': + resolution: {integrity: sha512-adAiOacOQe8Ym/YXPCEiq9mrPeKRmDtF2TgqPWTcDy6mF7TqR7hMJINkEEuMd1EeACmXnzMOnXlm9ICtvdYgPg==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@bufbuild/buf-linux-aarch64@1.47.2': + resolution: {integrity: sha512-52vY+Owffr5diw2PyfQJqH+Fld6zW6NhNZak4zojvc2MjZKubWM0TfNyM9jXz2YrwyB+cyxkabE60nBI80m37w==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@bufbuild/buf-linux-armv7@1.47.2': + resolution: {integrity: sha512-g9KtpObDeHZ/VG/0b5ZCieOao7L/WYZ0fPqFSs4N07D3APgEDhJG6vLyUcDgJMDgyLcgkNjNz0+XdYQb/tXyQw==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@bufbuild/buf-linux-x64@1.47.2': + resolution: {integrity: sha512-MODCK2BzD1Mgoyr+5Sp8xA8qMNdytj8hYheyhA5NnCGTkQf8sfqAjpBSAAmKk6Zar8HOlVXML6tzE/ioDFFGwQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@bufbuild/buf-win32-arm64@1.47.2': + resolution: {integrity: sha512-563YKYWJl3LrCY3G3+zuhb8HwOs6DzWslwGPFkKV2hwHyWyvd1DR1JjiLvw9zX64IKNctQ0HempSqc3kcboaqQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@bufbuild/buf-win32-x64@1.47.2': + resolution: {integrity: sha512-Sqcdv7La2xBDh3bTdEYb2f4UTMMqCcYe/D0RELhvQ5wDn6I35V3/2YT1OF5fRuf0BZLCo0OdO37S9L47uHSz2g==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@bufbuild/buf@1.47.2': + resolution: {integrity: sha512-glY5kCAoO4+a7HvDb+BLOdoHSdCk4mdXdkp53H8JFz7maOnkxCiHHXgRX+taFyEu25N8ybn7NjZFrZSdRwq2sA==} + engines: {node: '>=12'} + hasBin: true + + '@bufbuild/protobuf@1.10.0': + resolution: {integrity: sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==} + + '@connectrpc/connect-node@1.6.1': + resolution: {integrity: sha512-DxcD1wsF/aX9GegjAtl7VbpiZNjVJozy87VbaFoN6AF0Ln1Q757r5dgV59Gz0wmlk5f17txUsrEr1f2inlnnAg==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@bufbuild/protobuf': ^1.10.0 + '@connectrpc/connect': 1.6.1 + + '@connectrpc/connect@1.6.1': + resolution: {integrity: sha512-KchMDNtU4CDTdkyf0qG7ugJ6qHTOR/aI7XebYn3OTCNagaDYWiZUVKgRgwH79yeMkpNgvEUaXSK7wKjaBK9b/Q==} + peerDependencies: + '@bufbuild/protobuf': ^1.10.0 + + '@fastify/busboy@2.1.1': + resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} + engines: {node: '>=14'} + + typescript@5.6.3: + resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} + engines: {node: '>=14.17'} + hasBin: true + + undici@5.28.4: + resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} + engines: {node: '>=14.0'} + +snapshots: + + '@buf/minekube_gate.bufbuild_es@1.10.0-20241118150055-50fffb007499.1(@bufbuild/protobuf@1.10.0)': + dependencies: + '@bufbuild/protobuf': 1.10.0 + + '@buf/minekube_gate.connectrpc_es@1.6.1-20241118150055-50fffb007499.1(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0))': + dependencies: + '@buf/minekube_gate.bufbuild_es': 1.10.0-20241118150055-50fffb007499.1(@bufbuild/protobuf@1.10.0) + '@connectrpc/connect': 1.6.1(@bufbuild/protobuf@1.10.0) + transitivePeerDependencies: + - '@bufbuild/protobuf' + + '@bufbuild/buf-darwin-arm64@1.47.2': + optional: true + + '@bufbuild/buf-darwin-x64@1.47.2': + optional: true + + '@bufbuild/buf-linux-aarch64@1.47.2': + optional: true + + '@bufbuild/buf-linux-armv7@1.47.2': + optional: true + + '@bufbuild/buf-linux-x64@1.47.2': + optional: true + + '@bufbuild/buf-win32-arm64@1.47.2': + optional: true + + '@bufbuild/buf-win32-x64@1.47.2': + optional: true + + '@bufbuild/buf@1.47.2': + optionalDependencies: + '@bufbuild/buf-darwin-arm64': 1.47.2 + '@bufbuild/buf-darwin-x64': 1.47.2 + '@bufbuild/buf-linux-aarch64': 1.47.2 + '@bufbuild/buf-linux-armv7': 1.47.2 + '@bufbuild/buf-linux-x64': 1.47.2 + '@bufbuild/buf-win32-arm64': 1.47.2 + '@bufbuild/buf-win32-x64': 1.47.2 + + '@bufbuild/protobuf@1.10.0': {} + + '@connectrpc/connect-node@1.6.1(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0))': + dependencies: + '@bufbuild/protobuf': 1.10.0 + '@connectrpc/connect': 1.6.1(@bufbuild/protobuf@1.10.0) + undici: 5.28.4 + + '@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0)': + dependencies: + '@bufbuild/protobuf': 1.10.0 + + '@fastify/busboy@2.1.1': {} + + typescript@5.6.3: {} + + undici@5.28.4: + dependencies: + '@fastify/busboy': 2.1.1 diff --git a/.web/docs/developers/api/typescript/web/.npmrc b/.web/docs/developers/api/typescript/web/.npmrc new file mode 100644 index 00000000..c599297d --- /dev/null +++ b/.web/docs/developers/api/typescript/web/.npmrc @@ -0,0 +1 @@ +@buf:registry=https://buf.build/gen/npm/v1/ diff --git a/.web/docs/developers/api/typescript/web/index.md b/.web/docs/developers/api/typescript/web/index.md new file mode 100644 index 00000000..cec11e11 --- /dev/null +++ b/.web/docs/developers/api/typescript/web/index.md @@ -0,0 +1,105 @@ +# Web Web + +You can use the following `.npmrc` to install the dependencies from the `buf.build` registry. + +::: code-group + +```toml [.npmrc] + +``` + +::: + +or using `pnpm`: + +```bash +pnpm config set @buf:registry https://buf.build/gen/npm/v1/ +``` + +To install dependencies: + +::: code-group + +```bash [pnpm] +pnpm add @buf/minekube_gate.connectrpc_es@latest +``` + +```bash [bun] +bun add @buf/minekube_gate.connectrpc_es@latest +``` + +```bash [npm] +npm install @buf/minekube_gate.connectrpc_es@latest +``` + +```bash [yarn] +yarn add @buf/minekube_gate.connectrpc_es@latest +``` + +::: + +Refer to the [ConnectRPC](https://connectrpc.com/docs/web/using-clients) documentation for more information on how to use ConnectRPC with TypeScript on browser side. + +::: tip Browser support + +To use the Gate API in the browser, check out the [Web](/developers/api/typescript/web/) documentation. + +::: + +::: code-group + +```ts [index.js] + +``` + +::: + +::: warning + +Note that we had to append `.js` to the import path in line 3 due Node.js requiring `.js` for CommonJS modules, other than in [Bun](/developers/api/typescript/bun/). + +```ts +import { GateService } from '@buf/minekube_gate.connectrpc_es/minekube/gate/v1/gate_service_connect.js'; +``` + +::: + +## Sample project + +This sample project is located in the [`docs/developers/api/typescript/node`](https://github.com/minekube/gate/tree/main/.web/docs/developers/api/typescript/node) directory. + +To install dependencies: + +```bash +pnpm install +``` + +To run: + +```bash +node --experimental-strip-types index.ts +[ + { + "name": "server1", + "address": "localhost:25566", + "players": 0 + }, + { + "name": "server2", + "address": "localhost:25567", + "players": 0 + }, + { + "name": "server3", + "address": "localhost:25568", + "players": 0 + }, + { + "name": "server4", + "address": "localhost:25569", + "players": 0 + } +] +``` + +This project was created using `pnpm init` in pnpm v9.5.0. [pnpm](https://pnpm.io) is a fast, disk space efficient package manager. diff --git a/.web/docs/developers/api/typescript/web/index.ts b/.web/docs/developers/api/typescript/web/index.ts new file mode 100644 index 00000000..2c19af6e --- /dev/null +++ b/.web/docs/developers/api/typescript/web/index.ts @@ -0,0 +1,14 @@ +import { createClient } from '@connectrpc/connect'; +import { createConnectTransport } from '@connectrpc/connect-web'; +import { GateService } from '@buf/minekube_gate.connectrpc_es/minekube/gate/v1/gate_service_connect.js'; + +const transport = createConnectTransport({ + baseUrl: 'http://localhost:8080', +}); + +async function main() { + const client = createClient(GateService, transport); + const res = await client.listServers({}); + console.log(JSON.stringify(res.servers, null, 2)); +} +void main(); diff --git a/.web/docs/developers/api/typescript/web/package.json b/.web/docs/developers/api/typescript/web/package.json new file mode 100644 index 00000000..09ea406e --- /dev/null +++ b/.web/docs/developers/api/typescript/web/package.json @@ -0,0 +1,15 @@ +{ + "name": "node", + "module": "index.ts", + "type": "module", + "peerDependencies": { + "typescript": "^5.0.0" + }, + "dependencies": { + "@buf/minekube_gate.connectrpc_es": "^1.6.1-20241118150055-50fffb007499.1", + "@bufbuild/buf": "^1.47.2", + "@bufbuild/protobuf": "^1.0.0", + "@connectrpc/connect": "^1.0.0", + "@connectrpc/connect-web": "^1.6.1" + } +} diff --git a/.web/docs/developers/api/typescript/web/pnpm-lock.yaml b/.web/docs/developers/api/typescript/web/pnpm-lock.yaml new file mode 100644 index 00000000..6ca63b7b --- /dev/null +++ b/.web/docs/developers/api/typescript/web/pnpm-lock.yaml @@ -0,0 +1,163 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@buf/minekube_gate.connectrpc_es': + specifier: ^1.6.1-20241118150055-50fffb007499.1 + version: 1.6.1-20241118150055-50fffb007499.1(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0)) + '@bufbuild/buf': + specifier: ^1.47.2 + version: 1.47.2 + '@bufbuild/protobuf': + specifier: ^1.0.0 + version: 1.10.0 + '@connectrpc/connect': + specifier: ^1.0.0 + version: 1.6.1(@bufbuild/protobuf@1.10.0) + '@connectrpc/connect-web': + specifier: ^1.6.1 + version: 1.6.1(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0)) + typescript: + specifier: ^5.0.0 + version: 5.6.3 + +packages: + + '@buf/minekube_gate.bufbuild_es@1.10.0-20241118150055-50fffb007499.1': + resolution: {tarball: https://buf.build/gen/npm/v1/@buf/minekube_gate.bufbuild_es/-/minekube_gate.bufbuild_es-1.10.0-20241118150055-50fffb007499.1.tgz} + peerDependencies: + '@bufbuild/protobuf': ^1.10.0 + + '@buf/minekube_gate.connectrpc_es@1.6.1-20241118150055-50fffb007499.1': + resolution: {tarball: https://buf.build/gen/npm/v1/@buf/minekube_gate.connectrpc_es/-/minekube_gate.connectrpc_es-1.6.1-20241118150055-50fffb007499.1.tgz} + peerDependencies: + '@connectrpc/connect': ^1.6.1 + + '@bufbuild/buf-darwin-arm64@1.47.2': + resolution: {integrity: sha512-74WerFn06y+azgVfsnzhfbI5wla/OLPDnIvaNJBWHaqya/3bfascJkDylW2GVNHmwG1K/cscpmcc/RJPaO7ntQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@bufbuild/buf-darwin-x64@1.47.2': + resolution: {integrity: sha512-adAiOacOQe8Ym/YXPCEiq9mrPeKRmDtF2TgqPWTcDy6mF7TqR7hMJINkEEuMd1EeACmXnzMOnXlm9ICtvdYgPg==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@bufbuild/buf-linux-aarch64@1.47.2': + resolution: {integrity: sha512-52vY+Owffr5diw2PyfQJqH+Fld6zW6NhNZak4zojvc2MjZKubWM0TfNyM9jXz2YrwyB+cyxkabE60nBI80m37w==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@bufbuild/buf-linux-armv7@1.47.2': + resolution: {integrity: sha512-g9KtpObDeHZ/VG/0b5ZCieOao7L/WYZ0fPqFSs4N07D3APgEDhJG6vLyUcDgJMDgyLcgkNjNz0+XdYQb/tXyQw==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@bufbuild/buf-linux-x64@1.47.2': + resolution: {integrity: sha512-MODCK2BzD1Mgoyr+5Sp8xA8qMNdytj8hYheyhA5NnCGTkQf8sfqAjpBSAAmKk6Zar8HOlVXML6tzE/ioDFFGwQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@bufbuild/buf-win32-arm64@1.47.2': + resolution: {integrity: sha512-563YKYWJl3LrCY3G3+zuhb8HwOs6DzWslwGPFkKV2hwHyWyvd1DR1JjiLvw9zX64IKNctQ0HempSqc3kcboaqQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@bufbuild/buf-win32-x64@1.47.2': + resolution: {integrity: sha512-Sqcdv7La2xBDh3bTdEYb2f4UTMMqCcYe/D0RELhvQ5wDn6I35V3/2YT1OF5fRuf0BZLCo0OdO37S9L47uHSz2g==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@bufbuild/buf@1.47.2': + resolution: {integrity: sha512-glY5kCAoO4+a7HvDb+BLOdoHSdCk4mdXdkp53H8JFz7maOnkxCiHHXgRX+taFyEu25N8ybn7NjZFrZSdRwq2sA==} + engines: {node: '>=12'} + hasBin: true + + '@bufbuild/protobuf@1.10.0': + resolution: {integrity: sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==} + + '@connectrpc/connect-web@1.6.1': + resolution: {integrity: sha512-GVfxQOmt3TtgTaKeXLS/EA2IHa3nHxwe2BCHT7X0Q/0hohM+nP5DDnIItGEjGrGdt3LTTqWqE4s70N4h+qIMlQ==} + peerDependencies: + '@bufbuild/protobuf': ^1.10.0 + '@connectrpc/connect': 1.6.1 + + '@connectrpc/connect@1.6.1': + resolution: {integrity: sha512-KchMDNtU4CDTdkyf0qG7ugJ6qHTOR/aI7XebYn3OTCNagaDYWiZUVKgRgwH79yeMkpNgvEUaXSK7wKjaBK9b/Q==} + peerDependencies: + '@bufbuild/protobuf': ^1.10.0 + + typescript@5.6.3: + resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} + engines: {node: '>=14.17'} + hasBin: true + +snapshots: + + '@buf/minekube_gate.bufbuild_es@1.10.0-20241118150055-50fffb007499.1(@bufbuild/protobuf@1.10.0)': + dependencies: + '@bufbuild/protobuf': 1.10.0 + + '@buf/minekube_gate.connectrpc_es@1.6.1-20241118150055-50fffb007499.1(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0))': + dependencies: + '@buf/minekube_gate.bufbuild_es': 1.10.0-20241118150055-50fffb007499.1(@bufbuild/protobuf@1.10.0) + '@connectrpc/connect': 1.6.1(@bufbuild/protobuf@1.10.0) + transitivePeerDependencies: + - '@bufbuild/protobuf' + + '@bufbuild/buf-darwin-arm64@1.47.2': + optional: true + + '@bufbuild/buf-darwin-x64@1.47.2': + optional: true + + '@bufbuild/buf-linux-aarch64@1.47.2': + optional: true + + '@bufbuild/buf-linux-armv7@1.47.2': + optional: true + + '@bufbuild/buf-linux-x64@1.47.2': + optional: true + + '@bufbuild/buf-win32-arm64@1.47.2': + optional: true + + '@bufbuild/buf-win32-x64@1.47.2': + optional: true + + '@bufbuild/buf@1.47.2': + optionalDependencies: + '@bufbuild/buf-darwin-arm64': 1.47.2 + '@bufbuild/buf-darwin-x64': 1.47.2 + '@bufbuild/buf-linux-aarch64': 1.47.2 + '@bufbuild/buf-linux-armv7': 1.47.2 + '@bufbuild/buf-linux-x64': 1.47.2 + '@bufbuild/buf-win32-arm64': 1.47.2 + '@bufbuild/buf-win32-x64': 1.47.2 + + '@bufbuild/protobuf@1.10.0': {} + + '@connectrpc/connect-web@1.6.1(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0))': + dependencies: + '@bufbuild/protobuf': 1.10.0 + '@connectrpc/connect': 1.6.1(@bufbuild/protobuf@1.10.0) + + '@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0)': + dependencies: + '@bufbuild/protobuf': 1.10.0 + + typescript@5.6.3: {} diff --git a/.web/docs/developers/index.md b/.web/docs/developers/index.md index d54427ca..65432562 100644 --- a/.web/docs/developers/index.md +++ b/.web/docs/developers/index.md @@ -9,6 +9,14 @@ _If you want to learn how to extend Gate with your own code, you are in the righ The starter template is designed to help you get started with your own Gate powered project. Fork it! 🚀 - [minekube/gate-plugin-template](https://github.com/minekube/gate-plugin-template) +## Any Language + +Go to the [API](/developers/api/) 🌐 section to learn how to use Gate's API from any programming language. + +## Integration Options + + + ## Getting Started Gate is designed with developers in mind. @@ -35,7 +43,7 @@ func main() { return newSimpleProxy(proxy).init() // see code examples }, }) - + // Execute Gate entrypoint and block until shutdown. // We could also run gate.Start if we don't need Gate's command-line. gate.Execute() diff --git a/.web/docs/guide/config/index.md b/.web/docs/guide/config/index.md index 68423aae..4ee48923 100644 --- a/.web/docs/guide/config/index.md +++ b/.web/docs/guide/config/index.md @@ -3,5 +3,3 @@ ```yaml config.yml ``` - -TODO more detailed documentation about each section diff --git a/.web/docs/guide/index.md b/.web/docs/guide/index.md index d421ee4c..3d9a47f0 100644 --- a/.web/docs/guide/index.md +++ b/.web/docs/guide/index.md @@ -1,58 +1,158 @@ - # Introduction _Gate is a modern cloud-native, open source, fast, batteries-included and secure proxy for Minecraft servers -with a focus on scalability, flexibility, multi-version support and developer friendliness._ +that focuses on scalability, flexibility, multi-version support and developer friendliness._ --- -![server list ping](/images/server-list.png) +
+ Gate server list ping example +
-Gate is a tiny [binary](install/binaries) and can run locally, in [Docker](install/docker) containers or -scale with your growing demands in a [Kubernetes](install/kubernetes)-orchestrated -production environment in the cloud. - -It replaces legacy proxies like BungeeCord but also runs alongside them. -Gate is entirely written in Go and heavily inspired by the Velocity project. - -::: tip What is Go? -Gate is written in [Go](https://go.dev/), -an easy-to-learn, fast, reliable, efficient, statically typed, compiled programming language designed at Google. -It is one of the most used languages for modern applications and one of the fastest growing programming languages -that is used by companies like Google, Microsoft, Meta, Amazon, Twitter, PayPal, Twitch, Netflix, Dropbox, Uber, Cloudflare, Docker, and many more. -::: - -## Quick Start +## What is Gate? -If you already know the concepts of a Minecraft proxy, -you can skip this page and jump to the [Quick Start](quick-start) guide. +Gate is a lightweight yet powerful Minecraft proxy that can run anywhere - from your local machine to large-scale cloud deployments: -If you are a developer checkout the [Developers Guide](/developers/). +- 🚀 Run locally as a simple [binary](install/binaries) +- 🐳 Deploy with [Docker](install/docker) containers +- ☸️ Scale infinitely in [Kubernetes](install/kubernetes) clusters -## Why do we need a Minecraft proxy? +It's designed as a modern replacement for legacy proxies like BungeeCord, while maintaining compatibility to run alongside them. Built entirely in Go and inspired by the Velocity project, Gate brings enterprise-grade performance to Minecraft server networks. -### Use-cases +::: tip Why Go? +Gate is written in [Go](https://go.dev/) - a modern, fast, and reliable programming language designed by Google. -* You want to keep players connected to the proxy to move them between your different game servers like they would change the world. -* You want to enable cross game server plugins that e.g. handle player chat events or register proxy-wide commands - broadcast messages and more. -* You want to intercept and log packets on the network traffic between players and servers - -### How does a Minecraft proxy work? - -Gate presents itself as a normal Minecraft server in the player's server list, -but once the player connects Gate forwards the connection to one of the actual -game servers (e.g. Minecraft vanilla, paper, spigot, sponge, etc.) to play the game. - -The player can be moved around the network of Minecraft servers **without** -fully disconnecting, since we want the player to stay connected (and not want -them to re-login via the server-list every time). +Go powers the world's largest platforms and is used by companies like: +Google, Microsoft, Meta, Amazon, Twitter, PayPal, Twitch, Netflix, Dropbox, Uber, Cloudflare, Docker, and many more. +::: -Therefore, Gate reads all packets sent between players (Minecraft client) and -upstream servers, logs session state changes, emits different events like -[Login, Disconnect, ServerConnect, Chat, Kick etc.](https://github.com/minekube/gate/blob/master/pkg/edition/java/proxy/events.go) -that custom plugins/code can react to. +## Quick Start -The **advantages** for using a proxy are far-reaching depending on your use-case. +Ready to jump in? Choose your path: + +- 🎮 **Server Owners**: Head to the [Quick Start](quick-start) guide +- 💻 **Developers**: Check out the [Developer Guide](/developers/) + +## Why Use a Minecraft Proxy? + +
+
+
+

🎮 Seamless Player Experience

+
    +
  • Move players between servers instantly
  • +
  • No disconnects during server switches
  • +
  • Smooth transitions between game modes
  • +
  • Single point of entry for your network
  • +
+
+
+ +
+
+

🔌 Network-Wide Features

+
    +
  • Cross-server chat systems
  • +
  • Global command handling
  • +
  • Network-wide player management
  • +
  • Unified permission systems
  • +
+
+
+ +
+
+

🔍 Advanced Monitoring

+
    +
  • Real-time packet inspection
  • +
  • Network traffic analysis
  • +
  • Performance monitoring
  • +
  • Security audit capabilities
  • +
+
+
+ + +
+

Why Gate?

+
    +
  • Minimal resource footprint (10MB RAM)
  • +
  • Minecraft 1.7 to latest support
  • +
  • Modern Go-based architecture
  • +
  • Clean, documented APIs
  • +
+
+
+
+ +### How It Works + +Gate acts as an intelligent middleware between players and your Minecraft servers: + +1. Players connect to Gate like a normal Minecraft server +2. Gate forwards connections to your actual game servers (vanilla, Paper, Spigot, etc.) +3. Players can move between servers while maintaining their connection +4. Gate monitors all network traffic and emits events for: + - Login/Logout + - Server Connections + - Chat Messages + - Player Kicks + - [And more!](https://github.com/minekube/gate/blob/master/pkg/edition/java/proxy/events.go) + +This architecture enables powerful features like load balancing, server maintenance without disconnects, and network-wide plugins. + + diff --git a/.web/docs/guide/install/binaries.md b/.web/docs/guide/install/binaries.md index 29b40565..b30ac5e4 100644 --- a/.web/docs/guide/install/binaries.md +++ b/.web/docs/guide/install/binaries.md @@ -3,24 +3,130 @@ _The installation of Gate is ultra easy, NO Java needed! Gate is only a single executable file ready to run the proxy._ ---- +## Quick Install -Visit the page, -go to the Assets section at the bottom and download Gate for your operating system -Windows, macOS or Linux. +::: code-group -**Make Gate executable** +```sh [Linux/macOS] +curl -fsSL https://gate.minekube.com/install | bash -```sh console +✨ Installing Gate... +⚡ Downloading Gate 0.42.2 for darwin-arm64... +✅ Checksum verified for gate_0.42.2_darwin_arm64 +✨ Successfully installed Gate 0.42.2! +📍 Location: /Users/robin/.local/bin/gate +🚀 Run gate to start the proxy +``` + +```powershell [Windows] +powershell -c "irm https://gate.minekube.com/install.ps1 | iex" +``` + +::: + +## Manual Download + +If you prefer to download and install Gate manually: + +1. Visit the page +2. Download the appropriate binary for your system +3. Verify the SHA256 checksum (recommended) +4. Place the binary in your preferred location + +**Make Gate Executable** (Linux/macOS only) + +```sh chmod +x gate* ``` -::: tip If you do not have root access on the target system, you can still install Gate to the ~/.local/bin directory: +::: tip No Root Access? +You can still install Gate to your user directory: -```sh console +```sh mkdir -p ~/.local/bin mv gate* ~/.local/bin/gate -# and then append (or prepend) ~/.local/bin to $PATH +# Add to PATH: +export PATH="$HOME/.local/bin:$PATH" ``` ::: + +## Installation Locations + +- **Linux/macOS**: `~/.local/bin/gate` +- **Windows**: `%LOCALAPPDATA%\Gate\bin\gate.exe` + +Both locations are in user space and don't require administrative privileges. + +## Uninstalling Gate + +To uninstall Gate, simply remove the binary: + +::: code-group + +```sh [Linux/macOS] +rm ~/.local/bin/gate +``` + +```powershell [Windows] +Remove-Item "$env:LOCALAPPDATA\Gate\bin\gate.exe" +``` + +::: + +## Troubleshooting + +If you encounter any issues: + +1. **PATH not set**: + + - The scripts will provide commands to add Gate to your PATH + - Follow the on-screen instructions after installation + +2. **Checksum Verification Failed**: + + - This is a security feature ensuring the downloaded binary matches the official release + - Try running the installation again + - If it persists, please report it on our GitHub issues + +3. **Permission Denied**: + - Our scripts install to user space and shouldn't require elevated privileges + - If you see permission errors, ensure you have write access to the installation directory + +## Security Notes + +- Our installation scripts are transparent and open source +- They only download from official GitHub releases +- All binaries are verified using SHA256 checksums +- No system-wide changes are made without your permission +- Installation is contained within your user directory +- No data collection or tracking + +### What the Installation Scripts Do + +Our installation scripts are designed to be transparent and secure. Here's exactly what they do: + +1. **Safety First**: + - Installs to user space (Linux/macOS: `~/.local/bin`, Windows: `%LOCALAPPDATA%\Gate\bin`) + - Downloads only from official GitHub releases + - Verifies file integrity using SHA256 checksums + +2. **Installation Steps**: + - Detects system architecture (amd64/arm64) + - Creates installation directory if it doesn't exist + - Downloads the appropriate Gate binary + - Verifies the checksum to ensure file integrity + - Makes the binary executable (Linux/macOS only) + - Provides clear PATH setup instructions + +3. **No System Changes**: + - Only writes to your user directory + - Suggests PATH changes but doesn't modify system files + - Can be easily uninstalled by removing the binary + +### Verifying the Scripts + +Both installation scripts are open source and can be inspected: + +- Unix: [View install script](https://github.com/minekube/gate/blob/master/.web/docs/public/install) +- Windows: [View install.ps1 script](https://github.com/minekube/gate/blob/master/.web/docs/public/install.ps1) diff --git a/.web/docs/guide/quick-start.md b/.web/docs/guide/quick-start.md index bf371947..c36dac34 100644 --- a/.web/docs/guide/quick-start.md +++ b/.web/docs/guide/quick-start.md @@ -1,6 +1,7 @@ # Quick Start -_This page quickly explains how to run Gate as a Minecraft proxy for your servers._ +_This page quickly explains how to run Gate as a Minecraft proxy for your servers. +If you want to extend Gate with custom functionality, see the [Developers](/developers/) section._ --- @@ -39,3 +40,73 @@ The `servers` section defines the addresses of your Minecraft servers. and the `try` section defines the order in which players fallback to connect to. There are many more options to configure, see [Configuration](/guide/config/) for more! + +## Next Steps + + + + diff --git a/.web/docs/guide/why.md b/.web/docs/guide/why.md index 495a759f..6558893b 100644 --- a/.web/docs/guide/why.md +++ b/.web/docs/guide/why.md @@ -1,52 +1,123 @@ -# Why +# Why Gate? -_We recommend reading the [Introduction](index) if you haven't already._ +
+
+

🚀 Performance First

+
    +
  • Minimal resource footprint (10MB RAM)
  • +
  • Optimized for high throughput
  • +
  • Efficient protocol handling
  • +
  • Perfect for large networks
  • +
+
-Let's start with where we come from, the problem definition, -different parties involved and the solution space. +
+

🎮 Protocol Support

+
    +
  • Minecraft 1.7 to latest
  • +
  • Forge mod support
  • +
  • BungeeCord compatibility
  • +
  • Velocity forwarding
  • +
+
-## Advantages +
+

💻 Developer Experience

+
    +
  • Modern Go-based architecture
  • +
  • Clean, documented APIs
  • +
  • Multiple SDK options
  • +
  • Active community
  • +
+
+
-- Fast and needs less resources (CPU/Memory) leading to improved scalability -- Excellent protocol version support - - Allows newest version down to 1.7 - - Forge support (for modded servers) - - BungeeCord compatible plugin channels - - BungeeCord or Velocity's player info forwarding -- A simple API for plugins/extensions - - Extend with [your Go code](https://github.com/minekube/gate/tree/master/.examples/extend/simple-proxy) - - Or use a [script language](https://github.com/minekube/gate/issues/9) -- Perfect for Go developers - Gate and developers immensely benefit from the Go language and its wide ecosystem +## Who is Gate For? -Similar to the Minecraft proxies written in Java: BungeeCord, Waterfall and Velocity -_(where much of the knowledge comes from)_ -Gate delivers a rich interface to interact with connected players -on your cluster of Minecraft servers. +
+
+

Server Networks

+

Perfect for networks serving thousands of concurrent players with needs for custom functionality and scalability.

+
+
+

Go Developers

+

Ideal for developers who want to leverage Go's performance and ecosystem for Minecraft infrastructure.

+
+
-## Target audience +::: warning Coming from Java? +If your existing codebase is in Java or you need BungeeCord/Velocity plugins, you might want to stick with those platforms. Gate doesn't support Java plugins from SpigotMC. +::: -Gate supports small and large Minecraft networks that need to serve thousands of -concurrent players and encourages new and established Golang developers to extend Gate. +## Why Go? -Although Gate targets better performance, has more version support -(modded servers) and has a simpler API than the BungeeCord Java proxy, -and Gate lets you write extension code in the awesome Go programming language... +Gate leverages Go's strengths to deliver: -_If you already have all your code base in Java or need to -use plugins for other proxies like BungeeCord and Velocity, just stay there._ -You can't use Java plugins from SpigotMC with Gate. +- 🏃‍♂️ Fast compilation and deployment +- 🔧 Simple dependency management +- 🌐 Excellent networking capabilities +- ☁️ First-class cloud integration +- 📦 Single binary distribution -## Why not use an existing proxy written in Java? + diff --git a/.web/docs/index.md b/.web/docs/index.md index 622a5f40..373a725b 100644 --- a/.web/docs/index.md +++ b/.web/docs/index.md @@ -35,9 +35,7 @@ features: linkText: Install - icon: 🚀 title: Developer Friendly - details: - Gate is written in Go, a modern programming language that is easy to learn and - has a great ecosystem of tools and libraries. + details: Build integrations in TypeScript, Python, Go, Rust, Kotlin, or Java using our modern API with official SDKs. link: /developers/ linkText: Developers & Starter Template - icon: 🌐 diff --git a/.web/docs/public/install b/.web/docs/public/install new file mode 100644 index 00000000..4d8a441a --- /dev/null +++ b/.web/docs/public/install @@ -0,0 +1,218 @@ +#!/bin/bash +set -e + +# Colors for terminal output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Constants +REPO_OWNER="minekube" +REPO_NAME="gate" +INSTALL_DIR="${GATE_INSTALL_DIR:-$HOME/.local/bin}" +TEMP_DIR="/tmp/gate-installer" +REQUIRED_SPACE_MB=50 + +# Functions + +# Print messages with colors +print_info() { + echo -e "${GREEN}$1${NC}" +} + +print_warning() { + echo -e "${YELLOW}$1${NC}" +} + +print_error() { + echo -e "${RED}$1${NC}" +} + +# Detect system architecture +detect_arch() { + local arch + arch=$(uname -m) + case $arch in + x86_64) echo "amd64" ;; + aarch64|arm64) echo "arm64" ;; + i386|i686) echo "386" ;; + *) + print_error "Unsupported architecture: $arch" + exit 1 + ;; + esac +} + +# Detect operating system +detect_os() { + local os + os=$(uname -s) + case $os in + Linux) echo "linux" ;; + Darwin) echo "darwin" ;; + *) + print_error "Unsupported OS: $os" + exit 1 + ;; + esac +} + +# Check available disk space +check_disk_space() { + local install_dir="$1" + local available_space + + available_space=$(df -m "$install_dir" | awk 'NR==2 {print $4}') + + if [ "$available_space" -lt "$REQUIRED_SPACE_MB" ]; then + print_error "Insufficient disk space. Required: ${REQUIRED_SPACE_MB}MB, Available: ${available_space}MB" + exit 1 + fi +} + +# Download a file using curl or wget +download() { + local url="$1" + local output="$2" + + mkdir -p "$TEMP_DIR" + + if command -v curl >/dev/null; then + curl -L "$url" --output "$output" && return 0 + elif command -v wget >/dev/null; then + wget -q "$url" -O "$output" && return 0 + fi + + print_error "Failed to download from $url using curl or wget." + rm -rf "$TEMP_DIR" + return 1 +} + +# Verify the checksum of the downloaded file +verify_checksum() { + local file="$1" + local checksum_file="$2" + local filename + local expected_checksum + local actual_checksum + + filename=$(basename "$file") + expected_checksum=$(grep "$filename" "$checksum_file" | awk '{print $1}') + + if command -v sha256sum >/dev/null; then + actual_checksum=$(sha256sum "$file" | awk '{print $1}') + elif command -v shasum >/dev/null; then + actual_checksum=$(shasum -a 256 "$file" | awk '{print $1}') + else + print_warning "No SHA256 checksum tool found. Skipping verification." + return 0 + fi + + if [ "$expected_checksum" != "$actual_checksum" ]; then + print_error "Checksum verification failed for $filename." + print_error "Expected: $expected_checksum" + print_error "Actual: $actual_checksum" + rm -f "$file" "$checksum_file" + exit 1 + fi + + print_info "✅ Checksum verified for $filename" + rm -f "$checksum_file" +} + +# Get installation path +get_install_path() { + echo "$INSTALL_DIR/gate" +} + +# Update PATH for the current session +update_path_session() { + export PATH="$INSTALL_DIR:$PATH" +} + +# Add PATH permanently +add_path_permanently() { + local shell_rc + shell_rc="$HOME/.$(basename "$SHELL")rc" + + echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$shell_rc" + source "$shell_rc" +} + +# Main installation function +install_gate() { + print_info "✨ Installing Gate..." + + mkdir -p "$INSTALL_DIR" + mkdir -p "$TEMP_DIR" + + check_disk_space "$INSTALL_DIR" + + OS=$(detect_os) + ARCH=$(detect_arch) + + # Fetch the latest version from GitHub API + VERSION=$(curl -fsSL "https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/' | sed 's/^v//') + if [ -z "$VERSION" ]; then + print_error "Failed to detect the latest version." + exit 1 + fi + + INSTALL_PATH=$(get_install_path) + + # Inform if updating + if [ -f "$INSTALL_PATH" ]; then + current_version=$("$INSTALL_PATH" version 2>/dev/null || echo "unknown") + if [ "$current_version" != "unknown" ]; then + print_warning "🔄 Updating Gate from version $current_version to $VERSION at $INSTALL_PATH" + else + print_warning "🔄 Updating existing Gate installation at $INSTALL_PATH" + fi + fi + + # Set download URLs + BINARY_NAME="gate_${VERSION}_${OS}_${ARCH}" + if [ "$OS" = "windows" ]; then + BINARY_NAME="${BINARY_NAME}.exe" + fi + + DOWNLOAD_URL="https://github.com/$REPO_OWNER/$REPO_NAME/releases/download/v${VERSION}/${BINARY_NAME}" + CHECKSUMS_URL="https://github.com/$REPO_OWNER/$REPO_NAME/releases/download/v${VERSION}/checksums.txt" + + print_info "⚡ Downloading Gate ${VERSION} for ${OS}-${ARCH}..." + echo "📥 From: $DOWNLOAD_URL" + + # ✨ Change: Download binary with original name to TEMP_DIR + download "$DOWNLOAD_URL" "$TEMP_DIR/$BINARY_NAME" + + # ✨ Change: Download checksums file + download "$CHECKSUMS_URL" "$TEMP_DIR/checksums.txt" + + # ✨ Change: Verify checksum using the correctly named binary + verify_checksum "$TEMP_DIR/$BINARY_NAME" "$TEMP_DIR/checksums.txt" + + # ✨ Change: Move the verified binary to the installation path as 'gate' + mv "$TEMP_DIR/$BINARY_NAME" "$INSTALL_PATH" + chmod +x "$INSTALL_PATH" + + # Update PATH for the current session + update_path_session + + # Final messages + print_info "✨ Successfully installed Gate ${VERSION}!" + echo "📍 Location: $INSTALL_PATH" + echo + + # Provide PATH update instructions + print_warning "To use Gate, run this command now:" + echo " export PATH=\"$INSTALL_DIR:\$PATH\"" + echo + print_warning "Or add it permanently by running:" + echo " echo 'export PATH=\"$INSTALL_DIR:\$PATH\"' >> \"\$HOME/.$(basename $SHELL)rc\" && source \"\$HOME/.$(basename $SHELL)rc\"" + echo + print_info "🚀 Run gate to start the proxy" +} + +# Execute installation +install_gate \ No newline at end of file diff --git a/.web/docs/public/install.ps1 b/.web/docs/public/install.ps1 new file mode 100644 index 00000000..b8e3c026 --- /dev/null +++ b/.web/docs/public/install.ps1 @@ -0,0 +1,201 @@ +# Install.ps1 - PowerShell installation script for Gate + +# Exit script on errors +$ErrorActionPreference = "Stop" + +# Colors for terminal output +$RED = "Red" +$GREEN = "Green" +$YELLOW = "Yellow" +$NC = "White" # No Color + +# Constants +$REPO_OWNER = "minekube" +$REPO_NAME = "gate" +$DEFAULT_INSTALL_DIR = "$env:LOCALAPPDATA\Gate\bin" +$INSTALL_DIR = if ($env:GATE_INSTALL_DIR) { $env:GATE_INSTALL_DIR } else { $DEFAULT_INSTALL_DIR } +$TEMP_DIR = "$env:TEMP\gate-installer" +$REQUIRED_SPACE_MB = 50 + +# Functions + +function Write-Info { + param([string]$Message) + Write-Host $Message -ForegroundColor $GREEN +} + +function Write-WarningMsg { + param([string]$Message) + Write-Host $Message -ForegroundColor $YELLOW +} + +function Write-ErrorMsg { + param([string]$Message) + Write-Host $Message -ForegroundColor $RED + exit 1 +} + +function Detect-Arch { + $arch = [Environment]::ProcessorArchitecture.ToString() + switch ($arch) { + "X86" { return "386" } + "AMD64" { return "amd64" } + "ARM64" { return "arm64" } + default { + Write-ErrorMsg "Unsupported architecture: $arch" + } + } +} + +function Detect-OS { + $os = [System.Runtime.InteropServices.RuntimeInformation]::OSDescription + if ($os -like "*Windows*") { + return "windows" + } else { + Write-ErrorMsg "Unsupported OS: $os" + } +} + +function Check-DiskSpace { + param([string]$Path) + + # Get free space in MB + $drive = (Get-Item $Path).PSDrive.Name + $freeSpace = (Get-PSDrive -Name $drive).Free / 1MB + + if ($freeSpace -lt $REQUIRED_SPACE_MB) { + Write-ErrorMsg "Insufficient disk space. Required: $REQUIRED_SPACE_MB MB, Available: $([math]::Round($freeSpace,2)) MB" + } +} + +function Download-File { + param( + [string]$Url, + [string]$Destination + ) + + try { + Invoke-WebRequest -Uri $Url -OutFile $Destination -ErrorAction Stop + } + catch { + Write-ErrorMsg "Failed to download from $Url" + } +} + +function Verify-Checksum { + param( + [string]$File, + [string]$ChecksumFile + ) + + $filename = [System.IO.Path]::GetFileName($File) + $expected_checksum = Select-String -Path $ChecksumFile -Pattern $filename | ForEach-Object { ($_ -split '\s+')[0] } + + if (-not $expected_checksum) { + Write-ErrorMsg "Checksum for $filename not found in $ChecksumFile" + } + + try { + $hash = Get-FileHash -Path $File -Algorithm SHA256 + $actual_checksum = $hash.Hash + } + catch { + Write-ErrorMsg "Failed to compute checksum for $filename" + } + + if ($expected_checksum -ne $actual_checksum) { + Write-ErrorMsg "Checksum verification failed for $filename.`nExpected: $expected_checksum`nActual: $actual_checksum" + } + + Write-Info "✅ Checksum verified for $filename" +} + +function Update-PATHSession { + $env:PATH = "$INSTALL_DIR;$env:PATH" +} + +function Add-PATHTemporarily { + Write-Info "✨ Successfully installed Gate $VERSION!" + Write-Host "📍 Location: $INSTALL_PATH" -ForegroundColor $YELLOW + Write-Host "" + + Write-WarningMsg "To use Gate, run this command now:" + Write-Host " \$env:PATH = `"$INSTALL_DIR;`$env:PATH`"" -ForegroundColor $GREEN + Write-Host "" + + Write-WarningMsg "Or add it permanently by running the following commands:" + Write-Host " [Environment]::SetEnvironmentVariable('PATH', `"$INSTALL_DIR;`$env:PATH`", 'User')" -ForegroundColor $GREEN + Write-Host " Reload your PowerShell session or restart your terminal." -ForegroundColor $GREEN + Write-Host "" + + Write-Info "🚀 Run gate to start the proxy" +} + +# Main Installation Function + +function Install-Gate { + Write-Info "✨ Installing Gate..." + + # Create installation and temp directories + New-Item -ItemType Directory -Path $INSTALL_DIR -Force | Out-Null + New-Item -ItemType Directory -Path $TEMP_DIR -Force | Out-Null + + # Check disk space + Check-DiskSpace -Path $INSTALL_DIR + + # Detect OS and architecture + $OS = Detect-OS + $ARCH = Detect-Arch + + # Fetch the latest version from GitHub API + Write-Info "📡 Fetching the latest release information..." + try { + $apiUrl = "https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/releases/latest" + $releaseInfo = Invoke-RestMethod -Uri $apiUrl -Method Get -Headers @{ "User-Agent" = "PowerShell" } + $VERSION = $releaseInfo.tag_name -replace '^v', '' + } + catch { + Write-ErrorMsg "Failed to fetch release information from GitHub." + } + + if (-not $VERSION) { + Write-ErrorMsg "Failed to detect the latest version." + } + + # Set download URLs + $BinaryName = "gate_${VERSION}_${OS}_${ARCH}" + if ($OS -eq "windows") { + $BinaryName += ".exe" + } + + $DOWNLOAD_URL = "https://github.com/$REPO_OWNER/$REPO_NAME/releases/download/v$VERSION/$BinaryName" + $CHECKSUMS_URL = "https://github.com/$REPO_OWNER/$REPO_NAME/releases/download/v$VERSION/checksums.txt" + + Write-Info "⚡ Downloading Gate $VERSION for $OS-$ARCH..." + Write-Host "📥 From: $DOWNLOAD_URL" -ForegroundColor $YELLOW + + # Download binary + $binaryPath = Join-Path $TEMP_DIR $BinaryName + Download-File -Url $DOWNLOAD_URL -Destination $binaryPath + + # Download checksums.txt + $checksumsPath = Join-Path $TEMP_DIR "checksums.txt" + Download-File -Url $CHECKSUMS_URL -Destination $checksumsPath + + # Verify checksum + Verify-Checksum -File $binaryPath -ChecksumFile $checksumsPath + + # Move binary to installation path + $finalPath = Join-Path $INSTALL_DIR "gate.exe" + Move-Item -Path $binaryPath -Destination $finalPath -Force + Write-Host "✔️ Moved gate.exe to $finalPath" -ForegroundColor $GREEN + + # Update PATH for current session + Update-PATHSession + + # Final messages and PATH instructions + Add-PATHTemporarily +} + +# Execute installation +Install-Gate diff --git a/README.md b/README.md index 9874f3d6..2f7caf4a 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,11 @@ guides and any more information needed! Follow our [quick start guide](https://gate.minekube.com/guide/quick-start/) on creating a simple Minecraft network! -```shell -go run go.minekube.com/gate@latest -``` +| Platform | Installation Command | +|-------------|---------------------| +| Go | `go run go.minekube.com/gate@latest` | +| Linux/macOS | `curl -fsSL https://gate.minekube.com/install \| bash` | +| Windows | `powershell -c "irm https://gate.minekube.com/install.ps1 \| iex"` | [![Server list](.web/docs/images/server-list.png)](https://gate.minekube.com) @@ -45,7 +47,7 @@ graph LR C -->|10.0.0.1| D[Backend A] C -->|10.0.0.2| E[Backend B] C -->|10.0.0.3| F[Another Proxy] - + linkStyle 0 stroke:orange linkStyle 1 stroke:purple linkStyle 2 stroke:purple @@ -56,4 +58,3 @@ graph LR The starter template is designed to help you get started with your own Gate powered project. Fork it! 🚀 - [minekube/gate-plugin-template](https://github.com/minekube/gate-plugin-template) - diff --git a/api/minekube/gate/v1/gate_service.proto b/api/minekube/gate/v1/gate_service.proto new file mode 100644 index 00000000..8ff064a6 --- /dev/null +++ b/api/minekube/gate/v1/gate_service.proto @@ -0,0 +1,155 @@ +syntax = "proto3"; + +package minekube.gate.v1; + +// GateService is the service API for managing a Gate proxy instance. +// It provides methods for managing players and servers. +// All methods follow standard gRPC error codes and include detailed error messages. +service GateService { + // GetPlayer returns the player by the given id or username. + // Returns NOT_FOUND if the player is not online. + // Returns INVALID_ARGUMENT if neither id nor username is provided, or if the id format is invalid. + rpc GetPlayer(GetPlayerRequest) returns (GetPlayerResponse); + + // ListPlayers returns all online players. + // If servers are specified in the request, only returns players on those servers. + rpc ListPlayers(ListPlayersRequest) returns (ListPlayersResponse); + + // ListServers returns all registered servers. + rpc ListServers(ListServersRequest) returns (ListServersResponse); + + // RegisterServer adds a server to the proxy. + // Returns ALREADY_EXISTS if a server with the same name is already registered. + // Returns INVALID_ARGUMENT if the server name or address is invalid. + rpc RegisterServer(RegisterServerRequest) returns (RegisterServerResponse); + + // UnregisterServer removes a server from the proxy. + // Returns NOT_FOUND if no matching server is found. + // Returns INVALID_ARGUMENT if neither name nor address is provided. + rpc UnregisterServer(UnregisterServerRequest) returns (UnregisterServerResponse); + + // ConnectPlayer connects a player to a specified server. + // Returns NOT_FOUND if either the player or target server doesn't exist. + // Returns FAILED_PRECONDITION if the connection attempt fails. + rpc ConnectPlayer(ConnectPlayerRequest) returns (ConnectPlayerResponse); + + // DisconnectPlayer disconnects a player from the proxy. + // Returns NOT_FOUND if the player doesn't exist. + // Returns INVALID_ARGUMENT if the reason text is malformed. + rpc DisconnectPlayer(DisconnectPlayerRequest) returns (DisconnectPlayerResponse); +} + +// DisconnectPlayerRequest is the request for DisconnectPlayer method. +message DisconnectPlayerRequest { + // The player's username or ID to disconnect + string player = 1; + // The reason displayed to the player when they are disconnected. + // + // Formats: + // + // - `{"text":"Hello, world!"}` - JSON text component. See https://wiki.vg/Text_formatting for details. + // + // - `§aHello,\n§bworld!` - Simple color codes. See https://wiki.vg/Text_formatting#Colors + // + // Optional, if empty no reason will be shown. + string reason = 2; +} + +// DisconnectPlayerResponse is the response for DisconnectPlayer method. +message DisconnectPlayerResponse {} + +// ConnectPlayerRequest is the request for ConnectPlayer method. +message ConnectPlayerRequest { + // The player's username or ID to connect + string player = 1; + // The target server name to connect the player to + string server = 2; +} + +// ConnectPlayerResponse is the response for ConnectPlayer method. +message ConnectPlayerResponse {} + +// RegisterServerRequest is the request for RegisterServer method. +message RegisterServerRequest { + // The unique name of the server + string name = 1; + // The network address of the server (e.g. "localhost:25565") + string address = 2; +} + +// RegisterServerResponse is the response for RegisterServer method. +message RegisterServerResponse {} + +// UnregisterServerRequest is the request for UnregisterServer method. +message UnregisterServerRequest { + // The name of the server. + // Optional, if not set, the address will be used to match servers. + string name = 1; + + // The address of the server. + // Optional, if not set, the name will be used to match servers. + // If both name and address are set, only the server that matches both properties exactly will be unregistered. + // If only the address is set, the first server matching that address will be unregistered. + string address = 2; +} + +// UnregisterServerResponse is the response for UnregisterServer method. +message UnregisterServerResponse {} + +// ListServersRequest is the request for ListServers method. +message ListServersRequest {} + +// ListServersResponse is the response for ListServers method. +message ListServersResponse { + repeated Server servers = 1; +} + +// Server represents a backend server where Gate can connect players to. +message Server { + // The unique name of the server. + string name = 1; + // The network address of the server. + string address = 2; + // The number of players currently on the server. + int32 players = 3; +} + +// GetPlayerRequest is the request for GetPlayer method. +message GetPlayerRequest { + // Gets the player by their Minecraft UUID. + // Optional, if not set the username will be used. + // If both id and username are set, the id will be used. + // Must be a valid Minecraft UUID format (e.g. "550e8400-e29b-41d4-a716-446655440000") + string id = 1; + // Gets the player by their username. + // Optional, if not set the id will be used. + // Case-sensitive. + string username = 2; +} + +// GetPlayerResponse is the response for GetPlayer method. +message GetPlayerResponse { + // The player matching the request criteria + Player player = 1; +} + +// ListPlayersRequest is the request for ListPlayers method. +message ListPlayersRequest { + // Filter players by server names. + // Optional, if empty all online players are returned. + // If specified, only returns players on the listed servers. + repeated string servers = 1; +} + +// ListPlayersResponse is the response for ListPlayers method. +message ListPlayersResponse { + repeated Player players = 1; +} + +// Player represents an online player on the proxy. +message Player { + // The player's Minecraft UUID + string id = 1; + // The player's username + string username = 2; +} diff --git a/buf.gen.yaml b/buf.gen.yaml new file mode 100644 index 00000000..88b3d23e --- /dev/null +++ b/buf.gen.yaml @@ -0,0 +1,17 @@ +version: v2 +clean: true +managed: + enabled: true + override: + - file_option: go_package_prefix + value: go.minekube.com/gate/pkg/internal/api/gen +plugins: + - remote: buf.build/protocolbuffers/go + out: pkg/internal/api/gen + opt: paths=source_relative + - remote: buf.build/connectrpc/go + out: pkg/internal/api/gen + opt: paths=source_relative + - remote: buf.build/community/pseudomuto-doc + out: .web/docs/developers/api/gen + opt: markdown,definition.gen.md diff --git a/buf.yaml b/buf.yaml new file mode 100644 index 00000000..4818eed9 --- /dev/null +++ b/buf.yaml @@ -0,0 +1,11 @@ +# For details on buf.yaml configuration, visit https://buf.build/docs/configuration/v2/buf-yaml +version: v2 +modules: + - path: api + name: buf.build/minekube/gate +lint: + use: + - STANDARD +breaking: + use: + - FILE diff --git a/config-lite.yml b/config-lite.yml index 2ec1763b..4759df60 100644 --- a/config-lite.yml +++ b/config-lite.yml @@ -107,4 +107,14 @@ connect: # # It is supported to run multiple Gates on the same endpoint name for load balancing # (use the same connect.json token file from first Gate instance). - #name: your-endpoint-name \ No newline at end of file + #name: your-endpoint-name + +# Gate HTTP API configuration. +# See https://gate.minekube.com/guide/api for more information. +api: + # Whether to enable the API for Gate. + # Default: false + enabled: false + # The bind address to listen for API connections. + # Default: localhost:8080 + bind: localhost:8080 diff --git a/config.yml b/config.yml index 3346b3de..36bbf197 100644 --- a/config.yml +++ b/config.yml @@ -202,3 +202,13 @@ connect: # It is supported to run multiple Gates on the same endpoint name for load balancing # (use the same connect.json token file from first Gate instance). #name: your-endpoint-name + +# Gate HTTP API configuration. +# See https://gate.minekube.com/guide/api for more information. +api: + # Whether to enable the API for Gate. + # Default: false + enabled: false + # The bind address to listen for API connections. + # Default: localhost:8080 + bind: localhost:8080 diff --git a/go.mod b/go.mod index e2e1383c..bcd8a934 100644 --- a/go.mod +++ b/go.mod @@ -1,16 +1,17 @@ module go.minekube.com/gate -go 1.22.7 +go 1.23.2 toolchain go1.23.3 require ( + connectrpc.com/connect v1.17.0 github.com/Tnze/go-mc v1.20.2 github.com/agext/levenshtein v1.2.3 github.com/coder/websocket v1.8.12 github.com/dboslee/lru v0.0.1 github.com/edwingeng/deque/v2 v2.1.1 - github.com/gammazero/deque v0.2.1 + github.com/gammazero/deque v1.0.0 github.com/go-faker/faker/v4 v4.5.0 github.com/go-logr/logr v1.4.2 github.com/go-logr/zapr v1.3.0 @@ -34,21 +35,23 @@ require ( go.minekube.com/connect v0.6.2 go.uber.org/atomic v1.11.0 go.uber.org/zap v1.27.0 - golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 + golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f + golang.org/x/net v0.31.0 golang.org/x/sync v0.9.0 golang.org/x/text v0.20.0 golang.org/x/time v0.8.0 google.golang.org/grpc v1.68.0 + google.golang.org/protobuf v1.35.2 gopkg.in/yaml.v3 v3.0.1 ) require ( - buf.build/gen/go/minekube/connect/protocolbuffers/go v1.34.2-20240220124425-904ce30425c9.2 // indirect + buf.build/gen/go/minekube/connect/protocolbuffers/go v1.35.2-20240220124425-904ce30425c9.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/francoispqt/gojay v1.2.13 // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/go-gl/mathgl v1.1.0 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect @@ -56,7 +59,7 @@ require ( github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect - github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.6.0 // indirect @@ -70,9 +73,8 @@ require ( github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/image v0.11.0 // indirect - golang.org/x/sys v0.25.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/protobuf v1.34.2 // indirect + golang.org/x/image v0.18.0 // indirect + golang.org/x/sys v0.27.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) diff --git a/go.sum b/go.sum index 8799f9a3..4a89eec6 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,11 @@ -buf.build/gen/go/minekube/connect/protocolbuffers/go v1.34.2-20240220124425-904ce30425c9.2 h1:P9rrKBfkybGwL8Rb5UmzCnOa/mkcJtrUrRVEX5An9k8= -buf.build/gen/go/minekube/connect/protocolbuffers/go v1.34.2-20240220124425-904ce30425c9.2/go.mod h1:D/wczfxm9oSmKysNIdtRRiwwkOnJUw8xWj8hgDMBko0= +buf.build/gen/go/minekube/connect/protocolbuffers/go v1.35.2-20240220124425-904ce30425c9.1 h1:RV35ziPOz7DrN6S673Dq70Pydg3sFa3uGsYzaztavlo= +buf.build/gen/go/minekube/connect/protocolbuffers/go v1.35.2-20240220124425-904ce30425c9.1/go.mod h1:96yQVJkVjg/fSbxhL7wpEEz59WDdYZ4M9f7MIcGeMQY= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= +connectrpc.com/connect v1.17.0 h1:W0ZqMhtVzn9Zhn2yATuUokDLO5N+gIuBWMOnsQrfmZk= +connectrpc.com/connect v1.17.0/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8= dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= @@ -42,10 +44,10 @@ github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiD github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0= -github.com/gammazero/deque v0.2.1/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZDV34tuU= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/gammazero/deque v1.0.0 h1:LTmimT8H7bXkkCy6gZX7zNLtkbz4NdS2z8LZuor3j34= +github.com/gammazero/deque v1.0.0/go.mod h1:iflpYvtGfM3U8S8j+sZEKIak3SAKYpA5/SQewgfXDKo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= @@ -66,6 +68,8 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -124,8 +128,8 @@ github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= -github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= -github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pires/go-proxyproto v0.8.0 h1:5unRmEAPbHXHuLjDg01CxJWf91cw3lKHc/0xzKpXEe0= github.com/pires/go-proxyproto v0.8.0/go.mod h1:iknsfgnH8EkjrMeMyvfKByp9TiBZCKZM0jx2xmKqnVY= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -191,15 +195,9 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= @@ -213,7 +211,6 @@ github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHg github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zyedidia/generic v1.2.1 h1:Zv5KS/N2m0XZZiuLS82qheRG4X1o5gsWreGb0hR7XDc= github.com/zyedidia/generic v1.2.1/go.mod h1:ly2RBz4mnz1yeuVbQA/VFwGjK3mnHGRj1JuoG336Bis= go.minekube.com/brigodier v0.0.1 h1:v5x+fZNefM24JIi+fYQjQcjZ8rwJbfRSpnnpw4b/x6k= @@ -236,18 +233,15 @@ golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+ golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= -golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= +golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= +golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= golang.org/x/image v0.0.0-20190321063152-3fc05d484e9f/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.11.0 h1:ds2RoQvBvYTiJkwpSFDwCcDFNX7DqjL2WsUgTNk0Ooo= -golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8= +golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ= +golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -256,12 +250,8 @@ golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -271,11 +261,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -283,43 +268,20 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= -golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= @@ -332,20 +294,16 @@ google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f h1:C1QccEa9kUwvMgEUORqQD9S17QesQijxjZ84sO82mfo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= -google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/pkg/edition/java/config/config.go b/pkg/edition/java/config/config.go index 5018eff0..0e25632b 100644 --- a/pkg/edition/java/config/config.go +++ b/pkg/edition/java/config/config.go @@ -2,6 +2,8 @@ package config import ( "fmt" + "strings" + "time" liteconfig "go.minekube.com/gate/pkg/edition/java/lite/config" "go.minekube.com/gate/pkg/edition/java/proto/version" @@ -9,7 +11,6 @@ import ( "go.minekube.com/gate/pkg/util/configutil" "go.minekube.com/gate/pkg/util/favicon" "go.minekube.com/gate/pkg/util/validation" - "time" ) // DefaultConfig is a default Config. @@ -187,7 +188,7 @@ func (c *Config) Validate() (warns []error, errs []error) { return } - if len(c.Bind) == 0 { + if strings.TrimSpace(c.Bind) == "" { e("Bind is empty") } else { if err := validation.ValidHostPort(c.Bind); err != nil { diff --git a/pkg/edition/java/proto/state/register.go b/pkg/edition/java/proto/state/register.go index d0406cb9..3ca89f0e 100644 --- a/pkg/edition/java/proto/state/register.go +++ b/pkg/edition/java/proto/state/register.go @@ -311,7 +311,7 @@ func init() { m(0x43, version.Minecraft_1_20_2), m(0x45, version.Minecraft_1_20_3), m(0x47, version.Minecraft_1_20_5), - m(0x4C, version.Minecraft_1_21_2), + m(0x4C, version.Minecraft_1_21_2), ) Play.ClientBound.Register(&p.Disconnect{}, m(0x40, version.Minecraft_1_7_2), diff --git a/pkg/gate/api.go b/pkg/gate/api.go new file mode 100644 index 00000000..c4f9cd0d --- /dev/null +++ b/pkg/gate/api.go @@ -0,0 +1,76 @@ +package gate + +import ( + "bytes" + "context" + "sync" + + "github.com/go-logr/logr" + "github.com/robinbraemer/event" + + "go.minekube.com/gate/pkg/edition/java/proxy" + "go.minekube.com/gate/pkg/gate/config" + "go.minekube.com/gate/pkg/internal/api" + "go.minekube.com/gate/pkg/internal/hashutil" + "go.minekube.com/gate/pkg/internal/reload" + "go.minekube.com/gate/pkg/runtime/process" +) + +func setupAPI(cfg *config.Config, eventMgr event.Manager, initialEnable *proxy.Proxy) process.Runnable { + return process.RunnableFunc(func(ctx context.Context) error { + log := logr.FromContextOrDiscard(ctx).WithName("api") + ctx = logr.NewContext(ctx, log) + + var ( + mu sync.Mutex + stop context.CancelFunc + currentConfigHash []byte + ) + trigger := func(c *reload.ConfigUpdateEvent[config.Config]) { + newConfigHash, err := hashutil.JsonHash(c.Config.API) + if err != nil { + log.Error(err, "error hashing API config") + return + } + + mu.Lock() + defer mu.Unlock() + + // check if config changed + if bytes.Equal(newConfigHash, currentConfigHash) { + return // no change + } + currentConfigHash = newConfigHash + + if stop != nil { + stop() + stop = nil + } + + if c.Config.API.Enabled { + svc := api.NewService(initialEnable) + srv := api.NewServer(c.Config.API.Config, svc) + + var runCtx context.Context + runCtx, stop = context.WithCancel(ctx) + go func() { + if err := srv.Start(runCtx); err != nil { + log.Error(err, "failed to start api service") + return + } + log.Info("api service stopped") + }() + } + } + + defer reload.Subscribe(eventMgr, trigger)() + + trigger(&reload.ConfigUpdateEvent[config.Config]{ + Config: cfg, + PrevConfig: cfg, + }) + + <-ctx.Done() + return nil + }) +} diff --git a/pkg/gate/config/config.go b/pkg/gate/config/config.go index 9bff5005..a985ace4 100644 --- a/pkg/gate/config/config.go +++ b/pkg/gate/config/config.go @@ -5,6 +5,7 @@ import ( bconfig "go.minekube.com/gate/pkg/edition/bedrock/config" jconfig "go.minekube.com/gate/pkg/edition/java/config" + "go.minekube.com/gate/pkg/internal/api" connect "go.minekube.com/gate/pkg/util/connectutil/config" "go.minekube.com/gate/pkg/util/validation" ) @@ -27,6 +28,10 @@ var DefaultConfig = Config{ Bind: "0.0.0.0:9090", }, Connect: connect.DefaultConfig, + API: API{ + Enabled: false, + Config: api.DefaultConfig, + }, } // Config is the root configuration of Gate. @@ -40,6 +45,8 @@ type Config struct { HealthService HealthService `json:"healthService,omitempty" yaml:"healthService,omitempty"` // See Connect struct. Connect connect.Config `json:"connect,omitempty" yaml:"connect,omitempty"` + // See API struct. + API API `json:"api,omitempty" yaml:"api,omitempty"` } // Editions provides Minecraft edition specific configs. @@ -58,15 +65,21 @@ type Java struct { // Bedrock edition. type Bedrock struct { - Enabled bool - Config bconfig.Config + Enabled bool `json:"enabled,omitempty" yaml:"enabled,omitempty"` + Config bconfig.Config `json:"config,omitempty" yaml:"config,omitempty"` } // HealthService is a GRPC health probe service for use with Kubernetes pods. // (https://github.com/grpc-ecosystem/grpc-health-probe) type HealthService struct { - Enabled bool - Bind string + Enabled bool `json:"enabled,omitempty" yaml:"enabled,omitempty"` + Bind string `json:"bind,omitempty" yaml:"bind,omitempty"` +} + +// API is the configuration for the Gate API. +type API struct { + Enabled bool `json:"enabled,omitempty" yaml:"enabled,omitempty"` + Config api.Config `json:"config,omitempty" yaml:"config,omitempty"` } // Validate validates a Config and all enabled edition configs (Java / Bedrock). @@ -96,10 +109,15 @@ func (c *Config) Validate() (warns []error, errs []error) { warns = append(warns, prefix("java", warns2)...) errs = append(errs, prefix("java", errs2)...) } - if c.Editions.Bedrock.Enabled { - warns2, errs2 := c.Editions.Java.Config.Validate() - warns = append(warns, prefix("bedrock", warns2)...) - errs = append(errs, prefix("bedrock", errs2)...) + //if c.Editions.Bedrock.Enabled { + // warns2, errs2 := c.Editions.Bedrock.Config.Validate() + // warns = append(warns, prefix("bedrock", warns2)...) + // errs = append(errs, prefix("bedrock", errs2)...) + //} + if c.API.Enabled { + warns2, errs2 := c.API.Config.Validate() + warns = append(warns, prefix("api", warns2)...) + errs = append(errs, prefix("api", errs2)...) } return } diff --git a/pkg/gate/connect.go b/pkg/gate/connect.go index 591bd1e5..e76aac8a 100644 --- a/pkg/gate/connect.go +++ b/pkg/gate/connect.go @@ -3,13 +3,13 @@ package gate import ( "bytes" "context" - "crypto/sha1" - "encoding/json" "sync" "github.com/go-logr/logr" "github.com/robinbraemer/event" + "go.minekube.com/gate/pkg/gate/config" + "go.minekube.com/gate/pkg/internal/hashutil" "go.minekube.com/gate/pkg/internal/reload" "go.minekube.com/gate/pkg/runtime/process" connectcfg "go.minekube.com/gate/pkg/util/connectutil/config" @@ -39,7 +39,7 @@ func setupConnect( return } - newConfigHash, err := jsonHash(connect) + newConfigHash, err := hashutil.JsonHash(connect) if err != nil { log.Error(err, "error hashing Connect config") return @@ -89,13 +89,3 @@ func setupConnect( return nil })) } - -// jsonHash returns the sha1 hash of the JSON representation of v. -func jsonHash(v any) ([]byte, error) { - j, err := json.Marshal(v) - if err != nil { - return nil, err - } - h := sha1.Sum(j) - return h[:], nil -} diff --git a/pkg/gate/gate.go b/pkg/gate/gate.go index 36fdca4d..661128ea 100644 --- a/pkg/gate/gate.go +++ b/pkg/gate/gate.go @@ -14,6 +14,8 @@ import ( "github.com/go-logr/logr" "github.com/robinbraemer/event" "github.com/spf13/viper" + "gopkg.in/yaml.v3" + "go.minekube.com/gate/pkg/bridge" "go.minekube.com/gate/pkg/edition" bproxy "go.minekube.com/gate/pkg/edition/bedrock/proxy" @@ -25,7 +27,6 @@ import ( connectcfg "go.minekube.com/gate/pkg/util/connectutil/config" errorsutil "go.minekube.com/gate/pkg/util/errs" "go.minekube.com/gate/pkg/util/interrupt" - "gopkg.in/yaml.v3" ) // Options are Gate options. @@ -113,6 +114,10 @@ func New(options Options) (gate *Gate, err error) { return nil, err } + if err = gate.proc.Add(setupAPI(c, eventMgr, gate.Java())); err != nil { + return nil, err + } + return gate, nil } diff --git a/pkg/internal/api/config.go b/pkg/internal/api/config.go new file mode 100644 index 00000000..d20894f2 --- /dev/null +++ b/pkg/internal/api/config.go @@ -0,0 +1,32 @@ +package api + +import ( + "errors" + "fmt" + "strings" + + "go.minekube.com/gate/pkg/util/validation" +) + +// DefaultConfig is the default configuration for the Config. +var DefaultConfig = Config{ + Bind: "localhost:8080", +} + +// Config is the configuration for the Gate API. +type Config struct { + // Bind is the address to bind the API server to. + // Using a localhost address is recommended to avoid exposing the API to the public. + Bind string `json:"bind,omitempty" yaml:"bind,omitempty"` +} + +// Validate validates the API configuration. +func (c Config) Validate() (warns []error, errs []error) { + if strings.TrimSpace(c.Bind) == "" { + return nil, []error{errors.New("bind address must not be empty")} + } + if err := validation.ValidHostPort(c.Bind); err != nil { + return nil, []error{fmt.Errorf("invalid bind %q: %v", c.Bind, err)} + } + return nil, nil +} diff --git a/pkg/internal/api/convert.go b/pkg/internal/api/convert.go new file mode 100644 index 00000000..c0105eca --- /dev/null +++ b/pkg/internal/api/convert.go @@ -0,0 +1,37 @@ +package api + +import ( + "go.minekube.com/gate/pkg/edition/java/proxy" + pb "go.minekube.com/gate/pkg/internal/api/gen/minekube/gate/v1" +) + +func PlayersToProto(p []proxy.Player) []*pb.Player { + var players []*pb.Player + for _, player := range p { + players = append(players, PlayerToProto(player)) + } + return players +} + +func PlayerToProto(p proxy.Player) *pb.Player { + return &pb.Player{ + Id: p.ID().String(), + Username: p.Username(), + } +} + +func ServersToProto(s []proxy.RegisteredServer) []*pb.Server { + var servers []*pb.Server + for _, server := range s { + servers = append(servers, ServerToProto(server)) + } + return servers +} + +func ServerToProto(s proxy.RegisteredServer) *pb.Server { + return &pb.Server{ + Name: s.ServerInfo().Name(), + Address: s.ServerInfo().Addr().String(), + Players: int32(s.Players().Len()), + } +} diff --git a/pkg/internal/api/gen/minekube/gate/v1/gate_service.pb.go b/pkg/internal/api/gen/minekube/gate/v1/gate_service.pb.go new file mode 100644 index 00000000..7336d2ad --- /dev/null +++ b/pkg/internal/api/gen/minekube/gate/v1/gate_service.pb.go @@ -0,0 +1,1015 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.35.2 +// protoc (unknown) +// source: minekube/gate/v1/gate_service.proto + +package gatev1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// DisconnectPlayerRequest is the request for DisconnectPlayer method. +type DisconnectPlayerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The player's username or ID to disconnect + Player string `protobuf:"bytes,1,opt,name=player,proto3" json:"player,omitempty"` + // The reason displayed to the player when they are disconnected. + // + // Formats: + // + // - `{"text":"Hello, world!"}` - JSON text component. See https://wiki.vg/Text_formatting for details. + // + // - `§aHello,\n§bworld!` - Simple color codes. See https://wiki.vg/Text_formatting#Colors + // + // Optional, if empty no reason will be shown. + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` +} + +func (x *DisconnectPlayerRequest) Reset() { + *x = DisconnectPlayerRequest{} + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DisconnectPlayerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DisconnectPlayerRequest) ProtoMessage() {} + +func (x *DisconnectPlayerRequest) ProtoReflect() protoreflect.Message { + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DisconnectPlayerRequest.ProtoReflect.Descriptor instead. +func (*DisconnectPlayerRequest) Descriptor() ([]byte, []int) { + return file_minekube_gate_v1_gate_service_proto_rawDescGZIP(), []int{0} +} + +func (x *DisconnectPlayerRequest) GetPlayer() string { + if x != nil { + return x.Player + } + return "" +} + +func (x *DisconnectPlayerRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +// DisconnectPlayerResponse is the response for DisconnectPlayer method. +type DisconnectPlayerResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *DisconnectPlayerResponse) Reset() { + *x = DisconnectPlayerResponse{} + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DisconnectPlayerResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DisconnectPlayerResponse) ProtoMessage() {} + +func (x *DisconnectPlayerResponse) ProtoReflect() protoreflect.Message { + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DisconnectPlayerResponse.ProtoReflect.Descriptor instead. +func (*DisconnectPlayerResponse) Descriptor() ([]byte, []int) { + return file_minekube_gate_v1_gate_service_proto_rawDescGZIP(), []int{1} +} + +// ConnectPlayerRequest is the request for ConnectPlayer method. +type ConnectPlayerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The player's username or ID to connect + Player string `protobuf:"bytes,1,opt,name=player,proto3" json:"player,omitempty"` + // The target server name to connect the player to + Server string `protobuf:"bytes,2,opt,name=server,proto3" json:"server,omitempty"` +} + +func (x *ConnectPlayerRequest) Reset() { + *x = ConnectPlayerRequest{} + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConnectPlayerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConnectPlayerRequest) ProtoMessage() {} + +func (x *ConnectPlayerRequest) ProtoReflect() protoreflect.Message { + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConnectPlayerRequest.ProtoReflect.Descriptor instead. +func (*ConnectPlayerRequest) Descriptor() ([]byte, []int) { + return file_minekube_gate_v1_gate_service_proto_rawDescGZIP(), []int{2} +} + +func (x *ConnectPlayerRequest) GetPlayer() string { + if x != nil { + return x.Player + } + return "" +} + +func (x *ConnectPlayerRequest) GetServer() string { + if x != nil { + return x.Server + } + return "" +} + +// ConnectPlayerResponse is the response for ConnectPlayer method. +type ConnectPlayerResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ConnectPlayerResponse) Reset() { + *x = ConnectPlayerResponse{} + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConnectPlayerResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConnectPlayerResponse) ProtoMessage() {} + +func (x *ConnectPlayerResponse) ProtoReflect() protoreflect.Message { + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConnectPlayerResponse.ProtoReflect.Descriptor instead. +func (*ConnectPlayerResponse) Descriptor() ([]byte, []int) { + return file_minekube_gate_v1_gate_service_proto_rawDescGZIP(), []int{3} +} + +// RegisterServerRequest is the request for RegisterServer method. +type RegisterServerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The unique name of the server + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // The network address of the server (e.g. "localhost:25565") + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` +} + +func (x *RegisterServerRequest) Reset() { + *x = RegisterServerRequest{} + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RegisterServerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterServerRequest) ProtoMessage() {} + +func (x *RegisterServerRequest) ProtoReflect() protoreflect.Message { + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegisterServerRequest.ProtoReflect.Descriptor instead. +func (*RegisterServerRequest) Descriptor() ([]byte, []int) { + return file_minekube_gate_v1_gate_service_proto_rawDescGZIP(), []int{4} +} + +func (x *RegisterServerRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *RegisterServerRequest) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +// RegisterServerResponse is the response for RegisterServer method. +type RegisterServerResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *RegisterServerResponse) Reset() { + *x = RegisterServerResponse{} + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RegisterServerResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterServerResponse) ProtoMessage() {} + +func (x *RegisterServerResponse) ProtoReflect() protoreflect.Message { + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegisterServerResponse.ProtoReflect.Descriptor instead. +func (*RegisterServerResponse) Descriptor() ([]byte, []int) { + return file_minekube_gate_v1_gate_service_proto_rawDescGZIP(), []int{5} +} + +// UnregisterServerRequest is the request for UnregisterServer method. +type UnregisterServerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The name of the server. + // Optional, if not set, the address will be used to match servers. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // The address of the server. + // Optional, if not set, the name will be used to match servers. + // If both name and address are set, only the server that matches both properties exactly will be unregistered. + // If only the address is set, the first server matching that address will be unregistered. + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` +} + +func (x *UnregisterServerRequest) Reset() { + *x = UnregisterServerRequest{} + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UnregisterServerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UnregisterServerRequest) ProtoMessage() {} + +func (x *UnregisterServerRequest) ProtoReflect() protoreflect.Message { + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UnregisterServerRequest.ProtoReflect.Descriptor instead. +func (*UnregisterServerRequest) Descriptor() ([]byte, []int) { + return file_minekube_gate_v1_gate_service_proto_rawDescGZIP(), []int{6} +} + +func (x *UnregisterServerRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *UnregisterServerRequest) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +// UnregisterServerResponse is the response for UnregisterServer method. +type UnregisterServerResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *UnregisterServerResponse) Reset() { + *x = UnregisterServerResponse{} + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UnregisterServerResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UnregisterServerResponse) ProtoMessage() {} + +func (x *UnregisterServerResponse) ProtoReflect() protoreflect.Message { + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UnregisterServerResponse.ProtoReflect.Descriptor instead. +func (*UnregisterServerResponse) Descriptor() ([]byte, []int) { + return file_minekube_gate_v1_gate_service_proto_rawDescGZIP(), []int{7} +} + +// ListServersRequest is the request for ListServers method. +type ListServersRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ListServersRequest) Reset() { + *x = ListServersRequest{} + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListServersRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListServersRequest) ProtoMessage() {} + +func (x *ListServersRequest) ProtoReflect() protoreflect.Message { + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListServersRequest.ProtoReflect.Descriptor instead. +func (*ListServersRequest) Descriptor() ([]byte, []int) { + return file_minekube_gate_v1_gate_service_proto_rawDescGZIP(), []int{8} +} + +// ListServersResponse is the response for ListServers method. +type ListServersResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Servers []*Server `protobuf:"bytes,1,rep,name=servers,proto3" json:"servers,omitempty"` +} + +func (x *ListServersResponse) Reset() { + *x = ListServersResponse{} + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListServersResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListServersResponse) ProtoMessage() {} + +func (x *ListServersResponse) ProtoReflect() protoreflect.Message { + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListServersResponse.ProtoReflect.Descriptor instead. +func (*ListServersResponse) Descriptor() ([]byte, []int) { + return file_minekube_gate_v1_gate_service_proto_rawDescGZIP(), []int{9} +} + +func (x *ListServersResponse) GetServers() []*Server { + if x != nil { + return x.Servers + } + return nil +} + +// Server represents a backend server where Gate can connect players to. +type Server struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The unique name of the server. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // The network address of the server. + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + // The number of players currently on the server. + Players int32 `protobuf:"varint,3,opt,name=players,proto3" json:"players,omitempty"` +} + +func (x *Server) Reset() { + *x = Server{} + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Server) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Server) ProtoMessage() {} + +func (x *Server) ProtoReflect() protoreflect.Message { + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Server.ProtoReflect.Descriptor instead. +func (*Server) Descriptor() ([]byte, []int) { + return file_minekube_gate_v1_gate_service_proto_rawDescGZIP(), []int{10} +} + +func (x *Server) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Server) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *Server) GetPlayers() int32 { + if x != nil { + return x.Players + } + return 0 +} + +// GetPlayerRequest is the request for GetPlayer method. +type GetPlayerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Gets the player by their Minecraft UUID. + // Optional, if not set the username will be used. + // If both id and username are set, the id will be used. + // Must be a valid Minecraft UUID format (e.g. "550e8400-e29b-41d4-a716-446655440000") + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Gets the player by their username. + // Optional, if not set the id will be used. + // Case-sensitive. + Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"` +} + +func (x *GetPlayerRequest) Reset() { + *x = GetPlayerRequest{} + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetPlayerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetPlayerRequest) ProtoMessage() {} + +func (x *GetPlayerRequest) ProtoReflect() protoreflect.Message { + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetPlayerRequest.ProtoReflect.Descriptor instead. +func (*GetPlayerRequest) Descriptor() ([]byte, []int) { + return file_minekube_gate_v1_gate_service_proto_rawDescGZIP(), []int{11} +} + +func (x *GetPlayerRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *GetPlayerRequest) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +// GetPlayerResponse is the response for GetPlayer method. +type GetPlayerResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The player matching the request criteria + Player *Player `protobuf:"bytes,1,opt,name=player,proto3" json:"player,omitempty"` +} + +func (x *GetPlayerResponse) Reset() { + *x = GetPlayerResponse{} + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetPlayerResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetPlayerResponse) ProtoMessage() {} + +func (x *GetPlayerResponse) ProtoReflect() protoreflect.Message { + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetPlayerResponse.ProtoReflect.Descriptor instead. +func (*GetPlayerResponse) Descriptor() ([]byte, []int) { + return file_minekube_gate_v1_gate_service_proto_rawDescGZIP(), []int{12} +} + +func (x *GetPlayerResponse) GetPlayer() *Player { + if x != nil { + return x.Player + } + return nil +} + +// ListPlayersRequest is the request for ListPlayers method. +type ListPlayersRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Filter players by server names. + // Optional, if empty all online players are returned. + // If specified, only returns players on the listed servers. + Servers []string `protobuf:"bytes,1,rep,name=servers,proto3" json:"servers,omitempty"` +} + +func (x *ListPlayersRequest) Reset() { + *x = ListPlayersRequest{} + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListPlayersRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPlayersRequest) ProtoMessage() {} + +func (x *ListPlayersRequest) ProtoReflect() protoreflect.Message { + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListPlayersRequest.ProtoReflect.Descriptor instead. +func (*ListPlayersRequest) Descriptor() ([]byte, []int) { + return file_minekube_gate_v1_gate_service_proto_rawDescGZIP(), []int{13} +} + +func (x *ListPlayersRequest) GetServers() []string { + if x != nil { + return x.Servers + } + return nil +} + +// ListPlayersResponse is the response for ListPlayers method. +type ListPlayersResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Players []*Player `protobuf:"bytes,1,rep,name=players,proto3" json:"players,omitempty"` +} + +func (x *ListPlayersResponse) Reset() { + *x = ListPlayersResponse{} + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListPlayersResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPlayersResponse) ProtoMessage() {} + +func (x *ListPlayersResponse) ProtoReflect() protoreflect.Message { + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListPlayersResponse.ProtoReflect.Descriptor instead. +func (*ListPlayersResponse) Descriptor() ([]byte, []int) { + return file_minekube_gate_v1_gate_service_proto_rawDescGZIP(), []int{14} +} + +func (x *ListPlayersResponse) GetPlayers() []*Player { + if x != nil { + return x.Players + } + return nil +} + +// Player represents an online player on the proxy. +type Player struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The player's Minecraft UUID + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // The player's username + Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"` +} + +func (x *Player) Reset() { + *x = Player{} + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Player) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Player) ProtoMessage() {} + +func (x *Player) ProtoReflect() protoreflect.Message { + mi := &file_minekube_gate_v1_gate_service_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Player.ProtoReflect.Descriptor instead. +func (*Player) Descriptor() ([]byte, []int) { + return file_minekube_gate_v1_gate_service_proto_rawDescGZIP(), []int{15} +} + +func (x *Player) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *Player) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +var File_minekube_gate_v1_gate_service_proto protoreflect.FileDescriptor + +var file_minekube_gate_v1_gate_service_proto_rawDesc = []byte{ + 0x0a, 0x23, 0x6d, 0x69, 0x6e, 0x65, 0x6b, 0x75, 0x62, 0x65, 0x2f, 0x67, 0x61, 0x74, 0x65, 0x2f, + 0x76, 0x31, 0x2f, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x6d, 0x69, 0x6e, 0x65, 0x6b, 0x75, 0x62, 0x65, 0x2e, + 0x67, 0x61, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x22, 0x49, 0x0a, 0x17, 0x44, 0x69, 0x73, 0x63, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, + 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, + 0x6f, 0x6e, 0x22, 0x1a, 0x0a, 0x18, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x46, + 0x0a, 0x14, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x17, 0x0a, 0x15, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x45, 0x0a, 0x15, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x18, 0x0a, 0x16, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x47, 0x0a, 0x17, 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x1a, 0x0a, 0x18, 0x55, 0x6e, 0x72, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x49, 0x0a, 0x13, 0x4c, + 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x32, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x69, 0x6e, 0x65, 0x6b, 0x75, 0x62, 0x65, 0x2e, 0x67, + 0x61, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x07, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x22, 0x50, 0x0a, 0x06, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, + 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x22, 0x3e, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x50, + 0x6c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, + 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x45, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, + 0x6c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, + 0x06, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, + 0x6d, 0x69, 0x6e, 0x65, 0x6b, 0x75, 0x62, 0x65, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x06, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x22, + 0x2e, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x22, + 0x49, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x69, 0x6e, 0x65, 0x6b, 0x75, + 0x62, 0x65, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x52, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x22, 0x34, 0x0a, 0x06, 0x50, 0x6c, + 0x61, 0x79, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, + 0x32, 0xb8, 0x05, 0x0a, 0x0b, 0x47, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x54, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x22, 0x2e, + 0x6d, 0x69, 0x6e, 0x65, 0x6b, 0x75, 0x62, 0x65, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x23, 0x2e, 0x6d, 0x69, 0x6e, 0x65, 0x6b, 0x75, 0x62, 0x65, 0x2e, 0x67, 0x61, 0x74, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, + 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x24, 0x2e, 0x6d, 0x69, 0x6e, 0x65, 0x6b, 0x75, 0x62, 0x65, + 0x2e, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61, + 0x79, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x69, + 0x6e, 0x65, 0x6b, 0x75, 0x62, 0x65, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x73, 0x12, 0x24, 0x2e, 0x6d, 0x69, 0x6e, 0x65, 0x6b, 0x75, 0x62, 0x65, 0x2e, 0x67, 0x61, 0x74, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x69, 0x6e, 0x65, 0x6b, 0x75, + 0x62, 0x65, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, + 0x0a, 0x0e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x12, 0x27, 0x2e, 0x6d, 0x69, 0x6e, 0x65, 0x6b, 0x75, 0x62, 0x65, 0x2e, 0x67, 0x61, 0x74, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x6d, 0x69, 0x6e, 0x65, + 0x6b, 0x75, 0x62, 0x65, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x10, 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x29, 0x2e, 0x6d, 0x69, 0x6e, 0x65, 0x6b, 0x75, + 0x62, 0x65, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x72, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x6d, 0x69, 0x6e, 0x65, 0x6b, 0x75, 0x62, 0x65, 0x2e, 0x67, 0x61, + 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, + 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, + 0x26, 0x2e, 0x6d, 0x69, 0x6e, 0x65, 0x6b, 0x75, 0x62, 0x65, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6d, 0x69, 0x6e, 0x65, 0x6b, 0x75, + 0x62, 0x65, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x69, 0x0a, 0x10, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x6c, + 0x61, 0x79, 0x65, 0x72, 0x12, 0x29, 0x2e, 0x6d, 0x69, 0x6e, 0x65, 0x6b, 0x75, 0x62, 0x65, 0x2e, + 0x67, 0x61, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2a, 0x2e, 0x6d, 0x69, 0x6e, 0x65, 0x6b, 0x75, 0x62, 0x65, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x6c, 0x61, + 0x79, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0xcd, 0x01, 0x0a, 0x14, + 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x65, 0x6b, 0x75, 0x62, 0x65, 0x2e, 0x67, 0x61, 0x74, + 0x65, 0x2e, 0x76, 0x31, 0x42, 0x10, 0x47, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x41, 0x67, 0x6f, 0x2e, 0x6d, 0x69, 0x6e, + 0x65, 0x6b, 0x75, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x74, 0x65, 0x2f, 0x70, + 0x6b, 0x67, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x67, 0x65, 0x6e, 0x2f, 0x6d, 0x69, 0x6e, 0x65, 0x6b, 0x75, 0x62, 0x65, 0x2f, 0x67, 0x61, 0x74, + 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x67, 0x61, 0x74, 0x65, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x4d, 0x47, + 0x58, 0xaa, 0x02, 0x10, 0x4d, 0x69, 0x6e, 0x65, 0x6b, 0x75, 0x62, 0x65, 0x2e, 0x47, 0x61, 0x74, + 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x10, 0x4d, 0x69, 0x6e, 0x65, 0x6b, 0x75, 0x62, 0x65, 0x5c, + 0x47, 0x61, 0x74, 0x65, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1c, 0x4d, 0x69, 0x6e, 0x65, 0x6b, 0x75, + 0x62, 0x65, 0x5c, 0x47, 0x61, 0x74, 0x65, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x12, 0x4d, 0x69, 0x6e, 0x65, 0x6b, 0x75, 0x62, + 0x65, 0x3a, 0x3a, 0x47, 0x61, 0x74, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, +} + +var ( + file_minekube_gate_v1_gate_service_proto_rawDescOnce sync.Once + file_minekube_gate_v1_gate_service_proto_rawDescData = file_minekube_gate_v1_gate_service_proto_rawDesc +) + +func file_minekube_gate_v1_gate_service_proto_rawDescGZIP() []byte { + file_minekube_gate_v1_gate_service_proto_rawDescOnce.Do(func() { + file_minekube_gate_v1_gate_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_minekube_gate_v1_gate_service_proto_rawDescData) + }) + return file_minekube_gate_v1_gate_service_proto_rawDescData +} + +var file_minekube_gate_v1_gate_service_proto_msgTypes = make([]protoimpl.MessageInfo, 16) +var file_minekube_gate_v1_gate_service_proto_goTypes = []any{ + (*DisconnectPlayerRequest)(nil), // 0: minekube.gate.v1.DisconnectPlayerRequest + (*DisconnectPlayerResponse)(nil), // 1: minekube.gate.v1.DisconnectPlayerResponse + (*ConnectPlayerRequest)(nil), // 2: minekube.gate.v1.ConnectPlayerRequest + (*ConnectPlayerResponse)(nil), // 3: minekube.gate.v1.ConnectPlayerResponse + (*RegisterServerRequest)(nil), // 4: minekube.gate.v1.RegisterServerRequest + (*RegisterServerResponse)(nil), // 5: minekube.gate.v1.RegisterServerResponse + (*UnregisterServerRequest)(nil), // 6: minekube.gate.v1.UnregisterServerRequest + (*UnregisterServerResponse)(nil), // 7: minekube.gate.v1.UnregisterServerResponse + (*ListServersRequest)(nil), // 8: minekube.gate.v1.ListServersRequest + (*ListServersResponse)(nil), // 9: minekube.gate.v1.ListServersResponse + (*Server)(nil), // 10: minekube.gate.v1.Server + (*GetPlayerRequest)(nil), // 11: minekube.gate.v1.GetPlayerRequest + (*GetPlayerResponse)(nil), // 12: minekube.gate.v1.GetPlayerResponse + (*ListPlayersRequest)(nil), // 13: minekube.gate.v1.ListPlayersRequest + (*ListPlayersResponse)(nil), // 14: minekube.gate.v1.ListPlayersResponse + (*Player)(nil), // 15: minekube.gate.v1.Player +} +var file_minekube_gate_v1_gate_service_proto_depIdxs = []int32{ + 10, // 0: minekube.gate.v1.ListServersResponse.servers:type_name -> minekube.gate.v1.Server + 15, // 1: minekube.gate.v1.GetPlayerResponse.player:type_name -> minekube.gate.v1.Player + 15, // 2: minekube.gate.v1.ListPlayersResponse.players:type_name -> minekube.gate.v1.Player + 11, // 3: minekube.gate.v1.GateService.GetPlayer:input_type -> minekube.gate.v1.GetPlayerRequest + 13, // 4: minekube.gate.v1.GateService.ListPlayers:input_type -> minekube.gate.v1.ListPlayersRequest + 8, // 5: minekube.gate.v1.GateService.ListServers:input_type -> minekube.gate.v1.ListServersRequest + 4, // 6: minekube.gate.v1.GateService.RegisterServer:input_type -> minekube.gate.v1.RegisterServerRequest + 6, // 7: minekube.gate.v1.GateService.UnregisterServer:input_type -> minekube.gate.v1.UnregisterServerRequest + 2, // 8: minekube.gate.v1.GateService.ConnectPlayer:input_type -> minekube.gate.v1.ConnectPlayerRequest + 0, // 9: minekube.gate.v1.GateService.DisconnectPlayer:input_type -> minekube.gate.v1.DisconnectPlayerRequest + 12, // 10: minekube.gate.v1.GateService.GetPlayer:output_type -> minekube.gate.v1.GetPlayerResponse + 14, // 11: minekube.gate.v1.GateService.ListPlayers:output_type -> minekube.gate.v1.ListPlayersResponse + 9, // 12: minekube.gate.v1.GateService.ListServers:output_type -> minekube.gate.v1.ListServersResponse + 5, // 13: minekube.gate.v1.GateService.RegisterServer:output_type -> minekube.gate.v1.RegisterServerResponse + 7, // 14: minekube.gate.v1.GateService.UnregisterServer:output_type -> minekube.gate.v1.UnregisterServerResponse + 3, // 15: minekube.gate.v1.GateService.ConnectPlayer:output_type -> minekube.gate.v1.ConnectPlayerResponse + 1, // 16: minekube.gate.v1.GateService.DisconnectPlayer:output_type -> minekube.gate.v1.DisconnectPlayerResponse + 10, // [10:17] is the sub-list for method output_type + 3, // [3:10] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_minekube_gate_v1_gate_service_proto_init() } +func file_minekube_gate_v1_gate_service_proto_init() { + if File_minekube_gate_v1_gate_service_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_minekube_gate_v1_gate_service_proto_rawDesc, + NumEnums: 0, + NumMessages: 16, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_minekube_gate_v1_gate_service_proto_goTypes, + DependencyIndexes: file_minekube_gate_v1_gate_service_proto_depIdxs, + MessageInfos: file_minekube_gate_v1_gate_service_proto_msgTypes, + }.Build() + File_minekube_gate_v1_gate_service_proto = out.File + file_minekube_gate_v1_gate_service_proto_rawDesc = nil + file_minekube_gate_v1_gate_service_proto_goTypes = nil + file_minekube_gate_v1_gate_service_proto_depIdxs = nil +} diff --git a/pkg/internal/api/gen/minekube/gate/v1/gatev1connect/gate_service.connect.go b/pkg/internal/api/gen/minekube/gate/v1/gatev1connect/gate_service.connect.go new file mode 100644 index 00000000..a555b518 --- /dev/null +++ b/pkg/internal/api/gen/minekube/gate/v1/gatev1connect/gate_service.connect.go @@ -0,0 +1,326 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: minekube/gate/v1/gate_service.proto + +package gatev1connect + +import ( + connect "connectrpc.com/connect" + context "context" + errors "errors" + v1 "go.minekube.com/gate/pkg/internal/api/gen/minekube/gate/v1" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect.IsAtLeastVersion1_13_0 + +const ( + // GateServiceName is the fully-qualified name of the GateService service. + GateServiceName = "minekube.gate.v1.GateService" +) + +// These constants are the fully-qualified names of the RPCs defined in this package. They're +// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. +// +// Note that these are different from the fully-qualified method names used by +// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to +// reflection-formatted method names, remove the leading slash and convert the remaining slash to a +// period. +const ( + // GateServiceGetPlayerProcedure is the fully-qualified name of the GateService's GetPlayer RPC. + GateServiceGetPlayerProcedure = "/minekube.gate.v1.GateService/GetPlayer" + // GateServiceListPlayersProcedure is the fully-qualified name of the GateService's ListPlayers RPC. + GateServiceListPlayersProcedure = "/minekube.gate.v1.GateService/ListPlayers" + // GateServiceListServersProcedure is the fully-qualified name of the GateService's ListServers RPC. + GateServiceListServersProcedure = "/minekube.gate.v1.GateService/ListServers" + // GateServiceRegisterServerProcedure is the fully-qualified name of the GateService's + // RegisterServer RPC. + GateServiceRegisterServerProcedure = "/minekube.gate.v1.GateService/RegisterServer" + // GateServiceUnregisterServerProcedure is the fully-qualified name of the GateService's + // UnregisterServer RPC. + GateServiceUnregisterServerProcedure = "/minekube.gate.v1.GateService/UnregisterServer" + // GateServiceConnectPlayerProcedure is the fully-qualified name of the GateService's ConnectPlayer + // RPC. + GateServiceConnectPlayerProcedure = "/minekube.gate.v1.GateService/ConnectPlayer" + // GateServiceDisconnectPlayerProcedure is the fully-qualified name of the GateService's + // DisconnectPlayer RPC. + GateServiceDisconnectPlayerProcedure = "/minekube.gate.v1.GateService/DisconnectPlayer" +) + +// These variables are the protoreflect.Descriptor objects for the RPCs defined in this package. +var ( + gateServiceServiceDescriptor = v1.File_minekube_gate_v1_gate_service_proto.Services().ByName("GateService") + gateServiceGetPlayerMethodDescriptor = gateServiceServiceDescriptor.Methods().ByName("GetPlayer") + gateServiceListPlayersMethodDescriptor = gateServiceServiceDescriptor.Methods().ByName("ListPlayers") + gateServiceListServersMethodDescriptor = gateServiceServiceDescriptor.Methods().ByName("ListServers") + gateServiceRegisterServerMethodDescriptor = gateServiceServiceDescriptor.Methods().ByName("RegisterServer") + gateServiceUnregisterServerMethodDescriptor = gateServiceServiceDescriptor.Methods().ByName("UnregisterServer") + gateServiceConnectPlayerMethodDescriptor = gateServiceServiceDescriptor.Methods().ByName("ConnectPlayer") + gateServiceDisconnectPlayerMethodDescriptor = gateServiceServiceDescriptor.Methods().ByName("DisconnectPlayer") +) + +// GateServiceClient is a client for the minekube.gate.v1.GateService service. +type GateServiceClient interface { + // GetPlayer returns the player by the given id or username. + // Returns NOT_FOUND if the player is not online. + // Returns INVALID_ARGUMENT if neither id nor username is provided, or if the id format is invalid. + GetPlayer(context.Context, *connect.Request[v1.GetPlayerRequest]) (*connect.Response[v1.GetPlayerResponse], error) + // ListPlayers returns all online players. + // If servers are specified in the request, only returns players on those servers. + ListPlayers(context.Context, *connect.Request[v1.ListPlayersRequest]) (*connect.Response[v1.ListPlayersResponse], error) + // ListServers returns all registered servers. + ListServers(context.Context, *connect.Request[v1.ListServersRequest]) (*connect.Response[v1.ListServersResponse], error) + // RegisterServer adds a server to the proxy. + // Returns ALREADY_EXISTS if a server with the same name is already registered. + // Returns INVALID_ARGUMENT if the server name or address is invalid. + RegisterServer(context.Context, *connect.Request[v1.RegisterServerRequest]) (*connect.Response[v1.RegisterServerResponse], error) + // UnregisterServer removes a server from the proxy. + // Returns NOT_FOUND if no matching server is found. + // Returns INVALID_ARGUMENT if neither name nor address is provided. + UnregisterServer(context.Context, *connect.Request[v1.UnregisterServerRequest]) (*connect.Response[v1.UnregisterServerResponse], error) + // ConnectPlayer connects a player to a specified server. + // Returns NOT_FOUND if either the player or target server doesn't exist. + // Returns FAILED_PRECONDITION if the connection attempt fails. + ConnectPlayer(context.Context, *connect.Request[v1.ConnectPlayerRequest]) (*connect.Response[v1.ConnectPlayerResponse], error) + // DisconnectPlayer disconnects a player from the proxy. + // Returns NOT_FOUND if the player doesn't exist. + // Returns INVALID_ARGUMENT if the reason text is malformed. + DisconnectPlayer(context.Context, *connect.Request[v1.DisconnectPlayerRequest]) (*connect.Response[v1.DisconnectPlayerResponse], error) +} + +// NewGateServiceClient constructs a client for the minekube.gate.v1.GateService service. By +// default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, +// and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the +// connect.WithGRPC() or connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewGateServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) GateServiceClient { + baseURL = strings.TrimRight(baseURL, "/") + return &gateServiceClient{ + getPlayer: connect.NewClient[v1.GetPlayerRequest, v1.GetPlayerResponse]( + httpClient, + baseURL+GateServiceGetPlayerProcedure, + connect.WithSchema(gateServiceGetPlayerMethodDescriptor), + connect.WithClientOptions(opts...), + ), + listPlayers: connect.NewClient[v1.ListPlayersRequest, v1.ListPlayersResponse]( + httpClient, + baseURL+GateServiceListPlayersProcedure, + connect.WithSchema(gateServiceListPlayersMethodDescriptor), + connect.WithClientOptions(opts...), + ), + listServers: connect.NewClient[v1.ListServersRequest, v1.ListServersResponse]( + httpClient, + baseURL+GateServiceListServersProcedure, + connect.WithSchema(gateServiceListServersMethodDescriptor), + connect.WithClientOptions(opts...), + ), + registerServer: connect.NewClient[v1.RegisterServerRequest, v1.RegisterServerResponse]( + httpClient, + baseURL+GateServiceRegisterServerProcedure, + connect.WithSchema(gateServiceRegisterServerMethodDescriptor), + connect.WithClientOptions(opts...), + ), + unregisterServer: connect.NewClient[v1.UnregisterServerRequest, v1.UnregisterServerResponse]( + httpClient, + baseURL+GateServiceUnregisterServerProcedure, + connect.WithSchema(gateServiceUnregisterServerMethodDescriptor), + connect.WithClientOptions(opts...), + ), + connectPlayer: connect.NewClient[v1.ConnectPlayerRequest, v1.ConnectPlayerResponse]( + httpClient, + baseURL+GateServiceConnectPlayerProcedure, + connect.WithSchema(gateServiceConnectPlayerMethodDescriptor), + connect.WithClientOptions(opts...), + ), + disconnectPlayer: connect.NewClient[v1.DisconnectPlayerRequest, v1.DisconnectPlayerResponse]( + httpClient, + baseURL+GateServiceDisconnectPlayerProcedure, + connect.WithSchema(gateServiceDisconnectPlayerMethodDescriptor), + connect.WithClientOptions(opts...), + ), + } +} + +// gateServiceClient implements GateServiceClient. +type gateServiceClient struct { + getPlayer *connect.Client[v1.GetPlayerRequest, v1.GetPlayerResponse] + listPlayers *connect.Client[v1.ListPlayersRequest, v1.ListPlayersResponse] + listServers *connect.Client[v1.ListServersRequest, v1.ListServersResponse] + registerServer *connect.Client[v1.RegisterServerRequest, v1.RegisterServerResponse] + unregisterServer *connect.Client[v1.UnregisterServerRequest, v1.UnregisterServerResponse] + connectPlayer *connect.Client[v1.ConnectPlayerRequest, v1.ConnectPlayerResponse] + disconnectPlayer *connect.Client[v1.DisconnectPlayerRequest, v1.DisconnectPlayerResponse] +} + +// GetPlayer calls minekube.gate.v1.GateService.GetPlayer. +func (c *gateServiceClient) GetPlayer(ctx context.Context, req *connect.Request[v1.GetPlayerRequest]) (*connect.Response[v1.GetPlayerResponse], error) { + return c.getPlayer.CallUnary(ctx, req) +} + +// ListPlayers calls minekube.gate.v1.GateService.ListPlayers. +func (c *gateServiceClient) ListPlayers(ctx context.Context, req *connect.Request[v1.ListPlayersRequest]) (*connect.Response[v1.ListPlayersResponse], error) { + return c.listPlayers.CallUnary(ctx, req) +} + +// ListServers calls minekube.gate.v1.GateService.ListServers. +func (c *gateServiceClient) ListServers(ctx context.Context, req *connect.Request[v1.ListServersRequest]) (*connect.Response[v1.ListServersResponse], error) { + return c.listServers.CallUnary(ctx, req) +} + +// RegisterServer calls minekube.gate.v1.GateService.RegisterServer. +func (c *gateServiceClient) RegisterServer(ctx context.Context, req *connect.Request[v1.RegisterServerRequest]) (*connect.Response[v1.RegisterServerResponse], error) { + return c.registerServer.CallUnary(ctx, req) +} + +// UnregisterServer calls minekube.gate.v1.GateService.UnregisterServer. +func (c *gateServiceClient) UnregisterServer(ctx context.Context, req *connect.Request[v1.UnregisterServerRequest]) (*connect.Response[v1.UnregisterServerResponse], error) { + return c.unregisterServer.CallUnary(ctx, req) +} + +// ConnectPlayer calls minekube.gate.v1.GateService.ConnectPlayer. +func (c *gateServiceClient) ConnectPlayer(ctx context.Context, req *connect.Request[v1.ConnectPlayerRequest]) (*connect.Response[v1.ConnectPlayerResponse], error) { + return c.connectPlayer.CallUnary(ctx, req) +} + +// DisconnectPlayer calls minekube.gate.v1.GateService.DisconnectPlayer. +func (c *gateServiceClient) DisconnectPlayer(ctx context.Context, req *connect.Request[v1.DisconnectPlayerRequest]) (*connect.Response[v1.DisconnectPlayerResponse], error) { + return c.disconnectPlayer.CallUnary(ctx, req) +} + +// GateServiceHandler is an implementation of the minekube.gate.v1.GateService service. +type GateServiceHandler interface { + // GetPlayer returns the player by the given id or username. + // Returns NOT_FOUND if the player is not online. + // Returns INVALID_ARGUMENT if neither id nor username is provided, or if the id format is invalid. + GetPlayer(context.Context, *connect.Request[v1.GetPlayerRequest]) (*connect.Response[v1.GetPlayerResponse], error) + // ListPlayers returns all online players. + // If servers are specified in the request, only returns players on those servers. + ListPlayers(context.Context, *connect.Request[v1.ListPlayersRequest]) (*connect.Response[v1.ListPlayersResponse], error) + // ListServers returns all registered servers. + ListServers(context.Context, *connect.Request[v1.ListServersRequest]) (*connect.Response[v1.ListServersResponse], error) + // RegisterServer adds a server to the proxy. + // Returns ALREADY_EXISTS if a server with the same name is already registered. + // Returns INVALID_ARGUMENT if the server name or address is invalid. + RegisterServer(context.Context, *connect.Request[v1.RegisterServerRequest]) (*connect.Response[v1.RegisterServerResponse], error) + // UnregisterServer removes a server from the proxy. + // Returns NOT_FOUND if no matching server is found. + // Returns INVALID_ARGUMENT if neither name nor address is provided. + UnregisterServer(context.Context, *connect.Request[v1.UnregisterServerRequest]) (*connect.Response[v1.UnregisterServerResponse], error) + // ConnectPlayer connects a player to a specified server. + // Returns NOT_FOUND if either the player or target server doesn't exist. + // Returns FAILED_PRECONDITION if the connection attempt fails. + ConnectPlayer(context.Context, *connect.Request[v1.ConnectPlayerRequest]) (*connect.Response[v1.ConnectPlayerResponse], error) + // DisconnectPlayer disconnects a player from the proxy. + // Returns NOT_FOUND if the player doesn't exist. + // Returns INVALID_ARGUMENT if the reason text is malformed. + DisconnectPlayer(context.Context, *connect.Request[v1.DisconnectPlayerRequest]) (*connect.Response[v1.DisconnectPlayerResponse], error) +} + +// NewGateServiceHandler builds an HTTP handler from the service implementation. It returns the path +// on which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewGateServiceHandler(svc GateServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + gateServiceGetPlayerHandler := connect.NewUnaryHandler( + GateServiceGetPlayerProcedure, + svc.GetPlayer, + connect.WithSchema(gateServiceGetPlayerMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + gateServiceListPlayersHandler := connect.NewUnaryHandler( + GateServiceListPlayersProcedure, + svc.ListPlayers, + connect.WithSchema(gateServiceListPlayersMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + gateServiceListServersHandler := connect.NewUnaryHandler( + GateServiceListServersProcedure, + svc.ListServers, + connect.WithSchema(gateServiceListServersMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + gateServiceRegisterServerHandler := connect.NewUnaryHandler( + GateServiceRegisterServerProcedure, + svc.RegisterServer, + connect.WithSchema(gateServiceRegisterServerMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + gateServiceUnregisterServerHandler := connect.NewUnaryHandler( + GateServiceUnregisterServerProcedure, + svc.UnregisterServer, + connect.WithSchema(gateServiceUnregisterServerMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + gateServiceConnectPlayerHandler := connect.NewUnaryHandler( + GateServiceConnectPlayerProcedure, + svc.ConnectPlayer, + connect.WithSchema(gateServiceConnectPlayerMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + gateServiceDisconnectPlayerHandler := connect.NewUnaryHandler( + GateServiceDisconnectPlayerProcedure, + svc.DisconnectPlayer, + connect.WithSchema(gateServiceDisconnectPlayerMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + return "/minekube.gate.v1.GateService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case GateServiceGetPlayerProcedure: + gateServiceGetPlayerHandler.ServeHTTP(w, r) + case GateServiceListPlayersProcedure: + gateServiceListPlayersHandler.ServeHTTP(w, r) + case GateServiceListServersProcedure: + gateServiceListServersHandler.ServeHTTP(w, r) + case GateServiceRegisterServerProcedure: + gateServiceRegisterServerHandler.ServeHTTP(w, r) + case GateServiceUnregisterServerProcedure: + gateServiceUnregisterServerHandler.ServeHTTP(w, r) + case GateServiceConnectPlayerProcedure: + gateServiceConnectPlayerHandler.ServeHTTP(w, r) + case GateServiceDisconnectPlayerProcedure: + gateServiceDisconnectPlayerHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedGateServiceHandler returns CodeUnimplemented from all methods. +type UnimplementedGateServiceHandler struct{} + +func (UnimplementedGateServiceHandler) GetPlayer(context.Context, *connect.Request[v1.GetPlayerRequest]) (*connect.Response[v1.GetPlayerResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("minekube.gate.v1.GateService.GetPlayer is not implemented")) +} + +func (UnimplementedGateServiceHandler) ListPlayers(context.Context, *connect.Request[v1.ListPlayersRequest]) (*connect.Response[v1.ListPlayersResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("minekube.gate.v1.GateService.ListPlayers is not implemented")) +} + +func (UnimplementedGateServiceHandler) ListServers(context.Context, *connect.Request[v1.ListServersRequest]) (*connect.Response[v1.ListServersResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("minekube.gate.v1.GateService.ListServers is not implemented")) +} + +func (UnimplementedGateServiceHandler) RegisterServer(context.Context, *connect.Request[v1.RegisterServerRequest]) (*connect.Response[v1.RegisterServerResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("minekube.gate.v1.GateService.RegisterServer is not implemented")) +} + +func (UnimplementedGateServiceHandler) UnregisterServer(context.Context, *connect.Request[v1.UnregisterServerRequest]) (*connect.Response[v1.UnregisterServerResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("minekube.gate.v1.GateService.UnregisterServer is not implemented")) +} + +func (UnimplementedGateServiceHandler) ConnectPlayer(context.Context, *connect.Request[v1.ConnectPlayerRequest]) (*connect.Response[v1.ConnectPlayerResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("minekube.gate.v1.GateService.ConnectPlayer is not implemented")) +} + +func (UnimplementedGateServiceHandler) DisconnectPlayer(context.Context, *connect.Request[v1.DisconnectPlayerRequest]) (*connect.Response[v1.DisconnectPlayerResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("minekube.gate.v1.GateService.DisconnectPlayer is not implemented")) +} diff --git a/pkg/internal/api/server.go b/pkg/internal/api/server.go new file mode 100644 index 00000000..a06b8f68 --- /dev/null +++ b/pkg/internal/api/server.go @@ -0,0 +1,67 @@ +package api + +import ( + "context" + "errors" + "net" + "net/http" + "time" + + "github.com/go-logr/logr" + "golang.org/x/net/http2" + "golang.org/x/net/http2/h2c" + "golang.org/x/sync/errgroup" + + "go.minekube.com/gate/pkg/internal/api/gen/minekube/gate/v1/gatev1connect" +) + +func NewServer(cfg Config, h Handler) *Server { + return &Server{ + cfg: cfg, + h: h, + } +} + +type Server struct { + cfg Config + h Handler +} + +func (s *Server) Start(ctx context.Context) error { + log := logr.FromContextOrDiscard(ctx) + log.Info("starting api service", "bind", s.cfg.Bind) + + mux := http.NewServeMux() + mux.Handle(gatev1connect.NewGateServiceHandler(s.h)) + + hs := &http.Server{ + Addr: s.cfg.Bind, + Handler: h2c.NewHandler(mux, &http2.Server{ + IdleTimeout: time.Second * 30, + }), + ReadTimeout: time.Second * 5, + ReadHeaderTimeout: time.Second * 5, + WriteTimeout: time.Second * 10, + IdleTimeout: time.Second * 30, + BaseContext: func(net.Listener) context.Context { return ctx }, + } + + eg, ctx := errgroup.WithContext(ctx) + + eg.Go(func() error { + <-ctx.Done() + stopCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + return hs.Shutdown(stopCtx) + }) + eg.Go(func() error { return ignoreClosed(hs.ListenAndServe()) }) + + return eg.Wait() +} + +func ignoreClosed(err error) error { + if errors.Is(err, http.ErrServerClosed) { + return nil + } + return err +} diff --git a/pkg/internal/api/service.go b/pkg/internal/api/service.go new file mode 100644 index 00000000..fccdb7c0 --- /dev/null +++ b/pkg/internal/api/service.go @@ -0,0 +1,188 @@ +package api + +import ( + "context" + "errors" + "fmt" + + "connectrpc.com/connect" + "go.minekube.com/common/minecraft/component" + + "go.minekube.com/gate/pkg/edition/java/proxy" + pb "go.minekube.com/gate/pkg/internal/api/gen/minekube/gate/v1" + "go.minekube.com/gate/pkg/internal/api/gen/minekube/gate/v1/gatev1connect" + "go.minekube.com/gate/pkg/util/componentutil" + "go.minekube.com/gate/pkg/util/netutil" + "go.minekube.com/gate/pkg/util/uuid" +) + +func NewService(p *proxy.Proxy) *Service { + return &Service{ + p: p, + } +} + +type ( + Handler = gatev1connect.GateServiceHandler + + Service struct { + p *proxy.Proxy + } +) + +var _ Handler = (*Service)(nil) + +func (s *Service) ListPlayers(ctx context.Context, c *connect.Request[pb.ListPlayersRequest]) (*connect.Response[pb.ListPlayersResponse], error) { + var players []proxy.Player + if len(c.Msg.Servers) == 0 { + players = s.p.Players() + } else { + for _, svr := range c.Msg.Servers { + if s := s.p.Server(svr); s != nil { + s.Players().Range(func(p proxy.Player) bool { + players = append(players, p) + return true + }) + } + } + } + return connect.NewResponse(&pb.ListPlayersResponse{ + Players: PlayersToProto(players), + }), nil +} + +func (s *Service) RegisterServer(ctx context.Context, c *connect.Request[pb.RegisterServerRequest]) (*connect.Response[pb.RegisterServerResponse], error) { + serverAddr := netutil.NewAddr(c.Msg.Address, "tcp") + serverInfo := proxy.NewServerInfo(c.Msg.Name, serverAddr) + + _, err := s.p.Register(serverInfo) + if err != nil { + if errors.Is(err, proxy.ErrServerAlreadyExists) { + return nil, connect.NewError(connect.CodeAlreadyExists, fmt.Errorf("server %q already exists", serverInfo.Name())) + } + return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("invalid server info: %v", err)) + } + + return connect.NewResponse(&pb.RegisterServerResponse{}), nil +} + +func (s *Service) UnregisterServer(ctx context.Context, c *connect.Request[pb.UnregisterServerRequest]) (*connect.Response[pb.UnregisterServerResponse], error) { + var serverInfo proxy.ServerInfo + + switch { + case c.Msg.Name != "" && c.Msg.Address != "": + serverAddr := netutil.NewAddr(c.Msg.Address, "tcp") + serverInfo = proxy.NewServerInfo(c.Msg.Name, serverAddr) + case c.Msg.Name != "": + if s := s.p.Server(c.Msg.Name); s != nil { + serverInfo = s.ServerInfo() + } else { + return nil, connect.NewError(connect.CodeNotFound, errors.New("server not found by name")) + } + case c.Msg.Address != "": + var found bool + for _, s := range s.p.Servers() { + if s.ServerInfo().Addr().String() == c.Msg.Address { + serverInfo = s.ServerInfo() + found = true + break + } + } + if !found { + return nil, connect.NewError(connect.CodeNotFound, errors.New("server not found by address")) + } + default: + return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("invalid request: must specify either name and/or address")) + } + + found := s.p.Unregister(serverInfo) + if !found { + return nil, connect.NewError(connect.CodeNotFound, + fmt.Errorf("server not found with name %q and address %q", serverInfo.Name(), serverInfo.Addr())) + } + + return connect.NewResponse(&pb.UnregisterServerResponse{}), nil +} + +func (s *Service) ConnectPlayer(ctx context.Context, c *connect.Request[pb.ConnectPlayerRequest]) (*connect.Response[pb.ConnectPlayerResponse], error) { + var player proxy.Player + if id, err := uuid.Parse(c.Msg.Player); err == nil { + player = s.p.Player(id) + } else { + player = s.p.PlayerByName(c.Msg.Player) + } + if player == nil { + return nil, connect.NewError(connect.CodeNotFound, errors.New("player not found")) + } + + targetServer := s.p.Server(c.Msg.Server) + if targetServer == nil { + return nil, connect.NewError(connect.CodeNotFound, errors.New("server not found")) + } + + connectionRequest := player.CreateConnectionRequest(targetServer) + _, err := connectionRequest.Connect(ctx) + if err != nil { + return nil, connect.NewError(connect.CodeFailedPrecondition, err) + } + + return connect.NewResponse(&pb.ConnectPlayerResponse{}), nil +} + +func (s *Service) DisconnectPlayer(ctx context.Context, c *connect.Request[pb.DisconnectPlayerRequest]) (*connect.Response[pb.DisconnectPlayerResponse], error) { + var player proxy.Player + if id, err := uuid.Parse(c.Msg.Player); err == nil { + player = s.p.Player(id) + } else { + player = s.p.PlayerByName(c.Msg.Player) + } + + if player == nil { + return nil, connect.NewError(connect.CodeNotFound, errors.New("player not found")) + } + + var reason *component.Text + if c.Msg.Reason != "" { + var err error + reason, err = componentutil.ParseTextComponent(player.Protocol(), c.Msg.Reason) + if err != nil { + return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("could not parse reason: %v", err)) + } + } + + player.Disconnect(reason) + + return connect.NewResponse(&pb.DisconnectPlayerResponse{}), nil +} + +func (s *Service) ListServers(ctx context.Context, c *connect.Request[pb.ListServersRequest]) (*connect.Response[pb.ListServersResponse], error) { + return connect.NewResponse(&pb.ListServersResponse{ + Servers: ServersToProto(s.p.Servers()), + }), nil +} + +func (s *Service) GetPlayer(ctx context.Context, c *connect.Request[pb.GetPlayerRequest]) (*connect.Response[pb.GetPlayerResponse], error) { + req := c.Msg + + var player proxy.Player + switch { + case req.GetId() != "": + id, err := uuid.Parse(req.GetId()) + if err != nil { + return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("invalid player id: %v", err)) + } + player = s.p.Player(id) + case req.GetUsername() != "": + player = s.p.PlayerByName(req.GetUsername()) + default: + return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("id or username must be set")) + } + + if player == nil { + return nil, connect.NewError(connect.CodeNotFound, errors.New("player not found")) + } + + return connect.NewResponse(&pb.GetPlayerResponse{ + Player: PlayerToProto(player), + }), nil +} diff --git a/pkg/internal/hashutil/util.go b/pkg/internal/hashutil/util.go new file mode 100644 index 00000000..d85de324 --- /dev/null +++ b/pkg/internal/hashutil/util.go @@ -0,0 +1,16 @@ +package hashutil + +import ( + "crypto/sha1" + "encoding/json" +) + +// JsonHash returns the sha1 hash of the JSON representation of v. +func JsonHash(v any) ([]byte, error) { + j, err := json.Marshal(v) + if err != nil { + return nil, err + } + h := sha1.Sum(j) + return h[:], nil +} diff --git a/web/docs/.vitepress/theme/components/LandingAfter.vue b/web/docs/.vitepress/theme/components/LandingAfter.vue new file mode 100644 index 00000000..0519ecba --- /dev/null +++ b/web/docs/.vitepress/theme/components/LandingAfter.vue @@ -0,0 +1 @@ + \ No newline at end of file