Skip to content

Commit 17c0cb7

Browse files
Tri-Force Heroes NEX Server
0 parents  commit 17c0cb7

24 files changed

+1469
-0
lines changed

.gitignore

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# If you prefer the allow list template instead of the deny list, see community template:
2+
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
3+
#
4+
# Binaries for programs and plugins
5+
*.exe
6+
*.exe~
7+
*.dll
8+
*.so
9+
*.dylib
10+
11+
# Test binary, built with `go test -c`
12+
*.test
13+
14+
# Output of the go coverage tool, specifically when used with LiteIDE
15+
*.out
16+
17+
# Dependency directories (remove the comment below to include it)
18+
# vendor/
19+
20+
# Go workspace file
21+
go.work
22+
go.work.sum
23+
24+
# custom
25+
.vscode
26+
.env
27+
build
28+
log
29+
*.pem
30+
*.key

LICENSE

+661
Large diffs are not rendered by default.

Makefile

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# TODO - Assumes a UNIX-like OS
2+
3+
RED := $(shell tput setaf 1)
4+
BLUE := $(shell tput setaf 4)
5+
CYAN := $(shell tput setaf 14)
6+
ORANGE := $(shell tput setaf 202)
7+
YELLOW := $(shell tput setaf 214)
8+
RESET := $(shell tput sgr0)
9+
10+
ifeq ($(shell which go),)
11+
# TODO - Read contents from .git folder instead?
12+
$(error "$(RED)go command not found. Install go to continue $(BLUE)https://go.dev/doc/install$(RESET)")
13+
endif
14+
15+
ifneq ($(wildcard .git),)
16+
# * .git folder exists, build server build string from repo info
17+
ifeq ($(shell which git),)
18+
# TODO - Read contents from .git folder instead?
19+
$(error "$(RED)git command not found. Install git to continue $(ORANGE)https://git-scm.com/downloads$(RESET)")
20+
endif
21+
$(info "$(CYAN)Building server build string from repository info$(RESET)")
22+
# * Build server build string from repo info
23+
BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
24+
REMOTE_ORIGIN := $(shell git config --get remote.origin.url)
25+
26+
# * Handle multiple origin URL formats
27+
HTTPS_PREFIX_CHECK := $(shell echo $(REMOTE_ORIGIN) | head -c 8)
28+
HTTP_PREFIX_CHECK := $(shell echo $(REMOTE_ORIGIN) | head -c 7)
29+
GIT@_PREFIX_CHECK := $(shell echo $(REMOTE_ORIGIN) | head -c 4)
30+
31+
ifeq ($(HTTPS_PREFIX_CHECK), https://)
32+
REMOTE_PATH := $(shell echo $(REMOTE_ORIGIN) | cut -d/ -f4-)
33+
else ifeq ($(HTTP_PREFIX_CHECK), http://)
34+
REMOTE_PATH := $(shell echo $(REMOTE_ORIGIN) | cut -d/ -f4-)
35+
else ifeq ($(GIT@_PREFIX_CHECK), git@)
36+
REMOTE_PATH := $(shell echo $(REMOTE_ORIGIN) | cut -d: -f2-)
37+
else
38+
REMOTE_PATH := $(shell echo $(REMOTE_ORIGIN) | cut -d/ -f2-)
39+
endif
40+
41+
HASH := $(shell git rev-parse --short HEAD)
42+
SERVER_BUILD := $(BRANCH):$(REMOTE_PATH)@$(HASH)
43+
44+
else
45+
# * .git folder not present, assume downloaded from zip file and just use folder name
46+
$(info "$(CYAN)git repository not found. Building server build string from folder name$(RESET)")
47+
SERVER_BUILD := $(notdir $(CURDIR))
48+
endif
49+
50+
# * Final build string
51+
DATE_TIME := $(shell date --iso=seconds)
52+
BUILD_STRING := $(SERVER_BUILD), $(DATE_TIME)
53+
54+
all:
55+
ifeq ($(wildcard .env),)
56+
$(warning "$(YELLOW).env file not found, environment variables may not be populated correctly$(RESET)")
57+
endif
58+
go get -u
59+
go mod tidy
60+
go build -ldflags "-X 'main.serverBuildString=$(BUILD_STRING)'" -o ./build/$(notdir $(CURDIR))

README.md

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Tri-Force Heroes (3DS) replacement server
2+
Includes both the authentication and secure servers
3+
4+
## Compiling
5+
6+
### Setup
7+
Install [Go](https://go.dev/doc/install) and [git](https://git-scm.com/downloads), then clone and enter the repository
8+
9+
```bash
10+
$ git clone https://github.com/PretendoNetwork/tri-force-heroes
11+
$ cd tri-force-heroes
12+
```
13+
14+
### Compiling using `go`
15+
To compile using Go, `go get` the required modules and then `go build` to your desired location. You may also want to tidy the go modules, though this is optional
16+
17+
```bash
18+
$ go get -u
19+
$ go mod tidy
20+
$ go build -o build/TFH
21+
```
22+
23+
The server is now built to `build/TFH`
24+
25+
When compiling with only Go, the authentication servers build string is not automatically set. This should not cause any issues with gameplay, but it means that the server build will not be visible in any packet dumps or logs a title may produce
26+
27+
To compile the servers with the authentication server build string, add `-ldflags "-X 'main.serverBuildString=BUILD_STRING_HERE'"` to the build command, or use `make` to compile the server
28+
29+
### Compiling using `make`
30+
Compiling using `make` will read the local `.git` directory to create a dynamic authentication server build string, based on your repositories remote origin and current commit. It will also use the current folders name as the executables name
31+
32+
Install `make` onto your system (this varies by OS), and run `make` while inside the repository
33+
34+
```bash
35+
$ make
36+
```
37+
38+
The server is now built to `build/tri-force-heroes` with the authentication server build string already set
39+
40+
## Configuration
41+
All configuration options are handled via environment variables
42+
43+
`.env` files are supported
44+
45+
| Name | Description | Required |
46+
|-----------------------------------------|------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------|
47+
| `PN_TFH_POSTGRES_URI` | Fully qualified URI to your Postgres server (Example `postgres://username:password@localhost/TFH?sslmode=disable`) | Yes |
48+
| `PN_TFH_KERBEROS_PASSWORD` | Password used as part of the internal server data in Kerberos tickets | No (Default password `password` will be used) |
49+
| `PN_TFH_AUTHENTICATION_SERVER_PORT` | Port for the authentication server | Yes |
50+
| `PN_TFH_SECURE_SERVER_HOST` | Host name for the secure server (should point to the same address as the authentication server) | Yes |
51+
| `PN_TFH_SECURE_SERVER_PORT` | Port for the secure server | Yes |
52+
| `PN_TFH_ACCOUNT_GRPC_HOST` | Host name for your account server gRPC service | Yes |
53+
| `PN_TFH_ACCOUNT_GRPC_PORT` | Port for your account server gRPC service | Yes |
54+
| `PN_TFH_ACCOUNT_GRPC_API_KEY` | API key for your account server gRPC service | No (Assumed to be an open gRPC API) |

database/connect_postgres.go

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package database
2+
3+
import (
4+
"database/sql"
5+
"os"
6+
7+
_ "github.com/lib/pq"
8+
9+
"github.com/PretendoNetwork/tri-force-heroes/globals"
10+
)
11+
12+
var Postgres *sql.DB
13+
14+
func ConnectPostgres() {
15+
var err error
16+
17+
Postgres, err = sql.Open("postgres", os.Getenv("PN_TFH_POSTGRES_URI"))
18+
if err != nil {
19+
globals.Logger.Critical(err.Error())
20+
}
21+
22+
globals.Logger.Success("Connected to Postgres!")
23+
24+
initPostgres()
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package database
2+
3+
import (
4+
"database/sql"
5+
6+
ranking_types "github.com/PretendoNetwork/nex-protocols-go/ranking/types"
7+
"github.com/PretendoNetwork/tri-force-heroes/globals"
8+
"github.com/PretendoNetwork/tri-force-heroes/types"
9+
)
10+
11+
func GetRankingsByCategoryAndRankingOrderParam(category uint32, rankingOrderParam *ranking_types.RankingOrderParam) (error, []*ranking_types.RankingRankData) {
12+
rankings := make([]*ranking_types.RankingRankData, 0, rankingOrderParam.Length)
13+
14+
rows, err := Postgres.Query(`
15+
SELECT
16+
owner_pid,
17+
score,
18+
groups,
19+
param,
20+
common_data
21+
FROM rankings WHERE category=$1 ORDER BY score DESC LIMIT $2 OFFSET $3`,
22+
category,
23+
rankingOrderParam.Length,
24+
rankingOrderParam.Offset,
25+
)
26+
if err != nil {
27+
return err, rankings
28+
}
29+
30+
row := 1
31+
for rows.Next() {
32+
rankingRankData := ranking_types.NewRankingRankData()
33+
rankingRankData.UniqueID = 0
34+
rankingRankData.Order = uint32(row)
35+
rankingRankData.Category = category
36+
37+
// * A custom type is needed because
38+
// * Postgres doesn't support scanning
39+
// * uint8 slices by default
40+
var groups types.PQUInt8Array
41+
42+
err := rows.Scan(
43+
&rankingRankData.PrincipalID,
44+
&rankingRankData.Score,
45+
&groups,
46+
&rankingRankData.Param,
47+
&rankingRankData.CommonData,
48+
)
49+
50+
if err != nil && err != sql.ErrNoRows {
51+
globals.Logger.Critical(err.Error())
52+
}
53+
54+
if err == nil {
55+
rankingRankData.Groups = groups.Value
56+
rankings = append(rankings, rankingRankData)
57+
58+
row += 1
59+
}
60+
}
61+
62+
return nil, rankings
63+
}
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package database
2+
3+
func GetTotalRankingsByCategory(category uint32) (error, uint32) {
4+
var total uint32
5+
6+
err := Postgres.QueryRow(`SELECT COUNT(*) FROM rankings WHERE category=$1`, category).Scan(&total)
7+
if err != nil {
8+
return err, 0
9+
}
10+
11+
return nil, total
12+
}

database/init_postgres.go

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package database
2+
3+
import "github.com/PretendoNetwork/tri-force-heroes/globals"
4+
5+
func initPostgres() {
6+
var err error
7+
8+
_, err = Postgres.Exec(`CREATE TABLE IF NOT EXISTS rankings (
9+
id bigserial PRIMARY KEY,
10+
owner_pid integer,
11+
category integer,
12+
score integer,
13+
order_by integer,
14+
update_mode integer,
15+
groups integer[],
16+
param bigint,
17+
common_data bytea,
18+
created_at bigint
19+
)`)
20+
if err != nil {
21+
globals.Logger.Critical(err.Error())
22+
return
23+
}
24+
25+
globals.Logger.Success("Postgres tables created")
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package database
2+
3+
import (
4+
"time"
5+
6+
ranking_types "github.com/PretendoNetwork/nex-protocols-go/ranking/types"
7+
"github.com/lib/pq"
8+
)
9+
10+
func InsertRankingByPIDAndRankingScoreData(pid uint32, rankingScoreData *ranking_types.RankingScoreData) error {
11+
now := time.Now().UnixNano()
12+
13+
_, err := Postgres.Exec(`
14+
INSERT INTO rankings (
15+
owner_pid,
16+
category,
17+
score,
18+
order_by,
19+
update_mode,
20+
groups,
21+
param,
22+
common_data,
23+
created_at
24+
)
25+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
26+
pid,
27+
rankingScoreData.Category,
28+
rankingScoreData.Score,
29+
rankingScoreData.OrderBy,
30+
rankingScoreData.UpdateMode,
31+
pq.Array(rankingScoreData.Groups),
32+
rankingScoreData.Param,
33+
make([]byte, 0),
34+
now,
35+
)
36+
37+
return err
38+
}

globals/globals.go

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package globals
2+
3+
import (
4+
pb "github.com/PretendoNetwork/grpc-go/account"
5+
"github.com/PretendoNetwork/nex-go"
6+
"github.com/PretendoNetwork/plogger-go"
7+
"google.golang.org/grpc"
8+
"google.golang.org/grpc/metadata"
9+
)
10+
11+
var Logger *plogger.Logger
12+
var KerberosPassword = "password" // * Default password
13+
var AuthenticationServer *nex.Server
14+
var SecureServer *nex.Server
15+
var GRPCAccountClientConnection *grpc.ClientConn
16+
var GRPCAccountClient pb.AccountClient
17+
var GRPCAccountCommonMetadata metadata.MD

globals/password_from_pid.go

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package globals
2+
3+
import (
4+
"context"
5+
6+
pb "github.com/PretendoNetwork/grpc-go/account"
7+
"github.com/PretendoNetwork/nex-go"
8+
"github.com/PretendoNetwork/nex-protocols-go/globals"
9+
"google.golang.org/grpc/metadata"
10+
)
11+
12+
func PasswordFromPID(pid uint32) (string, uint32) {
13+
ctx := metadata.NewOutgoingContext(context.Background(), GRPCAccountCommonMetadata)
14+
15+
response, err := GRPCAccountClient.GetNEXPassword(ctx, &pb.GetNEXPasswordRequest{Pid: pid})
16+
if err != nil {
17+
globals.Logger.Error(err.Error())
18+
return "", nex.Errors.RendezVous.InvalidUsername
19+
}
20+
21+
return response.Password, 0
22+
}

globals/subscription.go

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package globals
2+
3+
var Timeline map[uint32][]uint8

globals/util.go

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package globals

go.mod

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
module github.com/PretendoNetwork/tri-force-heroes
2+
3+
go 1.19
4+
5+
require (
6+
github.com/PretendoNetwork/grpc-go v1.0.2
7+
github.com/PretendoNetwork/nex-go v1.0.41
8+
github.com/PretendoNetwork/nex-protocols-common-go v1.0.28
9+
github.com/PretendoNetwork/nex-protocols-go v1.0.55
10+
github.com/PretendoNetwork/plogger-go v1.0.4
11+
github.com/joho/godotenv v1.5.1
12+
github.com/lib/pq v1.10.9
13+
google.golang.org/grpc v1.58.3
14+
)
15+
16+
require (
17+
github.com/fatih/color v1.15.0 // indirect
18+
github.com/golang/protobuf v1.5.3 // indirect
19+
github.com/jwalton/go-supportscolor v1.2.0 // indirect
20+
github.com/mattn/go-colorable v0.1.13 // indirect
21+
github.com/mattn/go-isatty v0.0.19 // indirect
22+
github.com/superwhiskers/crunch/v3 v3.5.7 // indirect
23+
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
24+
golang.org/x/mod v0.13.0 // indirect
25+
golang.org/x/net v0.17.0 // indirect
26+
golang.org/x/sys v0.13.0 // indirect
27+
golang.org/x/term v0.13.0 // indirect
28+
golang.org/x/text v0.13.0 // indirect
29+
google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect
30+
google.golang.org/protobuf v1.31.0 // indirect
31+
)

0 commit comments

Comments
 (0)