Skip to content

Commit

Permalink
Experimental TypeScript Server
Browse files Browse the repository at this point in the history
  • Loading branch information
evolutionleo committed Jun 8, 2021
1 parent 9581d3b commit 2eee6c3
Show file tree
Hide file tree
Showing 49 changed files with 4,024 additions and 201 deletions.
Binary file modified Release/TypescriptServer.zip
Binary file not shown.
3 changes: 1 addition & 2 deletions TypescriptServer/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
node_modules/
dist/
node_modules/
12 changes: 12 additions & 0 deletions TypescriptServer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# What is this?

- This is a feature-rich server written in NodeJS
- The code is pretty documented, so feel free to look into the sources, tweak stuff, etc. to understand it better

# Where do I start?

- If you feel a bit overwhelmed with all the different files and folder - that's alright,
*you probably don't need to touch most of this stuff* to make a basic online game!
- Take a look in the **custom/** folder, the two files called `handlePacket.js` and `sendStuff.js`
are what you're looking for!
- Add a couple custom commands here + in GML and mess around a bit!
45 changes: 45 additions & 0 deletions TypescriptServer/out/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// get the command line arguments
import minimist from 'minimist';
const args = minimist(process.argv.slice(2));
const common_config = {
meta: {
game_name: 'online game',
version: 'v0.1',
framework_version: 'v3.0',
server: 'unknown'
},
tps: 30,
db_enabled: true
};
const prod_config = {
meta: {
server: 'production'
},
env_name: 'prod',
port: args.port || 1337,
db: args.db || 'mongodb://127.0.0.1:27017/oniline-game'
};
const dev_config = {
meta: {
server: 'development'
},
env_name: 'dev',
port: args.port || 1338,
db: args.db || 'mongodb://127.0.0.1:27017/online-game'
};
const default_config = dev_config;
const env = args.env || 'dev';
const config = {};
Object.assign(config, common_config);
if (env === 'production' || env === 'prod' || args.prod) {
Object.assign(config, prod_config);
}
else if (env === 'development' || env === 'dev' || args.dev) {
Object.assign(config, dev_config);
}
else {
Object.assign(config, default_config);
}
console.log('Config loaded! environment: ' + config.env_name);
global.config = config;
export default config;
70 changes: 70 additions & 0 deletions TypescriptServer/out/custom/handlePacket.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { findLobby } from '#internal/lobbyFunctions';
import MatchMaker from '#internal/matchmaker';
import { Account } from '#schemas/account';
const { make_match } = MatchMaker;
export default async function handlePacket(c, data) {
var cmd = data.cmd.toLowerCase();
// console.log('received command: ' + cmd);
switch (cmd) {
case 'hello':
console.log("Hello from client: " + data.kappa);
c.sendHello();
break;
case 'hello2':
console.log('Second hello from client: ' + data.kappa);
break;
case 'message':
console.log('Message from client: ' + data.msg);
c.sendMessage(data.msg + ' indeed');
break;
// preset commands
case 'login':
var { username, password } = data;
Account.login(username, password)
.then(function (account) {
// this also sends the message
c.login(account);
}).catch(function (reason) {
c.sendLogin('fail', reason);
});
break;
case 'register':
var { username, password } = data;
Account.register(username, password)
.then(function (account) {
// this also sends the message
c.register(account);
}).catch(function (reason) {
console.log('error: ' + reason);
c.sendRegister('fail', reason);
});
break;
case 'lobby list':
c.sendLobbyList();
break;
case 'lobby info':
var lobbyid = data.lobbyid;
c.sendLobbyInfo(lobbyid);
break;
case 'lobby join':
var lobbyid = data.lobbyid;
var lobby;
if (lobbyid) {
lobby = findLobby(lobbyid);
}
else {
lobby = make_match(c);
}
// it also sends the response
lobby.addPlayer(c);
break;
case 'lobby leave':
var lobby = c.lobby;
if (lobby !== null) {
lobby.kickPlayer(c, 'you left the lobby', false);
}
break;
// #######################
// Add your commands here:
}
}
78 changes: 78 additions & 0 deletions TypescriptServer/out/custom/sendStuff.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import packet from '#internal/packet';
export default class SendStuff {
constructor() { }
// basic send
write(data) {
this.socket.write(packet.build(data));
}
send(data) {
return this.write(data);
}
// different types of broadcast
broadcastList(clients, pack, notme) {
if (notme) {
notme = true;
}
clients.forEach(function (c) {
if (c === this && notme) { }
else {
c.write(pack);
}
});
}
broadcastAll(pack, notme) {
return this.broadcastList(global.clients, pack, notme);
}
broadcastLobby(pack, notme) {
if (this.lobby === null)
return -1;
return this.broadcastList(this.lobby.players, pack, notme);
}
// these functions can be later called using %insert_client%.sendThing()
// in handlePacket.js or wherever else where you have client objects
sendHello() {
this.write({ cmd: 'hello', str: 'Hello, client!' });
this.write({ cmd: 'hello2', str: 'Hello again, client!' });
}
sendMessage(msg) {
this.write({ cmd: 'message', msg: msg });
}
// these are some preset functions
sendRegister(status, reason) {
if (!reason)
reason = '';
this.write({ cmd: 'register', status: status, reason: reason });
}
sendLogin(status, reason) {
if (!reason)
reason = '';
this.write({ cmd: 'login', status: status, reason: reason, account: this.account, profile: this.profile });
}
sendJoinLobby(lobby) {
this.write({ cmd: 'lobby join', lobby: lobby.serialize() });
}
sendRejectLobby(lobby, reason) {
if (!reason)
reason = '';
this.write({ cmd: 'lobby reject', lobby: lobby.serialize(), reason: reason });
}
sendKickLobby(lobby, reason, forced) {
if (!forced)
forced = true;
if (!reason)
reason = '';
this.write({ cmd: 'lobby leave', lobby: lobby.serialize(), reason: reason, forced: forced });
}
sendUpdateLobby(lobby) {
this.write({ cmd: 'lobby update', lobby: lobby.serialize() });
}
sendLobbyList() {
this.write({ cmd: 'lobby list', lobbies: Object.values(global.lobbies).map(lobby => lobby.serialize()) }); // lobbies as an array
}
sendLobbyInfo(lobbyid) {
this.write({ cmd: 'lobby info', lobby: global.lobbies[lobbyid].serialize() });
}
sendPlay(lobby, start_pos) {
this.write({ cmd: 'play', lobby: lobby.serialize(), start_pos: start_pos });
}
}
3 changes: 3 additions & 0 deletions TypescriptServer/out/e.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
a: "string"
};
22 changes: 22 additions & 0 deletions TypescriptServer/out/internal/artificial_delay.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as crypto from 'crypto';
// this file is used to immitate delay/latency of the connection
export class delaySend {
static get() {
if (!this.enabled)
return -1;
return crypto.randomInt(this.min, this.max);
}
}
delaySend.enabled = false;
delaySend.min = 100;
delaySend.max = 2000;
export class delayReceive {
static get() {
if (!this.enabled)
return -1;
return crypto.randomInt(this.min, this.max);
}
}
delayReceive.enabled = false;
delayReceive.min = 100;
delayReceive.max = 2000;
83 changes: 83 additions & 0 deletions TypescriptServer/out/internal/entities/client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import SendStuff from '#custom/sendStuff';
import { Profile, freshProfile } from '#schemas/profile';
// this is a wrapper around sockets
export default class Client extends SendStuff {
constructor(socket) {
super();
this.socket = socket;
this.lobby = null; // no lobby
// these are the objects that contain all the meaningful data
this.account = null; // account info
this.profile = null; // gameplay info
}
// some events
onJoinLobby(lobby) {
this.sendJoinLobby(lobby);
}
onRejectLobby(lobby, reason) {
if (!reason)
reason = 'lobby is full!';
this.sendRejectLobby(lobby, reason);
}
onLeaveLobby(lobby) {
this.sendKickLobby(lobby, 'you left the lobby!', false);
}
onKickLobby(lobby, reason) {
if (!reason)
reason = '';
this.sendKickLobby(lobby, reason, true);
}
onPlay(lobby, start_pos) {
this.sendPlay(lobby, start_pos);
}
onDisconnect() {
this.save();
if (this.lobby !== null)
this.lobby.kickPlayer(this, 'disconnected', true);
}
// preset functions
// this one saves everything
save() {
if (this.account !== null) {
this.account.save(function (err) {
if (err) {
console.log('Error while saving account: ' + err);
}
else {
console.log('Saved the account successfully');
}
});
}
if (this.profile !== null) {
this.profile.save(function (err) {
if (err) {
console.log('Error while saving profile: ' + err);
}
else {
console.log('Saved the profile successfully.');
}
});
}
}
register(account) {
this.account = account;
this.profile = freshProfile(account);
// this.save() returns a Promise
this.save();
this.sendRegister('success');
}
login(account) {
this.account = account;
Profile.findOne({
account_id: this.account._id
}).then((profile) => {
if (profile) {
this.profile = profile;
this.sendLogin('success', this.profile);
}
else {
console.log('Error: Couldn\'t find a profile with these credentials!');
}
});
}
}
Loading

0 comments on commit 2eee6c3

Please sign in to comment.