Skip to content

feat: Sample matchmaker and gameclient #15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

lwaddicor
Copy link
Contributor

@lwaddicor lwaddicor commented Jan 17, 2022

This adds a simple matchmaker and a simple game client example.
It is designed to get a simple end to end running and not as an example of a production matchmaker. For this the unity matchmaker is recommended

@lwaddicor lwaddicor requested a review from a team as a code owner January 17, 2022 09:58

This is a very simple game client, designed to be used with the simple-matchmaker.

This app is designed to provide the simplest complete example of using the Multiplay. It uses a very simple matchmaker
Copy link
Contributor

@eth0net eth0net Jan 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This app is designed to provide the simplest complete example of using the Multiplay. It uses a very simple matchmaker
This app is designed to provide the simplest complete example of using the [Unity Multiplay platform](https://unity.com/products/multiplay). It uses [simple matchmaker](../simple-matchmaker)

or may temporarily set this for your terminal session as shown below.

Windows Example:
set MP_ACCESS_KEY=9ff2af788834439b83ae6692f34ea5e5
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are randomly generated

}

cfg.MatchSize = *matchSize
mm := simplematchmaker.NewSimpleMatchmaker(cfg, backendClient)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

backendClient is potentially nil here as I only see backendClient being set in one of the if else branches.

)

var (
//go:embed assets/help_en.txt
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the use of go embed 😃

@lwaddicor
Copy link
Contributor Author

lwaddicor commented Jan 17, 2022

Test evidence

This may need a few more cycles to really nail down. Just a sample of the matchmaker and client running against the linux dev fleet which appears to be running a http server.

Game Client 1:

Starting to find a match
Asking matchmaker about match for us (playerid: c9a6b8ff-5665-403c-9382-ba6ddf273165)
Matchmaker did not have a match ready
Asking matchmaker about match for us (playerid: c9a6b8ff-5665-403c-9382-ba6ddf273165)
Matchmaker did not have a match ready
Asking matchmaker about match for us (playerid: c9a6b8ff-5665-403c-9382-ba6ddf273165)
Matchmaker did not have a match ready
Asking matchmaker about match for us (playerid: c9a6b8ff-5665-403c-9382-ba6ddf273165)
Matchmaker found us a match
Connecting to match:
 - Allocation UUID: 03bc0ac3-0a46-4cf0-803e-2d89a3dce4f9:37315
 - Address: 109.169.15.15:37315
 - Other players:
 - - 4554326e-ca56-4f7c-9088-6cfecd96ede4 - 127.0.0.1:50998
 - - c9a6b8ff-5665-403c-9382-ba6ddf273165 - 127.0.0.1:51008
HTTP/1.1 400 Bad Request
Content-Type: text/plain; charset=utf-8
Connection: close

400 Bad Request
Starting to find a match
Asking matchmaker about match for us (playerid: 4554326e-ca56-4f7c-9088-6cfecd96ede4)
Matchmaker did not have a match ready
Asking matchmaker about match for us (playerid: 4554326e-ca56-4f7c-9088-6cfecd96ede4)
Matchmaker did not have a match ready
Asking matchmaker about match for us (playerid: 4554326e-ca56-4f7c-9088-6cfecd96ede4)
Matchmaker did not have a match ready
Asking matchmaker about match for us (playerid: 4554326e-ca56-4f7c-9088-6cfecd96ede4)
Matchmaker did not have a match ready
Asking matchmaker about match for us (playerid: 4554326e-ca56-4f7c-9088-6cfecd96ede4)
Matchmaker did not have a match ready
Asking matchmaker about match for us (playerid: 4554326e-ca56-4f7c-9088-6cfecd96ede4)
Matchmaker found us a match
Connecting to match:
 - Allocation UUID: 03bc0ac3-0a46-4cf0-803e-2d89a3dce4f9:37315
 - Address: 109.169.15.15:37315
 - Other players:
 - - 4554326e-ca56-4f7c-9088-6cfecd96ede4 - 127.0.0.1:50998
 - - c9a6b8ff-5665-403c-9382-ba6ddf273165 - 127.0.0.1:51008
HTTP/1.1 400 Bad Request
Content-Type: text/plain; charset=utf-8
Connection: close

400 Bad Request

The current output from the matchmaker, which

Players waiting: 0, Match size needed: 2
Players waiting: 0, Match size needed: 2
Players waiting: 0, Match size needed: 2
Players waiting: 0, Match size needed: 2
Players waiting: 0, Match size needed: 2
Handle player
Adding new unmatched player
Players waiting: 1, Match size needed: 2
Handle player
Player 4554326e-ca56-4f7c-9088-6cfecd96ede4 asked about match status, but it was not ready.
Player searching: 4554326e-ca56-4f7c-9088-6cfecd96ede4
Players waiting: 1, Match size needed: 2
Handle player
Player 4554326e-ca56-4f7c-9088-6cfecd96ede4 asked about match status, but it was not ready.
Player searching: 4554326e-ca56-4f7c-9088-6cfecd96ede4
Players waiting: 1, Match size needed: 2
Handle player
Adding new unmatched player
Handle player
Player 4554326e-ca56-4f7c-9088-6cfecd96ede4 asked about match status, but it was not ready.
Player searching: 4554326e-ca56-4f7c-9088-6cfecd96ede4
Players waiting: 2, Match size needed: 2
About to allocate for match
Handle player
Adding new unmatched player
Adding new unmatched player
Players waiting: 0, Match size needed: 2
Handle player
Adding new unmatched player
Got allocation: 109.169.15.15:37315

- Simple-game-client app starts
- Creates a Player UUID unique for the game client run.
- Repeatedly call the simple-matchmaker `/player` endpoint with the player UUID
- Eventually the endpoint will return an IP and Port to connecto
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Eventually the endpoint will return an IP and Port to connecto
- Eventually, the endpoint will return an IP and Port to connect to

Comment on lines +12 to +13
authService = "cf"
authRegion = "eu-west-1"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these used anywhere? I feel unused AWS4 auth vibes. :)

// setAllocationMatchInfo associates an allocation with a match.
func (m *SimpleMatchmaker) setAllocationMatchInfo(allocationUUID string, matchInfo matchmaker.MatchInfo) {
m.matchesMtx.Lock()
m.matchesMtx.Unlock()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing defer?

Suggested change
m.matchesMtx.Unlock()
defer m.matchesMtx.Unlock()

return nil
}

// handleConnection reflects and lines sent to it.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo?

Suggested change
// handleConnection reflects and lines sent to it.
// handleConnection reflects any lines sent to it.

Copy link
Contributor

@danmrichards danmrichards left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very cool, Lewis!

Just a few nitpicks and tidy ups before we make this public

}

fmt.Printf("Connecting to match:\n")
fmt.Printf(" - Allocation UUID: %s:%d\n", matchInfo.AllocationUUID)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too many format verbs there

Suggested change
fmt.Printf(" - Allocation UUID: %s:%d\n", matchInfo.AllocationUUID)
fmt.Printf(" - Allocation UUID: %s\n", matchInfo.AllocationUUID)

fmt.Printf(" - - %s - %s\n", pl.PlayerUUID, pl.IP)
}

tcpAddr, err := net.ResolveTCPAddr("tcp4", fmt.Sprintf("%s:%d", matchInfo.IP, matchInfo.Port))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick, worth using net.JoinHostPort instead for future support of IPv6?


var (
// AllocationNotFound is returned when an allocation is not found.
AllocationNotFound = errors.New("allocation not found")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick; sentinel errors like this should be named in the pattern ErrXXXX

Suggested change
AllocationNotFound = errors.New("allocation not found")
ErrAllocationNotFound = errors.New("allocation not found")

Comment on lines +11 to +14
const (
authService = "cf"
authRegion = "eu-west-1"
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These appear to be unused

Comment on lines 10 to 13
//"github.com/caarlos0/env"
//"github.com/google/uuid"
//"github.com/gorilla/mux"
//"github.com/lwaddicor/hackweekmatchmaker/mpclient"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't need these any more I assume?

}
content, err := ioutil.ReadAll(conn)
if err != nil && !os.IsTimeout(err) {
fmt.Printf("could not send to server: giving up: %s\n", err.Error())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be receive from server?

Comment on lines +4 to +5
To use multiplay, most games need a matchmaker which groups players.
For the most streamlined experience we recommend that you use the unity matchmaker to do this, but you may use an
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
To use multiplay, most games need a matchmaker which groups players.
For the most streamlined experience we recommend that you use the unity matchmaker to do this, but you may use an
To use Multiplay, most games need a matchmaker which groups players.
For the most streamlined experience we recommend that you use the Unity Matchmaker to do this, but you may use an

Should probably capitalise company and product names

alternative or your own custom implementation.

This sample provides an incredibly simple matchmaker to get you started locally. It will group incoming players
together and when enough have joined it will request a match from either its multiplay mock, or the real multiplay API.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
together and when enough have joined it will request a match from either its multiplay mock, or the real multiplay API.
together and when enough have joined it will request a match from either its Multiplay mock, or the real Multiplay API.

Same as above

set MP_ACCESS_KEY=9ff2af788834439b83ae6692f34ea5e5
set MP_SECRET_KEY=6323354e200a451dba319bc1b98ade59

For example on UNIX Style OS (OSX, Linux, BSD):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
For example on UNIX Style OS (OSX, Linux, BSD):
For example on UNIX Style OS (macOS, Linux, BSD):

OS X became macOS a few years ago

Comment on lines +3 to +4
This is a temporary package which provides multiplay API calls. This is a temporary package until the official
multiplay SDK library becomes available.
Copy link
Contributor

@eth0net eth0net Jan 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This is a temporary package which provides multiplay API calls. This is a temporary package until the official
multiplay SDK library becomes available.
This is a temporary package which provides Multiplay API calls. This is a temporary package until the official
Multiplay SDK library becomes available.

Product name

}

if cfg.SecretKey == "" {
return nil, fmt.Errorf("access key is empty")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return nil, fmt.Errorf("access key is empty")
return nil, fmt.Errorf("secret key is empty")

Comment on lines +33 to +36
fmt.Println("Fleet: ", cfg.FleetID)
fmt.Println("RegionID: ", cfg.RegionID)
fmt.Println("BuildConfig(Profile): ", cfg.BuildConfig)
fmt.Println("UUID: ", allocUUID)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fmt.Println("Fleet: ", cfg.FleetID)
fmt.Println("RegionID: ", cfg.RegionID)
fmt.Println("BuildConfig(Profile): ", cfg.BuildConfig)
fmt.Println("UUID: ", allocUUID)
fmt.Println("FleetID: ", cfg.FleetID)
fmt.Println("RegionID: ", cfg.RegionID)
fmt.Println("BuildConfigID(ProfileID): ", cfg.BuildConfig)
fmt.Println("UUID: ", allocUUID)

These are all IDs, so I'd suggest keeping the names aligned

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fmt.Println("Fleet: ", cfg.FleetID)
fmt.Println("RegionID: ", cfg.RegionID)
fmt.Println("BuildConfig(Profile): ", cfg.BuildConfig)
fmt.Println("UUID: ", allocUUID)
fmt.Println("Fleet: ", cfg.FleetID)
fmt.Println("Region: ", cfg.RegionID)
fmt.Println("BuildConfig(Profile): ", cfg.BuildConfig)
fmt.Println("Allocation: ", allocUUID)

Alternatively, drop the ID suffix

continue
}

// Spawn a goroutine to wait for this allocation to be processed be multiplay.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Spawn a goroutine to wait for this allocation to be processed be multiplay.
// Spawn a goroutine to wait for this allocation to be processed by multiplay.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants