Skip to content
This repository has been archived by the owner on Aug 20, 2022. It is now read-only.

Commit

Permalink
Added Protocol v2 for convenience
Browse files Browse the repository at this point in the history
  • Loading branch information
yahiaetman committed Dec 13, 2019
1 parent 659f885 commit cc97238
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 9 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ After running the server, run 2 clients then choose the clients to join the game

## How to use the Console Client

Run: `yarn console:client [name] [address=ws://localhost:8080]`. If the client and server are on the same device, you can use the default host (`localhost`). Otherwise, you need to find the Server IP by running `ipconfig` on the host machine.
Run: `yarn console:client [name] [address=ws://localhost:8080] [protocol]`. If the client and server are on the same device, you can use the default host (`localhost`). Otherwise, you need to find the Server IP by running `ipconfig` on the host machine. `protocol` is an optional argument to determine the protocol version requested by the client. The supported protocols are: `v1` (default) and `v2`.

The client can play their turn using on of the following commands:

Expand Down
Binary file modified docs/protocol.pdf
Binary file not shown.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "go-server",
"version": "0.0.2",
"version": "0.0.3",
"description": "Go Server is a 2-Player Websockets Go Judging Server.",
"main": "public/main/main.js",
"repository": "https://github.com/yahiaetman/Go-Server.git",
Expand Down
4 changes: 4 additions & 0 deletions src/common/go.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ export default class GoGame {
return state;
}

public get StateHistory(): GameState[] {
return _.map(this.history, (entry)=>_.cloneDeep(entry.state));
}

public get BoardSize(): number {
return this.history[this.history.length-1].state.board.length;
}
Expand Down
4 changes: 3 additions & 1 deletion src/examples/console-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type ClientEvent = {

const name = process.argv[2] ?? `Client-${process.pid}`; // Get the user name from the command line arguments if defined (default: 'client-' + process-id)
const url = process.argv[3] ?? 'ws://localhost:8080'; // Get the websocket url from the command line arguments if defined (default: ws://localhost:8080)
const protocol = process.argv[4] ?? null; // Get the protocol version requested by the client (Note: this is ignored by the client code and is added only for debugging purposes)

const game = new GoGame(); // Create a go game to track the game state

Expand Down Expand Up @@ -152,7 +153,8 @@ function processEvent(event: ClientEvent){
if(event.type == "MESSAGE"){ // If this is a server message
switch(event.message.type){
case "NAME": // And the message type is NAME
socket.send(JSON.stringify({type:"NAME", name:name})); // We reply with our name
let protocolFragment = protocol==null?{}:{protocol:protocol}
socket.send(JSON.stringify({type:"NAME", name:name, ...protocolFragment})); // We reply with our name
state = ClientState.READY; // Then go to ready
console.log("Client is ready to play");
break;
Expand Down
6 changes: 4 additions & 2 deletions src/examples/console-silly-agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ if(isMainThread){
};

const name = process.argv[2] ?? `Client-${process.pid}`;
const url = process.argv[3] ?? 'ws://localhost:8080'
const url = process.argv[3] ?? 'ws://localhost:8080';
const protocol = process.argv[4] ?? null;

const game = new GoGame();

Expand Down Expand Up @@ -108,7 +109,8 @@ if(isMainThread){
if(event.type == "MESSAGE"){
switch(event.message.type){
case "NAME":
socket.send(JSON.stringify({type:"NAME", name:name}));
let protocolFragment = protocol==null?{}:{protocol:protocol}
socket.send(JSON.stringify({type:"NAME", name:name, ...protocolFragment}));
state = ClientState.READY;
console.log("Client is ready to play");
break;
Expand Down
31 changes: 28 additions & 3 deletions src/main/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,21 @@ enum ServerState {
IDLE
};

enum Protocol {
v1="v1",
v2="v2"
};

function parseProtocol(name: string): Protocol | undefined {
name = name.toLowerCase();
return _.find(Protocol, protocol => Protocol[protocol] === name);
}

interface Client {
id: number,
name: string,
address: string,
protocol: Protocol,
socket: WebSocket,
ready: boolean,
alive: boolean,
Expand Down Expand Up @@ -114,6 +125,7 @@ export class Server {
id: Server.generateID(),
name: "",
address: request.connection.remoteAddress??"",
protocol: Protocol.v1,
socket: socket,
alive: true,
ready: false,
Expand All @@ -134,11 +146,17 @@ export class Server {
if(message.type == 'MOVE'){
this.processEvent({ type:"MESSAGE", client: client, message: message });
} else {
this.logger?.error(`Unexpected ${message.type} message from ${client.name} (${client.address})`);
this.logger?.error(`Unexpected ${message.type} message from ${client.name}@${client.address}`);
}
} else {
if(message.type == 'NAME'){
client.name = message.name;
let protocol = parseProtocol(message.protocol);
if(protocol){
client.protocol = message.protocol as Protocol;
} else {
this.logger?.error(`Unknown protocol "${message.protocol}" from ${client.name}@${client.address}, defaulting to "v1"`);
}
client.ready = true;
this.clients.push(client);
this.processEvent({type:"CONNECT", client: client});
Expand Down Expand Up @@ -249,7 +267,7 @@ export class Server {
if(this.state == ServerState.INIT){
switch(event.type){
case "CONNECT":{
this.logger?.info(`Welcome, ${event.client.name}@${event.client.address}`);
this.logger?.info(`Welcome, ${event.client.name}@${event.client.address} (Protocol: ${event.client.protocol})`);
this.options.statusUpdate?.(`Welcome, ${event.client.name}@${event.client.address}`);
this.options.serverUpdate?.();
break;
Expand Down Expand Up @@ -302,7 +320,14 @@ export class Server {
this.state = ServerState.IDLE;
let players = this.Players;
_.forEach(players, (player, color)=>{
this.send(player, {type: "START", configuration: this.gameManager.StartingConfiguration, color: color});
let config;
if(player?.protocol == Protocol.v2) {
let states = this.gameManager.Game.StateHistory;
if(states.length > 2) states.splice(0, states.length-2);
config = {...this.gameManager.StartingConfiguration, finalStates: states};
}
else config = this.gameManager.CurrentConfiguration;
this.send(player, {type: "START", configuration: config, color: color});
});
this.gameManager.start();
this.logger?.info("\n" + _.repeat(_.repeat("#", 80) + "\n", 4));
Expand Down
4 changes: 3 additions & 1 deletion src/types/client-messages.codec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import * as io from 'io-ts';
import * as ioe from './io-ts.extensions'
import { Move } from './move.codec';

export const NameMessage = io.interface({
type: io.literal("NAME"),
name: io.string
name: io.string,
protocol: ioe.withDefault(io.string, "v1")
});

export const MoveMessage = io.interface({
Expand Down

0 comments on commit cc97238

Please sign in to comment.