Skip to content

Instantly share code, notes, and snippets.

@olivernadj
Created May 9, 2019 10:13
Show Gist options
  • Save olivernadj/7e1cdc2f313863b8e88937c4819b627f to your computer and use it in GitHub Desktop.
Save olivernadj/7e1cdc2f313863b8e88937c4819b627f to your computer and use it in GitHub Desktop.
Week 3.3 Assignment: Multiplayer Simon Says - A Game using gRPC and Kubernetes
tags
Golang

Week 3.3 Assignment: Multiplayer Simon Says - A Game using gRPC and Kubernetes.

Implement a Simon Says game with gRPC streaming and create a deploy script for Kibernetes

Pre-request

You must have an access to a Kubernetes cluster with a working kubecli client. The cluster can be in the Cloud or running on your machine, e.g.: minikube. Up to you.

Install protobuf-compiler - You can download precompiled binaries of protoc for all platforms right on the ProtoBuf GitHub releases page. https://github.com/protocolbuffers/protobuf/releases/

Golang packages: go get -u github.com/golang/protobuf/protoc-gen-go go get -u github.com/golang/protobuf/proto go get -u google.golang.org/grpc

The contract

The following .proto specification is fix anything else is up to your imagination.

syntax = "proto3";

package simonsays;
option go_package = "symonsayspb"
/*
    The Simon Says service.
    Allows you to actually play the game.
*/
service SimonSays {
    /*
    Game process is the following:

    A Join Request should be sent to the game. This tells it
    to join a game (or start a new one if one isn't already waiting on a game).

    The Response stream will send through a BEGIN Response.State to let you know that
    the Game has been started.

    When the player recieves a START_TURN response, the server can take your input for the turn.

    When the player recieves a STOP_TURN response, the serer is no longer taking input for the turn.

    A WIN state says you won the game. A LOSE state means that you got an input wrong, and have lost.

    To send input, send a Request with an event type of Color.

    When you recieve a Response of type Color, then light up that colour.
    */
    rpc Game(stream Request) returns (stream Response) {}
}

message Request {
    //A Player of the Simon says game.
    message Player {
        string id = 1;
    }

    oneof event {
        Player join = 1;
        Color press = 2;
    }
}

message Response {
    enum State {
        BEGIN = 0;
        START_TURN = 1;
        STOP_TURN = 2;
        WIN = 3;
        LOSE = 4;
    }
    oneof event {
        State turn = 1;
        Color lightup = 2;
    }
}

enum Color {
    RED  = 0;
    GREEN = 1;
    YELLOW = 2;
    BLUE = 3;
}

Little guide for start

Create your project under proper go path

Init a git repo under the same path you will use for github.com

Eg.:

~$ cd ~/go/src/github.com/olivernadj
olivernadj$ mkdir -p simonsays/simonsays_client
olivernadj$ cd simonsays
simonsays$ mkdir simonsays_server
simonsays$ mkdir simonsayspb
simonsays$ touch simonsayspb/simonsays.proto

simonsays$ tree
.
├── simonsays_client
├── simonsayspb
│   └── simonsays.proto
└── simonsays_server

Generate your gRPC code

simonsays$ protoc -I simonsayspb/ simonsayspb/simonsays.proto --go_out=plugins=grpc:simonsayspb

If all good you should have a new file simonsays.pb.go file under simonsayspb/

Scaffolding

simonsays_client/client.go

code

simonsays_server/server.go

package main

import (
	"fmt"
	symonsayspb "github.com/olivernadj/simonsays/simonsayspb"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"log"
	"net"
)

type server struct{}

func main() {
	fmt.Println("Simon says hello")
	lis, err := net.Listen("tcp", "0.0.0.0:50051")
	if err != nil {
		log.Fatalf("Failed to listen: %v", err)
	}
	s := grpc.NewServer()
	symonsayspb.RegisterSimonSaysServer(s, &server{})
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

func (s *server) Game(stream symonsayspb.SimonSays_GameServer) error {
	return status.Errorf(codes.Unimplemented, "method Game not implemented")
}

Try to run

Start the server in a separate console

simonsays$ go run simonsays_server/server.go 
Simon says hello server

# this message appear only if a client request has inicialised 
Game function was invoked with a streaming request

Start the clien in a separate console

simonsays$ go run simonsays_client/client.go 
Simon says hello client
Starting to do a BiDi Streaming RPC...
Sending message: join:<id:"John" > 
Received: turn:BEGIN, light:UNSPECIFIED
Sending message: join:<id:"Jane" > 
Received: turn:BEGIN, light:UNSPECIFIED
Sending message: press:BLUE 
Received: turn:UNSPECIFIED, light:BLUE
Sending message: press:GREEN 
Received: turn:UNSPECIFIED, light:GREEN

Troubleshooting

https://github.com/olivernadj/simonsays

Implement business logic requested in .proto

Implement business logic requested in .proto and create Kubernetes deployment configs and script.

The force be with you!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment