Catan-servers is the backend for a didactic game aimed to teach different communication and process synchronization technologies.
- Description
- Requirements
- Configuration and installation
- Server API
- Command line tool
- Data Model
- Resource Servers SDK
- Available Resource Servers
- Merchant API
Each Resource Server has to be accesed in a different particular way: some servers should be accessed using HTTP, others using SocketIO, or other protocols... Each time a resource server is accessed, a resource UUID is provided. When the player has enough UUIDs of a particular resource, he can buy the houses that need this resource. For example: accessing the Wood Server three times using HTTP will provide three different Wood UUIDS... using this three UUIDs, the player can connect to the Central Server to buy a Hut (that require 3 Woods to be completed). The resources used will then be invalidated in the server, so each UUID can only be used once.
Requirements --------------- The server requires the following software to be installed and working: - Node 0.10.* - MongoDB 2.2.4 - Redis - RabbitMQ Configuration and installation --------------------------------- The server's configuration can be found in the config.js file. The default values should be right for a local installation. This same file contains the server configuration for both the Central Server and all of the Resource Servers.This project uses pm2 to launch the CentralServer and all its resource servers. The prerequisite is to install pm2 globally
npm install -g pm2
After that, execute
npm install
to install all project dependencies
When all is done, simply type
npm start
or
pm2 start processes.json
to start all the needed infrastructure
Please, refer to pm2 documentation to learn how to manage all the processes created
Each resource server has a separate init file, but the same config. For details on each server, refer to the server's chapter in this documentation.
Central Server API --------------- The API has some operations that can only be used in Edit Mode (setting the config.endpoint.edit flag to true). The edit mode is intended to debug and design the game server and to setup the initial data before starting the game. It should be set to false before starting the game. The operations that are disabled with this flag are marked with the (*) symbol.Returns a list of the available designs.
Example response:
[
{
"value": 1,
"type": "Choza",
"id": "456d2e3f-3bcf-45b9-9b79-37c7f076c8f6",
"_id": "5229cc3d83e867291a000001",
"__v": 0,
"resources": [
"Madera",
"Madera",
"Madera"
]
},
{
"value": 2,
"type": "Casucha",
"id": "5cf137a2-6d33-43ee-b90b-5f2d2486d6e5",
"_id": "523970b793efa2b835000001",
"__v": 0,
"resources": [
"Madera",
"Piedra"
]
}
]
Delete the design with the id indicated in the URL.
Create a new house design. The design parameters should be passed as a JSON with the new design. The parameters should be the following:
- name: name of the new house design
- resourcelist: array of resource names representing the resources required to complete this kind of building.
- value: points granted for constructing each instance of this kind of building.
Example request:
{
type: "Pisito",
resources: [ "Madera", "Piedra", "Metal"],
value: 20
}
Example response:
{
"value": 20,
"type": "Pisito",
"id": "8dc3add6-50ef-437a-b620-c27fc3691dc6",
"resources": [
"Madera",
"Piedra",
"Metal"
]
}
Gets the list of built houses.
Example response:
[
{
"designId": "ba439530-9797-402b-9082-38f5392e5798",
"owner": "dmj",
"id": "27bbf7fe-f688-4640-80e8-df575e8dfae2",
"_id": "524d7b145a9f701b11000001",
"__v": 0
},
{
"designId": "456d2e3f-3bcf-45b9-9b79-37c7f076c8f6",
"owner": "dmj",
"id": "dcbe7efb-a9a2-49e4-802e-90ab96ed5812",
"_id": "524d7b155a9f701b11000002",
"__v": 0
}
]
Builds a new house, with the resources passed as a parameter. All the parameters should be passed as a JSON in the body. The parameters are the following:
- login: Name of the user that will be the owner of the house.
- designId: ID of the design that wants to be used to build the house (will determine what resources are needed.
- resources: array with the resources needed to build the house. The resources must be valid resources generated by a Resource Server and should not have been used before in any building.
Example request:
{
"resources": [
"9baca2bb-f93f-47ce-9db3-e9a3bce101ce",
"0251bdd5-35b7-48a6-9afd-41a3bfec5c93",
"b9927b0d-04cc-4938-bda8-870d68652e8f"
],
"designId": "456d2e3f-3bcf-45b9-9b79-37c7f076c8f6",
"login": "dmj"
}
Example response:
{
"designId": "456d2e3f-3bcf-45b9-9b79-37c7f076c8f6",
"owner": "dmj",
"id": "14e43517-5493-4d02-9b8a-059230c9c621"
}
Gets a list of the available resource servers, along with their URLs and the produced resource.
Example response:
[
{
"description": "Simple HTTP server without authentication. Can be mined making a GET request to the '/chop' resource. It provides Madera",
"url": "http://localhost/3003",
"resourceName": "Madera",
"id": "4f5f4f08-8496-4b48-a993-0fcf3b0413e3",
"_id": "524e861f2960c4fb46000001",
"__v": 0
},
{
"description": "Socket IO server that provides Metal. To mine it, follow the protocol described in the documentation.",
"url": "http://localhost/3005",
"resourceName": "Metal",
"id": "3582d319-3c09-409c-9bc7-73d9560d8aa5",
"_id": "524e86234df82f1147000001",
"__v": 0
}
]
Gets a list of the actual resources generated in the server (for debugging purposes only).
Example response:
[
{
"name": "Madera",
"id": "39afc5f5-548e-40fe-8548-3a9e17835047",
"_id": "524e86232960c4fb46000002"
},
{
"name": "Madera",
"id": "a1b91c37-9194-4b87-ac13-d7213339a608",
"_id": "524e86272960c4fb46000003"
},
{
"name": "Metal",
"id": "25480c7e-9b35-416d-8340-12bb5e7a8556",
"_id": "524e86284df82f1147000002"
}
]
Returns the list of all the merchants registered in the system.
Example response:
[
{
"url": "http://173.31.62.88:5023",
"name": "dmj",
"id": "31dc2e62-f63e-443a-a383-04690dc24c02",
"_id": "524e8b8f69b656784c000001"
},
{
"url": "http://19.231.111.68:5023",
"name": "rzq",
"id": "0b8882f3-40a8-4b94-bdc6-84cf7570dd80",
"_id": "524e8c1669b656784c000002"
}
]
Register a new merchant in the server.
Example request:
{
"name": "dmj",
"url": "http://173.31.62.88:5023"
}
Example response:
{
"url": "http://173.31.62.88:5023",
"name": "dmj",
"id": "31dc2e62-f63e-443a-a383-04690dc24c02"
}
Unregister the given merchant.
Command line tool ------------------- The server has a command line tool, called catanCmd, in order to test and debug features and to prepare the initial conditions of a game (e.g. creating designs and resources). The followin help output shows the syntax:Usage: catanCmd.js <command> [options]
Commands:
createDesign [name] [resourceList] [value]
Use this command to create new designs, indicating the name, value and a comma-separated
list of the resources needed to build it. Repeat the name of the resource when multiple
instances of it are to be required
createHouse [login] [designId] [resourceList]
This command buys a new house for the user indicated in the login. The resource used to
build the house must exist, and will be deleted as usual once the house is constructed. The resources
should serialized as a comma-separated list of the resource IDs
createServer [resourceName] [url] [description]
This command register a new Resource Server in the system, to be used in the ResourceServer Directory
listHouses
Return a list of all the created houses
listResources
Return a list of all the available resources
listDesigns
Return a list of all the available designs
listResourceServers
Return a list of all the available Resource Servers
removeDesign [id]
Remove the selected design from the DB
removeHouse [id]
Remove the selected house from the DB
removeResource [id]
Remove the selected resource from the DB
removeResourceServer [id]
Remove the selected Resource Server from the DB
Options:
-h, --help output usage information
-V, --version output the version number
-
Design
-
House
-
Resource Server
-
Merchant
The resources for this server are granted via HTTP. A HTTP GET request to the /chop path of the server will return: an object containing the resource ID
{
name: "Madera",
id: "d51de2c4-8518-47ab-9a4c-8cc859f5f033"
}
or an error if there is no wood to chop
{
code: "Internal code of the error",
message: "Error message for human beings"
}
The resources of this server have to be negotiated under Socket.IO. The "Clown algorithm" to get them has been summarized in the following diagram.
This is the detailed description of each of the steps:
- When a new Socket.IO connection is received, the server sends blank
¡Hola Don Pepito!
message to the Client. - The client replies emitting an
¡Hola Don Jose!
message. This message can be repeated as many times as needed and each time it is repeated, it resets the internal state for the client to this point in the protocol (use it for errors, for example). - The server replies emitting a
¿Paso usted por mi casa?
message, indicating a house address in the payload.
{
address: "05a096a1-943c-4011-be14-24ceb886f9d9"
}
- The client has to visit the house in the indicated address, by sending an HTTP POST message to the HTTP endpoint
of the server with path
/casa
and a payload consisting of a JSON object with a single propertyaddress
with the address value provided before.
{
address: "05a096a1-943c-4011-be14-24ceb886f9d9"
}
On success, the server will return:
{
message: "Welcome to the house. This is your certificate.",
certificate: "a978a90e-bdf2-4cc8-a4b3-54b19e822dbe"
}
- The client will emit a
Por su casa yo pase
message to the server, indicating the certificate in the payload, with the following syntax:
{
certificate: "a978a90e-bdf2-4cc8-a4b3-54b19e822dbe"
}
- The server will check the certificate for validity. If it's correct, it will reply with a
¿Vio usted a mi abuela?
event, indicating the name of the grandmother in the payload in this way:
{
grandMaName: "49f2c370-262f-4771-bbbb-ae64a0618954"
}
- The client will have to visit the specified grandmother in the HTTP endpoint, by posting an HTTP POST message to the
/abuela
path, with the syntax indicated in the code below.
{
grandMaName: "49f2c370-262f-4771-bbbb-ae64a0618954"
}
The answer to this request will be a certificate similar to the one received in step 4.
{
message: "Hello sweetie. This is your certificate.",
certificate: "58bd6f3e-78cc-4d3a-99b0-407cfa42b53e"
}
- The client will issue an
A su abuela yo la vi
message to the server, with the provided message as the payload:
{
certificate: "58bd6f3e-78cc-4d3a-99b0-407cfa42b53e"
}
- The server will answer with an
¡Adios Don Pepito!
message, with the desired resource in the body or an error if the steel is currently depleted:
{
resource: "5a4c3971-131e-4b19-aa18-0ea562f16b64",
resourceType: "Metal"
}
- [Optional] The server will wait for the client to close the connection emitting an
¡Adios Don Jose!
. This step is not required, but it will be rude of you not to follow it (and I'm sure your mother told you to be polite).
When an Error happens during a socketIO step, the server will emit an Error
with the following payload
{
message: "Blablabla",
action: "how to solve this error",
data: {} //OPTIONAL js object with error related data
}
When an error happens during an HTTP POST request, the server will respond with a HTTP.statusCode !== 200
- CRUD of catalog items, or resource types the Merchant is willing to sell, indicating the price he expects.
- A buy mechanism, by which any other client willing to make a deal can pay the desired resources to get one of the articles.
- A internal mechanism to forbid access to the catalog editing routes for requests other than localhost.
It's worth mentioning that the central server DOES NOT provide any mechanism to verify the authenticity of the traded goods, so the merchants may want to control who they trust before making a deal. The use of black lists is encouraged to solve this issue (along with a mechanism to control the origin of goods that are rejected by the central server).
To enable the merchants to find themselves, the central server provides a Market API, where the merchants can register and list all the already registered Merchants.
The following sections explain the API with more detail.
All error messages will be reported with a JSON body specifing the nature of the problem. The scheme of that body will be the following:
{
code: 4501,
message: "The types of the resources didn't match the resource price"
}
The code should be an internal code for that particular type of error. The message is meant to be a human-readable message, so it doesn't need to have any particular syntax.
Retrieve the list of all catalog items and their prices.
[
{
id: "570ba3a5-b24b-4a7f-4a7f-f8e6d70ba615",
price: ["Madera", "Madera", "Piedra"],
type: "Circonio"
},
{
id: "2e1624a5-7f7b-fcfc-83fc-f8e8570babb5",
price: ["Rubi", "Circonio", "Plata"],
type: "Talco"
},
{
id: "17a52cb2-67ec-42d8-a904-b0fc2e657d80",
price: ["Piedra", "Papel", "Tijera"],
type: "Rubi"
}
]
Retrieve the specificied catalog Item, indicating how much stock there is for that item.
{
price: ["Madera", "Madera", "Piedra"],
type: "Circonio",
stock: 12
}
Buy one item of the catalog. The buyer must include the UUIDs and types of the products in the payload:
{
bill: [
{
type: "Madera",
value: "570ba3a5-b24b-4a7f-4a7f-f8e6d70ba615"
},
{
type: "Piedra",
value: "2e1624a5-7f7b-fcfc-83fc-f8e8570babb5"
}
]
}
If the payload is incorrect, the Merchant will reply with a status code 400 and an error message indicating what was the nature of the problem (see format above).
If the payload is correct, and there is enough stock of the traded good, the merchant will reply with the product and a 200 OK status:
{
type: "Plutonio",
value: "17a52cb2-67ec-42d8-a904-b0fc2e657d80"
}
Creates a new entry in the catalog, indicating the type of resource it is going to be traded and the amount and type of other resources needed to perform a transaction. The body of the request should be like the following:
{
price: ["Madera", "Madera", "Piedra"],
type: "Circonio"
}
If the new resource is created, a 200OK message will be returned.
Remove the specified entry from the catalog. It doesn't expect a body. If everything went well, it will return a 200OK with a valid JSON body. If the catalog item could not be found, a 404Not Found code will be returned.