├── .github └── workflows │ ├── auto-assign.yml │ ├── codeql-analysis.yml │ ├── go.yml │ ├── push.yaml │ └── reviewdog.yml ├── .gitignore ├── README.md ├── api ├── game0 │ └── game0.proto └── gen │ ├── game0 │ └── api │ │ ├── game0.pb.go │ │ ├── game0.pb.gw.go │ │ └── game0_grpc.pb.go │ └── gm │ └── api │ ├── gm.pb.go │ ├── gm.pb.gw.go │ └── gm_grpc.pb.go ├── buf.gen.yaml ├── buf.lock ├── buf.yaml ├── build └── package │ └── docker │ └── Dockerfile ├── cmd └── game0 │ ├── client │ └── main.go │ └── service │ └── main.go ├── deployment ├── docker-compose │ ├── docker-compose.yaml │ ├── infrastructure.yaml │ └── readme.md └── k8s │ └── readme.md ├── draws └── game.drawio.png ├── go.mod ├── go.sum ├── internal ├── clients │ └── game0 │ │ ├── grpc_cli.go │ │ ├── shell.go │ │ └── tcp_cli.go └── services │ └── game0 │ ├── db_nosql │ ├── factory.go │ └── game0 │ │ ├── dao.go │ │ ├── data.go │ │ └── keys.go │ ├── domain │ └── domain.go │ └── service.go ├── pkg ├── dfx │ ├── auth.go │ ├── game0_client.go │ └── game0_setting.go └── modules │ └── game0_module.go └── tests ├── README.md ├── common └── common.js └── game0 ├── game0-k6.proto └── game0.js /.github/workflows/auto-assign.yml: -------------------------------------------------------------------------------- 1 | name: Auto Assign 2 | on: 3 | issues: 4 | types: [ opened ] 5 | pull_request: 6 | types: [ opened ] 7 | jobs: 8 | run: 9 | runs-on: ubuntu-latest 10 | permissions: 11 | issues: write 12 | pull-requests: write 13 | steps: 14 | - name: 'Auto-assign issue' 15 | uses: pozil/auto-assign-issue@v1 16 | with: 17 | repo-token: ${{ secrets.GITHUB_TOKEN }} 18 | assignees: GStones 19 | numOfAssignee: 1 20 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: "Code scanning - action" 2 | 3 | on: 4 | pull_request: 5 | schedule: 6 | - cron: '0 10 * * 6' 7 | 8 | jobs: 9 | CodeQL-Build: 10 | 11 | permissions: 12 | actions: read 13 | contents: read 14 | security-events: write 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v3 20 | 21 | # Initializes the CodeQL tools for scanning. 22 | - name: Initialize CodeQL 23 | uses: github/codeql-action/init@v2 24 | with: 25 | languages: go 26 | 27 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 28 | # If this step fails, then you should remove it and run the build manually (see below) 29 | - name: Autobuild 30 | uses: github/codeql-action/autobuild@v2 31 | 32 | - name: Perform CodeQL Analysis 33 | uses: github/codeql-action/analyze@v2 34 | -------------------------------------------------------------------------------- /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | on: [ pull_request ] 3 | jobs: 4 | 5 | test: 6 | permissions: 7 | contents: read 8 | name: Test 9 | runs-on: ubuntu-latest 10 | steps: 11 | 12 | - uses: actions/checkout@v3 13 | with: 14 | fetch-depth: 50 # Need git history for testing. 15 | 16 | - uses: actions/setup-go@v4 17 | with: 18 | go-version-file: "go.mod" 19 | 20 | - name: Test 21 | run: go test -v -race -coverpkg=./... -coverprofile=coverage.txt ./... 22 | 23 | - uses: codecov/codecov-action@v3 24 | -------------------------------------------------------------------------------- /.github/workflows/push.yaml: -------------------------------------------------------------------------------- 1 | name: buf-push 2 | on: 3 | push: 4 | branches: 5 | - main 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v4 11 | - uses: bufbuild/buf-setup-action@v1 12 | # - uses: bufbuild/buf-lint-action@v1 13 | - uses: bufbuild/buf-breaking-action@v1 14 | with: 15 | # The 'main' branch of the GitHub repository that defines the module. 16 | against: "https://github.com/${GITHUB_REPOSITORY}.git#branch=main,ref=HEAD~1" 17 | - uses: bufbuild/buf-push-action@v1 18 | with: 19 | buf_token: ${{ secrets.BUF_TOKEN }} 20 | -------------------------------------------------------------------------------- /.github/workflows/reviewdog.yml: -------------------------------------------------------------------------------- 1 | name: reviewdog 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | 8 | jobs: 9 | reviewdog-pr: 10 | permissions: 11 | checks: write 12 | contents: read 13 | pull-requests: write 14 | if: github.event_name == 'pull_request' 15 | name: reviewdog on Pull Request 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v3 19 | 20 | - uses: actions/setup-go@v4 21 | with: 22 | go-version-file: "go.mod" 23 | 24 | - name: Install linters 25 | run: go install golang.org/x/lint/golint@latest 26 | 27 | - name: Setup reviewdog 28 | # uses: reviewdog/action-setup@v1 29 | run: | 30 | go install github.com/reviewdog/reviewdog/cmd/reviewdog@latest 31 | 32 | - name: Run reviewdog (github-pr-check) 33 | continue-on-error: true 34 | env: 35 | REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} 36 | run: | 37 | reviewdog -reporter=github-pr-check -runners=golint,govet -fail-on-error 38 | 39 | - name: Run reviewdog (github-pr-review with tee) 40 | env: 41 | REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} 42 | run: | 43 | # Remove Go Problem Matchers [1] as it reports duplicate results with 44 | # reviewdog. 45 | # [1]: https://github.com/actions/toolkit/blob/master/docs/commands.md#problem-matchers 46 | echo "::remove-matcher owner=go::" 47 | golint ./... | reviewdog -f=golint -name=golint-pr-review -reporter=github-pr-review -tee 48 | 49 | # - name: Run reviewdog (github-pr-check with -filter-mode=file) 50 | # env: 51 | # REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} 52 | # run: | 53 | # golint | reviewdog -f=golint -name=golint-pr-check-filter-mode-file -reporter=github-pr-check -filter-mode=file -level=warning --exclude="\bexported \w+ (\S*['.]*)([a-zA-Z'.*]*) should have comment or be unexported\b" 54 | 55 | - name: gofmt -s with reviewdog 56 | env: 57 | REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} 58 | run: | 59 | gofmt -s -d . | \ 60 | reviewdog -name="gofmt" -f=diff -f.diff.strip=0 -reporter=github-pr-review 61 | 62 | staticcheck: 63 | permissions: 64 | checks: write 65 | contents: read 66 | pull-requests: write 67 | if: github.event_name == 'pull_request' 68 | name: runner / staticcheck 69 | runs-on: ubuntu-latest 70 | steps: 71 | - uses: actions/checkout@v3 72 | - uses: actions/setup-go@v4 73 | with: 74 | go-version-file: "go.mod" 75 | - uses: reviewdog/action-staticcheck@v1 76 | with: 77 | github_token: ${{ secrets.github_token }} 78 | reporter: github-pr-review 79 | filter_mode: nofilter 80 | fail_on_error: true 81 | alex: 82 | name: runner / alex 83 | runs-on: ubuntu-latest 84 | steps: 85 | - uses: actions/checkout@v3 86 | - uses: reviewdog/action-alex@v1 87 | with: 88 | github_token: ${{ secrets.github_token }} 89 | reporter: github-check 90 | level: info -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /third_party/ 2 | /.idea/* 3 | /.vscode/* 4 | 5 | /logs/* 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Game Servers 2 | 3 | ## Introduction 4 | 5 | This project is a game server template, 6 | which is designed to provide a basic game server framework for developers. 7 | 8 | ## Architecture 9 | 10 | ![architecture](./draws/game.drawio.png) 11 | 12 | ## How to run 13 | 14 | * deploy infrastructure: 15 | ```shell 16 | # add ./deployment/docker-compose/.env file to custom your environment if you have 17 | docker compose -f ./deployment/docker-compose/infrastructure.yaml up -d 18 | ``` 19 | 20 | * run service: 21 | ```shell 22 | # fix the game-name to your game name 23 | go run ./cmd/{game-name}/service/main.go 24 | ``` 25 | 26 | ## How to build docker image? 27 | 28 | ```shell 29 | # replace to your register url,eg: game0.registry.com 30 | # replace to your server name,eg: game0,gm 31 | # replace to your git access token 32 | # how to get your git access token?: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic 33 | docker buildx build -t :latest --build-arg APP_NAME= --build-arg GIT_PWD= -f .\build\package\docker\Dockerfile . --push 34 | ``` 35 | 36 | ## How to test 37 | 38 | ### Integration Test 39 | 40 | * build your interactive client: 41 | ```shell 42 | go build -o {game-name}.exe ./cmd/{game-name}/client/main.go 43 | ``` 44 | * run your interactive client: 45 | ```shell 46 | # help 47 | ./{game-name}.exe shell 48 | ``` 49 | tips: http client use Postman to connect `localhost:8081`. 50 | 51 | ### Load Test 52 | 53 | * install [k6](https://grafana.com/docs/k6/latest/get-started/installation/) 54 | * run k6 load test 55 | ``` shell 56 | # fix the game-name to your game name 57 | k6 run ./tests/{game-name}/{game-name}.js 58 | ``` 59 | 60 | ## Proto file Manage 61 | 62 | * install [buf](https://buf.build/docs/installation) 63 | 64 | * manage proto file 65 | ```shell 66 | # generate proto file 67 | buf generate 68 | ``` 69 | ```shell 70 | # use buf Schema Registry to manage proto file 71 | # you need to sign up and login to buf Schema Registry,follow the steps below: 72 | # https://buf.build/docs/tutorials/getting-started-with-bsr#prerequisites 73 | buf registry login username 74 | # push proto file to buf Schema Registry 75 | buf push 76 | ``` 77 | * generate SDKS for different languages 78 | * visit https://buf.build/everyjoy/{game-name}/sdks 79 | * choose the language you want to generate, and follow the cmd to import the SDKS to your project. 80 | 81 | 82 | -------------------------------------------------------------------------------- /api/game0/game0.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package game0.pb; 4 | 5 | import "google/api/annotations.proto"; 6 | 7 | option go_package = "game0/api;pb"; 8 | 9 | service Game0Service { 10 | // Say hi to topic 11 | rpc Hi(HiRequest) returns (HiResponse) { 12 | option (google.api.http) = { 13 | post: "/v1/hello/hi" 14 | body: "*" 15 | }; 16 | } 17 | // Watch topic message 18 | rpc Watch(WatchRequest) returns (stream WatchResponse) { 19 | option (google.api.http) = {get: "/v1/hello/watch"}; 20 | } 21 | } 22 | 23 | message HiRequest { 24 | string uid = 1; 25 | string message = 2; 26 | string topic = 3; 27 | } 28 | 29 | message HiResponse { 30 | string message = 1; 31 | } 32 | 33 | message WatchRequest { 34 | string uid = 1; 35 | string topic = 2; 36 | } 37 | 38 | message WatchResponse { 39 | string message = 1; 40 | } 41 | -------------------------------------------------------------------------------- /api/gen/game0/api/game0.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.35.2 4 | // protoc (unknown) 5 | // source: game0/game0.proto 6 | 7 | package pb 8 | 9 | import ( 10 | _ "google.golang.org/genproto/googleapis/api/annotations" 11 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 12 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 13 | reflect "reflect" 14 | sync "sync" 15 | ) 16 | 17 | const ( 18 | // Verify that this generated code is sufficiently up-to-date. 19 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 20 | // Verify that runtime/protoimpl is sufficiently up-to-date. 21 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 22 | ) 23 | 24 | type HiRequest struct { 25 | state protoimpl.MessageState 26 | sizeCache protoimpl.SizeCache 27 | unknownFields protoimpl.UnknownFields 28 | 29 | Uid string `protobuf:"bytes,1,opt,name=uid,proto3" json:"uid,omitempty"` 30 | Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` 31 | Topic string `protobuf:"bytes,3,opt,name=topic,proto3" json:"topic,omitempty"` 32 | } 33 | 34 | func (x *HiRequest) Reset() { 35 | *x = HiRequest{} 36 | mi := &file_game0_game0_proto_msgTypes[0] 37 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 38 | ms.StoreMessageInfo(mi) 39 | } 40 | 41 | func (x *HiRequest) String() string { 42 | return protoimpl.X.MessageStringOf(x) 43 | } 44 | 45 | func (*HiRequest) ProtoMessage() {} 46 | 47 | func (x *HiRequest) ProtoReflect() protoreflect.Message { 48 | mi := &file_game0_game0_proto_msgTypes[0] 49 | if x != nil { 50 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 51 | if ms.LoadMessageInfo() == nil { 52 | ms.StoreMessageInfo(mi) 53 | } 54 | return ms 55 | } 56 | return mi.MessageOf(x) 57 | } 58 | 59 | // Deprecated: Use HiRequest.ProtoReflect.Descriptor instead. 60 | func (*HiRequest) Descriptor() ([]byte, []int) { 61 | return file_game0_game0_proto_rawDescGZIP(), []int{0} 62 | } 63 | 64 | func (x *HiRequest) GetUid() string { 65 | if x != nil { 66 | return x.Uid 67 | } 68 | return "" 69 | } 70 | 71 | func (x *HiRequest) GetMessage() string { 72 | if x != nil { 73 | return x.Message 74 | } 75 | return "" 76 | } 77 | 78 | func (x *HiRequest) GetTopic() string { 79 | if x != nil { 80 | return x.Topic 81 | } 82 | return "" 83 | } 84 | 85 | type HiResponse struct { 86 | state protoimpl.MessageState 87 | sizeCache protoimpl.SizeCache 88 | unknownFields protoimpl.UnknownFields 89 | 90 | Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` 91 | } 92 | 93 | func (x *HiResponse) Reset() { 94 | *x = HiResponse{} 95 | mi := &file_game0_game0_proto_msgTypes[1] 96 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 97 | ms.StoreMessageInfo(mi) 98 | } 99 | 100 | func (x *HiResponse) String() string { 101 | return protoimpl.X.MessageStringOf(x) 102 | } 103 | 104 | func (*HiResponse) ProtoMessage() {} 105 | 106 | func (x *HiResponse) ProtoReflect() protoreflect.Message { 107 | mi := &file_game0_game0_proto_msgTypes[1] 108 | if x != nil { 109 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 110 | if ms.LoadMessageInfo() == nil { 111 | ms.StoreMessageInfo(mi) 112 | } 113 | return ms 114 | } 115 | return mi.MessageOf(x) 116 | } 117 | 118 | // Deprecated: Use HiResponse.ProtoReflect.Descriptor instead. 119 | func (*HiResponse) Descriptor() ([]byte, []int) { 120 | return file_game0_game0_proto_rawDescGZIP(), []int{1} 121 | } 122 | 123 | func (x *HiResponse) GetMessage() string { 124 | if x != nil { 125 | return x.Message 126 | } 127 | return "" 128 | } 129 | 130 | type WatchRequest struct { 131 | state protoimpl.MessageState 132 | sizeCache protoimpl.SizeCache 133 | unknownFields protoimpl.UnknownFields 134 | 135 | Uid string `protobuf:"bytes,1,opt,name=uid,proto3" json:"uid,omitempty"` 136 | Topic string `protobuf:"bytes,2,opt,name=topic,proto3" json:"topic,omitempty"` 137 | } 138 | 139 | func (x *WatchRequest) Reset() { 140 | *x = WatchRequest{} 141 | mi := &file_game0_game0_proto_msgTypes[2] 142 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 143 | ms.StoreMessageInfo(mi) 144 | } 145 | 146 | func (x *WatchRequest) String() string { 147 | return protoimpl.X.MessageStringOf(x) 148 | } 149 | 150 | func (*WatchRequest) ProtoMessage() {} 151 | 152 | func (x *WatchRequest) ProtoReflect() protoreflect.Message { 153 | mi := &file_game0_game0_proto_msgTypes[2] 154 | if x != nil { 155 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 156 | if ms.LoadMessageInfo() == nil { 157 | ms.StoreMessageInfo(mi) 158 | } 159 | return ms 160 | } 161 | return mi.MessageOf(x) 162 | } 163 | 164 | // Deprecated: Use WatchRequest.ProtoReflect.Descriptor instead. 165 | func (*WatchRequest) Descriptor() ([]byte, []int) { 166 | return file_game0_game0_proto_rawDescGZIP(), []int{2} 167 | } 168 | 169 | func (x *WatchRequest) GetUid() string { 170 | if x != nil { 171 | return x.Uid 172 | } 173 | return "" 174 | } 175 | 176 | func (x *WatchRequest) GetTopic() string { 177 | if x != nil { 178 | return x.Topic 179 | } 180 | return "" 181 | } 182 | 183 | type WatchResponse struct { 184 | state protoimpl.MessageState 185 | sizeCache protoimpl.SizeCache 186 | unknownFields protoimpl.UnknownFields 187 | 188 | Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` 189 | } 190 | 191 | func (x *WatchResponse) Reset() { 192 | *x = WatchResponse{} 193 | mi := &file_game0_game0_proto_msgTypes[3] 194 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 195 | ms.StoreMessageInfo(mi) 196 | } 197 | 198 | func (x *WatchResponse) String() string { 199 | return protoimpl.X.MessageStringOf(x) 200 | } 201 | 202 | func (*WatchResponse) ProtoMessage() {} 203 | 204 | func (x *WatchResponse) ProtoReflect() protoreflect.Message { 205 | mi := &file_game0_game0_proto_msgTypes[3] 206 | if x != nil { 207 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 208 | if ms.LoadMessageInfo() == nil { 209 | ms.StoreMessageInfo(mi) 210 | } 211 | return ms 212 | } 213 | return mi.MessageOf(x) 214 | } 215 | 216 | // Deprecated: Use WatchResponse.ProtoReflect.Descriptor instead. 217 | func (*WatchResponse) Descriptor() ([]byte, []int) { 218 | return file_game0_game0_proto_rawDescGZIP(), []int{3} 219 | } 220 | 221 | func (x *WatchResponse) GetMessage() string { 222 | if x != nil { 223 | return x.Message 224 | } 225 | return "" 226 | } 227 | 228 | var File_game0_game0_proto protoreflect.FileDescriptor 229 | 230 | var file_game0_game0_proto_rawDesc = []byte{ 231 | 0x0a, 0x11, 0x67, 0x61, 0x6d, 0x65, 0x30, 0x2f, 0x67, 0x61, 0x6d, 0x65, 0x30, 0x2e, 0x70, 0x72, 232 | 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x67, 0x61, 0x6d, 0x65, 0x30, 0x2e, 0x70, 0x62, 0x1a, 0x1c, 0x67, 233 | 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 234 | 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4d, 0x0a, 0x09, 0x48, 235 | 0x69, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 236 | 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 237 | 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 238 | 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x03, 0x20, 239 | 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x22, 0x26, 0x0a, 0x0a, 0x48, 0x69, 240 | 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 241 | 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 242 | 0x67, 0x65, 0x22, 0x36, 0x0a, 0x0c, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 243 | 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 244 | 0x03, 0x75, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x02, 0x20, 245 | 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x22, 0x29, 0x0a, 0x0d, 0x57, 0x61, 246 | 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 247 | 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 248 | 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0xad, 0x01, 0x0a, 0x0c, 0x47, 0x61, 0x6d, 0x65, 0x30, 0x53, 249 | 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x02, 0x48, 0x69, 0x12, 0x13, 0x2e, 0x67, 250 | 0x61, 0x6d, 0x65, 0x30, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x69, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 251 | 0x74, 0x1a, 0x14, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x30, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x69, 0x52, 252 | 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x3a, 253 | 0x01, 0x2a, 0x22, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2f, 0x68, 0x69, 254 | 0x12, 0x53, 0x0a, 0x05, 0x57, 0x61, 0x74, 0x63, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x61, 0x6d, 0x65, 255 | 0x30, 0x2e, 0x70, 0x62, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 256 | 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x30, 0x2e, 0x70, 0x62, 0x2e, 0x57, 0x61, 0x74, 257 | 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 258 | 0x02, 0x11, 0x12, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2f, 0x77, 0x61, 259 | 0x74, 0x63, 0x68, 0x30, 0x01, 0x42, 0x0e, 0x5a, 0x0c, 0x67, 0x61, 0x6d, 0x65, 0x30, 0x2f, 0x61, 260 | 0x70, 0x69, 0x3b, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 261 | } 262 | 263 | var ( 264 | file_game0_game0_proto_rawDescOnce sync.Once 265 | file_game0_game0_proto_rawDescData = file_game0_game0_proto_rawDesc 266 | ) 267 | 268 | func file_game0_game0_proto_rawDescGZIP() []byte { 269 | file_game0_game0_proto_rawDescOnce.Do(func() { 270 | file_game0_game0_proto_rawDescData = protoimpl.X.CompressGZIP(file_game0_game0_proto_rawDescData) 271 | }) 272 | return file_game0_game0_proto_rawDescData 273 | } 274 | 275 | var file_game0_game0_proto_msgTypes = make([]protoimpl.MessageInfo, 4) 276 | var file_game0_game0_proto_goTypes = []any{ 277 | (*HiRequest)(nil), // 0: game0.pb.HiRequest 278 | (*HiResponse)(nil), // 1: game0.pb.HiResponse 279 | (*WatchRequest)(nil), // 2: game0.pb.WatchRequest 280 | (*WatchResponse)(nil), // 3: game0.pb.WatchResponse 281 | } 282 | var file_game0_game0_proto_depIdxs = []int32{ 283 | 0, // 0: game0.pb.Game0Service.Hi:input_type -> game0.pb.HiRequest 284 | 2, // 1: game0.pb.Game0Service.Watch:input_type -> game0.pb.WatchRequest 285 | 1, // 2: game0.pb.Game0Service.Hi:output_type -> game0.pb.HiResponse 286 | 3, // 3: game0.pb.Game0Service.Watch:output_type -> game0.pb.WatchResponse 287 | 2, // [2:4] is the sub-list for method output_type 288 | 0, // [0:2] is the sub-list for method input_type 289 | 0, // [0:0] is the sub-list for extension type_name 290 | 0, // [0:0] is the sub-list for extension extendee 291 | 0, // [0:0] is the sub-list for field type_name 292 | } 293 | 294 | func init() { file_game0_game0_proto_init() } 295 | func file_game0_game0_proto_init() { 296 | if File_game0_game0_proto != nil { 297 | return 298 | } 299 | type x struct{} 300 | out := protoimpl.TypeBuilder{ 301 | File: protoimpl.DescBuilder{ 302 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 303 | RawDescriptor: file_game0_game0_proto_rawDesc, 304 | NumEnums: 0, 305 | NumMessages: 4, 306 | NumExtensions: 0, 307 | NumServices: 1, 308 | }, 309 | GoTypes: file_game0_game0_proto_goTypes, 310 | DependencyIndexes: file_game0_game0_proto_depIdxs, 311 | MessageInfos: file_game0_game0_proto_msgTypes, 312 | }.Build() 313 | File_game0_game0_proto = out.File 314 | file_game0_game0_proto_rawDesc = nil 315 | file_game0_game0_proto_goTypes = nil 316 | file_game0_game0_proto_depIdxs = nil 317 | } 318 | -------------------------------------------------------------------------------- /api/gen/game0/api/game0.pb.gw.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. 2 | // source: game0/game0.proto 3 | 4 | /* 5 | Package pb is a reverse proxy. 6 | 7 | It translates gRPC into RESTful JSON APIs. 8 | */ 9 | package pb 10 | 11 | import ( 12 | "context" 13 | "io" 14 | "net/http" 15 | 16 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 17 | "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" 18 | "google.golang.org/grpc" 19 | "google.golang.org/grpc/codes" 20 | "google.golang.org/grpc/grpclog" 21 | "google.golang.org/grpc/metadata" 22 | "google.golang.org/grpc/status" 23 | "google.golang.org/protobuf/proto" 24 | ) 25 | 26 | // Suppress "imported and not used" errors 27 | var _ codes.Code 28 | var _ io.Reader 29 | var _ status.Status 30 | var _ = runtime.String 31 | var _ = utilities.NewDoubleArray 32 | var _ = metadata.Join 33 | 34 | func request_Game0Service_Hi_0(ctx context.Context, marshaler runtime.Marshaler, client Game0ServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 35 | var protoReq HiRequest 36 | var metadata runtime.ServerMetadata 37 | 38 | if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { 39 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 40 | } 41 | 42 | msg, err := client.Hi(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) 43 | return msg, metadata, err 44 | 45 | } 46 | 47 | func local_request_Game0Service_Hi_0(ctx context.Context, marshaler runtime.Marshaler, server Game0ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 48 | var protoReq HiRequest 49 | var metadata runtime.ServerMetadata 50 | 51 | if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { 52 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 53 | } 54 | 55 | msg, err := server.Hi(ctx, &protoReq) 56 | return msg, metadata, err 57 | 58 | } 59 | 60 | var ( 61 | filter_Game0Service_Watch_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} 62 | ) 63 | 64 | func request_Game0Service_Watch_0(ctx context.Context, marshaler runtime.Marshaler, client Game0ServiceClient, req *http.Request, pathParams map[string]string) (Game0Service_WatchClient, runtime.ServerMetadata, error) { 65 | var protoReq WatchRequest 66 | var metadata runtime.ServerMetadata 67 | 68 | if err := req.ParseForm(); err != nil { 69 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 70 | } 71 | if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Game0Service_Watch_0); err != nil { 72 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 73 | } 74 | 75 | stream, err := client.Watch(ctx, &protoReq) 76 | if err != nil { 77 | return nil, metadata, err 78 | } 79 | header, err := stream.Header() 80 | if err != nil { 81 | return nil, metadata, err 82 | } 83 | metadata.HeaderMD = header 84 | return stream, metadata, nil 85 | 86 | } 87 | 88 | // RegisterGame0ServiceHandlerServer registers the http handlers for service Game0Service to "mux". 89 | // UnaryRPC :call Game0ServiceServer directly. 90 | // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. 91 | // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterGame0ServiceHandlerFromEndpoint instead. 92 | // GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. 93 | func RegisterGame0ServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server Game0ServiceServer) error { 94 | 95 | mux.Handle("POST", pattern_Game0Service_Hi_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 96 | ctx, cancel := context.WithCancel(req.Context()) 97 | defer cancel() 98 | var stream runtime.ServerTransportStream 99 | ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) 100 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 101 | var err error 102 | var annotatedContext context.Context 103 | annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/game0.pb.Game0Service/Hi", runtime.WithHTTPPathPattern("/v1/hello/hi")) 104 | if err != nil { 105 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 106 | return 107 | } 108 | resp, md, err := local_request_Game0Service_Hi_0(annotatedContext, inboundMarshaler, server, req, pathParams) 109 | md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) 110 | annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) 111 | if err != nil { 112 | runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) 113 | return 114 | } 115 | 116 | forward_Game0Service_Hi_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 117 | 118 | }) 119 | 120 | mux.Handle("GET", pattern_Game0Service_Watch_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 121 | err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") 122 | _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 123 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 124 | return 125 | }) 126 | 127 | return nil 128 | } 129 | 130 | // RegisterGame0ServiceHandlerFromEndpoint is same as RegisterGame0ServiceHandler but 131 | // automatically dials to "endpoint" and closes the connection when "ctx" gets done. 132 | func RegisterGame0ServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { 133 | conn, err := grpc.NewClient(endpoint, opts...) 134 | if err != nil { 135 | return err 136 | } 137 | defer func() { 138 | if err != nil { 139 | if cerr := conn.Close(); cerr != nil { 140 | grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) 141 | } 142 | return 143 | } 144 | go func() { 145 | <-ctx.Done() 146 | if cerr := conn.Close(); cerr != nil { 147 | grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) 148 | } 149 | }() 150 | }() 151 | 152 | return RegisterGame0ServiceHandler(ctx, mux, conn) 153 | } 154 | 155 | // RegisterGame0ServiceHandler registers the http handlers for service Game0Service to "mux". 156 | // The handlers forward requests to the grpc endpoint over "conn". 157 | func RegisterGame0ServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { 158 | return RegisterGame0ServiceHandlerClient(ctx, mux, NewGame0ServiceClient(conn)) 159 | } 160 | 161 | // RegisterGame0ServiceHandlerClient registers the http handlers for service Game0Service 162 | // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "Game0ServiceClient". 163 | // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "Game0ServiceClient" 164 | // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in 165 | // "Game0ServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares. 166 | func RegisterGame0ServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client Game0ServiceClient) error { 167 | 168 | mux.Handle("POST", pattern_Game0Service_Hi_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 169 | ctx, cancel := context.WithCancel(req.Context()) 170 | defer cancel() 171 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 172 | var err error 173 | var annotatedContext context.Context 174 | annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/game0.pb.Game0Service/Hi", runtime.WithHTTPPathPattern("/v1/hello/hi")) 175 | if err != nil { 176 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 177 | return 178 | } 179 | resp, md, err := request_Game0Service_Hi_0(annotatedContext, inboundMarshaler, client, req, pathParams) 180 | annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) 181 | if err != nil { 182 | runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) 183 | return 184 | } 185 | 186 | forward_Game0Service_Hi_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 187 | 188 | }) 189 | 190 | mux.Handle("GET", pattern_Game0Service_Watch_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 191 | ctx, cancel := context.WithCancel(req.Context()) 192 | defer cancel() 193 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 194 | var err error 195 | var annotatedContext context.Context 196 | annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/game0.pb.Game0Service/Watch", runtime.WithHTTPPathPattern("/v1/hello/watch")) 197 | if err != nil { 198 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 199 | return 200 | } 201 | resp, md, err := request_Game0Service_Watch_0(annotatedContext, inboundMarshaler, client, req, pathParams) 202 | annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) 203 | if err != nil { 204 | runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) 205 | return 206 | } 207 | 208 | forward_Game0Service_Watch_0(annotatedContext, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) 209 | 210 | }) 211 | 212 | return nil 213 | } 214 | 215 | var ( 216 | pattern_Game0Service_Hi_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "hello", "hi"}, "")) 217 | 218 | pattern_Game0Service_Watch_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "hello", "watch"}, "")) 219 | ) 220 | 221 | var ( 222 | forward_Game0Service_Hi_0 = runtime.ForwardResponseMessage 223 | 224 | forward_Game0Service_Watch_0 = runtime.ForwardResponseStream 225 | ) 226 | -------------------------------------------------------------------------------- /api/gen/game0/api/game0_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.5.1 4 | // - protoc (unknown) 5 | // source: game0/game0.proto 6 | 7 | package pb 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | ) 15 | 16 | // This is a compile-time assertion to ensure that this generated file 17 | // is compatible with the grpc package it is being compiled against. 18 | // Requires gRPC-Go v1.64.0 or later. 19 | const _ = grpc.SupportPackageIsVersion9 20 | 21 | const ( 22 | Game0Service_Hi_FullMethodName = "/game0.pb.Game0Service/Hi" 23 | Game0Service_Watch_FullMethodName = "/game0.pb.Game0Service/Watch" 24 | ) 25 | 26 | // Game0ServiceClient is the client API for Game0Service service. 27 | // 28 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 29 | type Game0ServiceClient interface { 30 | // Say hi to topic 31 | Hi(ctx context.Context, in *HiRequest, opts ...grpc.CallOption) (*HiResponse, error) 32 | // Watch topic message 33 | Watch(ctx context.Context, in *WatchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[WatchResponse], error) 34 | } 35 | 36 | type game0ServiceClient struct { 37 | cc grpc.ClientConnInterface 38 | } 39 | 40 | func NewGame0ServiceClient(cc grpc.ClientConnInterface) Game0ServiceClient { 41 | return &game0ServiceClient{cc} 42 | } 43 | 44 | func (c *game0ServiceClient) Hi(ctx context.Context, in *HiRequest, opts ...grpc.CallOption) (*HiResponse, error) { 45 | cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) 46 | out := new(HiResponse) 47 | err := c.cc.Invoke(ctx, Game0Service_Hi_FullMethodName, in, out, cOpts...) 48 | if err != nil { 49 | return nil, err 50 | } 51 | return out, nil 52 | } 53 | 54 | func (c *game0ServiceClient) Watch(ctx context.Context, in *WatchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[WatchResponse], error) { 55 | cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) 56 | stream, err := c.cc.NewStream(ctx, &Game0Service_ServiceDesc.Streams[0], Game0Service_Watch_FullMethodName, cOpts...) 57 | if err != nil { 58 | return nil, err 59 | } 60 | x := &grpc.GenericClientStream[WatchRequest, WatchResponse]{ClientStream: stream} 61 | if err := x.ClientStream.SendMsg(in); err != nil { 62 | return nil, err 63 | } 64 | if err := x.ClientStream.CloseSend(); err != nil { 65 | return nil, err 66 | } 67 | return x, nil 68 | } 69 | 70 | // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. 71 | type Game0Service_WatchClient = grpc.ServerStreamingClient[WatchResponse] 72 | 73 | // Game0ServiceServer is the server API for Game0Service service. 74 | // All implementations should embed UnimplementedGame0ServiceServer 75 | // for forward compatibility. 76 | type Game0ServiceServer interface { 77 | // Say hi to topic 78 | Hi(context.Context, *HiRequest) (*HiResponse, error) 79 | // Watch topic message 80 | Watch(*WatchRequest, grpc.ServerStreamingServer[WatchResponse]) error 81 | } 82 | 83 | // UnimplementedGame0ServiceServer should be embedded to have 84 | // forward compatible implementations. 85 | // 86 | // NOTE: this should be embedded by value instead of pointer to avoid a nil 87 | // pointer dereference when methods are called. 88 | type UnimplementedGame0ServiceServer struct{} 89 | 90 | func (UnimplementedGame0ServiceServer) Hi(context.Context, *HiRequest) (*HiResponse, error) { 91 | return nil, status.Errorf(codes.Unimplemented, "method Hi not implemented") 92 | } 93 | func (UnimplementedGame0ServiceServer) Watch(*WatchRequest, grpc.ServerStreamingServer[WatchResponse]) error { 94 | return status.Errorf(codes.Unimplemented, "method Watch not implemented") 95 | } 96 | func (UnimplementedGame0ServiceServer) testEmbeddedByValue() {} 97 | 98 | // UnsafeGame0ServiceServer may be embedded to opt out of forward compatibility for this service. 99 | // Use of this interface is not recommended, as added methods to Game0ServiceServer will 100 | // result in compilation errors. 101 | type UnsafeGame0ServiceServer interface { 102 | mustEmbedUnimplementedGame0ServiceServer() 103 | } 104 | 105 | func RegisterGame0ServiceServer(s grpc.ServiceRegistrar, srv Game0ServiceServer) { 106 | // If the following call pancis, it indicates UnimplementedGame0ServiceServer was 107 | // embedded by pointer and is nil. This will cause panics if an 108 | // unimplemented method is ever invoked, so we test this at initialization 109 | // time to prevent it from happening at runtime later due to I/O. 110 | if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { 111 | t.testEmbeddedByValue() 112 | } 113 | s.RegisterService(&Game0Service_ServiceDesc, srv) 114 | } 115 | 116 | func _Game0Service_Hi_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 117 | in := new(HiRequest) 118 | if err := dec(in); err != nil { 119 | return nil, err 120 | } 121 | if interceptor == nil { 122 | return srv.(Game0ServiceServer).Hi(ctx, in) 123 | } 124 | info := &grpc.UnaryServerInfo{ 125 | Server: srv, 126 | FullMethod: Game0Service_Hi_FullMethodName, 127 | } 128 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 129 | return srv.(Game0ServiceServer).Hi(ctx, req.(*HiRequest)) 130 | } 131 | return interceptor(ctx, in, info, handler) 132 | } 133 | 134 | func _Game0Service_Watch_Handler(srv interface{}, stream grpc.ServerStream) error { 135 | m := new(WatchRequest) 136 | if err := stream.RecvMsg(m); err != nil { 137 | return err 138 | } 139 | return srv.(Game0ServiceServer).Watch(m, &grpc.GenericServerStream[WatchRequest, WatchResponse]{ServerStream: stream}) 140 | } 141 | 142 | // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. 143 | type Game0Service_WatchServer = grpc.ServerStreamingServer[WatchResponse] 144 | 145 | // Game0Service_ServiceDesc is the grpc.ServiceDesc for Game0Service service. 146 | // It's only intended for direct use with grpc.RegisterService, 147 | // and not to be introspected or modified (even as a copy) 148 | var Game0Service_ServiceDesc = grpc.ServiceDesc{ 149 | ServiceName: "game0.pb.Game0Service", 150 | HandlerType: (*Game0ServiceServer)(nil), 151 | Methods: []grpc.MethodDesc{ 152 | { 153 | MethodName: "Hi", 154 | Handler: _Game0Service_Hi_Handler, 155 | }, 156 | }, 157 | Streams: []grpc.StreamDesc{ 158 | { 159 | StreamName: "Watch", 160 | Handler: _Game0Service_Watch_Handler, 161 | ServerStreams: true, 162 | }, 163 | }, 164 | Metadata: "game0/game0.proto", 165 | } 166 | -------------------------------------------------------------------------------- /api/gen/gm/api/gm.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.34.2 4 | // protoc (unknown) 5 | // source: gm/gm.proto 6 | 7 | package pb 8 | 9 | import ( 10 | _ "google.golang.org/genproto/googleapis/api/annotations" 11 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 12 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 13 | reflect "reflect" 14 | sync "sync" 15 | ) 16 | 17 | const ( 18 | // Verify that this generated code is sufficiently up-to-date. 19 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 20 | // Verify that runtime/protoimpl is sufficiently up-to-date. 21 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 22 | ) 23 | 24 | type GetGameConfigRequest struct { 25 | state protoimpl.MessageState 26 | sizeCache protoimpl.SizeCache 27 | unknownFields protoimpl.UnknownFields 28 | 29 | GameName string `protobuf:"bytes,1,opt,name=game_name,json=gameName,proto3" json:"game_name,omitempty"` 30 | } 31 | 32 | func (x *GetGameConfigRequest) Reset() { 33 | *x = GetGameConfigRequest{} 34 | if protoimpl.UnsafeEnabled { 35 | mi := &file_gm_gm_proto_msgTypes[0] 36 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 37 | ms.StoreMessageInfo(mi) 38 | } 39 | } 40 | 41 | func (x *GetGameConfigRequest) String() string { 42 | return protoimpl.X.MessageStringOf(x) 43 | } 44 | 45 | func (*GetGameConfigRequest) ProtoMessage() {} 46 | 47 | func (x *GetGameConfigRequest) ProtoReflect() protoreflect.Message { 48 | mi := &file_gm_gm_proto_msgTypes[0] 49 | if protoimpl.UnsafeEnabled && x != nil { 50 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 51 | if ms.LoadMessageInfo() == nil { 52 | ms.StoreMessageInfo(mi) 53 | } 54 | return ms 55 | } 56 | return mi.MessageOf(x) 57 | } 58 | 59 | // Deprecated: Use GetGameConfigRequest.ProtoReflect.Descriptor instead. 60 | func (*GetGameConfigRequest) Descriptor() ([]byte, []int) { 61 | return file_gm_gm_proto_rawDescGZIP(), []int{0} 62 | } 63 | 64 | func (x *GetGameConfigRequest) GetGameName() string { 65 | if x != nil { 66 | return x.GameName 67 | } 68 | return "" 69 | } 70 | 71 | type GetGameConfigResponse struct { 72 | state protoimpl.MessageState 73 | sizeCache protoimpl.SizeCache 74 | unknownFields protoimpl.UnknownFields 75 | 76 | Rank string `protobuf:"bytes,1,opt,name=rank,proto3" json:"rank,omitempty"` 77 | } 78 | 79 | func (x *GetGameConfigResponse) Reset() { 80 | *x = GetGameConfigResponse{} 81 | if protoimpl.UnsafeEnabled { 82 | mi := &file_gm_gm_proto_msgTypes[1] 83 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 84 | ms.StoreMessageInfo(mi) 85 | } 86 | } 87 | 88 | func (x *GetGameConfigResponse) String() string { 89 | return protoimpl.X.MessageStringOf(x) 90 | } 91 | 92 | func (*GetGameConfigResponse) ProtoMessage() {} 93 | 94 | func (x *GetGameConfigResponse) ProtoReflect() protoreflect.Message { 95 | mi := &file_gm_gm_proto_msgTypes[1] 96 | if protoimpl.UnsafeEnabled && x != nil { 97 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 98 | if ms.LoadMessageInfo() == nil { 99 | ms.StoreMessageInfo(mi) 100 | } 101 | return ms 102 | } 103 | return mi.MessageOf(x) 104 | } 105 | 106 | // Deprecated: Use GetGameConfigResponse.ProtoReflect.Descriptor instead. 107 | func (*GetGameConfigResponse) Descriptor() ([]byte, []int) { 108 | return file_gm_gm_proto_rawDescGZIP(), []int{1} 109 | } 110 | 111 | func (x *GetGameConfigResponse) GetRank() string { 112 | if x != nil { 113 | return x.Rank 114 | } 115 | return "" 116 | } 117 | 118 | var File_gm_gm_proto protoreflect.FileDescriptor 119 | 120 | var file_gm_gm_proto_rawDesc = []byte{ 121 | 0x0a, 0x0b, 0x67, 0x6d, 0x2f, 0x67, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x67, 122 | 0x6d, 0x2e, 0x70, 0x62, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 123 | 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 124 | 0x74, 0x6f, 0x22, 0x33, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x47, 0x61, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 125 | 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x61, 126 | 0x6d, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x67, 127 | 0x61, 0x6d, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x2b, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x47, 0x61, 128 | 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 129 | 0x12, 0x12, 0x0a, 0x04, 0x72, 0x61, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 130 | 0x72, 0x61, 0x6e, 0x6b, 0x32, 0x6e, 0x0a, 0x09, 0x47, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 131 | 0x65, 0x12, 0x61, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x47, 0x61, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x66, 132 | 0x69, 0x67, 0x12, 0x1b, 0x2e, 0x67, 0x6d, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x47, 0x61, 133 | 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 134 | 0x1c, 0x2e, 0x67, 0x6d, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x47, 0x61, 0x6d, 0x65, 0x43, 135 | 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 136 | 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x61, 0x6d, 0x65, 0x2f, 137 | 0x72, 0x61, 0x6e, 0x6b, 0x42, 0x0b, 0x5a, 0x09, 0x67, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x3b, 0x70, 138 | 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 139 | } 140 | 141 | var ( 142 | file_gm_gm_proto_rawDescOnce sync.Once 143 | file_gm_gm_proto_rawDescData = file_gm_gm_proto_rawDesc 144 | ) 145 | 146 | func file_gm_gm_proto_rawDescGZIP() []byte { 147 | file_gm_gm_proto_rawDescOnce.Do(func() { 148 | file_gm_gm_proto_rawDescData = protoimpl.X.CompressGZIP(file_gm_gm_proto_rawDescData) 149 | }) 150 | return file_gm_gm_proto_rawDescData 151 | } 152 | 153 | var file_gm_gm_proto_msgTypes = make([]protoimpl.MessageInfo, 2) 154 | var file_gm_gm_proto_goTypes = []any{ 155 | (*GetGameConfigRequest)(nil), // 0: gm.pb.GetGameConfigRequest 156 | (*GetGameConfigResponse)(nil), // 1: gm.pb.GetGameConfigResponse 157 | } 158 | var file_gm_gm_proto_depIdxs = []int32{ 159 | 0, // 0: gm.pb.GMService.GetGameConfig:input_type -> gm.pb.GetGameConfigRequest 160 | 1, // 1: gm.pb.GMService.GetGameConfig:output_type -> gm.pb.GetGameConfigResponse 161 | 1, // [1:2] is the sub-list for method output_type 162 | 0, // [0:1] is the sub-list for method input_type 163 | 0, // [0:0] is the sub-list for extension type_name 164 | 0, // [0:0] is the sub-list for extension extendee 165 | 0, // [0:0] is the sub-list for field type_name 166 | } 167 | 168 | func init() { file_gm_gm_proto_init() } 169 | func file_gm_gm_proto_init() { 170 | if File_gm_gm_proto != nil { 171 | return 172 | } 173 | if !protoimpl.UnsafeEnabled { 174 | file_gm_gm_proto_msgTypes[0].Exporter = func(v any, i int) any { 175 | switch v := v.(*GetGameConfigRequest); i { 176 | case 0: 177 | return &v.state 178 | case 1: 179 | return &v.sizeCache 180 | case 2: 181 | return &v.unknownFields 182 | default: 183 | return nil 184 | } 185 | } 186 | file_gm_gm_proto_msgTypes[1].Exporter = func(v any, i int) any { 187 | switch v := v.(*GetGameConfigResponse); i { 188 | case 0: 189 | return &v.state 190 | case 1: 191 | return &v.sizeCache 192 | case 2: 193 | return &v.unknownFields 194 | default: 195 | return nil 196 | } 197 | } 198 | } 199 | type x struct{} 200 | out := protoimpl.TypeBuilder{ 201 | File: protoimpl.DescBuilder{ 202 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 203 | RawDescriptor: file_gm_gm_proto_rawDesc, 204 | NumEnums: 0, 205 | NumMessages: 2, 206 | NumExtensions: 0, 207 | NumServices: 1, 208 | }, 209 | GoTypes: file_gm_gm_proto_goTypes, 210 | DependencyIndexes: file_gm_gm_proto_depIdxs, 211 | MessageInfos: file_gm_gm_proto_msgTypes, 212 | }.Build() 213 | File_gm_gm_proto = out.File 214 | file_gm_gm_proto_rawDesc = nil 215 | file_gm_gm_proto_goTypes = nil 216 | file_gm_gm_proto_depIdxs = nil 217 | } 218 | -------------------------------------------------------------------------------- /api/gen/gm/api/gm.pb.gw.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. 2 | // source: gm/gm.proto 3 | 4 | /* 5 | Package pb is a reverse proxy. 6 | 7 | It translates gRPC into RESTful JSON APIs. 8 | */ 9 | package pb 10 | 11 | import ( 12 | "context" 13 | "io" 14 | "net/http" 15 | 16 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 17 | "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" 18 | "google.golang.org/grpc" 19 | "google.golang.org/grpc/codes" 20 | "google.golang.org/grpc/grpclog" 21 | "google.golang.org/grpc/metadata" 22 | "google.golang.org/grpc/status" 23 | "google.golang.org/protobuf/proto" 24 | ) 25 | 26 | // Suppress "imported and not used" errors 27 | var _ codes.Code 28 | var _ io.Reader 29 | var _ status.Status 30 | var _ = runtime.String 31 | var _ = utilities.NewDoubleArray 32 | var _ = metadata.Join 33 | 34 | var ( 35 | filter_GMService_GetGameConfig_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} 36 | ) 37 | 38 | func request_GMService_GetGameConfig_0(ctx context.Context, marshaler runtime.Marshaler, client GMServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 39 | var protoReq GetGameConfigRequest 40 | var metadata runtime.ServerMetadata 41 | 42 | if err := req.ParseForm(); err != nil { 43 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 44 | } 45 | if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GMService_GetGameConfig_0); err != nil { 46 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 47 | } 48 | 49 | msg, err := client.GetGameConfig(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) 50 | return msg, metadata, err 51 | 52 | } 53 | 54 | func local_request_GMService_GetGameConfig_0(ctx context.Context, marshaler runtime.Marshaler, server GMServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 55 | var protoReq GetGameConfigRequest 56 | var metadata runtime.ServerMetadata 57 | 58 | if err := req.ParseForm(); err != nil { 59 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 60 | } 61 | if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GMService_GetGameConfig_0); err != nil { 62 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 63 | } 64 | 65 | msg, err := server.GetGameConfig(ctx, &protoReq) 66 | return msg, metadata, err 67 | 68 | } 69 | 70 | // RegisterGMServiceHandlerServer registers the http handlers for service GMService to "mux". 71 | // UnaryRPC :call GMServiceServer directly. 72 | // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. 73 | // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterGMServiceHandlerFromEndpoint instead. 74 | // GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. 75 | func RegisterGMServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server GMServiceServer) error { 76 | 77 | mux.Handle("GET", pattern_GMService_GetGameConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 78 | ctx, cancel := context.WithCancel(req.Context()) 79 | defer cancel() 80 | var stream runtime.ServerTransportStream 81 | ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) 82 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 83 | var err error 84 | var annotatedContext context.Context 85 | annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gm.pb.GMService/GetGameConfig", runtime.WithHTTPPathPattern("/v1/game/rank")) 86 | if err != nil { 87 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 88 | return 89 | } 90 | resp, md, err := local_request_GMService_GetGameConfig_0(annotatedContext, inboundMarshaler, server, req, pathParams) 91 | md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) 92 | annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) 93 | if err != nil { 94 | runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) 95 | return 96 | } 97 | 98 | forward_GMService_GetGameConfig_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 99 | 100 | }) 101 | 102 | return nil 103 | } 104 | 105 | // RegisterGMServiceHandlerFromEndpoint is same as RegisterGMServiceHandler but 106 | // automatically dials to "endpoint" and closes the connection when "ctx" gets done. 107 | func RegisterGMServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { 108 | conn, err := grpc.NewClient(endpoint, opts...) 109 | if err != nil { 110 | return err 111 | } 112 | defer func() { 113 | if err != nil { 114 | if cerr := conn.Close(); cerr != nil { 115 | grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) 116 | } 117 | return 118 | } 119 | go func() { 120 | <-ctx.Done() 121 | if cerr := conn.Close(); cerr != nil { 122 | grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) 123 | } 124 | }() 125 | }() 126 | 127 | return RegisterGMServiceHandler(ctx, mux, conn) 128 | } 129 | 130 | // RegisterGMServiceHandler registers the http handlers for service GMService to "mux". 131 | // The handlers forward requests to the grpc endpoint over "conn". 132 | func RegisterGMServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { 133 | return RegisterGMServiceHandlerClient(ctx, mux, NewGMServiceClient(conn)) 134 | } 135 | 136 | // RegisterGMServiceHandlerClient registers the http handlers for service GMService 137 | // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "GMServiceClient". 138 | // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "GMServiceClient" 139 | // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in 140 | // "GMServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares. 141 | func RegisterGMServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client GMServiceClient) error { 142 | 143 | mux.Handle("GET", pattern_GMService_GetGameConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 144 | ctx, cancel := context.WithCancel(req.Context()) 145 | defer cancel() 146 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 147 | var err error 148 | var annotatedContext context.Context 149 | annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gm.pb.GMService/GetGameConfig", runtime.WithHTTPPathPattern("/v1/game/rank")) 150 | if err != nil { 151 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 152 | return 153 | } 154 | resp, md, err := request_GMService_GetGameConfig_0(annotatedContext, inboundMarshaler, client, req, pathParams) 155 | annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) 156 | if err != nil { 157 | runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) 158 | return 159 | } 160 | 161 | forward_GMService_GetGameConfig_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 162 | 163 | }) 164 | 165 | return nil 166 | } 167 | 168 | var ( 169 | pattern_GMService_GetGameConfig_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "game", "rank"}, "")) 170 | ) 171 | 172 | var ( 173 | forward_GMService_GetGameConfig_0 = runtime.ForwardResponseMessage 174 | ) 175 | -------------------------------------------------------------------------------- /api/gen/gm/api/gm_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.5.1 4 | // - protoc (unknown) 5 | // source: gm/gm.proto 6 | 7 | package pb 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | ) 15 | 16 | // This is a compile-time assertion to ensure that this generated file 17 | // is compatible with the grpc package it is being compiled against. 18 | // Requires gRPC-Go v1.64.0 or later. 19 | const _ = grpc.SupportPackageIsVersion9 20 | 21 | const ( 22 | GMService_GetGameConfig_FullMethodName = "/gm.pb.GMService/GetGameConfig" 23 | ) 24 | 25 | // GMServiceClient is the client API for GMService service. 26 | // 27 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 28 | type GMServiceClient interface { 29 | GetGameConfig(ctx context.Context, in *GetGameConfigRequest, opts ...grpc.CallOption) (*GetGameConfigResponse, error) 30 | } 31 | 32 | type gMServiceClient struct { 33 | cc grpc.ClientConnInterface 34 | } 35 | 36 | func NewGMServiceClient(cc grpc.ClientConnInterface) GMServiceClient { 37 | return &gMServiceClient{cc} 38 | } 39 | 40 | func (c *gMServiceClient) GetGameConfig(ctx context.Context, in *GetGameConfigRequest, opts ...grpc.CallOption) (*GetGameConfigResponse, error) { 41 | cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) 42 | out := new(GetGameConfigResponse) 43 | err := c.cc.Invoke(ctx, GMService_GetGameConfig_FullMethodName, in, out, cOpts...) 44 | if err != nil { 45 | return nil, err 46 | } 47 | return out, nil 48 | } 49 | 50 | // GMServiceServer is the server API for GMService service. 51 | // All implementations should embed UnimplementedGMServiceServer 52 | // for forward compatibility. 53 | type GMServiceServer interface { 54 | GetGameConfig(context.Context, *GetGameConfigRequest) (*GetGameConfigResponse, error) 55 | } 56 | 57 | // UnimplementedGMServiceServer should be embedded to have 58 | // forward compatible implementations. 59 | // 60 | // NOTE: this should be embedded by value instead of pointer to avoid a nil 61 | // pointer dereference when methods are called. 62 | type UnimplementedGMServiceServer struct{} 63 | 64 | func (UnimplementedGMServiceServer) GetGameConfig(context.Context, *GetGameConfigRequest) (*GetGameConfigResponse, error) { 65 | return nil, status.Errorf(codes.Unimplemented, "method GetGameConfig not implemented") 66 | } 67 | func (UnimplementedGMServiceServer) testEmbeddedByValue() {} 68 | 69 | // UnsafeGMServiceServer may be embedded to opt out of forward compatibility for this service. 70 | // Use of this interface is not recommended, as added methods to GMServiceServer will 71 | // result in compilation errors. 72 | type UnsafeGMServiceServer interface { 73 | mustEmbedUnimplementedGMServiceServer() 74 | } 75 | 76 | func RegisterGMServiceServer(s grpc.ServiceRegistrar, srv GMServiceServer) { 77 | // If the following call pancis, it indicates UnimplementedGMServiceServer was 78 | // embedded by pointer and is nil. This will cause panics if an 79 | // unimplemented method is ever invoked, so we test this at initialization 80 | // time to prevent it from happening at runtime later due to I/O. 81 | if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { 82 | t.testEmbeddedByValue() 83 | } 84 | s.RegisterService(&GMService_ServiceDesc, srv) 85 | } 86 | 87 | func _GMService_GetGameConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 88 | in := new(GetGameConfigRequest) 89 | if err := dec(in); err != nil { 90 | return nil, err 91 | } 92 | if interceptor == nil { 93 | return srv.(GMServiceServer).GetGameConfig(ctx, in) 94 | } 95 | info := &grpc.UnaryServerInfo{ 96 | Server: srv, 97 | FullMethod: GMService_GetGameConfig_FullMethodName, 98 | } 99 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 100 | return srv.(GMServiceServer).GetGameConfig(ctx, req.(*GetGameConfigRequest)) 101 | } 102 | return interceptor(ctx, in, info, handler) 103 | } 104 | 105 | // GMService_ServiceDesc is the grpc.ServiceDesc for GMService service. 106 | // It's only intended for direct use with grpc.RegisterService, 107 | // and not to be introspected or modified (even as a copy) 108 | var GMService_ServiceDesc = grpc.ServiceDesc{ 109 | ServiceName: "gm.pb.GMService", 110 | HandlerType: (*GMServiceServer)(nil), 111 | Methods: []grpc.MethodDesc{ 112 | { 113 | MethodName: "GetGameConfig", 114 | Handler: _GMService_GetGameConfig_Handler, 115 | }, 116 | }, 117 | Streams: []grpc.StreamDesc{}, 118 | Metadata: "gm/gm.proto", 119 | } 120 | -------------------------------------------------------------------------------- /buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v2 2 | plugins: 3 | - remote: buf.build/protocolbuffers/go 4 | out: api/gen/ 5 | - remote: buf.build/grpc/go 6 | out: api/gen/ 7 | opt: require_unimplemented_servers=false 8 | - remote: buf.build/grpc-ecosystem/gateway 9 | out: api/gen/ 10 | opt: generate_unbound_methods=true 11 | - remote: buf.build/grpc-ecosystem/openapiv2 12 | out: third_party/OpenAPI -------------------------------------------------------------------------------- /buf.lock: -------------------------------------------------------------------------------- 1 | # Generated by buf. DO NOT EDIT. 2 | version: v2 3 | deps: 4 | - name: buf.build/googleapis/googleapis 5 | commit: ee48893a270147348e3edc6c1a03de0e 6 | digest: b5:ef3c9849abc866b9625eb0f652bda8ea6a1477230eaeeb320c8cb63b16562575c0d3129524643e842c35156b40796aff79d048116b670ae95e9034b0c5a868c0 7 | - name: buf.build/grpc-ecosystem/grpc-gateway 8 | commit: 3f42134f4c564983838425bc43c7a65f 9 | digest: b5:291b947d8ac09492517557e4e72e294788cb8201afc7d0df7bda80fa10931adb60d4d669208a7696bf24f1ecb2a33a16d4c1e766e6f31809248b00343119569b 10 | -------------------------------------------------------------------------------- /buf.yaml: -------------------------------------------------------------------------------- 1 | version: v2 2 | modules: 3 | - path: api/ 4 | name: buf.build/moke-game/game 5 | deps: 6 | - buf.build/googleapis/googleapis 7 | - buf.build/grpc-ecosystem/grpc-gateway 8 | lint: 9 | use: 10 | - DEFAULT 11 | except: 12 | - FIELD_NOT_REQUIRED 13 | - PACKAGE_DIRECTORY_MATCH 14 | - PACKAGE_NO_IMPORT_CYCLE 15 | - PACKAGE_VERSION_SUFFIX 16 | disallow_comment_ignores: true 17 | breaking: 18 | use: 19 | - FILE 20 | except: 21 | - EXTENSION_NO_DELETE 22 | - FIELD_SAME_DEFAULT 23 | -------------------------------------------------------------------------------- /build/package/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG APP_NAME=game0 2 | ARG GIT_URL="git-ej.getqccode.com" 3 | ARG GIT_USR="docker" 4 | # how to get your git access token: 5 | #https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic 6 | ARG GIT_PWD="your_git_access_token" 7 | # Step 1: Modules caching 8 | FROM golang:1.22.5-alpine as modules 9 | ARG GIT_USR 10 | ARG GIT_PWD 11 | ARG GIT_URL 12 | RUN apk add --no-cache ca-certificates git 13 | COPY go.mod go.sum /modules/ 14 | RUN echo "machine ${GIT_URL} login ${GIT_USR} password ${GIT_PWD}" > ~/.netrc 15 | WORKDIR /modules 16 | ENV GO111MODULE="on" 17 | ENV GOPROXY="https://goproxy.cn,https://gocenter.io,direct" 18 | RUN go env -w GOPRIVATE=${GIT_URL} 19 | RUN go mod download 20 | 21 | 22 | # Step 2: Builder 23 | FROM golang:1.22.5-alpine as builder 24 | ARG APP_NAME 25 | COPY --from=modules /go/pkg /go/pkg 26 | COPY . /app 27 | WORKDIR /app 28 | RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \ 29 | go build -o /bin/app ./cmd/${APP_NAME}/service 30 | 31 | # Step 3: Final 32 | FROM alpine 33 | RUN #sed -i -e 's/http:/https:/' /etc/apk/repositories 34 | RUN apk --no-cache add tzdata 35 | # you can fix it to your TZ 36 | #ENV TZ=Asia/Shanghai 37 | COPY --from=builder /bin/app /app 38 | CMD ["/app"] -------------------------------------------------------------------------------- /cmd/game0/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/moke-game/game/internal/clients/game0" 9 | ) 10 | 11 | var options struct { 12 | host string 13 | tcpHost string 14 | } 15 | 16 | const ( 17 | defaultHost = "localhost:8081" 18 | defaultTcpHost = "localhost:8888" 19 | ) 20 | 21 | func main() { 22 | rootCmd := &cobra.Command{ 23 | Use: "game", 24 | Short: "cli", 25 | Aliases: []string{"cli"}, 26 | } 27 | rootCmd.PersistentFlags().StringVar( 28 | &options.host, 29 | "host", 30 | defaultHost, 31 | "grpc http service (:)", 32 | ) 33 | 34 | rootCmd.PersistentFlags().StringVar( 35 | &options.tcpHost, 36 | "tcp_host", 37 | defaultTcpHost, 38 | "tcp service (:)", 39 | ) 40 | 41 | sGrpc := &cobra.Command{ 42 | Use: "grpc", 43 | Short: "Run an interactive grpc client", 44 | Run: func(cmd *cobra.Command, args []string) { 45 | game0.RunGrpc(options.host) 46 | }, 47 | } 48 | sTcp := &cobra.Command{ 49 | Use: "tcp", 50 | Short: "Run an interactive tcp client", 51 | Run: func(cmd *cobra.Command, args []string) { 52 | game0.RunTcp(options.tcpHost) 53 | }, 54 | } 55 | rootCmd.AddCommand(sGrpc, sTcp) 56 | _ = rootCmd.ExecuteContext(context.Background()) 57 | } 58 | -------------------------------------------------------------------------------- /cmd/game0/service/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gstones/moke-kit/fxmain" 5 | "github.com/gstones/moke-kit/mq/pkg/mfx" 6 | "github.com/gstones/moke-kit/orm/pkg/ofx" 7 | 8 | analytics "github.com/moke-game/platform/services/analytics/pkg/module" 9 | auth "github.com/moke-game/platform/services/auth/pkg/module" 10 | buddy "github.com/moke-game/platform/services/buddy/pkg/module" 11 | chat "github.com/moke-game/platform/services/chat/pkg/module" 12 | knapsack "github.com/moke-game/platform/services/knapsack/pkg/module" 13 | leaderboard "github.com/moke-game/platform/services/leaderboard/pkg/module" 14 | mail "github.com/moke-game/platform/services/mail/pkg/module" 15 | matchmaking "github.com/moke-game/platform/services/matchmaking/pkg/module" 16 | party "github.com/moke-game/platform/services/party/pkg/module" 17 | profile "github.com/moke-game/platform/services/profile/pkg/module" 18 | 19 | "github.com/moke-game/game/pkg/modules" 20 | ) 21 | 22 | func main() { 23 | fxmain.Main( 24 | // infrastructures 25 | mfx.NatsModule, 26 | // local(channel) message queue 27 | mfx.LocalModule, 28 | ofx.RedisCacheModule, 29 | 30 | // service 31 | modules.AllModule, 32 | mail.MailModule, 33 | analytics.AnalyticsModule, 34 | auth.AuthAllModule, 35 | profile.ProfileModule, 36 | knapsack.KnapsackModule, 37 | party.PartyModule, 38 | buddy.BuddyModule, 39 | leaderboard.LeaderboardModule, 40 | chat.ChatModule, 41 | matchmaking.MatchmakingModule, 42 | ) 43 | } 44 | -------------------------------------------------------------------------------- /deployment/docker-compose/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | game: 4 | environment: 5 | - NATS_URL=nats://game-nats:4222 6 | - DATABASE_URL=mongodb://game-mongodb:27017 7 | - CACHE_URL=redis://game-redis:6379 8 | container_name: game 9 | image: ${REGISTRY}/${GAME_NAME}:latest 10 | labels: 11 | - "com.centurylinklabs.watchtower.enable=true" 12 | ports: 13 | - "8081:8081" 14 | - "8888:8888" 15 | restart: always 16 | networks: 17 | - game-network 18 | ## Auto update container to latest image 19 | # watchtower: 20 | # image: containrrr/watchtower 21 | # volumes: 22 | # - /root/.docker/config.json:/config.json 23 | # - /var/run/docker.sock:/var/run/docker.sock 24 | # command: 25 | # --interval 30 26 | # --cleanup 27 | # --label-enable 28 | networks: 29 | game-network: -------------------------------------------------------------------------------- /deployment/docker-compose/infrastructure.yaml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | services: 3 | game-redis: 4 | container_name: game-redis 5 | image: redis:latest 6 | ports: 7 | - "6379:6379" 8 | # command: 9 | # --requirepass ${REDIS_HOST_PASSWORD} 10 | restart: always 11 | networks: 12 | - game-network 13 | game-mongodb: 14 | container_name: game-mongodb 15 | image: mongo:latest 16 | # env_file: 17 | # - .env 18 | restart: always 19 | volumes: 20 | - mongo-data:/data/db 21 | ports: 22 | - "27017:27017" 23 | networks: 24 | - game-network 25 | game-nats: 26 | container_name: game-nats 27 | image: nats:latest 28 | ports: 29 | - "4222:4222" 30 | - "6222:6222" 31 | - "8222:8222" 32 | restart: always 33 | command: 34 | - "-js" 35 | hostname: nats-server 36 | networks: 37 | - game-network 38 | volumes: 39 | mongo-data: 40 | networks: 41 | game-network: -------------------------------------------------------------------------------- /deployment/docker-compose/readme.md: -------------------------------------------------------------------------------- 1 | # Run with Docker Compose 2 | * fix .env file 3 | 4 | ```bash 5 | cp .env.example .env 6 | ``` 7 | 8 | * deploy 9 | 10 | ```bash 11 | # deploy infrastructure services 12 | docker compose -f ./infrastructure.yaml up -d 13 | # deploy self services 14 | docker compose up -d 15 | ``` 16 | 17 | 18 | -------------------------------------------------------------------------------- /deployment/k8s/readme.md: -------------------------------------------------------------------------------- 1 | # Run with K8s 2 | 3 | * create helm package 4 | 5 | ```bash 6 | helm create game 7 | ``` 8 | 9 | * fix helm values.yaml 10 | Please refer to [quickstart](https://helm.sh/docs/intro/quickstart/) 11 | 12 | 13 | -------------------------------------------------------------------------------- /draws/game.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moke-game/game/efe4b36da91f000e651c3b3b568cfd829a5102df/draws/game.drawio.png -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/moke-game/game 2 | 3 | go 1.24.2 4 | 5 | require ( 6 | github.com/abiosoft/ishell v2.0.0+incompatible 7 | github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.1 8 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 9 | github.com/gstones/moke-kit v1.0.5-0.20250414125136-0f0537f47883 10 | github.com/gstones/zinx v1.2.7-0.20240617071724-88bd884d8d08 11 | github.com/moke-game/platform v0.0.0-20250415025501-5e99e8ee1e09 12 | github.com/redis/go-redis/v9 v9.7.3 13 | github.com/spf13/cobra v1.9.1 14 | go.uber.org/fx v1.23.0 15 | go.uber.org/zap v1.27.0 16 | google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e 17 | google.golang.org/grpc v1.71.1 18 | google.golang.org/protobuf v1.36.6 19 | open-match.dev/open-match v1.8.1 20 | ) 21 | 22 | require ( 23 | agones.dev/agones v1.48.0 // indirect 24 | github.com/ClickHouse/ch-go v0.65.1 // indirect 25 | github.com/ClickHouse/clickhouse-go/v2 v2.34.0 // indirect 26 | github.com/ThinkingDataAnalytics/go-sdk/v2 v2.2.0 // indirect 27 | github.com/ThreeDotsLabs/watermill v1.4.6 // indirect 28 | github.com/ThreeDotsLabs/watermill-nats/v2 v2.1.3 // indirect 29 | github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db // indirect 30 | github.com/andybalholm/brotli v1.1.1 // indirect 31 | github.com/aws/aws-sdk-go-v2 v1.36.3 // indirect 32 | github.com/aws/aws-sdk-go-v2/config v1.29.14 // indirect 33 | github.com/aws/aws-sdk-go-v2/credentials v1.17.67 // indirect 34 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect 35 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect 36 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect 37 | github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect 38 | github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.30.2 // indirect 39 | github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect 40 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect 41 | github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 // indirect 42 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect 43 | github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 // indirect 44 | github.com/aws/smithy-go v1.22.3 // indirect 45 | github.com/cenkalti/backoff/v4 v4.3.0 // indirect 46 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 47 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 48 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect 49 | github.com/duke-git/lancet/v2 v2.3.5 // indirect 50 | github.com/fatih/color v1.18.0 // indirect 51 | github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect 52 | github.com/fsnotify/fsnotify v1.9.0 // indirect 53 | github.com/go-faster/city v1.0.1 // indirect 54 | github.com/go-faster/errors v0.7.1 // indirect 55 | github.com/go-jose/go-jose/v4 v4.1.0 // indirect 56 | github.com/go-logr/logr v1.4.2 // indirect 57 | github.com/go-logr/stdr v1.2.2 // indirect 58 | github.com/golang-jwt/jwt v3.2.2+incompatible // indirect 59 | github.com/golang/snappy v1.0.0 // indirect 60 | github.com/google/uuid v1.6.0 // indirect 61 | github.com/gorilla/websocket v1.5.3 // indirect 62 | github.com/hashicorp/errwrap v1.1.0 // indirect 63 | github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 64 | github.com/hashicorp/go-multierror v1.1.1 // indirect 65 | github.com/hashicorp/go-retryablehttp v0.7.7 // indirect 66 | github.com/hashicorp/go-rootcerts v1.0.2 // indirect 67 | github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 // indirect 68 | github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect 69 | github.com/hashicorp/go-sockaddr v1.0.7 // indirect 70 | github.com/hashicorp/hcl v1.0.1-vault-7 // indirect 71 | github.com/hashicorp/vault/api v1.16.0 // indirect 72 | github.com/inconshreveable/mousetrap v1.1.0 // indirect 73 | github.com/jinzhu/inflection v1.0.0 // indirect 74 | github.com/jinzhu/now v1.1.5 // indirect 75 | github.com/json-iterator/go v1.1.12 // indirect 76 | github.com/kelseyhightower/envconfig v1.4.0 // indirect 77 | github.com/klauspost/compress v1.18.0 // indirect 78 | github.com/klauspost/cpuid/v2 v2.2.10 // indirect 79 | github.com/klauspost/reedsolomon v1.12.4 // indirect 80 | github.com/lithammer/shortuuid/v3 v3.0.7 // indirect 81 | github.com/mattn/go-colorable v0.1.14 // indirect 82 | github.com/mattn/go-isatty v0.0.20 // indirect 83 | github.com/mitchellh/go-homedir v1.1.0 // indirect 84 | github.com/mitchellh/mapstructure v1.5.0 // indirect 85 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 86 | github.com/modern-go/reflect2 v1.0.2 // indirect 87 | github.com/montanaflynn/stats v0.7.1 // indirect 88 | github.com/nats-io/nats.go v1.41.1 // indirect 89 | github.com/nats-io/nkeys v0.4.10 // indirect 90 | github.com/nats-io/nuid v1.0.1 // indirect 91 | github.com/oklog/ulid v1.3.1 // indirect 92 | github.com/paulmach/orb v0.11.1 // indirect 93 | github.com/pierrec/lz4/v4 v4.1.22 // indirect 94 | github.com/pkg/errors v0.9.1 // indirect 95 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect 96 | github.com/ryanuber/go-glob v1.0.0 // indirect 97 | github.com/samber/lo v1.49.1 // indirect 98 | github.com/segmentio/asm v1.2.0 // indirect 99 | github.com/shopspring/decimal v1.4.0 // indirect 100 | github.com/soheilhy/cmux v0.1.5 // indirect 101 | github.com/spf13/pflag v1.0.6 // indirect 102 | github.com/stretchr/objx v0.5.2 // indirect 103 | github.com/stretchr/testify v1.10.0 // indirect 104 | github.com/supabase-community/functions-go v0.1.0 // indirect 105 | github.com/supabase-community/gotrue-go v1.2.1 // indirect 106 | github.com/supabase-community/postgrest-go v0.0.11 // indirect 107 | github.com/supabase-community/storage-go v0.7.0 // indirect 108 | github.com/supabase-community/supabase-go v0.0.4 // indirect 109 | github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect 110 | github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect 111 | github.com/tjfoc/gmsm v1.4.1 // indirect 112 | github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 // indirect 113 | github.com/xdg-go/pbkdf2 v1.0.0 // indirect 114 | github.com/xdg-go/scram v1.1.2 // indirect 115 | github.com/xdg-go/stringprep v1.0.4 // indirect 116 | github.com/xtaci/kcp-go v5.4.20+incompatible // indirect 117 | github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect 118 | go.mongodb.org/mongo-driver v1.17.3 // indirect 119 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 120 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect 121 | go.opentelemetry.io/otel v1.35.0 // indirect 122 | go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 // indirect 123 | go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect 124 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 // indirect 125 | go.opentelemetry.io/otel/metric v1.35.0 // indirect 126 | go.opentelemetry.io/otel/sdk v1.35.0 // indirect 127 | go.opentelemetry.io/otel/sdk/metric v1.35.0 // indirect 128 | go.opentelemetry.io/otel/trace v1.35.0 // indirect 129 | go.opentelemetry.io/proto/otlp v1.5.0 // indirect 130 | go.uber.org/atomic v1.11.0 // indirect 131 | go.uber.org/automaxprocs v1.6.0 // indirect 132 | go.uber.org/dig v1.18.1 // indirect 133 | go.uber.org/multierr v1.11.0 // indirect 134 | golang.org/x/crypto v0.37.0 // indirect 135 | golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect 136 | golang.org/x/net v0.39.0 // indirect 137 | golang.org/x/sync v0.13.0 // indirect 138 | golang.org/x/sys v0.32.0 // indirect 139 | golang.org/x/text v0.24.0 // indirect 140 | golang.org/x/time v0.11.0 // indirect 141 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e // indirect 142 | gopkg.in/fsnotify.v1 v1.4.7 // indirect 143 | gopkg.in/yaml.v3 v3.0.1 // indirect 144 | gorm.io/gorm v1.25.12 // indirect 145 | ) 146 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | agones.dev/agones v1.48.0 h1:DQBZucNURhkKlbBN1ut8CGL2GRZ2kgUuzVO7GlpxY0w= 2 | agones.dev/agones v1.48.0/go.mod h1:lpYdaQ8eKvQNQZlSFHFOWKSYpKNTUVwk3aJJJUePVSo= 3 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 4 | cloud.google.com/go v0.120.0 h1:wc6bgG9DHyKqF5/vQvX1CiZrtHnxJjBlKUyF9nP6meA= 5 | cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= 6 | cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= 7 | cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= 8 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 9 | github.com/ClickHouse/ch-go v0.65.1 h1:SLuxmLl5Mjj44/XbINsK2HFvzqup0s6rwKLFH347ZhU= 10 | github.com/ClickHouse/ch-go v0.65.1/go.mod h1:bsodgURwmrkvkBe5jw1qnGDgyITsYErfONKAHn05nv4= 11 | github.com/ClickHouse/clickhouse-go/v2 v2.34.0 h1:Y4rqkdrRHgExvC4o/NTbLdY5LFQ3LHS77/RNFxFX3Co= 12 | github.com/ClickHouse/clickhouse-go/v2 v2.34.0/go.mod h1:yioSINoRLVZkLyDzdMXPLRIqhDvel8iLBlwh6Iefso8= 13 | github.com/ThinkingDataAnalytics/go-sdk/v2 v2.2.0 h1:kDxNimWNjY5JJAPKnDoQPe5OhtTIaVJILGtmN2JjdhY= 14 | github.com/ThinkingDataAnalytics/go-sdk/v2 v2.2.0/go.mod h1:uhiHUKG8fMwf4Ou3186EBBagFrBdAsAA5GHiLMWQN2A= 15 | github.com/ThreeDotsLabs/watermill v1.4.6 h1:rWoXlxdBgUyg/bZ3OO0pON+nESVd9r6tnLTgkZ6CYrU= 16 | github.com/ThreeDotsLabs/watermill v1.4.6/go.mod h1:lBnrLbxOjeMRgcJbv+UiZr8Ylz8RkJ4m6i/VN/Nk+to= 17 | github.com/ThreeDotsLabs/watermill-nats/v2 v2.1.3 h1:/5IfNugBb9H+BvEHHNRnICmF3jaI9P7wVRzA12kDDDs= 18 | github.com/ThreeDotsLabs/watermill-nats/v2 v2.1.3/go.mod h1:stjbT+s4u/s5ime5jdIyvPyjBGwGeJewIN7jxH8gp4k= 19 | github.com/abiosoft/ishell v2.0.0+incompatible h1:zpwIuEHc37EzrsIYah3cpevrIc8Oma7oZPxr03tlmmw= 20 | github.com/abiosoft/ishell v2.0.0+incompatible/go.mod h1:HQR9AqF2R3P4XXpMpI0NAzgHf/aS6+zVXRj14cVk9qg= 21 | github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db h1:CjPUSXOiYptLbTdr1RceuZgSFDQ7U15ITERUGrUORx8= 22 | github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db/go.mod h1:rB3B4rKii8V21ydCbIzH5hZiCQE7f5E9SzUb/ZZx530= 23 | github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= 24 | github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= 25 | github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM= 26 | github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg= 27 | github.com/aws/aws-sdk-go-v2/config v1.29.14 h1:f+eEi/2cKCg9pqKBoAIwRGzVb70MRKqWX4dg1BDcSJM= 28 | github.com/aws/aws-sdk-go-v2/config v1.29.14/go.mod h1:wVPHWcIFv3WO89w0rE10gzf17ZYy+UVS1Geq8Iei34g= 29 | github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9Bc4+D7nZua0KGYOM= 30 | github.com/aws/aws-sdk-go-v2/credentials v1.17.67/go.mod h1:p3C44m+cfnbv763s52gCqrjaqyPikj9Sg47kUVaNZQQ= 31 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw= 32 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M= 33 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q= 34 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY= 35 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0= 36 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q= 37 | github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= 38 | github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= 39 | github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.30.2 h1:EviBG5LJBYTOa0fZp9a4BQlOAqDqgcHkrUK+w0u/Uhw= 40 | github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.30.2/go.mod h1:WIJ+qX03sGSWC6+BSA1LBO6Jmkewbu4TvwXspbai9N4= 41 | github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE= 42 | github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA= 43 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2F1JbDaGooxTq18wmmFzbJRfXfVfy96/1CXM= 44 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY= 45 | github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 h1:1Gw+9ajCV1jogloEv1RRnvfRFia2cL6c9cuKV2Ps+G8= 46 | github.com/aws/aws-sdk-go-v2/service/sso v1.25.3/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI= 47 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 h1:hXmVKytPfTy5axZ+fYbR5d0cFmC3JvwLm5kM83luako= 48 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1/go.mod h1:MlYRNmYu/fGPoxBQVvBYr9nyr948aY/WLUvwBMBJubs= 49 | github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 h1:1XuUZ8mYJw9B6lzAkXhqHlJd/XvaX32evhproijJEZY= 50 | github.com/aws/aws-sdk-go-v2/service/sts v1.33.19/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4= 51 | github.com/aws/smithy-go v1.22.3 h1:Z//5NuZCSW6R4PhQ93hShNbyBbn8BWCmCVCt+Q8Io5k= 52 | github.com/aws/smithy-go v1.22.3/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= 53 | github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= 54 | github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= 55 | github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= 56 | github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= 57 | github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= 58 | github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= 59 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 60 | github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= 61 | github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 62 | github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= 63 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 64 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= 65 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 66 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 67 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 68 | github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= 69 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 70 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 71 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= 72 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 73 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= 74 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= 75 | github.com/duke-git/lancet/v2 v2.3.5 h1:vb49UWkkdyu2eewilZbl0L3X3T133znSQG0FaeJIBMg= 76 | github.com/duke-git/lancet/v2 v2.3.5/go.mod h1:zGa2R4xswg6EG9I6WnyubDbFO/+A/RROxIbXcwryTsc= 77 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 78 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 79 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 80 | github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= 81 | github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= 82 | github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWTLOJKlh+lOBt6nUQgXAfB7oVIQt5cNreqSLI= 83 | github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M= 84 | github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= 85 | github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= 86 | github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw= 87 | github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6vO3VcTw= 88 | github.com/go-faster/errors v0.7.1 h1:MkJTnDoEdi9pDabt1dpWf7AA8/BaSYZqibYyhZ20AYg= 89 | github.com/go-faster/errors v0.7.1/go.mod h1:5ySTjWFiphBs07IKuiL69nxdfd5+fzh1u7FPGZP2quo= 90 | github.com/go-jose/go-jose/v4 v4.1.0 h1:cYSYxd3pw5zd2FSXk2vGdn9igQU2PS8MuxrCOCl0FdY= 91 | github.com/go-jose/go-jose/v4 v4.1.0/go.mod h1:GG/vqmYm3Von2nYiB2vGTXzdoNKE5tix5tuc6iAd+sw= 92 | github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 93 | github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= 94 | github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 95 | github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 96 | github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 97 | github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= 98 | github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= 99 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 100 | github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= 101 | github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= 102 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 103 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 104 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 105 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 106 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 107 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 108 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 109 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 110 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 111 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 112 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 113 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 114 | github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= 115 | github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= 116 | github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 117 | github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= 118 | github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 119 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 120 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 121 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 122 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 123 | github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 124 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 125 | github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 126 | github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 127 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 128 | github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 129 | github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 130 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 131 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 132 | github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= 133 | github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 134 | github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.1 h1:KcFzXwzM/kGhIRHvc8jdixfIJjVzuUJdnv+5xsPutog= 135 | github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.1/go.mod h1:qOchhhIlmRcqk/O9uCo/puJlyo07YINaIqdZfZG3Jkc= 136 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= 137 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= 138 | github.com/gstones/moke-kit v1.0.5-0.20250414125136-0f0537f47883 h1:spAnuLc/C7AIaMxbdUb2NGfJM87RxzPCjm1dGg56on4= 139 | github.com/gstones/moke-kit v1.0.5-0.20250414125136-0f0537f47883/go.mod h1:jJsse+hpKKiP3t0i3lutXQjq3tmobqe59mVDUvysjvQ= 140 | github.com/gstones/zinx v1.2.7-0.20240617071724-88bd884d8d08 h1:YjrnGjuIRVs2t0MjMs4DFQox9GH/4jlOELMRVD5d+xg= 141 | github.com/gstones/zinx v1.2.7-0.20240617071724-88bd884d8d08/go.mod h1:tgm/iZBMyKKZj4totfeu4+PMzSLb4JH8pnGdcG3ql+8= 142 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 143 | github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= 144 | github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 145 | github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= 146 | github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= 147 | github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= 148 | github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= 149 | github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= 150 | github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= 151 | github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= 152 | github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= 153 | github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= 154 | github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= 155 | github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 h1:U+kC2dOhMFQctRfhK0gRctKAPTloZdMU5ZJxaesJ/VM= 156 | github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0/go.mod h1:Ll013mhdmsVDuoIXVfBtvgGJsXDYkTw1kooNcoCXuE0= 157 | github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= 158 | github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= 159 | github.com/hashicorp/go-sockaddr v1.0.7 h1:G+pTkSO01HpR5qCxg7lxfsFEZaG+C0VssTy/9dbT+Fw= 160 | github.com/hashicorp/go-sockaddr v1.0.7/go.mod h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw= 161 | github.com/hashicorp/hcl v1.0.1-vault-7 h1:ag5OxFVy3QYTFTJODRzTKVZ6xvdfLLCA1cy/Y6xGI0I= 162 | github.com/hashicorp/hcl v1.0.1-vault-7/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= 163 | github.com/hashicorp/vault/api v1.16.0 h1:nbEYGJiAPGzT9U4oWgaaB0g+Rj8E59QuHKyA5LhwQN4= 164 | github.com/hashicorp/vault/api v1.16.0/go.mod h1:KhuUhzOD8lDSk29AtzNjgAu2kxRA9jL9NAbkFlqvkBA= 165 | github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= 166 | github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= 167 | github.com/jarcoal/httpmock v1.3.1 h1:iUx3whfZWVf3jT01hQTO/Eo5sAYtB2/rqaUuOtpInww= 168 | github.com/jarcoal/httpmock v1.3.1/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg= 169 | github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= 170 | github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= 171 | github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= 172 | github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 173 | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= 174 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 175 | github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= 176 | github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= 177 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 178 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 179 | github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= 180 | github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= 181 | github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= 182 | github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= 183 | github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= 184 | github.com/klauspost/reedsolomon v1.12.4 h1:5aDr3ZGoJbgu/8+j45KtUJxzYm8k08JGtB9Wx1VQ4OA= 185 | github.com/klauspost/reedsolomon v1.12.4/go.mod h1:d3CzOMOt0JXGIFZm1StgkyF14EYr3xneR2rNWo7NcMU= 186 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 187 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 188 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 189 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 190 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 191 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 192 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 193 | github.com/lithammer/shortuuid/v3 v3.0.7 h1:trX0KTHy4Pbwo/6ia8fscyHoGA+mf1jWbPJVuvyJQQ8= 194 | github.com/lithammer/shortuuid/v3 v3.0.7/go.mod h1:vMk8ke37EmiewwolSO1NLW8vP4ZaKlRuDIi8tWWmAts= 195 | github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= 196 | github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= 197 | github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= 198 | github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 199 | github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 200 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 201 | github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= 202 | github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 203 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 204 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 205 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 206 | github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= 207 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 208 | github.com/moke-game/platform v0.0.0-20250415025501-5e99e8ee1e09 h1:y5amd2mVJw+Kz6AWJ61Dlm62jsOXZhvicpeeH6Slpao= 209 | github.com/moke-game/platform v0.0.0-20250415025501-5e99e8ee1e09/go.mod h1:KDYqukGz7n/H6k4bNQKW8rqLyKU7OFjVbOSjHr0FJdg= 210 | github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= 211 | github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= 212 | github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= 213 | github.com/nats-io/nats.go v1.41.1 h1:lCc/i5x7nqXbspxtmXaV4hRguMPHqE/kYltG9knrCdU= 214 | github.com/nats-io/nats.go v1.41.1/go.mod h1:mzHiutcAdZrg6WLfYVKXGseqqow2fWmwlTEUOHsI4jY= 215 | github.com/nats-io/nkeys v0.4.10 h1:glmRrpCmYLHByYcePvnTBEAwawwapjCPMjy2huw20wc= 216 | github.com/nats-io/nkeys v0.4.10/go.mod h1:OjRrnIKnWBFl+s4YK5ChQfvHP2fxqZexrKJoVVyWB3U= 217 | github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= 218 | github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= 219 | github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= 220 | github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= 221 | github.com/paulmach/orb v0.11.1 h1:3koVegMC4X/WeiXYz9iswopaTwMem53NzTJuTF20JzU= 222 | github.com/paulmach/orb v0.11.1/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU= 223 | github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY= 224 | github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= 225 | github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= 226 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 227 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 228 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 229 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= 230 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 231 | github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= 232 | github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= 233 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 234 | github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM= 235 | github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA= 236 | github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= 237 | github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= 238 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 239 | github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= 240 | github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= 241 | github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew= 242 | github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o= 243 | github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= 244 | github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= 245 | github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= 246 | github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= 247 | github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= 248 | github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= 249 | github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= 250 | github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= 251 | github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= 252 | github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 253 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 254 | github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= 255 | github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= 256 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 257 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 258 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 259 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 260 | github.com/supabase-community/functions-go v0.1.0 h1:6K26R1CL4qMjH6CxvmEtV/PP3lX2vTxo63mYJ30jhy0= 261 | github.com/supabase-community/functions-go v0.1.0/go.mod h1:nnIju6x3+OZSojtGQCQzu0h3kv4HdIZk+UWCnNxtSak= 262 | github.com/supabase-community/gotrue-go v1.2.1 h1:8FvrCyx++6evFtOu1aOpbsfEy6s24HGCbBfPMmQW7qI= 263 | github.com/supabase-community/gotrue-go v1.2.1/go.mod h1:86DXBiAUNcbCfgbeOPEh0PQxScLfowUbYgakETSFQOw= 264 | github.com/supabase-community/postgrest-go v0.0.11 h1:717GTUMfLJxSBuAeEQG2MuW5Q62Id+YrDjvjprTSErg= 265 | github.com/supabase-community/postgrest-go v0.0.11/go.mod h1:cw6LfzMyK42AOSBA1bQ/HZ381trIJyuui2GWhraW7Cc= 266 | github.com/supabase-community/storage-go v0.7.0 h1:cJ8HLbbnL54H5rHPtHfiwtpRwcbDfA3in9HL/ucHnqA= 267 | github.com/supabase-community/storage-go v0.7.0/go.mod h1:oBKcJf5rcUXy3Uj9eS5wR6mvpwbmvkjOtAA+4tGcdvQ= 268 | github.com/supabase-community/supabase-go v0.0.4 h1:sxMenbq6N8a3z9ihNpN3lC2FL3E1YuTQsjX09VPRp+U= 269 | github.com/supabase-community/supabase-go v0.0.4/go.mod h1:SSHsXoOlc+sq8XeXaf0D3gE2pwrq5bcUfzm0+08u/o8= 270 | github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 h1:89CEmDvlq/F7SJEOqkIdNDGJXrQIhuIx9D2DBXjavSU= 271 | github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU= 272 | github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b h1:fj5tQ8acgNUr6O8LEplsxDhUIe2573iLkJc+PqnzZTI= 273 | github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4= 274 | github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= 275 | github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= 276 | github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= 277 | github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 h1:nrZ3ySNYwJbSpD6ce9duiP+QkD3JuLCcWkdaehUS/3Y= 278 | github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80/go.mod h1:iFyPdL66DjUD96XmzVL3ZntbzcflLnznH0fr99w5VqE= 279 | github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= 280 | github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= 281 | github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= 282 | github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= 283 | github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= 284 | github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= 285 | github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= 286 | github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= 287 | github.com/xtaci/kcp-go v5.4.20+incompatible h1:TN1uey3Raw0sTz0Fg8GkfM0uH3YwzhnZWQ1bABv5xAg= 288 | github.com/xtaci/kcp-go v5.4.20+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE= 289 | github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E= 290 | github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0= 291 | github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= 292 | github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= 293 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= 294 | github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM= 295 | github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI= 296 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 297 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 298 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 299 | go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= 300 | go.mongodb.org/mongo-driver v1.17.3 h1:TQyXhnsWfWtgAhMtOgtYHMTkZIfBTpMTsMnd9ZBeHxQ= 301 | go.mongodb.org/mongo-driver v1.17.3/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= 302 | go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= 303 | go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= 304 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw= 305 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM= 306 | go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= 307 | go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= 308 | go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 h1:QcFwRrZLc82r8wODjvyCbP7Ifp3UANaBSmhDSFjnqSc= 309 | go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0/go.mod h1:CXIWhUomyWBG/oY2/r/kLp6K/cmx9e/7DLpBuuGdLCA= 310 | go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= 311 | go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= 312 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= 313 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo= 314 | go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= 315 | go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= 316 | go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= 317 | go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= 318 | go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= 319 | go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= 320 | go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= 321 | go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= 322 | go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= 323 | go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= 324 | go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= 325 | go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= 326 | go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= 327 | go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= 328 | go.uber.org/dig v1.18.1 h1:rLww6NuajVjeQn+49u5NcezUJEGwd5uXmyoCKW2g5Es= 329 | go.uber.org/dig v1.18.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= 330 | go.uber.org/fx v1.23.0 h1:lIr/gYWQGfTwGcSXWXu4vP5Ws6iqnNEIY+F/aFzCKTg= 331 | go.uber.org/fx v1.23.0/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU= 332 | go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= 333 | go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 334 | go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= 335 | go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= 336 | go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= 337 | go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= 338 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 339 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 340 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 341 | golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 342 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 343 | golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 344 | golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= 345 | golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= 346 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 347 | golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM= 348 | golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8= 349 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 350 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 351 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 352 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 353 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 354 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 355 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 356 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 357 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 358 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 359 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 360 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 361 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 362 | golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 363 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 364 | golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 365 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 366 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 367 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 368 | golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= 369 | golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= 370 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 371 | golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98= 372 | golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= 373 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 374 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 375 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 376 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 377 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 378 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 379 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 380 | golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= 381 | golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= 382 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 383 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 384 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 385 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 386 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 387 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 388 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 389 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 390 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 391 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 392 | golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= 393 | golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 394 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 395 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 396 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 397 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 398 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 399 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 400 | golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= 401 | golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= 402 | golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= 403 | golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= 404 | golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= 405 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 406 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 407 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 408 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 409 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 410 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 411 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 412 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 413 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 414 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 415 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 416 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 417 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 418 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 419 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 420 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 421 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 422 | google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e h1:UdXH7Kzbj+Vzastr5nVfccbmFsmYNygVLSPk1pEfDoY= 423 | google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e/go.mod h1:085qFyf2+XaZlRdCgKNCIZ3afY2p4HHZdoIRpId8F4A= 424 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e h1:ztQaXfzEXTmCBvbtWYRhJxW+0iJcz2qXfd38/e9l7bA= 425 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= 426 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 427 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 428 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 429 | google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 430 | google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= 431 | google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= 432 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 433 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 434 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 435 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 436 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 437 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 438 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 439 | google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 440 | google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= 441 | google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= 442 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 443 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 444 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 445 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 446 | gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= 447 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 448 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 449 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 450 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 451 | gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= 452 | gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= 453 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 454 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 455 | open-match.dev/open-match v1.8.1 h1:Tp5fxeUVBugt091zFxMJim6TalE9sFDB2mNGw5zRWQQ= 456 | open-match.dev/open-match v1.8.1/go.mod h1:FjKE1hS+BGFMxVUQvPLqXWMUjjFysYrPESdEfEpDxvM= 457 | -------------------------------------------------------------------------------- /internal/clients/game0/grpc_cli.go: -------------------------------------------------------------------------------- 1 | package game0 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | pb "github.com/moke-game/game/api/gen/game0/api" 8 | 9 | "github.com/abiosoft/ishell" 10 | mm "github.com/grpc-ecosystem/go-grpc-middleware/v2/metadata" 11 | "github.com/gstones/moke-kit/logging/slogger" 12 | "google.golang.org/grpc" 13 | "google.golang.org/grpc/metadata" 14 | ) 15 | 16 | type DemoGrpc struct { 17 | client pb.Game0ServiceClient 18 | cmd *ishell.Cmd 19 | } 20 | 21 | func NewDemoGrpcCli(conn *grpc.ClientConn) *DemoGrpc { 22 | cmd := &ishell.Cmd{ 23 | Name: "game", 24 | Help: "game interactive", 25 | Aliases: []string{"D"}, 26 | } 27 | p := &DemoGrpc{ 28 | client: pb.NewGame0ServiceClient(conn), 29 | cmd: cmd, 30 | } 31 | p.initSubShells() 32 | return p 33 | } 34 | 35 | func (p *DemoGrpc) GetCmd() *ishell.Cmd { 36 | return p.cmd 37 | } 38 | 39 | func (p *DemoGrpc) initSubShells() { 40 | p.cmd.AddCmd(&ishell.Cmd{ 41 | Name: "hi", 42 | Help: "say hi", 43 | Aliases: []string{"hi"}, 44 | Func: p.sayHi, 45 | }) 46 | p.cmd.AddCmd(&ishell.Cmd{ 47 | Name: "watch", 48 | Help: "watch topic", 49 | Aliases: []string{"w"}, 50 | Func: p.watch, 51 | }) 52 | 53 | } 54 | 55 | func (p *DemoGrpc) sayHi(c *ishell.Context) { 56 | c.ShowPrompt(false) 57 | defer c.ShowPrompt(true) 58 | msg := "hello" 59 | in := slogger.ReadLine(c, "message(default:hello): ") 60 | if in != "" { 61 | msg = in 62 | } 63 | topic := "game" 64 | t := slogger.ReadLine(c, "topic(default:game): ") 65 | if t != "" { 66 | topic = t 67 | } 68 | md := metadata.Pairs("authorization", fmt.Sprintf("%s %v", "bearer", "test")) 69 | ctx := mm.MD(md).ToOutgoing(context.Background()) 70 | if response, err := p.client.Hi(ctx, &pb.HiRequest{ 71 | Uid: "10000", 72 | Message: msg, 73 | Topic: topic, 74 | }); err != nil { 75 | slogger.Warn(c, err) 76 | } else { 77 | slogger.Infof(c, "Response: %s", response.Message) 78 | } 79 | } 80 | 81 | func (p *DemoGrpc) watch(c *ishell.Context) { 82 | c.ShowPrompt(false) 83 | defer c.ShowPrompt(true) 84 | 85 | topic := "game" 86 | t := slogger.ReadLine(c, "topic(default:game): ") 87 | if t != "" { 88 | topic = t 89 | } 90 | 91 | md := metadata.Pairs("authorization", fmt.Sprintf("%s %v", "bearer", "test")) 92 | ctx := mm.MD(md).ToOutgoing(context.Background()) 93 | if stream, err := p.client.Watch(ctx, &pb.WatchRequest{ 94 | Topic: topic, 95 | }); err != nil { 96 | slogger.Warn(c, err) 97 | } else { 98 | for { 99 | if response, err := stream.Recv(); err != nil { 100 | slogger.Warn(c, err) 101 | break 102 | } else { 103 | slogger.Infof(c, "Response: %s \r\n", response.Message) 104 | } 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /internal/clients/game0/shell.go: -------------------------------------------------------------------------------- 1 | package game0 2 | 3 | import ( 4 | "net" 5 | 6 | "github.com/abiosoft/ishell" 7 | 8 | "github.com/gstones/moke-kit/logging/slogger" 9 | "github.com/gstones/moke-kit/server/tools" 10 | ) 11 | 12 | func RunGrpc(url string) { 13 | sh := ishell.New() 14 | slogger.Info(sh, "interactive game connect to "+url) 15 | 16 | if conn, err := tools.DialInsecure(url); err != nil { 17 | slogger.Die(sh, err) 18 | } else { 19 | gameGrpc := NewDemoGrpcCli(conn) 20 | sh.AddCmd(gameGrpc.GetCmd()) 21 | 22 | sh.Interrupt(func(c *ishell.Context, count int, input string) { 23 | if count >= 2 { 24 | c.Stop() 25 | } 26 | if count == 1 { 27 | conn.Close() 28 | slogger.Done(c, "interrupted, press again to exit") 29 | } 30 | }) 31 | } 32 | sh.Run() 33 | } 34 | 35 | func RunTcp(url string) { 36 | sh := ishell.New() 37 | slogger.Info(sh, "interactive game tcp connect to "+url) 38 | if conn, err := net.Dial("tcp", url); err != nil { 39 | slogger.Die(sh, err) 40 | } else { 41 | gameTcp := NewTcpCli(conn) 42 | sh.AddCmd(gameTcp.GetCmd()) 43 | 44 | sh.Interrupt(func(c *ishell.Context, count int, input string) { 45 | if count >= 2 { 46 | c.Stop() 47 | } 48 | if count == 1 { 49 | conn.Close() 50 | slogger.Done(c, "interrupted, press again to exit") 51 | } 52 | }) 53 | } 54 | sh.Run() 55 | } 56 | -------------------------------------------------------------------------------- /internal/clients/game0/tcp_cli.go: -------------------------------------------------------------------------------- 1 | package game0 2 | 3 | import ( 4 | "io" 5 | "net" 6 | 7 | "github.com/abiosoft/ishell" 8 | "github.com/gstones/moke-kit/logging/slogger" 9 | "github.com/gstones/zinx/zconf" 10 | "github.com/gstones/zinx/ziface" 11 | "github.com/gstones/zinx/zpack" 12 | "google.golang.org/protobuf/proto" 13 | 14 | pb "github.com/moke-game/game/api/gen/game0/api" 15 | ) 16 | 17 | type DemoTcp struct { 18 | conn net.Conn 19 | cmd *ishell.Cmd 20 | } 21 | 22 | func NewTcpCli(conn net.Conn) *DemoTcp { 23 | cmd := &ishell.Cmd{ 24 | Name: "game", 25 | Help: "game interactive", 26 | Aliases: []string{"D"}, 27 | } 28 | p := &DemoTcp{ 29 | conn: conn, 30 | cmd: cmd, 31 | } 32 | p.initSubShells() 33 | return p 34 | } 35 | 36 | func (dz *DemoTcp) GetCmd() *ishell.Cmd { 37 | return dz.cmd 38 | } 39 | 40 | func (dz *DemoTcp) initSubShells() { 41 | dz.cmd.AddCmd(&ishell.Cmd{ 42 | Name: "hi", 43 | Help: "say hi", 44 | Aliases: []string{"hi"}, 45 | Func: dz.sayHi, 46 | }) 47 | dz.cmd.AddCmd(&ishell.Cmd{ 48 | Name: "watch", 49 | Help: "watch topic", 50 | Aliases: []string{"w"}, 51 | Func: dz.watch, 52 | }) 53 | 54 | } 55 | 56 | func (dz *DemoTcp) sayHi(c *ishell.Context) { 57 | c.ShowPrompt(false) 58 | defer c.ShowPrompt(true) 59 | 60 | msg := "hello" 61 | in := slogger.ReadLine(c, "message(default:hello): ") 62 | if in != "" { 63 | msg = in 64 | } 65 | topic := "game" 66 | t := slogger.ReadLine(c, "topic(default:game): ") 67 | if t != "" { 68 | topic = t 69 | } 70 | 71 | req := &pb.HiRequest{ 72 | Message: msg, 73 | Topic: topic, 74 | Uid: "10000", 75 | } 76 | data, err := proto.Marshal(req) 77 | if err != nil { 78 | slogger.Warn(c, err) 79 | return 80 | } 81 | dp := zpack.NewDataPack() 82 | sendData, _ := dp.Pack(zpack.NewMsgPackage(1, data)) 83 | _, err = dz.conn.Write(sendData) 84 | if err != nil { 85 | return 86 | } 87 | } 88 | 89 | func (dz *DemoTcp) watch(c *ishell.Context) { 90 | c.ShowPrompt(false) 91 | defer c.ShowPrompt(true) 92 | 93 | slogger.Info(c, "Enter watch topic...") 94 | topic := slogger.ReadLine(c, "topic: ") 95 | 96 | req := &pb.WatchRequest{ 97 | Topic: topic, 98 | Uid: "10000", 99 | } 100 | data, err := proto.Marshal(req) 101 | if err != nil { 102 | slogger.Warn(c, err) 103 | return 104 | } 105 | dp := zpack.NewDataPack() 106 | sendData, _ := dp.Pack(zpack.NewMsgPackage(2, data)) 107 | _, err = dz.conn.Write(sendData) 108 | if err != nil { 109 | return 110 | } 111 | watchResponse(c, dz.conn) 112 | } 113 | 114 | func watchResponse(c *ishell.Context, conn net.Conn) { 115 | dp := zpack.NewDataPack() 116 | go func() { 117 | for { 118 | id, data, err := unPackResponse(dp, conn) 119 | if err != nil { 120 | slogger.Warn(c, err) 121 | return 122 | } 123 | if id == 1 { 124 | resp := &pb.HiResponse{} 125 | err := proto.Unmarshal(data, resp) 126 | if err != nil { 127 | slogger.Warn(c, err) 128 | return 129 | } 130 | slogger.Infof(c, "response: %s \r\n", resp.String()) 131 | continue 132 | } else if id == 2 { 133 | resp := &pb.WatchResponse{} 134 | err := proto.Unmarshal(data, resp) 135 | if err != nil { 136 | slogger.Warn(c, err) 137 | return 138 | } 139 | slogger.Infof(c, "watching:%d %s \r\n", id, resp.String()) 140 | continue 141 | } 142 | } 143 | }() 144 | 145 | } 146 | 147 | func unPackResponse(dp ziface.IDataPack, conn io.Reader) (uint32, []byte, error) { 148 | zconf.GlobalObject.MaxPacketSize = 0 149 | //先读出流中的head部分 150 | headData := make([]byte, dp.GetHeadLen()) 151 | _, err := conn.Read(headData) 152 | if err != nil { 153 | return 0, nil, err 154 | } 155 | //将headData字节流 拆包到msg中 156 | msgHead, err := dp.Unpack(headData) 157 | if err != nil { 158 | return 0, nil, err 159 | } 160 | if msgHead.GetDataLen() > 0 { 161 | //msg是有data数据的,需要再次读取data数据 162 | data := make([]byte, msgHead.GetDataLen()) 163 | //根据dataLen从io中读取字节流 164 | _, err := io.ReadFull(conn, data) 165 | if err != nil { 166 | return 0, nil, err 167 | } 168 | return msgHead.GetMsgID(), data, nil 169 | } 170 | 171 | return msgHead.GetMsgID(), nil, nil 172 | } 173 | -------------------------------------------------------------------------------- /internal/services/game0/db_nosql/factory.go: -------------------------------------------------------------------------------- 1 | package db_nosql 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/gstones/moke-kit/orm/nerrors" 7 | "github.com/gstones/moke-kit/orm/nosql/diface" 8 | "go.uber.org/zap" 9 | 10 | "github.com/moke-game/game/internal/services/game0/db_nosql/game0" 11 | ) 12 | 13 | type Database struct { 14 | logger *zap.Logger 15 | coll diface.ICollection 16 | } 17 | 18 | func OpenDatabase(l *zap.Logger, coll diface.ICollection) Database { 19 | return Database{ 20 | logger: l, 21 | coll: coll, 22 | } 23 | } 24 | 25 | func (db *Database) LoadOrCreateDemo(id string) (*game0.Dao, error) { 26 | if dm, err := game0.NewDemoModel(id, db.coll); err != nil { 27 | return nil, err 28 | } else if err = dm.Load(); errors.Is(err, nerrors.ErrNotFound) { 29 | if dm, err = game0.NewDemoModel(id, db.coll); err != nil { 30 | return nil, err 31 | } else if err := dm.InitDefault(); err != nil { 32 | return nil, err 33 | } else if err = dm.Create(); err != nil { 34 | if err = dm.Load(); err != nil { 35 | return nil, err 36 | } else { 37 | return dm, nil 38 | } 39 | } else { 40 | return dm, nil 41 | } 42 | } else if err != nil { 43 | return nil, err 44 | } else { 45 | return dm, nil 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /internal/services/game0/db_nosql/game0/dao.go: -------------------------------------------------------------------------------- 1 | package game0 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/gstones/moke-kit/orm/nosql" 7 | "github.com/gstones/moke-kit/orm/nosql/diface" 8 | ) 9 | 10 | type Dao struct { 11 | nosql.DocumentBase `bson:"-"` 12 | Id string `bson:"_id"` 13 | Data *Data `bson:"data"` 14 | } 15 | 16 | func (dm *Dao) Init(id string, doc diface.ICollection) error { 17 | key, e := NewDemoKey(id) 18 | if e != nil { 19 | return e 20 | } 21 | 22 | dm.Data = &Data{} 23 | dm.DocumentBase.Init(context.Background(), &dm.Data, dm.clear, doc, key) 24 | return nil 25 | } 26 | 27 | func (dm *Dao) SetMessage(message string) { 28 | dm.Data.Message = message 29 | } 30 | 31 | func (dm *Dao) clear() { 32 | dm.Data = nil 33 | } 34 | 35 | func (dm *Dao) InitDefault() error { 36 | 37 | return nil 38 | } 39 | 40 | func NewDemoModel(id string, doc diface.ICollection) (*Dao, error) { 41 | dm := &Dao{} 42 | if err := dm.Init(id, doc); err != nil { 43 | return nil, err 44 | } 45 | return dm, nil 46 | } 47 | -------------------------------------------------------------------------------- /internal/services/game0/db_nosql/game0/data.go: -------------------------------------------------------------------------------- 1 | package game0 2 | 3 | type Data struct { 4 | Message string `bson:"message"` 5 | } 6 | -------------------------------------------------------------------------------- /internal/services/game0/db_nosql/game0/keys.go: -------------------------------------------------------------------------------- 1 | package game0 2 | 3 | import "github.com/gstones/moke-kit/orm/nosql/key" 4 | 5 | func NewDemoKey(id string) (key.Key, error) { 6 | return key.NewKeyFromParts("game", id) 7 | } 8 | -------------------------------------------------------------------------------- /internal/services/game0/domain/domain.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "time" 7 | 8 | "github.com/gstones/moke-kit/mq/common" 9 | "github.com/gstones/moke-kit/mq/miface" 10 | "github.com/redis/go-redis/v9" 11 | "go.uber.org/zap" 12 | 13 | "github.com/moke-game/game/internal/services/game0/db_nosql" 14 | ) 15 | 16 | type Game struct { 17 | logger *zap.Logger 18 | nosqlDb db_nosql.Database 19 | mq miface.MessageQueue 20 | redis *redis.Client 21 | } 22 | 23 | func NewGame( 24 | logger *zap.Logger, 25 | database db_nosql.Database, 26 | mq miface.MessageQueue, 27 | redis *redis.Client, 28 | ) *Game { 29 | return &Game{ 30 | logger: logger, 31 | nosqlDb: database, 32 | mq: mq, 33 | redis: redis, 34 | } 35 | } 36 | 37 | func (d *Game) Hi(uid, topic, message string) error { 38 | // nosqlDb create 39 | if data, err := d.nosqlDb.LoadOrCreateDemo(uid); err != nil { 40 | return err 41 | } else { 42 | if err := data.Update(func() bool { 43 | data.SetMessage(message) 44 | return true 45 | }); err != nil { 46 | return err 47 | } 48 | } 49 | d.redis.Set(context.Background(), topic, message, time.Minute) 50 | //nats mq publish 51 | natsTopic := common.NatsHeader.CreateTopic(topic) 52 | if err := d.mq.Publish( 53 | natsTopic, 54 | miface.WithBytes([]byte(fmt.Sprintf("nats mq: %s", message))), 55 | ); err != nil { 56 | return err 57 | } 58 | // local(channel) mq publish 59 | localTopic := common.LocalHeader.CreateTopic(topic) 60 | if err := d.mq.Publish( 61 | localTopic, 62 | miface.WithBytes([]byte(fmt.Sprintf("local mq: %s", message))), 63 | ); err != nil { 64 | return err 65 | } 66 | 67 | return nil 68 | } 69 | 70 | func (d *Game) Watch(ctx context.Context, topic string, callback func(message string) error) error { 71 | //nats mq subscribe 72 | natsTopic := common.NatsHeader.CreateTopic(topic) 73 | if _, err := d.mq.Subscribe( 74 | ctx, 75 | natsTopic, 76 | func(msg miface.Message, err error) common.ConsumptionCode { 77 | if err := callback(string(msg.Data())); err != nil { 78 | return common.ConsumeNackPersistentFailure 79 | } 80 | return common.ConsumeAck 81 | }); err != nil { 82 | return err 83 | } 84 | 85 | //local(channel) mq subscribe 86 | localTopic := common.LocalHeader.CreateTopic(topic) 87 | if _, err := d.mq.Subscribe( 88 | ctx, 89 | localTopic, 90 | func(msg miface.Message, err error) common.ConsumptionCode { 91 | if err := callback(string(msg.Data())); err != nil { 92 | return common.ConsumeNackPersistentFailure 93 | } 94 | return common.ConsumeAck 95 | }); err != nil { 96 | return err 97 | } 98 | 99 | <-ctx.Done() 100 | return nil 101 | } 102 | -------------------------------------------------------------------------------- /internal/services/game0/service.go: -------------------------------------------------------------------------------- 1 | package game0 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/gstones/moke-kit/mq/miface" 7 | "github.com/gstones/moke-kit/mq/pkg/mfx" 8 | "github.com/gstones/moke-kit/orm/nosql/diface" 9 | "github.com/gstones/moke-kit/orm/pkg/ofx" 10 | "github.com/gstones/moke-kit/server/pkg/sfx" 11 | "github.com/gstones/moke-kit/server/siface" 12 | "github.com/gstones/moke-kit/utility" 13 | "github.com/gstones/zinx/ziface" 14 | "github.com/redis/go-redis/v9" 15 | "go.uber.org/fx" 16 | "go.uber.org/zap" 17 | "google.golang.org/protobuf/proto" 18 | pb2 "open-match.dev/open-match/pkg/pb" 19 | 20 | pb "github.com/moke-game/game/api/gen/game0/api" 21 | "github.com/moke-game/game/internal/services/game0/db_nosql" 22 | "github.com/moke-game/game/internal/services/game0/domain" 23 | "github.com/moke-game/game/pkg/dfx" 24 | ) 25 | 26 | type Service struct { 27 | utility.WithoutAuth 28 | logger *zap.Logger 29 | gameHandler *domain.Game 30 | } 31 | 32 | func (s *Service) Run(request *pb2.RunRequest, server pb2.MatchFunction_RunServer) error { 33 | s.logger.Info("Run", zap.Any("request", request)) 34 | 35 | return nil 36 | } 37 | 38 | // ---------------- grpc ---------------- 39 | 40 | func (s *Service) Watch(request *pb.WatchRequest, server pb.Game0Service_WatchServer) error { 41 | topic := request.GetTopic() 42 | s.logger.Info("Watch", zap.String("topic", topic)) 43 | 44 | if err := s.gameHandler.Watch( 45 | server.Context(), 46 | topic, 47 | func(message string) error { 48 | if err := server.Send(&pb.WatchResponse{ 49 | Message: message, 50 | }); err != nil { 51 | return err 52 | } 53 | return nil 54 | }); err != nil { 55 | return err 56 | } 57 | 58 | return nil 59 | } 60 | 61 | func (s *Service) Hi(_ context.Context, request *pb.HiRequest) (*pb.HiResponse, error) { 62 | message := request.GetMessage() 63 | s.logger.Info("Hi", zap.String("message", message)) 64 | 65 | if err := s.gameHandler.Hi(request.GetUid(), request.GetTopic(), request.GetMessage()); err != nil { 66 | return nil, err 67 | } 68 | return &pb.HiResponse{ 69 | Message: "response: " + message, 70 | }, nil 71 | 72 | } 73 | func (s *Service) RegisterWithGrpcServer(server siface.IGrpcServer) error { 74 | pb.RegisterGame0ServiceServer(server.GrpcServer(), s) 75 | pb2.RegisterMatchFunctionServer(server.GrpcServer(), s) 76 | return nil 77 | } 78 | 79 | // ---------------- gateway ---------------- 80 | 81 | func (s *Service) RegisterWithGatewayServer(server siface.IGatewayServer) error { 82 | return pb.RegisterGame0ServiceHandlerFromEndpoint( 83 | context.Background(), 84 | server.GatewayRuntimeMux(), 85 | server.Endpoint(), 86 | server.GatewayOption(), 87 | ) 88 | } 89 | 90 | //---------------- zinx ---------------- 91 | 92 | func (s *Service) PreHandle(_ ziface.IRequest) { 93 | 94 | } 95 | 96 | func (s *Service) Handle(request ziface.IRequest) { 97 | switch request.GetMsgID() { 98 | case 1: 99 | req := &pb.HiRequest{} 100 | if err := proto.Unmarshal(request.GetData(), req); err != nil { 101 | s.logger.Error("unmarshal request data error", zap.Error(err)) 102 | } else { 103 | if err := s.gameHandler.Hi(req.GetUid(), req.GetTopic(), req.GetMessage()); err != nil { 104 | s.logger.Error("Hi error", zap.Error(err)) 105 | } 106 | } 107 | case 2: 108 | req := &pb.WatchRequest{} 109 | if err := proto.Unmarshal(request.GetData(), req); err != nil { 110 | s.logger.Error("unmarshal request data error", zap.Error(err)) 111 | } else { 112 | if err := s.gameHandler.Watch( 113 | request.GetConnection().Context(), 114 | req.GetTopic(), 115 | func(message string) error { 116 | resp := &pb.WatchResponse{ 117 | Message: message, 118 | } 119 | if data, err := proto.Marshal(resp); err != nil { 120 | return err 121 | } else if err := request.GetConnection().SendMsg(2, data); err != nil { 122 | return err 123 | } 124 | return nil 125 | }); err != nil { 126 | s.logger.Error("Watch error", zap.Error(err)) 127 | } 128 | } 129 | } 130 | } 131 | 132 | func (s *Service) PostHandle(_ ziface.IRequest) { 133 | 134 | } 135 | 136 | func (s *Service) RegisterWithServer(server siface.IZinxServer) { 137 | server.ZinxServer().AddRouter(1, s) 138 | server.ZinxServer().AddRouter(2, s) 139 | } 140 | 141 | func NewService( 142 | logger *zap.Logger, 143 | coll diface.ICollection, 144 | mq miface.MessageQueue, 145 | redis *redis.Client, 146 | ) (result *Service, err error) { 147 | handler := domain.NewGame( 148 | logger, 149 | db_nosql.OpenDatabase(logger, coll), 150 | mq, 151 | redis, 152 | ) 153 | 154 | result = &Service{ 155 | logger: logger, 156 | gameHandler: handler, 157 | } 158 | return 159 | } 160 | 161 | var GrpcService = fx.Provide( 162 | func( 163 | l *zap.Logger, 164 | dProvider ofx.DocumentStoreParams, 165 | setting dfx.SettingsParams, 166 | mqParams mfx.MessageQueueParams, 167 | redisClient ofx.RedisParams, 168 | ) (out sfx.GrpcServiceResult, err error) { 169 | if coll, err := dProvider.DriverProvider.OpenDbDriver(setting.DbName); err != nil { 170 | return out, err 171 | } else if s, err := NewService( 172 | l, 173 | coll, 174 | mqParams.MessageQueue, 175 | redisClient.Redis, 176 | ); err != nil { 177 | return out, err 178 | } else { 179 | out.GrpcService = s 180 | } 181 | return 182 | }, 183 | ) 184 | 185 | var HttpService = fx.Provide( 186 | func( 187 | l *zap.Logger, 188 | dProvider ofx.DocumentStoreParams, 189 | setting dfx.SettingsParams, 190 | mqParams mfx.MessageQueueParams, 191 | redisClient ofx.RedisParams, 192 | ) (out sfx.GatewayServiceResult, err error) { 193 | if coll, err := dProvider.DriverProvider.OpenDbDriver(setting.DbName); err != nil { 194 | return out, err 195 | } else if s, err := NewService( 196 | l, 197 | coll, 198 | mqParams.MessageQueue, 199 | redisClient.Redis, 200 | ); err != nil { 201 | return out, err 202 | } else { 203 | out.GatewayService = s 204 | } 205 | return 206 | }, 207 | ) 208 | 209 | var TcpService = fx.Provide( 210 | func( 211 | l *zap.Logger, 212 | dProvider ofx.DocumentStoreParams, 213 | setting dfx.SettingsParams, 214 | mqParams mfx.MessageQueueParams, 215 | redisClient ofx.RedisParams, 216 | ) (out sfx.ZinxServiceResult, err error) { 217 | if coll, err := dProvider.DriverProvider.OpenDbDriver(setting.DbName); err != nil { 218 | return out, err 219 | } else if s, err := NewService( 220 | l, 221 | coll, 222 | mqParams.MessageQueue, 223 | redisClient.Redis, 224 | ); err != nil { 225 | return out, err 226 | } else { 227 | out.ZinxService = s 228 | } 229 | return 230 | }, 231 | ) 232 | -------------------------------------------------------------------------------- /pkg/dfx/auth.go: -------------------------------------------------------------------------------- 1 | package dfx 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/auth" 7 | "github.com/gstones/moke-kit/server/pkg/sfx" 8 | "github.com/gstones/moke-kit/utility" 9 | "go.uber.org/fx" 10 | "go.uber.org/zap" 11 | "google.golang.org/grpc" 12 | ) 13 | 14 | // Author is a game auth service 15 | type Author struct { 16 | unAuthMethods map[string]struct{} 17 | } 18 | 19 | // Auth is a game auth method 20 | func (d *Author) Auth(ctx context.Context) (context.Context, error) { 21 | method, _ := grpc.Method(ctx) 22 | if _, ok := d.unAuthMethods[method]; ok { 23 | return context.WithValue(ctx, utility.WithOutTag, true), nil 24 | } 25 | token, err := auth.AuthFromMD(ctx, string(utility.TokenContextKey)) 26 | if err != nil { 27 | return ctx, err 28 | } 29 | // TODO check token with your custom auth middleware 30 | //CheckToken(token) 31 | _ = token 32 | return ctx, nil 33 | } 34 | 35 | //AddUnAuthMethod(method string) 36 | 37 | // AddUnAuthMethod add you want to disable auth method here 38 | func (d *Author) AddUnAuthMethod(method string) { 39 | if d.unAuthMethods == nil { 40 | d.unAuthMethods = make(map[string]struct{}) 41 | } 42 | d.unAuthMethods[method] = struct{}{} 43 | } 44 | 45 | // AuthModule is a game auth module 46 | // you can implement your own auth service or auth function 47 | // Auth will check every rpc/http request, 48 | // if you want to disable it for a service, add `utility.WithoutAuth` in struct of your service 49 | // 50 | // type service struct { 51 | // utility.WithoutAuth 52 | // } 53 | // 54 | // or disable it for a method, add the method name by `AddUnAuthMethod` 55 | var AuthModule = fx.Provide( 56 | func( 57 | l *zap.Logger, 58 | ) (out sfx.AuthMiddlewareResult, err error) { 59 | out.AuthMiddleware = &Author{ 60 | unAuthMethods: make(map[string]struct{}), 61 | } 62 | return 63 | }, 64 | ) 65 | -------------------------------------------------------------------------------- /pkg/dfx/game0_client.go: -------------------------------------------------------------------------------- 1 | package dfx 2 | 3 | import ( 4 | "go.uber.org/fx" 5 | "go.uber.org/zap" 6 | 7 | pb "github.com/moke-game/game/api/gen/game0/api" 8 | 9 | "github.com/gstones/moke-kit/server/pkg/sfx" 10 | "github.com/gstones/moke-kit/server/tools" 11 | ) 12 | 13 | type DemoClientParams struct { 14 | fx.In 15 | 16 | Game0Client pb.Game0ServiceClient `name:"Game0Client"` 17 | } 18 | 19 | type DemoClientResult struct { 20 | fx.Out 21 | 22 | Game0Client pb.Game0ServiceClient `name:"Game0Client"` 23 | } 24 | 25 | func NewDemoClient(host string, logger *zap.Logger, sSetting sfx.SecuritySettingsParams) (pb.Game0ServiceClient, error) { 26 | if sSetting.MTLSEnable { 27 | if conn, err := tools.DialWithSecurity( 28 | host, 29 | sSetting.ClientCert, 30 | sSetting.ClientKey, 31 | sSetting.ServerName, 32 | sSetting.ServerCaCert, 33 | ); err != nil { 34 | return nil, err 35 | } else { 36 | return pb.NewGame0ServiceClient(conn), nil 37 | } 38 | } else { 39 | if conn, err := tools.DialInsecure(host); err != nil { 40 | return nil, err 41 | } else { 42 | return pb.NewGame0ServiceClient(conn), nil 43 | } 44 | } 45 | } 46 | 47 | // Game0ClientModule you can inject it to other module 48 | var Game0ClientModule = fx.Provide( 49 | func( 50 | setting SettingsParams, 51 | sSetting sfx.SecuritySettingsParams, 52 | logger *zap.Logger, 53 | ) (out DemoClientResult, err error) { 54 | if cli, e := NewDemoClient(setting.GameUrl, logger, sSetting); e != nil { 55 | err = e 56 | } else { 57 | out.Game0Client = cli 58 | } 59 | return 60 | }, 61 | ) 62 | -------------------------------------------------------------------------------- /pkg/dfx/game0_setting.go: -------------------------------------------------------------------------------- 1 | package dfx 2 | 3 | import ( 4 | "go.uber.org/fx" 5 | 6 | "github.com/gstones/moke-kit/utility" 7 | ) 8 | 9 | // SettingsParams you can customize it as your need 10 | type SettingsParams struct { 11 | fx.In 12 | 13 | GameUrl string `name:"GameUrl"` 14 | DbName string `name:"DbName"` 15 | } 16 | 17 | type SettingsResult struct { 18 | fx.Out 19 | 20 | GameUrl string `name:"GameUrl" envconfig:"GAME_URL" default:"localhost:8081"` 21 | DbName string `name:"DbName" envconfig:"DB_NAME" default:"game"` 22 | } 23 | 24 | func (g *SettingsResult) LoadFromEnv() (err error) { 25 | err = utility.Load(g) 26 | return 27 | } 28 | 29 | // SettingsModule config your app settings 30 | var SettingsModule = fx.Provide( 31 | func() (out SettingsResult, err error) { 32 | err = out.LoadFromEnv() 33 | return 34 | }, 35 | ) 36 | -------------------------------------------------------------------------------- /pkg/modules/game0_module.go: -------------------------------------------------------------------------------- 1 | package modules 2 | 3 | import ( 4 | "go.uber.org/fx" 5 | 6 | "github.com/moke-game/game/internal/services/game0" 7 | 8 | "github.com/moke-game/game/pkg/dfx" 9 | ) 10 | 11 | // GrpcModule grpc service module 12 | // can inject it to any fxmain.Main(), if you want to start a game grpc service 13 | var GrpcModule = fx.Module("grpcService", 14 | dfx.SettingsModule, 15 | dfx.AuthModule, 16 | game0.GrpcService, 17 | ) 18 | 19 | // HttpModule http service module 20 | // can inject it to any fxmain.Main(), if you want to start a game http service 21 | var HttpModule = fx.Module("httpService", 22 | dfx.SettingsModule, 23 | dfx.AuthModule, 24 | game0.GrpcService, 25 | game0.HttpService, 26 | ) 27 | 28 | // TcpModule tcp service module 29 | // can inject it to any fxmain.Main(), if you want to start a game tcp service 30 | var TcpModule = fx.Module("tcpService", 31 | dfx.SettingsModule, 32 | game0.TcpService, 33 | ) 34 | 35 | // AllModule all service module 36 | // can inject it to any fxmain.Main(), if you want to start game all type services 37 | var AllModule = fx.Module("allService", 38 | //dfx.AuthModule, 39 | dfx.SettingsModule, 40 | game0.GrpcService, 41 | game0.HttpService, 42 | game0.TcpService, 43 | ) 44 | 45 | // GrpcClientModule grpc client module 46 | // can inject it to any fxmain.Main(), if you want a game grpc client to rpc game service 47 | var GrpcClientModule = fx.Module("grpcClient", 48 | dfx.SettingsModule, 49 | dfx.Game0ClientModule, 50 | ) 51 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | # Load Test 2 | Load test with [k6](https://grafana.com/docs/k6/latest/) -------------------------------------------------------------------------------- /tests/common/common.js: -------------------------------------------------------------------------------- 1 | export const makeParams = (token) => { 2 | return { 3 | metadata: { 4 | 'x-my-header': 'k6test', 5 | 'x-my-header-bin': new Uint8Array([1, 2, 3]), 6 | 'authorization': "bearer " + token, 7 | }, 8 | tags: {k6test: 'yes'}, 9 | }; 10 | } -------------------------------------------------------------------------------- /tests/game0/game0-k6.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package game.pb; 4 | option go_package = "game/api;pb"; 5 | 6 | service DemoService { 7 | rpc Hi (HiRequest) returns (HiResponse) {}; 8 | rpc Watch(WatchRequest) returns (stream WatchResponse) {}; 9 | } 10 | 11 | message HiRequest { 12 | string uid = 1; 13 | string message = 2; 14 | } 15 | 16 | message HiResponse { 17 | string message = 1; 18 | } 19 | 20 | message WatchRequest { 21 | string uid = 1; 22 | string topic = 2; 23 | } 24 | 25 | message WatchResponse { 26 | string message = 1; 27 | } 28 | -------------------------------------------------------------------------------- /tests/game0/game0.js: -------------------------------------------------------------------------------- 1 | import {Client, StatusOK} from 'k6/net/grpc'; 2 | import {check, sleep} from 'k6'; 3 | import {makeParams} from "../common/common.js"; 4 | 5 | const client = new Client(); 6 | client.load(['./'], 'game-k6.proto'); 7 | 8 | const GRPC_ADDR = __ENV.SERVER_HOST || '127.0.0.1:8081'; 9 | 10 | export default function () { 11 | client.connect(GRPC_ADDR, { 12 | plaintext: true 13 | }); 14 | const data = { 15 | uid: 'test', 16 | message: 'hello', 17 | }; 18 | const params = makeParams("test"); 19 | let response = client.invoke('game.pb.DemoService/Hi', data,params); 20 | console.log(response); 21 | check(response, { 22 | 'status is OK': (r) => r && r.status === StatusOK, 23 | }); 24 | client.close(); 25 | sleep(1); 26 | } 27 | 28 | 29 | --------------------------------------------------------------------------------