-
Notifications
You must be signed in to change notification settings - Fork 14
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
chore(docs): add starting tutorial.md #1859
Changes from all commits
5bc493a
6dcfd11
9dae926
7d2a3e1
47f845f
7803541
6769ba4
2003c90
dc9016a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
EXTERNAL_HOST= | ||
CERTIFICATE_FILE= | ||
PRIVATE_KEY_FILE= | ||
PUBLIC_KEY_FILE= |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
# Getting started as a user | ||
|
||
Documention type: Tutorial | ||
|
||
Last updated: 2003c90b4aecc5150116e83a0f14d18f44bf3536 | ||
|
||
--- | ||
|
||
This project isn't really geared towards an player of the game, but if you want to try it out, this is how to do so: | ||
|
||
## Requirements | ||
|
||
// TODO: Link to the install docs for each item | ||
|
||
- Internet | ||
- Linux | ||
- Git | ||
- Docker | ||
- Docker Compose | ||
- NodeJS (v20.x - v21.x) | ||
- The debug copy of the game | ||
|
||
## Setup | ||
|
||
After getting the requirements above ready, perform the following steps: | ||
|
||
### On the computer where you are running the server | ||
|
||
1. Open a terminal or command prompt | ||
2. Type `git clone https://github.com/rustymotors/server.git rusty-server` and press enter | ||
3. Type `cd rusty-server` and press enter | ||
4. Type `./mcos/pull_nginx_image.sh` and press enter (this step may take a while, depending on your internet speed) | ||
5. Type `docker-compose up -d` and press enter | ||
6. Type `corepack enable pnpm` and press enter | ||
7. Type `pnpm install` and press enter | ||
8. Type `pnpm run build` and press enter | ||
9. Type `cp .env.example .env` and press enter | ||
10. Open the `.env` file with your favorite text editing program (the simpler the better) and edit the values as follows: | ||
a. `EXTERNAL_HOST=` - Add the hostname or ip of the computer you are running this server on. This value MUST be reachable from where you install the game. | ||
b. `CERTIFICATE_FILE=` - The relitive path from the `rusty-server` folder to the SSL certificate. If you want to use the one I have included with the repository (highly recomended), the value will be `data/mcouniverse.crt` | ||
c. `PRIVATE_KEY_FILE` - The path to the private key. Use `data/private_key.pem` for the working copy | ||
d. `PUBLIC_KEY_FILE` - The path to the public key. Use `data/pub.key` for the working copy | ||
11. Type `npm start` and press enter | ||
12. If the last message on your screen is `Server listening at http://0.0.0.0:3000`, then the server is running! | ||
|
||
### On the computer where you are running the game | ||
|
||
1. Open a web browser | ||
2. In the address bar, type `<enternal_ip>/cert` where \<enternal_ip\> is the value you saved in the .env file on the server. Do not include the brackets, and press enter | ||
3. Some text should load. The first line should contain `BEGIN CERTIFICATE` | ||
4. Click "Save" when asked if you want to open or save | ||
5. Select the folder you want to save in (I like the Desktop), but before you press "save", make sure to edit the file name so it says `"cert.crt"`. THE QUOTES ARE IMPORTANT | ||
6. Sorry for the caps. Click "Save" if you haven't already | ||
7. In the folder where you saved the certificate, you should see a file named "cert" with an icon that looks like a certificate. Double-click on it. | ||
|
||
--- | ||
|
||
## 7.5. From this point on, I'm going to tell you to do a bunch of things that Windows will warn you NOT to do. This is because in order to have the game connect to our server we have to use some very old security methods that are no longer advised to be used. If you don't trust me, that's fine. But it won't work otherwise. Let's proceed. | ||
|
||
8. We are looking at a windows that says "The CA Root Certificate is not trusted". Press "Install Certificate" | ||
9. Click "Next" | ||
10. You are now on a screen that asks where you want to save this certificate. | ||
11. Click on the "Place all certificates in the following store" and click "browse" | ||
12. Select "Trusted Roor Certification Authorities". This should be the second one down. | ||
13. Click "Ok" | ||
14. Click "Next" | ||
15. Click "Finish" | ||
16 You now have a window warning you that you are installing a untrusted root certificate that is unknown to Windows. Click "Yes" | ||
16. Click "ok" and then click "Ok" again. | ||
17. Return to your web browser. | ||
18. In the address bar, type `<enternal_ip>/key` where \<enternal_ip\> is the value you saved in the .env file on the server. Do not include the brackets, and press enter | ||
19. A long string of letters and numbers should load. | ||
20. Click "Save" when asked if you want to open or save | ||
21. Select the folder you want to save in (I like the Desktop), but before you press "save", make sure to edit the file name so it says `"pub.key"`. Again, make sure to include the quotes | ||
22. Click "Save" | ||
23. Copy the file you just saved to your game install folder. Tell Wndows it is ok to overwrite the existing file of the same name. | ||
24. Return to your web browser | ||
25. In the address bar, type `<enternal_ip>/registry` where \<enternal_ip\> is the value you saved in the .env file on the server. Do not include the brackets, and press enter | ||
26. Some text will load. The first line should contain "Windows Registry Editor" | ||
27. Click "Save" when asked if you want to open or save | ||
28. Select the folder you want to save in (I like the Desktop), but before you press "save", make sure to edit the file name so it says `"client.reg"`. Again, make sure to include the quotes | ||
29. Click "Save" | ||
|
||
30. This next step has a slight change, depending on what version of Windows you have installed the game under | ||
a. If you are using Windows XP (or lower), you will need to edit this file we just save. To do so, right-click on the saved file and choose "edit" | ||
If Windows prompts you that the file is not signed, click "open". | ||
Every line that starts `HKEY_LOCAL_MACHINE\Software\WOW6432Node\`, change to say `HKEY_LOCAL_MACHINE\Software\`. Leve the rest of the line. Save. | ||
b. If you are using a version of Windows that is newer then Windows XP, no action is needed here | ||
31. Double-click on the saved file. | ||
32. f Windows prompts you that the file is not signed, click "open". | ||
33. Windows will ask you if you are sure you want to import this registry file. Click "yes" | ||
34. Click "Ok" | ||
|
||
## Running | ||
|
||
If you haven't followed all the steps under the Setup section, this will probably not work well | ||
|
||
37. Double-click the debug copy of the game | ||
38. There are two pre-created logins, depending on what part you to see: | ||
a. Username: "admin", Password: "admin" - No existing account, profile creation possible (not playabl, even if it says it was created) | ||
b. Username: "molly", Password: "molly" - Existing account, can login to the server and reach the lobby. Any activities past that probably won't work. |
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -30,9 +30,7 @@ import { generateToken } from "../../nps/services/token.js"; | |||||||||||||||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||||||||||||||||
* @param {import("fastify").FastifyInstance} webServer The web server | ||||||||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||||||||
export async function addWebRoutes( | ||||||||||||||||||||||||||||||||||||||||||||||||||
webServer: import("fastify").FastifyInstance, | ||||||||||||||||||||||||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
export function addWebRoutes(webServer: import("fastify").FastifyInstance) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
webServer.addContentTypeParser("*", function (request, payload, done) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
let data = ""; | ||||||||||||||||||||||||||||||||||||||||||||||||||
payload.on("data", (chunk) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -43,7 +41,7 @@ export async function addWebRoutes( | |||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
webServer.get("/", async (_request, reply) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
webServer.get("/", (_request, reply) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
return reply.send("Hello, world!"); | ||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -114,27 +112,36 @@ export async function addWebRoutes( | |||||||||||||||||||||||||||||||||||||||||||||||||
return reply.send(generateShardList(config.host)); | ||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
webServer.get("/cert", (_request, reply) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
webServer.get("/cert", async (_request, reply) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
const config = getServerConfiguration({}); | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (typeof config.host === "undefined") { | ||||||||||||||||||||||||||||||||||||||||||||||||||
throw new Error("No host defined in config"); | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
return reply.send(handleGetCert(config)); | ||||||||||||||||||||||||||||||||||||||||||||||||||
const certFile = await handleGetCert(config); | ||||||||||||||||||||||||||||||||||||||||||||||||||
reply.header("Content-Type", "text/plain"); | ||||||||||||||||||||||||||||||||||||||||||||||||||
reply.header("Content-Disposition", "attachment; filename=cert.crt"); | ||||||||||||||||||||||||||||||||||||||||||||||||||
reply.send(certFile); | ||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
webServer.get("/key", (_request, reply) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
webServer.get("/key", async (_request, reply) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
const config = getServerConfiguration({}); | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (typeof config.host === "undefined") { | ||||||||||||||||||||||||||||||||||||||||||||||||||
throw new Error("No host defined in config"); | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
return reply.send(handleGetKey(config)); | ||||||||||||||||||||||||||||||||||||||||||||||||||
const keyFile = await handleGetKey(config); | ||||||||||||||||||||||||||||||||||||||||||||||||||
reply.header("Content-Type", "text/plain"); | ||||||||||||||||||||||||||||||||||||||||||||||||||
reply.header("Content-Disposition", "attachment; filename=pub.key"); | ||||||||||||||||||||||||||||||||||||||||||||||||||
reply.send(keyFile); | ||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+126
to
+134
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to the webServer.get("/key", async (_request, reply) => {
const config = getServerConfiguration({});
if (typeof config.host === "undefined") {
throw new Error("No host defined in config");
}
+ try {
const keyFile = await handleGetKey(config);
reply.header("Content-Type", "text/plain");
reply.header("Content-Disposition", "attachment; filename=pub.key");
reply.send(keyFile);
+ } catch (error) {
+ reply.status(500).send('Internal Server Error');
+ }
}); Would you like help in creating unit tests for this route handler? Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
webServer.get("/registry", (_request, reply) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
const config = getServerConfiguration({}); | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (typeof config.host === "undefined") { | ||||||||||||||||||||||||||||||||||||||||||||||||||
throw new Error("No host defined in config"); | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
return reply.send(handleGetRegistry(config)); | ||||||||||||||||||||||||||||||||||||||||||||||||||
const regFile = handleGetRegistry(config); | ||||||||||||||||||||||||||||||||||||||||||||||||||
reply.header("Content-Type", "text/plain"); | ||||||||||||||||||||||||||||||||||||||||||||||||||
reply.header("Content-Disposition", "attachment; filename=client.reg"); | ||||||||||||||||||||||||||||||||||||||||||||||||||
reply.send(regFile); | ||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+142
to
+145
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The webServer.get("/registry", (_request, reply) => {
const config = getServerConfiguration({});
if (typeof config.host === "undefined") {
throw new Error("No host defined in config");
}
+ try {
- const regFile = handleGetRegistry(config);
+ const regFile = await handleGetRegistry(config);
reply.header("Content-Type", "text/plain");
reply.header("Content-Disposition", "attachment; filename=client.reg");
reply.send(regFile);
+ } catch (error) {
+ reply.status(500).send('Internal Server Error');
+ }
}); Would you like help in creating unit tests for this route handler? Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { describe, it, expect, vi } from "vitest"; | ||
import { generateShardList } from "../../shard/src/ShardServer"; | ||
import { | ||
handleGetCert, | ||
handleGetKey, | ||
handleGetRegistry, | ||
} from "../../shard/src/index"; | ||
|
||
function mockConfig() { | ||
return { | ||
certificateFile: "test", | ||
privateKeyFile: "test", | ||
publicKeyFile: "test", | ||
host: "test", | ||
}; | ||
} | ||
|
||
describe("web", () => { | ||
it("handleGetCert", async () => { | ||
vi.mock("fs/promises", async (importOriginal) => { | ||
return { | ||
...(await importOriginal<typeof import("node:fs/promises")>()), | ||
readFile: () => { | ||
return "test"; | ||
}, | ||
}; | ||
}); | ||
const config = mockConfig(); | ||
const result = await handleGetCert(config); | ||
expect(result).toBe("test"); | ||
}); | ||
|
||
it("handleGetRegistry", () => { | ||
const config = mockConfig(); | ||
const result = handleGetRegistry(config); | ||
expect(result).toContain('Windows Registry Editor Version 5.00'); | ||
expect(result).toContain('"ShardUrlDev"="http://test/ShardList/"'); | ||
}); | ||
|
||
it("handleGetKey", async () => { | ||
const config = mockConfig(); | ||
const result = await handleGetKey(config); | ||
expect(result).toBe("test"); | ||
}); | ||
|
||
it("generateShardList", () => { | ||
const config = mockConfig(); | ||
const result = generateShardList(config.host); | ||
expect(result).toContain("LoginServerIP=test"); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The async implementation for the
/cert
route handler is well done. However, consider adding error handling for thehandleGetCert
function to manage potential failures gracefully. Additionally, it's important to ensure this new code path is covered by tests to maintain code quality and reliability.Would you like assistance in creating unit tests for this route handler?
Committable suggestion